From 86750b2db73516e3bb6107594005c4b686135176 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 17 Jan 2017 11:31:03 +0100 Subject: [PATCH 001/242] removed volk dependency. Checked and working --- cmake/modules/FindVolk.cmake | 144 ------------------ srslte/CMakeLists.txt | 19 --- srslte/include/srslte/utils/vector_simd.h | 20 +++ srslte/lib/CMakeLists.txt | 7 - srslte/lib/utils/vector.c | 167 ++++----------------- srslte/lib/utils/vector_simd.c | 170 ++++++++++++++++++++++ 6 files changed, 222 insertions(+), 305 deletions(-) delete mode 100644 cmake/modules/FindVolk.cmake diff --git a/cmake/modules/FindVolk.cmake b/cmake/modules/FindVolk.cmake deleted file mode 100644 index 5dbe17cd5..000000000 --- a/cmake/modules/FindVolk.cmake +++ /dev/null @@ -1,144 +0,0 @@ -INCLUDE(FindPkgConfig) -PKG_CHECK_MODULES(PC_VOLK volk QUIET) - -FIND_PATH( - VOLK_INCLUDE_DIRS - NAMES volk/volk.h - HINTS $ENV{VOLK_DIR}/include - ${CMAKE_INSTALL_PREFIX}/include - ${PC_VOLK_INCLUDE_DIR} - PATHS /usr/local/include - /usr/include -) - -FIND_LIBRARY( - VOLK_LIBRARIES - NAMES volk - HINTS $ENV{VOLK_DIR}/lib - ${CMAKE_INSTALL_PREFIX}/lib - ${CMAKE_INSTALL_PREFIX}/lib64 - ${PC_VOLK_LIBDIR} - PATHS /usr/local/lib - /usr/local/lib64 - /usr/lib - /usr/lib64 -) - -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(VOLK DEFAULT_MSG VOLK_LIBRARIES VOLK_INCLUDE_DIRS) -MARK_AS_ADVANCED(VOLK_LIBRARIES VOLK_INCLUDE_DIRS VOLK_DEFINITIONS) - -IF(VOLK_FOUND) - SET(CMAKE_REQUIRED_LIBRARIES ${VOLK_LIBRARIES} m) - CHECK_FUNCTION_EXISTS_MATH(volk_16i_s32f_convert_32f HAVE_VOLK_CONVERT_IF_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32f_index_max_16u HAVE_VOLK_MAX_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32f_x2_max_32f HAVE_VOLK_MAX_VEC_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32f_accumulator_s32f HAVE_VOLK_ACC_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32fc_s32fc_multiply_32fc HAVE_VOLK_MULT_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32fc_conjugate_32fc HAVE_VOLK_CONJ_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32fc_x2_multiply_32fc HAVE_VOLK_MULT2_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32fc_x2_multiply_conjugate_32fc HAVE_VOLK_MULT2_CONJ_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32fc_32f_multiply_32fc HAVE_VOLK_MULT_REAL_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32f_s32f_multiply_32f HAVE_VOLK_MULT_FLOAT_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32fc_magnitude_32f HAVE_VOLK_MAG_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32fc_magnitude_squared_32f HAVE_VOLK_MAG_SQUARE_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32f_x2_divide_32f HAVE_VOLK_DIVIDE_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32fc_x2_dot_prod_32fc HAVE_VOLK_DOTPROD_FC_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32fc_32f_dot_prod_32fc HAVE_VOLK_DOTPROD_CFC_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32fc_x2_conjugate_dot_prod_32fc HAVE_VOLK_DOTPROD_CONJ_FC_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32f_x2_dot_prod_32f HAVE_VOLK_DOTPROD_F_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32fc_s32f_atan2_32f HAVE_VOLK_ATAN_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32f_s32f_convert_16i HAVE_VOLK_CONVERT_FI_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32fc_deinterleave_32f_x2 HAVE_VOLK_DEINTERLEAVE_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32f_x2_interleave_32fc HAVE_VOLK_INTERLEAVE_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32f_x2_subtract_32f HAVE_VOLK_SUB_FLOAT_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32f_x2_add_32f HAVE_VOLK_ADD_FLOAT_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32fc_x2_square_dist_32f HAVE_VOLK_SQUARE_DIST_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32fc_deinterleave_real_32f HAVE_VOLK_DEINTERLEAVE_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32fc_index_max_16u HAVE_VOLK_MAX_ABS_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_32f_x2_multiply_32f HAVE_VOLK_MULT_REAL2_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_16i_max_star_16i HAVE_VOLK_MAX_STAR_S_FUNCTION) - CHECK_FUNCTION_EXISTS_MATH(volk_8i_convert_16i HAVE_VOLK_CONVERT_CI_FUNCTION) - - - - SET(VOLK_DEFINITIONS "HAVE_VOLK") - IF(${HAVE_VOLK_CONVERT_CI_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_CONVERT_CI_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_MAX_STAR_S_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MAX_STAR_S_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_MAX_ABS_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MAX_ABS_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_MAX_VEC_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MAX_VEC_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_DOTPROD_CONJ_FC_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_DOTPROD_CONJ_FC_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_MAG_SQUARE_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MAG_SQUARE_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_SQUARE_DIST_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_SQUARE_DIST_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_DEINTERLEAVE_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_DEINTERLEAVE_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_INTERLEAVE_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_INTERLEAVE_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_SUB_FLOAT_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_SUB_FLOAT_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_ADD_FLOAT_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_ADD_FLOAT_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_MULT2_CONJ_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MULT2_CONJ_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_DEINTERLEAVE_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_DEINTERLEAVE_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_CONVERT_FI_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_CONVERT_FI_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_MAX_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MAX_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_ACC_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_ACC_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_MULT_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MULT_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_CONJ_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_CONJ_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_MULT2_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MULT2_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_MULT_FLOAT_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MULT_FLOAT_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_MULT_REAL_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MULT_REAL_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_MAG_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MAG_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_DIVIDE_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_DIVIDE_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_DOTPROD_FC_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_DOTPROD_FC_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_DOTPROD_F_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_DOTPROD_F_FUNCTION") - ENDIF() - IF(${HAVE_VOLK_ATAN_FUNCTION}) - SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_ATAN_FUNCTION") - ENDIF() -ENDIF(VOLK_FOUND) diff --git a/srslte/CMakeLists.txt b/srslte/CMakeLists.txt index 0ecf9ddf6..82daf4df2 100644 --- a/srslte/CMakeLists.txt +++ b/srslte/CMakeLists.txt @@ -74,25 +74,6 @@ else(BLADERF_FOUND OR UHD_FOUND) add_definitions(-DDISABLE_RF) endif(BLADERF_FOUND OR UHD_FOUND) -include(CheckFunctionExistsMath) -if(${DISABLE_VOLK}) - if(${DISABLE_VOLK} EQUAL 0) - find_package(Volk) - else(${DISABLE_VOLK} EQUAL 0) - message(STATUS "VOLK library disabled (DISABLE_VOLK=1)") - endif(${DISABLE_VOLK} EQUAL 0) -else(${DISABLE_VOLK}) - find_package(Volk) -endif(${DISABLE_VOLK}) - -if(VOLK_FOUND) - include_directories(${VOLK_INCLUDE_DIRS}) - link_directories(${VOLK_LIBRARY_DIRS}) - message(STATUS " Compiling with VOLK SIMD library.") -else(VOLK_FOUND) - message(STATUS " VOLK SIMD library NOT found. Using generic implementation.") -endif(VOLK_FOUND) - ######################################################################## # Add subdirectories ######################################################################## diff --git a/srslte/include/srslte/utils/vector_simd.h b/srslte/include/srslte/utils/vector_simd.h index cd6eb4d28..cfdef5ecd 100644 --- a/srslte/include/srslte/utils/vector_simd.h +++ b/srslte/include/srslte/utils/vector_simd.h @@ -49,6 +49,26 @@ SRSLTE_API void srslte_vec_lut_sss_simd(short *x, unsigned short *lut, short *y, SRSLTE_API void srslte_vec_convert_fi_simd(float *x, int16_t *z, float scale, uint32_t len); +SRSLTE_API void srslte_vec_prod_ccc_simd(cf_t *x,cf_t *y, cf_t *z, uint32_t len); + +SRSLTE_API void srslte_vec_abs_square_cf_simd(cf_t *x, float *abs_square, uint32_t len); + +SRSLTE_API cf_t srslte_vec_dot_prod_ccc_simd(cf_t *x, cf_t *y, uint32_t len); + +SRSLTE_API void srslte_vec_sum_fff_simd(float *x, float *y, float *z, uint32_t len); + +SRSLTE_API cf_t srslte_vec_dot_prod_conj_ccc_simd(cf_t *x, cf_t *y, uint32_t len); + +SRSLTE_API void srslte_vec_prod_conj_ccc_simd(cf_t *x,cf_t *y, cf_t *z, uint32_t len); + +SRSLTE_API void srslte_vec_sc_prod_ccc_simd(cf_t *x, cf_t h, cf_t *z, uint32_t len); + +SRSLTE_API float srslte_vec_acc_ff_simd(float *x, uint32_t len); + +SRSLTE_API cf_t srslte_vec_dot_prod_cfc_simd(cf_t *x, float *y, uint32_t len); + +SRSLTE_API void srslte_vec_convert_if_simd(int16_t *x, float *z, float scale, uint32_t len); + #ifdef __cplusplus } #endif diff --git a/srslte/lib/CMakeLists.txt b/srslte/lib/CMakeLists.txt index 3a73d8761..1e7b11df6 100644 --- a/srslte/lib/CMakeLists.txt +++ b/srslte/lib/CMakeLists.txt @@ -90,13 +90,6 @@ if(RF_FOUND) endif(BLADERF_FOUND) endif(RF_FOUND) -if(VOLK_FOUND) - target_link_libraries(srslte ${VOLK_LIBRARIES}) - if(NOT DisableMEX) - target_link_libraries(srslte_static ${VOLK_LIBRARIES}) - endif(NOT DisableMEX) -endif(VOLK_FOUND) - INSTALL(TARGETS srslte DESTINATION ${LIBRARY_DIR}) SRSLTE_SET_PIC(srslte) diff --git a/srslte/lib/utils/vector.c b/srslte/lib/utils/vector.c index 469320177..578a644c2 100644 --- a/srslte/lib/utils/vector.c +++ b/srslte/lib/utils/vector.c @@ -35,10 +35,6 @@ #include "srslte/utils/vector_simd.h" #include "srslte/utils/bit.h" -#ifdef HAVE_VOLK -#include "volk/volk.h" -#endif - int srslte_vec_acc_ii(int *x, uint32_t len) { int i; int z=0; @@ -48,19 +44,14 @@ int srslte_vec_acc_ii(int *x, uint32_t len) { return z; } +// Used in PRACH detector float srslte_vec_acc_ff(float *x, uint32_t len) { -#ifdef HAVE_VOLK_ACC_FUNCTION - float result; - volk_32f_accumulator_s32f(&result,x,len); - return result; -#else int i; float z=0; for (i=0;i y[i]) { @@ -752,17 +656,11 @@ void srslte_vec_max_fff(float *x, float *y, float *z, uint32_t len) { z[i] = y[i]; } } -#endif } +// CP autocorr uint32_t srslte_vec_max_abs_ci(cf_t *x, uint32_t len) { -#ifdef HAVE_VOLK_MAX_ABS_FUNCTION - uint32_t target=0; - volk_32fc_index_max_16u(&target,x,len); - return target; - -#else uint32_t i; float m=-FLT_MAX; uint32_t p=0; @@ -775,7 +673,6 @@ uint32_t srslte_vec_max_abs_ci(cf_t *x, uint32_t len) { } } return p; -#endif } void srslte_vec_quant_fuc(float *in, uint8_t *out, float gain, float offset, float clip, uint32_t len) { diff --git a/srslte/lib/utils/vector_simd.c b/srslte/lib/utils/vector_simd.c index 1612f2c07..01a3d4c64 100644 --- a/srslte/lib/utils/vector_simd.c +++ b/srslte/lib/utils/vector_simd.c @@ -280,3 +280,173 @@ void srslte_vec_convert_fi_simd(float *x, int16_t *z, float scale, uint32_t len) } #endif } + + +// for enb no-volk +void srslte_vec_sum_fff_simd(float *x, float *y, float *z, uint32_t len) { +#ifdef LV_HAVE_SSE + unsigned int number = 0; + const unsigned int points = len / 4; + + const float* xPtr = (const float*) x; + const float* yPtr = (const float*) y; + float* zPtr = (float*) z; + + __m128 xVal, yVal, zVal; + for(;number < points; number++){ + + xVal = _mm_load_ps(xPtr); + yVal = _mm_load_ps(yPtr); + + zVal = _mm_add_ps(xVal, yVal); + + _mm_store_ps(zPtr, zVal); + + xPtr += 4; + yPtr += 4; + zPtr += 4; + } + + number = points * 4; + for(;number < len; number++){ + z[number] = x[number] + y[number]; + } +#endif +} + +static inline __m128 _mm_complexmul_ps(__m128 x, __m128 y) { + __m128 yl, yh, tmp1, tmp2; + yl = _mm_moveldup_ps(y); // Load yl with cr,cr,dr,dr + yh = _mm_movehdup_ps(y); // Load yh with ci,ci,di,di + tmp1 = _mm_mul_ps(x, yl); // tmp1 = ar*cr,ai*cr,br*dr,bi*dr + x = _mm_shuffle_ps(x, x, 0xB1); // Re-arrange x to be ai,ar,bi,br + tmp2 = _mm_mul_ps(x, yh); // tmp2 = ai*ci,ar*ci,bi*di,br*di + return _mm_addsub_ps(tmp1, tmp2); // ar*cr-ai*ci, ai*cr+ar*ci, br*dr-bi*di, bi*dr+br*di +} + +void srslte_vec_prod_ccc_simd(cf_t *x,cf_t *y, cf_t *z, uint32_t len) +{ +#ifdef LV_HAVE_SSE + unsigned int number = 0; + const unsigned int halfPoints = len / 2; + + __m128 xVal, yVal, zVal; + float* zPtr = (float*) z; + const float* xPtr = (const float*) x; + const float* yPtr = (const float*) y; + + for(; number < halfPoints; number++){ + xVal = _mm_load_ps(xPtr); + yVal = _mm_load_ps(yPtr); + zVal = _mm_complexmul_ps(xVal, yVal); + _mm_store_ps(zPtr, zVal); + + xPtr += 4; + yPtr += 4; + zPtr += 4; + } + + if((len % 2) != 0){ + *zPtr = (*xPtr) * (*yPtr); + } +#endif +} + +static inline __m128 _mm_complexmulconj_ps(__m128 x, __m128 y) { + const __m128 conjugator = _mm_setr_ps(0, -0.f, 0, -0.f); + y = _mm_xor_ps(y, conjugator); + return _mm_complexmul_ps(x, y); +} + +void srslte_vec_prod_conj_ccc_simd(cf_t *x,cf_t *y, cf_t *z, uint32_t len) { +#ifdef LV_HAVE_SSE + unsigned int number = 0; + const unsigned int halfPoints = len / 2; + + __m128 xVal, yVal, zVal; + float* zPtr = (float*) z; + const float* xPtr = (const float*) x; + const float* yPtr = (const float*) y; + + for(; number < halfPoints; number++){ + xVal = _mm_load_ps(xPtr); + yVal = _mm_load_ps(yPtr); + zVal = _mm_complexmulconj_ps(xVal, yVal); + _mm_store_ps(zPtr, zVal); + + xPtr += 4; + yPtr += 4; + zPtr += 4; + } + + if((len % 2) != 0){ + *zPtr = (*xPtr) * (*yPtr); + } +#endif +} + +void srslte_vec_sc_prod_ccc_simd(cf_t *x, cf_t h, cf_t *z, uint32_t len) { +#ifdef LV_HAVE_SSE + unsigned int number = 0; + const unsigned int halfPoints = len / 2; + + __m128 xVal, yl, yh, zVal, tmp1, tmp2; + float* zPtr = (float*) z; + const float* xPtr = (const float*) x; + + // Set up constant scalar vector + yl = _mm_set_ps1(creal(h)); + yh = _mm_set_ps1(cimag(h)); + + for(;number < halfPoints; number++){ + + xVal = _mm_load_ps(xPtr); + tmp1 = _mm_mul_ps(xVal,yl); + xVal = _mm_shuffle_ps(xVal,xVal,0xB1); + tmp2 = _mm_mul_ps(xVal,yh); + zVal = _mm_addsub_ps(tmp1,tmp2); + _mm_storeu_ps(zPtr,zVal); + + xPtr += 4; + zPtr += 4; + } + + if((len % 2) != 0) { + *zPtr = (*xPtr) * h; + } +#endif +} + +void srslte_vec_abs_square_cf_simd(cf_t *x, float *z, uint32_t len) { +#ifdef LV_HAVE_SSE + unsigned int number = 0; + const unsigned int quarterPoints = len / 4; + + const float* xPtr = (const float*) x; + float* zPtr = z; + + __m128 xVal1, xVal2, zVal; + for(; number < quarterPoints; number++){ + xVal1 = _mm_load_ps(xPtr); + xPtr += 4; + xVal2 = _mm_load_ps(xPtr); + xPtr += 4; + xVal1 = _mm_mul_ps(xVal1, xVal1); + xVal2 = _mm_mul_ps(xVal2, xVal2); + zVal = _mm_hadd_ps(xVal1, xVal2); + _mm_store_ps(zPtr, zVal); + zPtr += 4; + } + + number = quarterPoints * 4; + for(; number < len; number++){ + float val1Real = *xPtr++; + float val1Imag = *xPtr++; + *zPtr++ = (val1Real * val1Real) + (val1Imag * val1Imag); + } +#endif +} + + + + From 40c161c2e6f74ed62765d7a6767f8d4a98295a8f Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 20 Jan 2017 11:50:16 +0100 Subject: [PATCH 002/242] ifdef for simd functions --- srslte/lib/utils/vector_simd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/srslte/lib/utils/vector_simd.c b/srslte/lib/utils/vector_simd.c index 01a3d4c64..c150209ca 100644 --- a/srslte/lib/utils/vector_simd.c +++ b/srslte/lib/utils/vector_simd.c @@ -314,6 +314,7 @@ void srslte_vec_sum_fff_simd(float *x, float *y, float *z, uint32_t len) { #endif } +#ifdef LV_HAVE_SSE static inline __m128 _mm_complexmul_ps(__m128 x, __m128 y) { __m128 yl, yh, tmp1, tmp2; yl = _mm_moveldup_ps(y); // Load yl with cr,cr,dr,dr @@ -323,6 +324,7 @@ static inline __m128 _mm_complexmul_ps(__m128 x, __m128 y) { tmp2 = _mm_mul_ps(x, yh); // tmp2 = ai*ci,ar*ci,bi*di,br*di return _mm_addsub_ps(tmp1, tmp2); // ar*cr-ai*ci, ai*cr+ar*ci, br*dr-bi*di, bi*dr+br*di } +#endif void srslte_vec_prod_ccc_simd(cf_t *x,cf_t *y, cf_t *z, uint32_t len) { @@ -352,11 +354,13 @@ void srslte_vec_prod_ccc_simd(cf_t *x,cf_t *y, cf_t *z, uint32_t len) #endif } +#ifdef LV_HAVE_SSE static inline __m128 _mm_complexmulconj_ps(__m128 x, __m128 y) { const __m128 conjugator = _mm_setr_ps(0, -0.f, 0, -0.f); y = _mm_xor_ps(y, conjugator); return _mm_complexmul_ps(x, y); } +#endif void srslte_vec_prod_conj_ccc_simd(cf_t *x,cf_t *y, cf_t *z, uint32_t len) { #ifdef LV_HAVE_SSE From 949d4b8df84a1f7895c03375c50ce6ed77eac155 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 25 Jan 2017 10:18:27 +0100 Subject: [PATCH 003/242] novolk: use unaligned load/store SSE intrinsics, allow debug builds --- srslte/lib/fec/rm_turbo.c | 13 +++++++++---- srslte/lib/utils/vector_simd.c | 18 ++++++++++-------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/srslte/lib/fec/rm_turbo.c b/srslte/lib/fec/rm_turbo.c index 5856a4e46..751c9fe0c 100644 --- a/srslte/lib/fec/rm_turbo.c +++ b/srslte/lib/fec/rm_turbo.c @@ -327,8 +327,11 @@ int srslte_rm_turbo_rx_lut_sse(int16_t *input, int16_t *output, uint32_t in_len, lutVal = _mm_loadu_si128(lutPtr); for (int j=0;j<8;j++) { - int16_t x = (int16_t) _mm_extract_epi16(xVal, j); - uint16_t l = (uint16_t) _mm_extract_epi16(lutVal, j); + // For -O0 builds: shuffle j-th element to pos 0 and extract from there + _mm_shuffle_epi8(xVal,_mm_set1_epi8(j)); + int16_t x = (int16_t) _mm_extract_epi16(xVal, 0); + _mm_shuffle_epi8(lutVal,_mm_set1_epi8(j)); + uint16_t l = (uint16_t) _mm_extract_epi16(lutVal, 0); output[l] += x; } xPtr ++; @@ -346,8 +349,10 @@ int srslte_rm_turbo_rx_lut_sse(int16_t *input, int16_t *output, uint32_t in_len, lutVal = _mm_loadu_si128(lutPtr); for (int j=0;j<8;j++) { - int16_t x = (int16_t) _mm_extract_epi16(xVal, j); - uint16_t l = (uint16_t) _mm_extract_epi16(lutVal, j); + _mm_shuffle_epi8(xVal,_mm_set1_epi8(j)); + int16_t x = (int16_t) _mm_extract_epi16(xVal, 0); + _mm_shuffle_epi8(lutVal,_mm_set1_epi8(j)); + uint16_t l = (uint16_t) _mm_extract_epi16(lutVal, 0); output[l] += x; } xPtr++; diff --git a/srslte/lib/utils/vector_simd.c b/srslte/lib/utils/vector_simd.c index c150209ca..8d91c5f42 100644 --- a/srslte/lib/utils/vector_simd.c +++ b/srslte/lib/utils/vector_simd.c @@ -227,8 +227,10 @@ void srslte_vec_lut_sss_simd(short *x, unsigned short *lut, short *y, uint32_t l lutVal = _mm_load_si128(lutPtr); for (int i=0;i<8;i++) { - int16_t x = (int16_t) _mm_extract_epi16(xVal, i); - uint16_t l = (uint16_t) _mm_extract_epi16(lutVal, i); + _mm_shuffle_epi8(xVal,_mm_set1_epi8(i)); + int16_t x = (int16_t) _mm_extract_epi16(xVal, 0); + _mm_shuffle_epi8(lutVal,_mm_set1_epi8(i)); + uint16_t l = (uint16_t) _mm_extract_epi16(lutVal, 0); y[l] = x; } xPtr ++; @@ -295,12 +297,12 @@ void srslte_vec_sum_fff_simd(float *x, float *y, float *z, uint32_t len) { __m128 xVal, yVal, zVal; for(;number < points; number++){ - xVal = _mm_load_ps(xPtr); - yVal = _mm_load_ps(yPtr); + xVal = _mm_loadu_ps(xPtr); + yVal = _mm_loadu_ps(yPtr); zVal = _mm_add_ps(xVal, yVal); - _mm_store_ps(zPtr, zVal); + _mm_storeu_ps(zPtr, zVal); xPtr += 4; yPtr += 4; @@ -338,10 +340,10 @@ void srslte_vec_prod_ccc_simd(cf_t *x,cf_t *y, cf_t *z, uint32_t len) const float* yPtr = (const float*) y; for(; number < halfPoints; number++){ - xVal = _mm_load_ps(xPtr); - yVal = _mm_load_ps(yPtr); + xVal = _mm_loadu_ps(xPtr); + yVal = _mm_loadu_ps(yPtr); zVal = _mm_complexmul_ps(xVal, yVal); - _mm_store_ps(zPtr, zVal); + _mm_storeu_ps(zPtr, zVal); xPtr += 4; yPtr += 4; From 78de0c718b9f3059d7e47c8c2ce9b661fcdded8e Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 25 Jan 2017 15:20:47 +0100 Subject: [PATCH 004/242] fixed alignment problem in vec_abs_simd --- srslte/lib/utils/vector_simd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/srslte/lib/utils/vector_simd.c b/srslte/lib/utils/vector_simd.c index c150209ca..25c1d2b7d 100644 --- a/srslte/lib/utils/vector_simd.c +++ b/srslte/lib/utils/vector_simd.c @@ -431,14 +431,14 @@ void srslte_vec_abs_square_cf_simd(cf_t *x, float *z, uint32_t len) { __m128 xVal1, xVal2, zVal; for(; number < quarterPoints; number++){ - xVal1 = _mm_load_ps(xPtr); + xVal1 = _mm_loadu_ps(xPtr); xPtr += 4; - xVal2 = _mm_load_ps(xPtr); + xVal2 = _mm_loadu_ps(xPtr); xPtr += 4; xVal1 = _mm_mul_ps(xVal1, xVal1); xVal2 = _mm_mul_ps(xVal2, xVal2); zVal = _mm_hadd_ps(xVal1, xVal2); - _mm_store_ps(zPtr, zVal); + _mm_storeu_ps(zPtr, zVal); zPtr += 4; } From f2a35c6dd1ec58e3db91029b50e7252ec441e6d2 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 25 Jan 2017 17:30:16 +0100 Subject: [PATCH 005/242] fixed tests with new simd functions --- CMakeLists.txt | 2 - srslte/include/srslte/utils/vector_simd.h | 2 + srslte/lib/utils/vector.c | 11 +-- srslte/lib/utils/vector_simd.c | 109 ++++++++++++++-------- 4 files changed, 77 insertions(+), 47 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 206139295..ae8e9c532 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -115,9 +115,7 @@ if(CMAKE_COMPILER_IS_GNUCC) if (HAVE_AVX2) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mfpmath=sse -mavx2 -Ofast -funroll-loops -DLV_HAVE_AVX -DLV_HAVE_SSE") else (HAVE_AVX2) - message("NOT HAVE AVX2") if(HAVE_AVX) - message("HAVE AVX") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mfpmath=sse -mavx -Ofast -funroll-loops -DLV_HAVE_AVX -DLV_HAVE_SSE") elseif(HAVE_SSE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mfpmath=sse -msse4.1 -Ofast -funroll-loops -DLV_HAVE_SSE") diff --git a/srslte/include/srslte/utils/vector_simd.h b/srslte/include/srslte/utils/vector_simd.h index cfdef5ecd..81aed443f 100644 --- a/srslte/include/srslte/utils/vector_simd.h +++ b/srslte/include/srslte/utils/vector_simd.h @@ -51,6 +51,8 @@ SRSLTE_API void srslte_vec_convert_fi_simd(float *x, int16_t *z, float scale, ui SRSLTE_API void srslte_vec_prod_ccc_simd(cf_t *x,cf_t *y, cf_t *z, uint32_t len); +SRSLTE_API void srslte_vec_sc_prod_cfc_simd(cf_t *x, float h, cf_t *z, uint32_t len); + SRSLTE_API void srslte_vec_abs_square_cf_simd(cf_t *x, float *abs_square, uint32_t len); SRSLTE_API cf_t srslte_vec_dot_prod_ccc_simd(cf_t *x, cf_t *y, uint32_t len); diff --git a/srslte/lib/utils/vector.c b/srslte/lib/utils/vector.c index 578a644c2..52e8b54d0 100644 --- a/srslte/lib/utils/vector.c +++ b/srslte/lib/utils/vector.c @@ -200,20 +200,19 @@ void srslte_vec_norm_cfc(cf_t *x, float amplitude, cf_t *y, uint32_t len) { } // Used throughout -void srslte_vec_sc_prod_cfc(cf_t *x, float h, cf_t *z, uint32_t len) { -#ifndef LV_HAVE_SSE +void srslte_vec_sc_prod_cfc(cf_t *x, float h, cf_t *z, uint32_t len) { + #ifndef LV_HAVE_SSE int i; for (i=0;i Date: Wed, 25 Jan 2017 17:38:22 +0100 Subject: [PATCH 006/242] restored rm_turbo (test not passing) --- srslte/lib/fec/rm_turbo.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/srslte/lib/fec/rm_turbo.c b/srslte/lib/fec/rm_turbo.c index 751c9fe0c..31cbd82ca 100644 --- a/srslte/lib/fec/rm_turbo.c +++ b/srslte/lib/fec/rm_turbo.c @@ -327,11 +327,8 @@ int srslte_rm_turbo_rx_lut_sse(int16_t *input, int16_t *output, uint32_t in_len, lutVal = _mm_loadu_si128(lutPtr); for (int j=0;j<8;j++) { - // For -O0 builds: shuffle j-th element to pos 0 and extract from there - _mm_shuffle_epi8(xVal,_mm_set1_epi8(j)); - int16_t x = (int16_t) _mm_extract_epi16(xVal, 0); - _mm_shuffle_epi8(lutVal,_mm_set1_epi8(j)); - uint16_t l = (uint16_t) _mm_extract_epi16(lutVal, 0); + int16_t x = (int16_t) _mm_extract_epi16(xVal, j); + uint16_t l = (uint16_t) _mm_extract_epi16(lutVal, j); output[l] += x; } xPtr ++; @@ -349,10 +346,8 @@ int srslte_rm_turbo_rx_lut_sse(int16_t *input, int16_t *output, uint32_t in_len, lutVal = _mm_loadu_si128(lutPtr); for (int j=0;j<8;j++) { - _mm_shuffle_epi8(xVal,_mm_set1_epi8(j)); - int16_t x = (int16_t) _mm_extract_epi16(xVal, 0); - _mm_shuffle_epi8(lutVal,_mm_set1_epi8(j)); - uint16_t l = (uint16_t) _mm_extract_epi16(lutVal, 0); + int16_t x = (int16_t) _mm_extract_epi16(xVal, j); + uint16_t l = (uint16_t) _mm_extract_epi16(lutVal, j); output[l] += x; } xPtr++; @@ -718,4 +713,3 @@ int srslte_rm_turbo_rx(float *w_buff, uint32_t w_buff_len, float *input, uint32_ return 0; } - From 2758ba4118bc9764552a5ea59c8eebe49d3f9c6a Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 25 Jan 2017 17:40:28 +0100 Subject: [PATCH 007/242] fixed lut in vector simd (now all tests passing) --- srslte/lib/utils/vector_simd.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/srslte/lib/utils/vector_simd.c b/srslte/lib/utils/vector_simd.c index ba30e190f..16bbbc0bb 100644 --- a/srslte/lib/utils/vector_simd.c +++ b/srslte/lib/utils/vector_simd.c @@ -227,10 +227,8 @@ void srslte_vec_lut_sss_simd(short *x, unsigned short *lut, short *y, uint32_t l lutVal = _mm_loadu_si128(lutPtr); for (int i=0;i<8;i++) { - _mm_shuffle_epi8(xVal,_mm_set1_epi8(i)); - int16_t x = (int16_t) _mm_extract_epi16(xVal, 0); - _mm_shuffle_epi8(lutVal,_mm_set1_epi8(i)); - uint16_t l = (uint16_t) _mm_extract_epi16(lutVal, 0); + int16_t x = (int16_t) _mm_extract_epi16(xVal, i); + uint16_t l = (uint16_t) _mm_extract_epi16(lutVal, i); y[l] = x; } xPtr ++; From 9acb1002e96c6e5ed655bc885749030b75463132 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 26 Jan 2017 17:48:32 +0100 Subject: [PATCH 008/242] added more functions to simd for UE --- srslte/include/srslte/utils/vector_simd.h | 10 +- srslte/lib/utils/vector.c | 33 ++++- srslte/lib/utils/vector_simd.c | 164 +++++++++++++++++++++- 3 files changed, 193 insertions(+), 14 deletions(-) diff --git a/srslte/include/srslte/utils/vector_simd.h b/srslte/include/srslte/utils/vector_simd.h index 81aed443f..8380a75de 100644 --- a/srslte/include/srslte/utils/vector_simd.h +++ b/srslte/include/srslte/utils/vector_simd.h @@ -53,11 +53,15 @@ SRSLTE_API void srslte_vec_prod_ccc_simd(cf_t *x,cf_t *y, cf_t *z, uint32_t len) SRSLTE_API void srslte_vec_sc_prod_cfc_simd(cf_t *x, float h, cf_t *z, uint32_t len); +SRSLTE_API void srslte_vec_sc_prod_fff_simd(float *x, float h, float *z, uint32_t len); + SRSLTE_API void srslte_vec_abs_square_cf_simd(cf_t *x, float *abs_square, uint32_t len); SRSLTE_API cf_t srslte_vec_dot_prod_ccc_simd(cf_t *x, cf_t *y, uint32_t len); -SRSLTE_API void srslte_vec_sum_fff_simd(float *x, float *y, float *z, uint32_t len); +SRSLTE_API void srslte_vec_sum_fff_simd(float *x, float *y, float *z, uint32_t len); + +SRSLTE_API void srslte_vec_sub_fff_simd(float *x, float *h, float *z, uint32_t len); SRSLTE_API cf_t srslte_vec_dot_prod_conj_ccc_simd(cf_t *x, cf_t *y, uint32_t len); @@ -65,6 +69,10 @@ SRSLTE_API void srslte_vec_prod_conj_ccc_simd(cf_t *x,cf_t *y, cf_t *z, uint32_t SRSLTE_API void srslte_vec_sc_prod_ccc_simd(cf_t *x, cf_t h, cf_t *z, uint32_t len); +SRSLTE_API cf_t srslte_vec_dot_prod_conj_ccc_simd(cf_t *x, cf_t *y, uint32_t len); + +SRSLTE_API void srslte_vec_sc_prod_cfc_simd(cf_t *x, float h, cf_t *z, uint32_t len); + SRSLTE_API float srslte_vec_acc_ff_simd(float *x, uint32_t len); SRSLTE_API cf_t srslte_vec_dot_prod_cfc_simd(cf_t *x, float *y, uint32_t len); diff --git a/srslte/lib/utils/vector.c b/srslte/lib/utils/vector.c index 52e8b54d0..10fe38165 100644 --- a/srslte/lib/utils/vector.c +++ b/srslte/lib/utils/vector.c @@ -44,7 +44,7 @@ int srslte_vec_acc_ii(int *x, uint32_t len) { return z; } -// Used in PRACH detector +// Used in PRACH detector, AGC and chest_dl for noise averaging float srslte_vec_acc_ff(float *x, uint32_t len) { int i; float z=0; @@ -79,10 +79,14 @@ void srslte_vec_square_dist(cf_t symbol, cf_t *points, float *distance, uint32_t } void srslte_vec_sub_fff(float *x, float *y, float *z, uint32_t len) { +#ifndef LV_HAVE_SSE int i; for (i=0;i Date: Fri, 27 Jan 2017 11:56:59 +0000 Subject: [PATCH 009/242] Added GCC_ARCH option to manually set -march in GCC --- CMakeLists.txt | 15 ++++++++------- cmake/modules/FindSSE.cmake | 8 ++++---- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ae8e9c532..d36de57aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,6 +54,7 @@ configure_file( option(DisableMEX "DisableMEX" ON) option(StaticMKL "StaticMKL" OFF) option(DisableBladeRF "DisableBladeRF" OFF) +set(GCC_ARCH native CACHE STRING "GCC compile for specific architecture.") ######################################################################## # Install Dirs @@ -101,24 +102,24 @@ endif(CMAKE_COMPILER_IS_GNUCXX) if(CMAKE_COMPILER_IS_GNUCC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-write-strings -Wno-format-extra-args -Winline -Wno-unused-result -Wno-format -std=c99 -D_GNU_SOURCE -g") + find_package(SSE) + if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") - find_package(SSE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0") if(HAVE_AVX) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mfpmath=sse -mavx -DLV_HAVE_AVX -DLV_HAVE_SSE") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=${GCC_ARCH} -mfpmath=sse -mavx -DLV_HAVE_AVX -DLV_HAVE_SSE") elseif(HAVE_SSE) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mfpmath=sse -msse4.1 -DLV_HAVE_SSE") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=${GCC_ARCH} -mfpmath=sse -msse4.1 -DLV_HAVE_SSE") endif(HAVE_AVX) else(${CMAKE_BUILD_TYPE} STREQUAL "Debug") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3") - find_package(SSE) if (HAVE_AVX2) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mfpmath=sse -mavx2 -Ofast -funroll-loops -DLV_HAVE_AVX -DLV_HAVE_SSE") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=${GCC_ARCH} -mfpmath=sse -mavx2 -Ofast -funroll-loops -DLV_HAVE_AVX -DLV_HAVE_SSE") else (HAVE_AVX2) if(HAVE_AVX) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mfpmath=sse -mavx -Ofast -funroll-loops -DLV_HAVE_AVX -DLV_HAVE_SSE") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=${GCC_ARCH} -mfpmath=sse -mavx -Ofast -funroll-loops -DLV_HAVE_AVX -DLV_HAVE_SSE") elseif(HAVE_SSE) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mfpmath=sse -msse4.1 -Ofast -funroll-loops -DLV_HAVE_SSE") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=${GCC_ARCH} -mfpmath=sse -msse4.1 -Ofast -funroll-loops -DLV_HAVE_SSE") endif(HAVE_AVX) endif (HAVE_AVX2) diff --git a/cmake/modules/FindSSE.cmake b/cmake/modules/FindSSE.cmake index 7b258f70f..9dbbeef3e 100644 --- a/cmake/modules/FindSSE.cmake +++ b/cmake/modules/FindSSE.cmake @@ -1,9 +1,9 @@ include(CheckCSourceRuns) -option(ENABLE_SSE "Enable compile-time SSE4.1 support." ON) -option(ENABLE_AVX "Enable compile-time AVX support." ON) -option(ENABLE_AVX2 "Enable compile-time AVX2 support." ON) +option(ENABLE_SSE "Enable compile-time SSE4.1 support." ON) +option(ENABLE_AVX "Enable compile-time AVX support." ON) +option(ENABLE_AVX2 "Enable compile-time AVX2 support." ON) if (ENABLE_SSE) # @@ -96,4 +96,4 @@ if (ENABLE_SSE) endif() -mark_as_advanced(HAVE_SSE, HAVE_AVX, HAVE_AVX2) \ No newline at end of file +mark_as_advanced(HAVE_SSE, HAVE_AVX, HAVE_AVX2) From 979a590dc92e2a83aac74eb9b7c270031528ff97 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 7 Apr 2017 14:54:24 +0200 Subject: [PATCH 010/242] comment references to uhd::register_handler --- srslte/lib/rf/uhd_c_api.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/srslte/lib/rf/uhd_c_api.cpp b/srslte/lib/rf/uhd_c_api.cpp index 92af48f69..1b7772e68 100644 --- a/srslte/lib/rf/uhd_c_api.cpp +++ b/srslte/lib/rf/uhd_c_api.cpp @@ -9,6 +9,7 @@ extern "C" { #include "uhd_c_api.h" } +/* #if UHD_VERSION < 31100 static void (*handler)(const char*); @@ -26,6 +27,7 @@ void rf_uhd_register_msg_handler_c(void (*new_handler)(const char*)) uhd::msg::register_handler(translate_handler); #endif } +*/ void uhd_tx_metadata_set_time_spec(uhd_tx_metadata_handle *md, time_t secs, double frac_secs) { From 8e440f512ab1ac9490aad73a5688882c31fc70e1 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 7 Apr 2017 15:06:51 +0200 Subject: [PATCH 011/242] comment references to uhd::register_handler --- srslte/lib/rf/uhd_c_api.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/srslte/lib/rf/uhd_c_api.cpp b/srslte/lib/rf/uhd_c_api.cpp index 1b7772e68..93792722d 100644 --- a/srslte/lib/rf/uhd_c_api.cpp +++ b/srslte/lib/rf/uhd_c_api.cpp @@ -19,15 +19,17 @@ void translate_handler(uhd::msg::type_t type, const std::string & msg) handler(msg.c_str()); } #endif +*/ void rf_uhd_register_msg_handler_c(void (*new_handler)(const char*)) { +/* #if UHD_VERSION < 31100 handler = new_handler; uhd::msg::register_handler(translate_handler); #endif -} */ +} void uhd_tx_metadata_set_time_spec(uhd_tx_metadata_handle *md, time_t secs, double frac_secs) { From ec34d56e77082a66a01d45c825f7dce739c4d17e Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 8 Jun 2017 15:15:00 +0200 Subject: [PATCH 012/242] final merging changes --- CMakeLists.txt | 2 - lib/src/phy/rf/uhd_c_api.cpp | 4 -- lib/src/phy/utils/vector.c | 20 ++++-- lib/src/phy/utils/vector_simd.c | 8 +-- srslte/CMakeLists.txt | 84 ---------------------- srslte/include/srslte/utils/vector_simd.h | 86 ----------------------- 6 files changed, 17 insertions(+), 187 deletions(-) delete mode 100644 srslte/CMakeLists.txt delete mode 100644 srslte/include/srslte/utils/vector_simd.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1cc2640e2..d7871d71d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -195,8 +195,6 @@ endmacro(ADD_CXX_COMPILER_FLAG_IF_AVAILABLE) if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=${GCC_ARCH} -Wall -Wno-comment -Wno-reorder -Wno-unused-but-set-variable -Wno-unused-variable -std=c++03") - find_package(SSE) - if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -DDEBUG_MODE") else(${CMAKE_BUILD_TYPE} STREQUAL "Debug") diff --git a/lib/src/phy/rf/uhd_c_api.cpp b/lib/src/phy/rf/uhd_c_api.cpp index c0fb6bfd3..da348c17b 100644 --- a/lib/src/phy/rf/uhd_c_api.cpp +++ b/lib/src/phy/rf/uhd_c_api.cpp @@ -9,7 +9,6 @@ extern "C" { #include "uhd_c_api.h" } -/* #if UHD_VERSION < 31100 static void (*handler)(const char*); @@ -19,16 +18,13 @@ void translate_handler(uhd::msg::type_t type, const std::string & msg) handler(msg.c_str()); } #endif -*/ void rf_uhd_register_msg_handler_c(void (*new_handler)(const char*)) { -/* #if UHD_VERSION < 31100 handler = new_handler; uhd::msg::register_handler(translate_handler); #endif -*/ } void uhd_tx_metadata_set_time_spec(uhd_tx_metadata_handle *md, time_t secs, double frac_secs) diff --git a/lib/src/phy/utils/vector.c b/lib/src/phy/utils/vector.c index 3146c760d..daa03d0b4 100644 --- a/lib/src/phy/utils/vector.c +++ b/lib/src/phy/utils/vector.c @@ -57,12 +57,18 @@ int srslte_vec_acc_ii(int *x, uint32_t len) { // Used in PRACH detector, AGC and chest_dl for noise averaging float srslte_vec_acc_ff(float *x, uint32_t len) { - int i; - float z=0; - for (i=0;i -#include -#include "srslte/config.h" - -SRSLTE_API int srslte_vec_dot_prod_sss_simd(short *x, short *y, uint32_t len); - -SRSLTE_API void srslte_vec_sum_sss_simd(short *x, short *y, short *z, uint32_t len); - -SRSLTE_API void srslte_vec_sub_sss_simd(short *x, short *y, short *z, uint32_t len); - -SRSLTE_API void srslte_vec_prod_sss_simd(short *x, short *y, short *z, uint32_t len); - -SRSLTE_API void srslte_vec_sc_div2_sss_simd(short *x, int n_rightshift, short *z, uint32_t len); - -SRSLTE_API void srslte_vec_lut_sss_simd(short *x, unsigned short *lut, short *y, uint32_t len); - -SRSLTE_API void srslte_vec_convert_fi_simd(float *x, int16_t *z, float scale, uint32_t len); - -SRSLTE_API void srslte_vec_prod_ccc_simd(cf_t *x,cf_t *y, cf_t *z, uint32_t len); - -SRSLTE_API void srslte_vec_sc_prod_cfc_simd(cf_t *x, float h, cf_t *z, uint32_t len); - -SRSLTE_API void srslte_vec_sc_prod_fff_simd(float *x, float h, float *z, uint32_t len); - -SRSLTE_API void srslte_vec_abs_square_cf_simd(cf_t *x, float *abs_square, uint32_t len); - -SRSLTE_API cf_t srslte_vec_dot_prod_ccc_simd(cf_t *x, cf_t *y, uint32_t len); - -SRSLTE_API void srslte_vec_sum_fff_simd(float *x, float *y, float *z, uint32_t len); - -SRSLTE_API void srslte_vec_sub_fff_simd(float *x, float *h, float *z, uint32_t len); - -SRSLTE_API cf_t srslte_vec_dot_prod_conj_ccc_simd(cf_t *x, cf_t *y, uint32_t len); - -SRSLTE_API void srslte_vec_prod_conj_ccc_simd(cf_t *x,cf_t *y, cf_t *z, uint32_t len); - -SRSLTE_API void srslte_vec_sc_prod_ccc_simd(cf_t *x, cf_t h, cf_t *z, uint32_t len); - -SRSLTE_API cf_t srslte_vec_dot_prod_conj_ccc_simd(cf_t *x, cf_t *y, uint32_t len); - -SRSLTE_API void srslte_vec_sc_prod_cfc_simd(cf_t *x, float h, cf_t *z, uint32_t len); - -SRSLTE_API float srslte_vec_acc_ff_simd(float *x, uint32_t len); - -SRSLTE_API cf_t srslte_vec_dot_prod_cfc_simd(cf_t *x, float *y, uint32_t len); - -SRSLTE_API void srslte_vec_convert_if_simd(int16_t *x, float *z, float scale, uint32_t len); - -#ifdef __cplusplus -} -#endif - -#endif From 2bba9d187d32ce18fc0e752f423c637b10ab0335 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 7 Jul 2017 16:36:27 +0200 Subject: [PATCH 013/242] fixed dotprodconj. Removed unaligned load/store --- lib/src/phy/utils/vector.c | 2 +- lib/src/phy/utils/vector_simd.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/src/phy/utils/vector.c b/lib/src/phy/utils/vector.c index 61d0271b6..8ceefe3da 100644 --- a/lib/src/phy/utils/vector.c +++ b/lib/src/phy/utils/vector.c @@ -608,7 +608,7 @@ cf_t srslte_vec_dot_prod_conj_ccc(cf_t *x, cf_t *y, uint32_t len) { uint32_t i; cf_t res = 0; for (i=0;i Date: Fri, 7 Jul 2017 18:04:59 +0200 Subject: [PATCH 014/242] missing return statement --- lib/include/srslte/common/metrics_hub.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/include/srslte/common/metrics_hub.h b/lib/include/srslte/common/metrics_hub.h index 8443ef65a..9575347a2 100644 --- a/lib/include/srslte/common/metrics_hub.h +++ b/lib/include/srslte/common/metrics_hub.h @@ -34,6 +34,7 @@ public: bool init(metrics_interface *m_, float report_period_secs=1.0) { m = m_; start_periodic(report_period_secs*1e6); + return true; } void stop() { thread_cancel(); @@ -47,7 +48,7 @@ private: void run_period() { metrics_t metric; m->get_metrics(metric); - for (int i=0;iset_metrics(metric); } } From f629e10fcfdf70cbc43b0e7c00a4eb18ac15f08b Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 7 Jul 2017 18:44:17 +0200 Subject: [PATCH 015/242] fixed bug in sub_sse() and added couple of avx functions --- lib/include/srslte/phy/utils/vector_simd.h | 4 ++ lib/src/phy/utils/vector.c | 12 +++- lib/src/phy/utils/vector_simd.c | 65 +++++++++++++++++++++- 3 files changed, 76 insertions(+), 5 deletions(-) diff --git a/lib/include/srslte/phy/utils/vector_simd.h b/lib/include/srslte/phy/utils/vector_simd.h index 6fe55f89d..1010cbed6 100644 --- a/lib/include/srslte/phy/utils/vector_simd.h +++ b/lib/include/srslte/phy/utils/vector_simd.h @@ -49,8 +49,12 @@ SRSLTE_API void srslte_vec_sub_sss_avx2(short *x, short *y, short *z, uint32_t l SRSLTE_API void srslte_vec_sum_fff_sse(float *x, float *y, float *z, uint32_t len); +SRSLTE_API void srslte_vec_sum_fff_avx(float *x, float *y, float *z, uint32_t len); + SRSLTE_API void srslte_vec_sub_fff_sse(float *x, float *y, float *z, uint32_t len); +SRSLTE_API void srslte_vec_sub_fff_avx(float *x, float *y, float *z, uint32_t len); + SRSLTE_API void srslte_vec_sc_prod_fff_sse(float *x, float h, float *z, uint32_t len); SRSLTE_API void srslte_vec_sc_prod_ccc_sse(cf_t *x, cf_t h, cf_t *z, uint32_t len); diff --git a/lib/src/phy/utils/vector.c b/lib/src/phy/utils/vector.c index 8ceefe3da..2a2001ae3 100644 --- a/lib/src/phy/utils/vector.c +++ b/lib/src/phy/utils/vector.c @@ -101,9 +101,13 @@ void srslte_vec_sub_fff(float *x, float *y, float *z, uint32_t len) { for (i=0;i Date: Tue, 11 Jul 2017 13:17:26 +0200 Subject: [PATCH 016/242] fixed segfault due to race condition in scrambling sequence pre-generation --- lib/include/srslte/phy/phch/pdsch.h | 3 ++- lib/include/srslte/phy/phch/pucch.h | 3 ++- lib/include/srslte/phy/phch/pusch.h | 3 ++- lib/src/phy/phch/pdsch.c | 24 +++++++++++++----------- lib/src/phy/phch/pucch.c | 8 +++++--- lib/src/phy/phch/pusch.c | 27 ++++++++++++++------------- 6 files changed, 38 insertions(+), 30 deletions(-) diff --git a/lib/include/srslte/phy/phch/pdsch.h b/lib/include/srslte/phy/phch/pdsch.h index 7730d2fa1..ad01c4ef8 100644 --- a/lib/include/srslte/phy/phch/pdsch.h +++ b/lib/include/srslte/phy/phch/pdsch.h @@ -48,7 +48,8 @@ #include "srslte/phy/phch/pdsch_cfg.h" typedef struct { - srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME]; + srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME]; + bool sequence_generated; } srslte_pdsch_user_t; /* PDSCH object */ diff --git a/lib/include/srslte/phy/phch/pucch.h b/lib/include/srslte/phy/phch/pucch.h index 3542dc53f..56d512418 100644 --- a/lib/include/srslte/phy/phch/pucch.h +++ b/lib/include/srslte/phy/phch/pucch.h @@ -80,7 +80,8 @@ typedef struct SRSLTE_API { } srslte_pucch_cfg_t; typedef struct { - srslte_sequence_t seq_f2[SRSLTE_NSUBFRAMES_X_FRAME]; + srslte_sequence_t seq_f2[SRSLTE_NSUBFRAMES_X_FRAME]; + bool sequence_generated; } srslte_pucch_user_t; /* PUCCH object */ diff --git a/lib/include/srslte/phy/phch/pusch.h b/lib/include/srslte/phy/phch/pusch.h index bf04a4781..e5ee43995 100644 --- a/lib/include/srslte/phy/phch/pusch.h +++ b/lib/include/srslte/phy/phch/pusch.h @@ -61,7 +61,8 @@ typedef struct { } srslte_pusch_hopping_cfg_t; typedef struct { - srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME]; + srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME]; + bool sequences_generated; } srslte_pusch_user_t; /* PUSCH object */ diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index 8791ac8e7..9b6128c64 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "prb_dl.h" #include "srslte/phy/phch/pdsch.h" @@ -362,6 +363,7 @@ int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti) { return SRSLTE_ERROR; } } + q->users[rnti]->sequence_generated = true; } } return SRSLTE_SUCCESS; @@ -467,15 +469,15 @@ int srslte_pdsch_decode_multi(srslte_pdsch_t *q, srslte_demod_soft_demodulate_s(cfg->grant.mcs.mod, q->d, q->e, cfg->nbits.nof_re); /* descramble */ - if (!q->users[rnti]) { - srslte_sequence_t seq; + if (q->users[rnti] && q->users[rnti]->sequence_generated) { + srslte_scrambling_s_offset(&q->users[rnti]->seq[cfg->sf_idx], q->e, 0, cfg->nbits.nof_bits); + } else { + srslte_sequence_t seq; if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { - return SRSLTE_ERROR; + return SRSLTE_ERROR; } - srslte_scrambling_s_offset(&seq, q->e, 0, cfg->nbits.nof_bits); + srslte_scrambling_s_offset(&seq, q->e, 0, cfg->nbits.nof_bits); srslte_sequence_free(&seq); - } else { - srslte_scrambling_s_offset(&q->users[rnti]->seq[cfg->sf_idx], q->e, 0, cfg->nbits.nof_bits); } if (SRSLTE_VERBOSE_ISDEBUG()) { @@ -537,15 +539,15 @@ int srslte_pdsch_encode(srslte_pdsch_t *q, } /* scramble */ - if (!q->users[rnti]) { - srslte_sequence_t seq; + if (q->users[rnti] && q->users[rnti]->sequence_generated) { + srslte_scrambling_bytes(&q->users[rnti]->seq[cfg->sf_idx], (uint8_t*) q->e, cfg->nbits.nof_bits); + } else { + srslte_sequence_t seq; if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { - return SRSLTE_ERROR; + return SRSLTE_ERROR; } srslte_scrambling_bytes(&seq, (uint8_t*) q->e, cfg->nbits.nof_bits); srslte_sequence_free(&seq); - } else { - srslte_scrambling_bytes(&q->users[rnti]->seq[cfg->sf_idx], (uint8_t*) q->e, cfg->nbits.nof_bits); } srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->e, q->d, cfg->nbits.nof_bits); diff --git a/lib/src/phy/phch/pucch.c b/lib/src/phy/phch/pucch.c index c58f69871..6a889b89c 100644 --- a/lib/src/phy/phch/pucch.c +++ b/lib/src/phy/phch/pucch.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "srslte/phy/ch_estimation/refsignal_ul.h" #include "srslte/phy/phch/pucch.h" @@ -489,7 +490,7 @@ void srslte_pucch_clear_rnti(srslte_pucch_t *q, uint16_t rnti) { int srslte_pucch_set_crnti(srslte_pucch_t *q, uint16_t rnti) { if (!q->users[rnti]) { - q->users[rnti] = malloc(sizeof(srslte_pucch_user_t)); + q->users[rnti] = calloc(1, sizeof(srslte_pucch_user_t)); if (q->users[rnti]) { for (uint32_t sf_idx=0;sf_idxusers[rnti]->sequence_generated = true; } } return SRSLTE_SUCCESS; @@ -591,7 +593,7 @@ static int uci_mod_bits(srslte_pucch_t *q, srslte_pucch_format_t format, uint8_t case SRSLTE_PUCCH_FORMAT_2: case SRSLTE_PUCCH_FORMAT_2A: case SRSLTE_PUCCH_FORMAT_2B: - if (q->users[rnti]) { + if (q->users[rnti] && q->users[rnti]->sequence_generated) { memcpy(q->bits_scram, bits, SRSLTE_PUCCH2_NOF_BITS*sizeof(uint8_t)); srslte_scrambling_b(&q->users[rnti]->seq_f2[sf_idx], q->bits_scram); srslte_mod_modulate(&q->mod, q->bits_scram, q->d, SRSLTE_PUCCH2_NOF_BITS); @@ -796,7 +798,7 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format, case SRSLTE_PUCCH_FORMAT_2: case SRSLTE_PUCCH_FORMAT_2A: case SRSLTE_PUCCH_FORMAT_2B: - if (q->users[rnti]) { + if (q->users[rnti] && q->users[rnti]->sequence_generated) { pucch_encode_(q, format, n_pucch, sf_idx, rnti, NULL, ref, true); srslte_vec_prod_conj_ccc(q->z, ref, q->z_tmp, SRSLTE_PUCCH_MAX_SYMBOLS); for (int i=0;imax_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) { return SRSLTE_ERROR; } - } + } + q->users[rnti]->sequences_generated = true; } } return SRSLTE_SUCCESS; @@ -444,15 +445,15 @@ int srslte_pusch_encode(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softb return SRSLTE_ERROR; } - if (!q->users[rnti]) { - srslte_sequence_t seq; + if (q->users[rnti] && q->users[rnti]->sequences_generated) { + srslte_scrambling_bytes(&q->users[rnti]->seq[cfg->sf_idx], (uint8_t*) q->q, cfg->nbits.nof_bits); + } else { + srslte_sequence_t seq; if (srslte_sequence_pusch(&seq, rnti, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { - return SRSLTE_ERROR; + return SRSLTE_ERROR; } - srslte_scrambling_bytes(&seq, (uint8_t*) q->q, cfg->nbits.nof_bits); + srslte_scrambling_bytes(&seq, (uint8_t*) q->q, cfg->nbits.nof_bits); srslte_sequence_free(&seq); - } else { - srslte_scrambling_bytes(&q->users[rnti]->seq[cfg->sf_idx], (uint8_t*) q->q, cfg->nbits.nof_bits); } // Correct UCI placeholder/repetition bits @@ -535,13 +536,13 @@ int srslte_pusch_decode(srslte_pusch_t *q, srslte_sequence_t *seq = NULL; // Create sequence if does not exist - if (!q->users[rnti]) { - seq = &q->tmp_seq; + if (q->users[rnti] && q->users[rnti]->sequences_generated) { + seq = &q->users[rnti]->seq[cfg->sf_idx]; + } else { + seq = &q->tmp_seq; if (srslte_sequence_pusch(seq, rnti, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { - return SRSLTE_ERROR; + return SRSLTE_ERROR; } - } else { - seq = &q->users[rnti]->seq[cfg->sf_idx]; } // Decode RI/HARQ bits before descrambling @@ -553,7 +554,7 @@ int srslte_pusch_decode(srslte_pusch_t *q, // Descrambling srslte_scrambling_s_offset(seq, q->q, 0, cfg->nbits.nof_bits); - if (!q->users[rnti]) { + if (!(q->users[rnti] && q->users[rnti]->sequences_generated)) { srslte_sequence_free(seq); } From a6317980579d29a48ccbc7047e3ec38f8bf4cd4c Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 23 Aug 2017 12:43:20 +0200 Subject: [PATCH 017/242] Fixes #89. Removed sampling rate warnings --- lib/src/phy/rf/rf_uhd_imp.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/src/phy/rf/rf_uhd_imp.c b/lib/src/phy/rf/rf_uhd_imp.c index 319093994..3a047ceba 100644 --- a/lib/src/phy/rf/rf_uhd_imp.c +++ b/lib/src/phy/rf/rf_uhd_imp.c @@ -328,7 +328,7 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_rx_antennas) if (args[0]=='\0') { if (find_string(devices_str, "type=b200") && !strstr(args, "recv_frame_size")) { // If B200 is available, use it - args = "type=b200"; + args = "type=b200,master_clock_rate=30.72e6"; handler->devname = DEVNAME_B200; } else if (find_string(devices_str, "type=x300")) { // Else if X300 is available, set master clock rate now (can't be changed later) @@ -344,6 +344,8 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_rx_antennas) handler->dynamic_rate = false; handler->devname = DEVNAME_X300; } else if (strstr(args, "type=b200")) { + snprintf(args2, sizeof(args2), "%s,master_clock_rate=30.72e6", args); + args = args2; handler->devname = DEVNAME_B200; } } @@ -399,7 +401,11 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_rx_antennas) }; handler->nof_rx_channels = nof_rx_antennas; - handler->nof_tx_channels = 1; + handler->nof_tx_channels = 1; + + /* Set default rate to avoid decimation warnings */ + uhd_usrp_set_rx_rate(handler->usrp, 1.92e6, 0); + uhd_usrp_set_tx_rate(handler->usrp, 1.92e6, 0); /* Initialize rx and tx stremers */ uhd_rx_streamer_make(&handler->rx_stream); From afb825d939ba937a69355f0b31d37c98dad14711 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 29 Aug 2017 15:07:47 +0200 Subject: [PATCH 018/242] increased timeout for RRCConnectionRelease transmission --- srsenb/src/upper/rrc.cc | 5 ++--- srsenb/src/upper/s1ap.cc | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index de1c61b9e..03ea65f2c 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -314,12 +314,11 @@ void rrc::release_complete(uint16_t rnti) if (!users[rnti].is_idle()) { rlc->clear_buffer(rnti); users[rnti].send_connection_release(); - // There is no RRCReleaseComplete message from UE thus sleep to enable all retx in PHY +50% - usleep(1500*8*cfg.mac_cnfg.ulsch_cnfg.max_harq_tx); + // There is no RRCReleaseComplete message from UE thus wait ~100 subframes for tx + usleep(100000); } rem_user(rnti); } else { - rrc_log->error("Received ReleaseComplete for unknown rnti=0x%x\n", rnti); } } diff --git a/srsenb/src/upper/s1ap.cc b/srsenb/src/upper/s1ap.cc index 9328060e6..eba9186e7 100644 --- a/srsenb/src/upper/s1ap.cc +++ b/srsenb/src/upper/s1ap.cc @@ -594,7 +594,7 @@ bool s1ap::handle_uectxtreleasecommand(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASECOMMA s1ap_log->warning("Not handling S1AP message extension\n"); } - uint16_t rnti; + uint16_t rnti = 0; if(msg->UE_S1AP_IDs.choice_type == LIBLTE_S1AP_UE_S1AP_IDS_CHOICE_UE_S1AP_ID_PAIR) { if(msg->UE_S1AP_IDs.choice.uE_S1AP_ID_pair.ext) { From 2dbc0f066369cbbcac7e39ee17afd720b6b0d799 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 5 Sep 2017 10:54:36 +0200 Subject: [PATCH 019/242] Fix memory alignment in PUCCH processing. Fixes #94 --- lib/include/srslte/phy/phch/uci.h | 8 +++++--- lib/src/phy/phch/pucch.c | 1 + lib/src/phy/phch/uci.c | 17 ++++++++++++++++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/lib/include/srslte/phy/phch/uci.h b/lib/include/srslte/phy/phch/uci.h index bad87866e..01eae8e89 100644 --- a/lib/include/srslte/phy/phch/uci.h +++ b/lib/include/srslte/phy/phch/uci.h @@ -57,8 +57,8 @@ typedef struct SRSLTE_API { } srslte_uci_cqi_pusch_t; typedef struct SRSLTE_API { - uint8_t cqi_table[16][32]; - int16_t cqi_table_s[16][32]; // aligned for simd + uint8_t *cqi_table[16]; + int16_t *cqi_table_s[16]; } srslte_uci_cqi_pucch_t; typedef struct SRSLTE_API { @@ -85,7 +85,9 @@ typedef struct { SRSLTE_API void srslte_uci_cqi_pucch_init(srslte_uci_cqi_pucch_t *q); -SRSLTE_API int srslte_uci_encode_cqi_pucch(uint8_t *cqi_data, +SRSLTE_API void srslte_uci_cqi_pucch_free(srslte_uci_cqi_pucch_t *q); + +SRSLTE_API int srslte_uci_encode_cqi_pucch(uint8_t *cqi_data, uint32_t cqi_len, uint8_t b_bits[SRSLTE_UCI_CQI_CODED_PUCCH_B]); diff --git a/lib/src/phy/phch/pucch.c b/lib/src/phy/phch/pucch.c index 6a889b89c..8964a739d 100644 --- a/lib/src/phy/phch/pucch.c +++ b/lib/src/phy/phch/pucch.c @@ -464,6 +464,7 @@ void srslte_pucch_free(srslte_pucch_t *q) { } free(q->users); } + srslte_uci_cqi_pucch_free(&q->cqi); if (q->z) { free(q->z); } diff --git a/lib/src/phy/phch/uci.c b/lib/src/phy/phch/uci.c index 821e5be5f..215a80988 100644 --- a/lib/src/phy/phch/uci.c +++ b/lib/src/phy/phch/uci.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "srslte/phy/phch/uci.h" #include "srslte/phy/fec/cbsegm.h" @@ -109,7 +110,9 @@ void srslte_uci_cqi_pucch_init(srslte_uci_cqi_pucch_t *q) { uint32_t nwords = 16; for (uint32_t w=0;wcqi_table[w] = srslte_vec_malloc(SRSLTE_UCI_CQI_CODED_PUCCH_B*sizeof(int8_t)); + q->cqi_table_s[w] = srslte_vec_malloc(SRSLTE_UCI_CQI_CODED_PUCCH_B*sizeof(int16_t)); + uint8_t *ptr = word; srslte_bit_unpack(w, &ptr, 4); srslte_uci_encode_cqi_pucch(word, 4, q->cqi_table[w]); for (int j=0;jcqi_table[w]) { + free(q->cqi_table[w]); + } + if (q->cqi_table_s[w]) { + free(q->cqi_table_s[w]); + } + } +} + /* Encode UCI CQI/PMI as described in 5.2.3.3 of 36.212 */ int srslte_uci_encode_cqi_pucch(uint8_t *cqi_data, uint32_t cqi_len, uint8_t b_bits[SRSLTE_UCI_CQI_CODED_PUCCH_B]) From 2b775462f72602701af800ffe57376d183de53ff Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 25 Sep 2017 13:07:01 +0200 Subject: [PATCH 020/242] Added LV_HAVE_AVX512 to CMakeLists --- CMakeLists.txt | 5 ++++ cmake/modules/FindSSE.cmake | 46 +++++++++++++++++++++++++++++++++---- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d354a5497..40d3ef4da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -282,6 +282,11 @@ if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") endif(HAVE_AVX) endif (HAVE_AVX2) + if (HAVE_AVX512) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mavx512f -DLV_HAVE_AVX512") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx512f -DLV_HAVE_AVX512") + endif(HAVE_AVX512) + if(NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug") if(HAVE_SSE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Ofast -funroll-loops") diff --git a/cmake/modules/FindSSE.cmake b/cmake/modules/FindSSE.cmake index de8b38d1d..4c9673a9d 100644 --- a/cmake/modules/FindSSE.cmake +++ b/cmake/modules/FindSSE.cmake @@ -4,10 +4,11 @@ include(CheckCSourceRuns) -option(ENABLE_SSE "Enable compile-time SSE4.1 support." ON) -option(ENABLE_AVX "Enable compile-time AVX support." ON) -option(ENABLE_AVX2 "Enable compile-time AVX2 support." ON) -option(ENABLE_FMA "Enable compile-time FMA support." ON) +option(ENABLE_SSE "Enable compile-time SSE4.1 support." ON) +option(ENABLE_AVX "Enable compile-time AVX support." ON) +option(ENABLE_AVX2 "Enable compile-time AVX2 support." ON) +option(ENABLE_FMA "Enable compile-time FMA support." ON) +option(ENABLE_AVX512 "Enable compile-time AVX512 support." ON) if (ENABLE_SSE) # @@ -135,6 +136,41 @@ if (ENABLE_SSE) endif() endif() + if (ENABLE_AVX512) + + # + # Check compiler for AVX intrinsics + # + if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG ) + set(CMAKE_REQUIRED_FLAGS "-mavx512f") + check_c_source_runs(" + #include + int main() + { + __m512i a, b, c; + const int src[16] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8 , 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF}; + int dst[16]; + a = _mm512_loadu_si512( (__m512i*)src ); + b = _mm512_loadu_si512( (__m512i*)src ); + c = _mm512_add_epi32( a, b ); + _mm512_storeu_si512( (__m512i*)dst, c ); + int i = 0; + for( i = 0; i < 16; i++ ){ + if( ( src[i] + src[i] ) != dst[i] ){ + return -1; + } + } + return 0; + }" + HAVE_AVX512) + endif() + + if (HAVE_AVX512) + message(STATUS "AVX512 is enabled - target CPU must support it") + endif() + endif() + + endif() -mark_as_advanced(HAVE_SSE, HAVE_AVX, HAVE_AVX2, HAVE_FMA) +mark_as_advanced(HAVE_SSE, HAVE_AVX, HAVE_AVX2, HAVE_FMA, HAVE_AVX512) From 8078238cb59624d6c7ef5eec87195f361092c9ea Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 25 Sep 2017 13:08:38 +0200 Subject: [PATCH 021/242] Removed test macros from mat.h --- lib/include/srslte/phy/utils/mat.h | 8 +------- lib/src/phy/utils/mat.c | 1 + lib/src/phy/utils/test/mat_test.c | 32 +++++++++++++++++++++++++++--- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/lib/include/srslte/phy/utils/mat.h b/lib/include/srslte/phy/utils/mat.h index d960590c4..942559955 100644 --- a/lib/include/srslte/phy/utils/mat.h +++ b/lib/include/srslte/phy/utils/mat.h @@ -27,14 +27,8 @@ #ifndef SRSLTE_MAT_H #define SRSLTE_MAT_H -#include "srslte/phy/utils/simd.h" #include "srslte/config.h" - - -/* - * Generic Macros - */ -#define RANDOM_CF() (((float)rand())/((float)RAND_MAX) + _Complex_I*((float)rand())/((float)RAND_MAX)) +#include "srslte/phy/utils/simd.h" /* Generic implementation for complex reciprocal */ SRSLTE_API cf_t srslte_mat_cf_recip_gen(cf_t a); diff --git a/lib/src/phy/utils/mat.c b/lib/src/phy/utils/mat.c index 439daa2ce..bbfc38135 100644 --- a/lib/src/phy/utils/mat.c +++ b/lib/src/phy/utils/mat.c @@ -27,6 +27,7 @@ #include #include +#include #include "srslte/phy/utils/mat.h" diff --git a/lib/src/phy/utils/test/mat_test.c b/lib/src/phy/utils/test/mat_test.c index 49be5c9ae..46081da98 100644 --- a/lib/src/phy/utils/test/mat_test.c +++ b/lib/src/phy/utils/test/mat_test.c @@ -33,12 +33,18 @@ #include #include "srslte/phy/utils/mat.h" +#include "srslte/phy/utils/simd.h" +#include "srslte/phy/utils/vector.h" bool zf_solver = false; bool mmse_solver = false; bool verbose = false; +#define RANDOM_F() ((float)rand())/((float)RAND_MAX) +#define RANDOM_S() ((int16_t)(rand() && 0x800F)) +#define RANDOM_CF() (RANDOM_F() + _Complex_I*RANDOM_F()) + 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 + @@ -49,16 +55,16 @@ double elapsed_us(struct timeval *ts_start, struct timeval *ts_end) { } } -#define NOF_REPETITIONS 1000 +#define BLOCK_SIZE 1000 #define RUN_TEST(FUNCTION) /*TYPE NAME (void)*/ { \ int i;\ struct timeval start, end;\ gettimeofday(&start, NULL); \ bool ret = true; \ - for (i = 0; i < NOF_REPETITIONS; i++) {ret &= FUNCTION ();}\ + for (i = 0; i < BLOCK_SIZE; i++) {ret &= FUNCTION ();}\ gettimeofday(&end, NULL);\ if (verbose) printf("%32s: %s ... %6.2f us/call\n", #FUNCTION, (ret)?"Pass":"Fail", \ - elapsed_us(&start, &end)/NOF_REPETITIONS);\ + elapsed_us(&start, &end)/BLOCK_SIZE);\ passed &= ret;\ } @@ -373,6 +379,24 @@ bool test_mmse_solver_avx(void) { #endif /* LV_HAVE_AVX */ +bool test_vec_dot_prod_ccc(void) { + __attribute__((aligned(256))) cf_t a[14]; + __attribute__((aligned(256))) cf_t b[14]; + cf_t res = 0, gold = 0; + + for (int i = 0; i < 14; i++) { + a[i] = RANDOM_CF(); + b[i] = RANDOM_CF(); + } + + res = srslte_vec_dot_prod_ccc(a, b, 14); + + for (int i=0;i<14;i++) { + gold += a[i]*b[i]; + } + + return (cabsf(res - gold) < 1e-3); +} int main(int argc, char **argv) { bool passed = true; @@ -405,6 +429,8 @@ int main(int argc, char **argv) { #endif /* LV_HAVE_AVX */ } + RUN_TEST(test_vec_dot_prod_ccc); + printf("%s!\n", (passed) ? "Ok" : "Failed"); if (!passed) { From 1c3b5552be004064e16527fba55e2d419a1143b2 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 25 Sep 2017 13:15:59 +0200 Subject: [PATCH 022/242] added c16 type and architecture independent inline SIMD calls --- lib/include/srslte/config.h | 1 + lib/include/srslte/phy/utils/simd.h | 833 +++++++++++++++++++++++++++- 2 files changed, 832 insertions(+), 2 deletions(-) diff --git a/lib/include/srslte/config.h b/lib/include/srslte/config.h index 68076c0c8..8a988a971 100644 --- a/lib/include/srslte/config.h +++ b/lib/include/srslte/config.h @@ -59,5 +59,6 @@ // cf_t definition typedef _Complex float cf_t; +typedef _Complex short int c16_t; #endif // CONFIG_H diff --git a/lib/include/srslte/phy/utils/simd.h b/lib/include/srslte/phy/utils/simd.h index 420d07213..774dd54bd 100644 --- a/lib/include/srslte/phy/utils/simd.h +++ b/lib/include/srslte/phy/utils/simd.h @@ -27,6 +27,8 @@ #ifndef SRSLTE_SIMD_H_H #define SRSLTE_SIMD_H_H +#include + /* * SSE Macros */ @@ -44,7 +46,7 @@ /* * AVX Macros */ -#ifdef LV_HAVE_AVX +#ifdef LV_HAVE_AVX2 #define _MM256_MULJ_PS(X) _mm256_permute_ps(_MM256_CONJ_PS(X), 0b10110001) #define _MM256_CONJ_PS(X) (_mm256_xor_ps(X, _mm256_set_ps(-0.0f, 0.0f, -0.0f, 0.0f, -0.0f, 0.0f, -0.0f, 0.0f))) @@ -60,7 +62,7 @@ #define _MM256_PROD_PS(a, b) _mm256_addsub_ps(_mm256_mul_ps(a,_mm256_moveldup_ps(b)),\ _mm256_mul_ps(_mm256_shuffle_ps(a,a,0xB1),_mm256_movehdup_ps(b))) #endif /* LV_HAVE_FMA */ -#endif /* LV_HAVE_AVX */ +#endif /* LV_HAVE_AVX2 */ /* @@ -78,4 +80,831 @@ _mm256_fmsubadd_ps(_mm256_shuffle_ps(A,A,0xB1),_mm256_movehdup_ps(B), C)) #endif /* LV_HAVE_FMA */ + + +/* Memory Sizes for Single Floating Point and fixed point */ +#ifdef LV_HAVE_AVX512 + +#define SRSLTE_SIMD_F_SIZE 16 +#define SRSLTE_SIMD_CF_SIZE 16 + +#define SRSLTE_SIMD_S_SIZE 32 +#define SRSLTE_SIMD_C16_SIZE 0 + +#else +#ifdef LV_HAVE_AVX2 + +#define SRSLTE_SIMD_F_SIZE 8 +#define SRSLTE_SIMD_CF_SIZE 8 + +#define SRSLTE_SIMD_S_SIZE 16 +#define SRSLTE_SIMD_C16_SIZE 16 + +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + +#define SRSLTE_SIMD_F_SIZE 4 +#define SRSLTE_SIMD_CF_SIZE 4 + +#define SRSLTE_SIMD_S_SIZE 8 +#define SRSLTE_SIMD_C16_SIZE 8 + +#else /* LV_HAVE_SSE */ + +#define SRSLTE_SIMD_F_SIZE 0 +#define SRSLTE_SIMD_CF_SIZE 0 + +#define SRSLTE_SIMD_S_SIZE 0 +#define SRSLTE_SIMD_C16_SIZE 0 + +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ + + + +#if SRSLTE_SIMD_F_SIZE + +/* Data types */ +#ifdef LV_HAVE_AVX512 +typedef __m512 simd_f_t; +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 +typedef __m256 simd_f_t; +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE +typedef __m128 simd_f_t; +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ + +/* Single precision Floating point functions */ +static inline simd_f_t srslte_simd_f_load(float *ptr) { +#ifdef LV_HAVE_AVX512 + return _mm512_load_ps(ptr); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_load_ps(ptr); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + return _mm_load_ps(ptr); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +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 + return _mm256_loadu_ps(ptr); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + return _mm_loadu_ps(ptr); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline void srslte_simd_f_store(float *ptr, simd_f_t simdreg) { +#ifdef LV_HAVE_AVX512 + _mm512_store_ps(ptr, simdreg); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + _mm256_store_ps(ptr, simdreg); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + _mm_store_ps(ptr, simdreg); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline void srslte_simd_f_storeu(float *ptr, simd_f_t simdreg) { +#ifdef LV_HAVE_AVX512 + _mm512_storeu_ps(ptr, simdreg); +#else /* LV_HAVE_AVX512 */ + #ifdef LV_HAVE_AVX2 + _mm256_storeu_ps(ptr, simdreg); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + _mm_storeu_ps(ptr, simdreg); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline simd_f_t srslte_simd_f_set1(float x) { +#ifdef LV_HAVE_AVX512 + return _mm512_set1_ps(x); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_set1_ps(x); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + return _mm_set1_ps(x); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline simd_f_t srslte_simd_f_mul(simd_f_t a, simd_f_t b) { +#ifdef LV_HAVE_AVX512 + return _mm512_mul_ps(a, b); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_mul_ps(a, b); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + return _mm_mul_ps(a, b); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline simd_f_t srslte_simd_f_addsub(simd_f_t a, simd_f_t b) { +#ifdef LV_HAVE_AVX512 + __m512 r = _mm512_add_ps(a, b); + return _mm512_mask_sub_ps(r, 0b1010101010101010, a, b); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_addsub_ps(a, b); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + return _mm_addsub_ps(a, b); +#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); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_sub_ps(a, b); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + return _mm_sub_ps(a, b); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline simd_f_t srslte_simd_f_add(simd_f_t a, simd_f_t b) { +#ifdef LV_HAVE_AVX512 + return _mm512_add_ps(a, b); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_add_ps(a, b); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + return _mm_add_ps(a, b); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline simd_f_t srslte_simd_f_zero (void) { +#ifdef LV_HAVE_AVX512 + return _mm512_setzero_ps(); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_setzero_ps(); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + return _mm_setzero_ps(); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline simd_f_t srslte_simd_f_swap(simd_f_t a) { +#ifdef LV_HAVE_AVX512 + return _mm512_permute_ps(a, 0b10110001); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_permute_ps(a, 0b10110001); +#else /* LV_HAVE_AVX2 */ + #ifdef LV_HAVE_SSE + return _mm_shuffle_ps(a, a, 0b10110001); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline simd_f_t srslte_simd_f_hadd(simd_f_t a, simd_f_t b) { +#ifdef LV_HAVE_AVX512 + const __m512i idx1 = _mm512_setr_epi32((0b00000), (0b00010), + (0b00100), (0b00110), + (0b01000), (0b01010), + (0b01100), (0b01110), + (0b10000), (0b10010), + (0b10100), (0b10110), + (0b11000), (0b11010), + (0b11100), (0b11110)); + const __m512i idx2 = _mm512_or_epi32(idx1, _mm512_set1_epi32(1)); + + simd_f_t a1 = _mm512_permutex2var_ps(a, idx1, b); + simd_f_t b1 = _mm512_permutex2var_ps(a, idx2, b); + return _mm512_add_ps(a1, b1); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + simd_f_t a1 = _mm256_permute2f128_ps(a, b, 0b00100000); + simd_f_t b1 = _mm256_permute2f128_ps(a, b, 0b00110001); + return _mm256_hadd_ps(a1, b1); +#else /* LV_HAVE_AVX2 */ + #ifdef LV_HAVE_SSE + return _mm_hadd_ps(a, b); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline simd_f_t srslte_simd_f_sqrt(simd_f_t a) { +#ifdef LV_HAVE_AVX512 + return _mm512_sqrt_ps(a); +#else /* LV_HAVE_AVX512 */ + #ifdef LV_HAVE_AVX2 + return _mm256_sqrt_ps(a); +#else /* LV_HAVE_AVX2 */ + #ifdef LV_HAVE_SSE + return _mm_sqrt_ps(a); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +#endif /* SRSLTE_SIMD_F_SIZE */ + + +#if SRSLTE_SIMD_CF_SIZE + +typedef struct { + simd_f_t re; + simd_f_t im; +} simd_cf_t; + +/* Complex Single precission Floating point functions */ +static inline simd_cf_t srslte_simd_cfi_load(cf_t *ptr) { + simd_cf_t ret; +#ifdef LV_HAVE_AVX512 + __m512 in1 = _mm512_permute_ps(_mm512_load_ps((float*)(ptr)), 0b11011000); + __m512 in2 = _mm512_permute_ps(_mm512_load_ps((float*)(ptr + 8)), 0b11011000); + ret.re = _mm512_unpacklo_ps(in1, in2); + ret.im = _mm512_unpackhi_ps(in1, in2); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + __m256 in1 = _mm256_permute_ps(_mm256_load_ps((float*)(ptr)), 0b11011000); + __m256 in2 = _mm256_permute_ps(_mm256_load_ps((float*)(ptr + 4)), 0b11011000); + ret.re = _mm256_unpacklo_ps(in1, in2); + ret.im = _mm256_unpackhi_ps(in1, in2); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + __m128 i1 = _mm_load_ps((float*)(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)); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ + return ret; +} + +/* Complex Single precission Floating point functions */ +static inline simd_cf_t srslte_simd_cfi_loadu(cf_t *ptr) { + simd_cf_t ret; +#ifdef LV_HAVE_AVX512 + __m512 in1 = _mm512_permute_ps(_mm512_loadu_ps((float*)(ptr)), 0b11011000); + __m512 in2 = _mm512_permute_ps(_mm512_loadu_ps((float*)(ptr + 8)), 0b11011000); + ret.re = _mm512_unpacklo_ps(in1, in2); + ret.im = _mm512_unpackhi_ps(in1, in2); +#else /* LV_HAVE_AVX512 */ + #ifdef LV_HAVE_AVX2 + __m256 in1 = _mm256_permute_ps(_mm256_loadu_ps((float*)(ptr)), 0b11011000); + __m256 in2 = _mm256_permute_ps(_mm256_loadu_ps((float*)(ptr + 4)), 0b11011000); + ret.re = _mm256_unpacklo_ps(in1, in2); + ret.im = _mm256_unpackhi_ps(in1, in2); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + __m128 i1 = _mm_loadu_ps((float*)(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)); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ + return ret; +} + +static inline simd_cf_t srslte_simd_cf_load(float *re, float *im) { + simd_cf_t ret; +#ifdef LV_HAVE_AVX512 + ret.re = _mm512_load_ps(re); + ret.im = _mm512_load_ps(im); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + ret.re = _mm256_load_ps(re); + ret.im = _mm256_load_ps(im); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + ret.re = _mm_load_ps(re); + ret.im = _mm_load_ps(im); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ + return ret; +} + +static inline simd_cf_t srslte_simd_cf_loadu(float *re, float *im) { + simd_cf_t ret; +#ifdef LV_HAVE_AVX512 + ret.re = _mm512_loadu_ps(re); + ret.im = _mm512_loadu_ps(im); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + ret.re = _mm256_loadu_ps(re); + ret.im = _mm256_loadu_ps(im); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + ret.re = _mm_loadu_ps(re); + ret.im = _mm_loadu_ps(im); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ + return ret; +} + +static inline void srslte_simd_cfi_store(cf_t *ptr, simd_cf_t simdreg) { +#ifdef LV_HAVE_AVX512 + __m512 out1 = _mm512_permute_ps(simdreg.re, 0b11011000); + __m512 out2 = _mm512_permute_ps(simdreg.im, 0b11011000); + _mm512_store_ps((float*)(ptr), _mm512_unpacklo_ps(out1, out2)); + _mm512_store_ps((float*)(ptr + 8), _mm512_unpackhi_ps(out1, out2)); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + __m256 out1 = _mm256_permute_ps(simdreg.re, 0b11011000); + __m256 out2 = _mm256_permute_ps(simdreg.im, 0b11011000); + _mm256_store_ps((float*)(ptr), _mm256_unpacklo_ps(out1, out2)); + _mm256_store_ps((float*)(ptr + 4), _mm256_unpackhi_ps(out1, out2)); +#else /* LV_HAVE_AVX2 */ +#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)); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline void srslte_simd_cfi_storeu(cf_t *ptr, simd_cf_t simdreg) { +#ifdef LV_HAVE_AVX512 + __m512 out1 = _mm512_permute_ps(simdreg.re, 0b11011000); + __m512 out2 = _mm512_permute_ps(simdreg.im, 0b11011000); + _mm512_storeu_ps((float*)(ptr), _mm512_unpacklo_ps(out1, out2)); + _mm512_storeu_ps((float*)(ptr + 8), _mm512_unpackhi_ps(out1, out2)); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + __m256 out1 = _mm256_permute_ps(simdreg.re, 0b11011000); + __m256 out2 = _mm256_permute_ps(simdreg.im, 0b11011000); + _mm256_storeu_ps((float*)(ptr), _mm256_unpacklo_ps(out1, out2)); + _mm256_storeu_ps((float*)(ptr + 4), _mm256_unpackhi_ps(out1, out2)); +#else /* LV_HAVE_AVX2 */ +#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)); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline void srslte_simd_cf_store(float *re, float *im, simd_cf_t simdreg) { +#ifdef LV_HAVE_AVX512 + _mm512_store_ps(re, simdreg.re); + _mm512_store_ps(im, simdreg.im); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + _mm256_store_ps((float *) re, simdreg.re); + _mm256_store_ps((float *) im, simdreg.im); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_SSE + _mm_store_ps((float *) re, simdreg.re); + _mm_store_ps((float *) im, simdreg.im); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline void srslte_simd_cf_storeu(float *re, float *im, simd_cf_t simdreg) { +#ifdef LV_HAVE_AVX512 + _mm512_storeu_ps(re, simdreg.re); + _mm512_storeu_ps(im, simdreg.im); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + _mm256_storeu_ps((float *) re, simdreg.re); + _mm256_storeu_ps((float *) im, simdreg.im); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_SSE + _mm_storeu_ps((float *) re, simdreg.re); + _mm_storeu_ps((float *) im, simdreg.im); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline simd_cf_t srslte_simd_cf_set1 (cf_t x) { + simd_cf_t ret; +#ifdef LV_HAVE_AVX512 + ret.re = _mm512_set1_ps(__real__ x); + ret.im = _mm512_set1_ps(__imag__ x); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + ret.re = _mm256_set1_ps(__real__ x); + ret.im = _mm256_set1_ps(__imag__ x); +#else +#ifdef LV_HAVE_SSE + ret.re = _mm_set1_ps(__real__ x); + ret.im = _mm_set1_ps(__imag__ x); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ + return ret; +} + +static inline simd_cf_t srslte_simd_cf_prod (simd_cf_t a, simd_cf_t b) { + simd_cf_t ret; +#ifdef LV_HAVE_AVX512 + ret.re = _mm512_sub_ps(_mm512_mul_ps(a.re, b.re), + _mm512_mul_ps(a.im, b.im)); + ret.im = _mm512_add_ps(_mm512_mul_ps(a.re, b.im), + _mm512_mul_ps(a.im, b.re)); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + ret.re = _mm256_sub_ps(_mm256_mul_ps(a.re, b.re), + _mm256_mul_ps(a.im, b.im)); + ret.im = _mm256_add_ps(_mm256_mul_ps(a.re, b.im), + _mm256_mul_ps(a.im, b.re)); +#else +#ifdef LV_HAVE_SSE + ret.re = _mm_sub_ps(_mm_mul_ps(a.re, b.re), + _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)); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ + return ret; +} + +static inline simd_cf_t srslte_simd_cf_conjprod (simd_cf_t a, simd_cf_t b) { + simd_cf_t ret; +#ifdef LV_HAVE_AVX512 + ret.re = _mm512_add_ps(_mm512_mul_ps(a.re, b.re), + _mm512_mul_ps(a.im, b.im)); + ret.im = _mm512_sub_ps(_mm512_mul_ps(a.im, b.re), + _mm512_mul_ps(a.re, b.im)); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + ret.re = _mm256_add_ps(_mm256_mul_ps(a.re, b.re), + _mm256_mul_ps(a.im, b.im)); + ret.im = _mm256_sub_ps(_mm256_mul_ps(a.im, b.re), + _mm256_mul_ps(a.re, b.im)); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + ret.re = _mm_add_ps(_mm_mul_ps(a.re, b.re), + _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)); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ + return ret; +} + +static inline simd_cf_t srslte_simd_cf_add (simd_cf_t a, simd_cf_t b) { + simd_cf_t ret; +#ifdef LV_HAVE_AVX512 + ret.re = _mm512_add_ps(a.re, b.re); + ret.im = _mm512_add_ps(a.im, b.im); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + ret.re = _mm256_add_ps(a.re, b.re); + ret.im = _mm256_add_ps(a.im, b.im); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + ret.re = _mm_add_ps(a.re, b.re); + ret.im = _mm_add_ps(a.im, b.im); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ + return ret; +} + +static inline simd_cf_t srslte_simd_cf_zero (void) { + simd_cf_t ret; +#ifdef LV_HAVE_AVX512 + ret.re = _mm512_setzero_ps(); + ret.im = _mm512_setzero_ps(); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + ret.re = _mm256_setzero_ps(); + ret.im = _mm256_setzero_ps(); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + ret.re = _mm_setzero_ps(); + ret.im = _mm_setzero_ps(); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ + return ret; +} + +#endif /* SRSLTE_SIMD_CF_SIZE */ + + +#if SRSLTE_SIMD_S_SIZE + + +#ifdef LV_HAVE_AVX512 +typedef __m512i simd_s_t; +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 +typedef __m256i simd_s_t; +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE +typedef __m128i simd_s_t; +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ + +static inline simd_s_t srslte_simd_s_load(int16_t *ptr) { +#ifdef LV_HAVE_AVX512 + return _mm512_load_si512(ptr); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_load_si256(ptr); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + return _mm_load_si128(ptr); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline simd_s_t srslte_simd_s_loadu(int16_t *ptr) { +#ifdef LV_HAVE_AVX512 + return _mm512_load_si512(ptr); +#else /* LV_HAVE_AVX512 */ + #ifdef LV_HAVE_AVX2 + return _mm256_load_si256(ptr); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + return _mm_load_si128(ptr); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline void srslte_simd_s_store(int16_t *ptr, simd_s_t simdreg) { +#ifdef LV_HAVE_AVX512 + _mm512_store_si512(ptr, simdreg); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + _mm256_store_si256(ptr, simdreg); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + _mm_store_si128(ptr, simdreg); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline void srslte_simd_s_storeu(int16_t *ptr, simd_s_t simdreg) { +#ifdef LV_HAVE_AVX512 + _mm512_storeu_si512(ptr, simdreg); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + _mm256_storeu_si256(ptr, simdreg); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + _mm_storeu_si128(ptr, simdreg); +#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(); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_setzero_si256(); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + return _mm_setzero_si128(); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline simd_s_t srslte_simd_s_mul(simd_s_t a, simd_s_t b) { +#ifdef LV_HAVE_AVX512 + return _mm512_mullo_epi16(a, b); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_mullo_epi16(a, b); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + return _mm_mullo_epi16(a, b); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline simd_s_t srslte_simd_s_add(simd_s_t a, simd_s_t b) { +#ifdef LV_HAVE_AVX512 + return _mm512_add_epi16(a, b); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_add_epi16(a, b); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + return _mm_add_epi16(a, b); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline simd_s_t srslte_simd_s_sub(simd_s_t a, simd_s_t b) { +#ifdef LV_HAVE_AVX512 + return _mm512_sub_epi16(a, b); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_sub_epi16(a, b); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + return _mm_sub_epi16(a, b); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +#endif /* SRSLTE_SIMD_S_SIZE */ + + +#if SRSLTE_SIMD_C16_SIZE + +typedef struct { +#ifdef LV_HAVE_AVX512 + union { + __m512i m512; + int16_t i16[32]; + } re; + union { + __m512i m512; + int16_t i16[32]; + } 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; +#else +#ifdef LV_HAVE_SSE + union { + __m128i m128; + int16_t i16[8]; + } re; + union { + __m128i m128; + int16_t i16[8]; + } im; +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} simd_c16_t; + +/* Fixed point precision (16-bit) functions */ +static inline simd_c16_t srslte_simd_c16i_load(c16_t *ptr) { + simd_c16_t ret; +#ifdef LV_HAVE_AVX512 + __m512i in1 = _mm512_load_si512((__m512i*)(ptr)); + __m512i in2 = _mm512_load_si512((__m512i*)(ptr + 8)); + ret.re.m512 = _mm512_mask_blend_epi16(0xAAAAAAAA, in1,_mm512_shufflelo_epi16(_mm512_shufflehi_epi16(in2, 0b10100000), 0b10100000)); + ret.im.m512 = _mm512_mask_blend_epi16(0xAAAAAAAA, _mm512_shufflelo_epi16(_mm512_shufflehi_epi16(in1, 0b11110101), 0b11110101),in2); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_AVX2 + __m256i in1 = _mm256_load_si256((__m256i*)(ptr)); + __m256i in2 = _mm256_load_si256((__m256i*)(ptr + 8)); + ret.re.m256 = _mm256_blend_epi16(in1,_mm256_shufflelo_epi16(_mm256_shufflehi_epi16(in2, 0b10100000), 0b10100000), 0b10101010); + ret.im.m256 = _mm256_blend_epi16(_mm256_shufflelo_epi16(_mm256_shufflehi_epi16(in1, 0b11110101), 0b11110101),in2, 0b10101010); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + __m128i in1 = _mm_load_si128((__m128i*)(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); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ + return ret; +} + +static inline simd_c16_t srslte_simd_c16_load(int16_t *re, int16_t *im) { + simd_c16_t ret; +#ifdef LV_HAVE_AVX2 + ret.re.m256 = _mm256_load_si256((__m256i*)(re)); + ret.im.m256 = _mm256_load_si256((__m256i*)(im)); +#else +#ifdef LV_HAVE_SSE + ret.re.m128 = _mm_load_si128((__m128i*)(re)); + ret.im.m128 = _mm_load_si128((__m128i*)(im)); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ + return ret; +} + +static inline void srslte_simd_c16i_store(c16_t *ptr, simd_c16_t simdreg) { +#ifdef LV_HAVE_AVX2 + __m256i re_sw = _mm256_shufflelo_epi16(_mm256_shufflehi_epi16(simdreg.re.m256, 0b10110001), 0b10110001); + __m256i im_sw = _mm256_shufflelo_epi16(_mm256_shufflehi_epi16(simdreg.im.m256, 0b10110001), 0b10110001); + _mm256_store_si256((__m256i *) (ptr), _mm256_blend_epi16(simdreg.re.m256, im_sw, 0b10101010)); + _mm256_store_si256((__m256i *) (ptr + 8), _mm256_blend_epi16(re_sw, simdreg.im.m256, 0b10101010)); +#else +#ifdef LV_HAVE_SSE + __m128i re_sw = _mm_shufflelo_epi16(_mm_shufflehi_epi16(simdreg.re.m128, 0b10110001), 0b10110001); + __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)); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +} + +static inline void srslte_simd_c16_store(int16_t *re, int16_t *im, simd_c16_t simdreg) { +#ifdef LV_HAVE_AVX2 + _mm256_store_si256((__m256i *) re, simdreg.re.m256); + _mm256_store_si256((__m256i *) im, simdreg.im.m256); +#else +#ifdef LV_HAVE_SSE + _mm_store_si128((__m128i *) re, simdreg.re.m128); + _mm_store_si128((__m128i *) im, simdreg.im.m128); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +} + +static inline simd_c16_t srslte_simd_c16_prod (simd_c16_t a, simd_c16_t b) { + simd_c16_t ret; +#ifdef LV_HAVE_AVX2 + ret.re.m256 = _mm256_sub_epi16(_mm256_mulhrs_epi16(a.re.m256, _mm256_slli_epi16(b.re.m256, 1)), + _mm256_mulhrs_epi16(a.im.m256, _mm256_slli_epi16(b.im.m256, 1))); + ret.im.m256 = _mm256_add_epi16(_mm256_mulhrs_epi16(a.re.m256, _mm256_slli_epi16(b.im.m256, 1)), + _mm256_mulhrs_epi16(a.im.m256, _mm256_slli_epi16(b.re.m256, 1))); +#else +#ifdef LV_HAVE_SSE + ret.re.m128 = _mm_sub_epi16(_mm_mulhrs_epi16(a.re.m128, _mm_slli_epi16(b.re.m128, 1)), + _mm_mulhrs_epi16(a.im.m128, _mm_slli_epi16(b.im.m128, 1))); + ret.im.m128 = _mm_add_epi16(_mm_mulhrs_epi16(a.re.m128, _mm_slli_epi16(b.im.m128, 1)), + _mm_mulhrs_epi16(a.im.m128, _mm_slli_epi16(b.re.m128, 1))); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ + return ret; +} + +static inline simd_c16_t srslte_simd_c16_add (simd_c16_t a, simd_c16_t b) { + simd_c16_t ret; +#ifdef LV_HAVE_AVX2 + ret.re.m256 = _mm256_add_epi16(a.re.m256, b.re.m256); + ret.im.m256 = _mm256_add_epi16(a.im.m256, b.im.m256); +#else +#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); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ + return ret; +} + +static inline simd_c16_t srslte_simd_c16_zero (void) { + simd_c16_t ret; +#ifdef LV_HAVE_AVX2 + ret.re.m256 = _mm256_setzero_si256(); + ret.im.m256 = _mm256_setzero_si256(); +#else +#ifdef LV_HAVE_SSE + ret.re.m128 = _mm_setzero_si128(); + ret.im.m128 = _mm_setzero_si128(); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ + return ret; +} + +#endif /* SRSLTE_SIMD_C16_SIZE */ + + + #endif //SRSLTE_SIMD_H_H From c9f6bfccd47d6dfcda2930e7cb81465e38fb3b9d Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 25 Sep 2017 13:19:34 +0200 Subject: [PATCH 023/242] Refactored vector library with SIMD independent architecture inline functions test-benchmark --- lib/include/srslte/phy/utils/vector.h | 8 +- lib/include/srslte/phy/utils/vector_simd.h | 65 +- lib/src/phy/utils/test/CMakeLists.txt | 3 + lib/src/phy/utils/test/vector_test.c | 555 +++++++++++ lib/src/phy/utils/vector.c | 228 +---- lib/src/phy/utils/vector_simd.c | 1018 ++++++++++---------- 6 files changed, 1138 insertions(+), 739 deletions(-) create mode 100644 lib/src/phy/utils/test/vector_test.c diff --git a/lib/include/srslte/phy/utils/vector.h b/lib/include/srslte/phy/utils/vector.h index 4a55d18b6..0fadfb334 100644 --- a/lib/include/srslte/phy/utils/vector.h +++ b/lib/include/srslte/phy/utils/vector.h @@ -80,8 +80,8 @@ SRSLTE_API void srslte_vec_load_file(char *filename, void *buffer, uint32_t len) SRSLTE_API void srslte_vec_sum_ch(uint8_t *x, uint8_t *y, char *z, uint32_t len); SRSLTE_API void srslte_vec_sum_fff(float *x, float *y, float *z, uint32_t len); SRSLTE_API void srslte_vec_sum_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len); -SRSLTE_API void srslte_vec_sub_sss(short *x, short *y, short *z, uint32_t len); -SRSLTE_API void srslte_vec_sum_sss(short *x, short *y, short *z, uint32_t len); +SRSLTE_API void srslte_vec_sub_sss(int16_t *x, int16_t *y, int16_t *z, uint32_t len); +SRSLTE_API void srslte_vec_sum_sss(int16_t *x, int16_t *y, int16_t *z, uint32_t len); /* substract two vectors z=x-y */ SRSLTE_API void srslte_vec_sub_fff(float *x, float *y, float *z, uint32_t len); @@ -91,7 +91,7 @@ SRSLTE_API void srslte_vec_sub_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len); SRSLTE_API void srslte_vec_ema_filter(cf_t *new_data, cf_t *average, cf_t *output, float coeff, uint32_t len); /* Square distance */ -SRSLTE_API void srslte_vec_square_dist(cf_t symbol, cf_t *points, float *distance, uint32_t npoints); +//SRSLTE_API void srslte_vec_square_dist(cf_t symbol, cf_t *points, float *distance, uint32_t npoints); /* scalar addition */ SRSLTE_API void srslte_vec_sc_add_fff(float *x, float h, float *z, uint32_t len); @@ -132,7 +132,7 @@ SRSLTE_API void srslte_vec_prod_conj_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len /* real vector product (element-wise) */ SRSLTE_API void srslte_vec_prod_fff(float *x, float *y, float *z, uint32_t len); -SRSLTE_API void srslte_vec_prod_sss(short *x, short *y, short *z, uint32_t len); +SRSLTE_API void srslte_vec_prod_sss(int16_t *x, int16_t *y, int16_t *z, uint32_t len); /* Dot-product */ SRSLTE_API cf_t srslte_vec_dot_prod_cfc(cf_t *x, float *y, uint32_t len); diff --git a/lib/include/srslte/phy/utils/vector_simd.h b/lib/include/srslte/phy/utils/vector_simd.h index 1010cbed6..8ea2ce9bc 100644 --- a/lib/include/srslte/phy/utils/vector_simd.h +++ b/lib/include/srslte/phy/utils/vector_simd.h @@ -35,47 +35,66 @@ extern "C" { #include #include "srslte/config.h" -SRSLTE_API int srslte_vec_dot_prod_sss_sse(short *x, short *y, uint32_t len); +#ifdef LV_HAVE_AVX512 +#define SRSLTE_IS_ALIGNED(PTR) (((size_t)(PTR) & 0x3F) == 0) +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX +#define SRSLTE_IS_ALIGNED(PTR) (((size_t)(PTR) & 0x1F) == 0) +#else /* LV_HAVE_AVX */ +#ifdef LV_HAVE_SSE +#define SRSLTE_IS_ALIGNED(PTR) (((size_t)(PTR) & 0x0F) == 0) +#else /* LV_HAVE_SSE */ +#define SRSLTE_IS_ALIGNED(PTR) (true) +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX */ +#endif /* LV_HAVE_AVX512 */ + +SRSLTE_API int srslte_vec_dot_prod_sss_simd(int16_t *x, int16_t *y, int len); + +SRSLTE_API void srslte_vec_sum_sss_simd(int16_t *x, int16_t *y, int16_t *z, int len); + +SRSLTE_API void srslte_vec_sub_sss_simd(int16_t *x, int16_t *y, int16_t *z, int len); -SRSLTE_API int srslte_vec_dot_prod_sss_avx2(short *x, short *y, uint32_t len); - -SRSLTE_API void srslte_vec_sum_sss_sse(short *x, short *y, short *z, uint32_t len); +SRSLTE_API void srslte_vec_sub_sss_avx2(short *x, short *y, short *z, uint32_t len); -SRSLTE_API void srslte_vec_sum_sss_avx2(short *x, short *y, short *z, uint32_t len); +SRSLTE_API cf_t srslte_vec_acc_cc_simd(cf_t *x, int len); -SRSLTE_API void srslte_vec_sub_sss_sse(short *x, short *y, short *z, uint32_t len); +SRSLTE_API void srslte_vec_add_fff_simd(float *x, float *y, float *z, int len); -SRSLTE_API void srslte_vec_sub_sss_avx2(short *x, short *y, short *z, uint32_t len); +SRSLTE_API void srslte_vec_sub_fff_simd(float *x, float *y, float *z, int len); -SRSLTE_API void srslte_vec_sum_fff_sse(float *x, float *y, float *z, uint32_t len); +SRSLTE_API void srslte_vec_sc_prod_fff_simd(float *x, float h, float *z, int len); -SRSLTE_API void srslte_vec_sum_fff_avx(float *x, float *y, float *z, uint32_t len); +SRSLTE_API void srslte_vec_sc_prod_ccc_simd(cf_t *x, cf_t h, cf_t *z, int len); -SRSLTE_API void srslte_vec_sub_fff_sse(float *x, float *y, float *z, uint32_t len); +SRSLTE_API void srslte_vec_prod_fff_simd(float *x, float *y, float *z, int len); -SRSLTE_API void srslte_vec_sub_fff_avx(float *x, float *y, float *z, uint32_t len); +SRSLTE_API void srslte_vec_prod_ccc_simd(cf_t *x,cf_t *y, cf_t *z, int len); -SRSLTE_API void srslte_vec_sc_prod_fff_sse(float *x, float h, float *z, uint32_t len); +SRSLTE_API void srslte_vec_prod_conj_ccc_simd(cf_t *x,cf_t *y, cf_t *z, int len); -SRSLTE_API void srslte_vec_sc_prod_ccc_sse(cf_t *x, cf_t h, cf_t *z, uint32_t len); +SRSLTE_API void srslte_vec_prod_ccc_cf_simd(float *a_re, float *a_im, float *b_re, float *b_im, float *r_re, float *r_im, int len); -SRSLTE_API void srslte_vec_prod_ccc_sse(cf_t *x,cf_t *y, cf_t *z, uint32_t len); - -SRSLTE_API void srslte_vec_prod_sss_sse(short *x, short *y, short *z, uint32_t len); +SRSLTE_API void srslte_vec_prod_ccc_c16_simd(int16_t *a_re, int16_t *a_im, int16_t *b_re, int16_t *b_im, int16_t *r_re, + int16_t *r_im, int len); -SRSLTE_API void srslte_vec_prod_sss_avx2(short *x, short *y, short *z, uint32_t len); +SRSLTE_API void srslte_vec_prod_sss_simd(int16_t *x, int16_t *y, int16_t *z, int len); -SRSLTE_API cf_t srslte_vec_dot_prod_conj_ccc_sse(cf_t *x, cf_t *y, uint32_t len); +SRSLTE_API cf_t srslte_vec_dot_prod_conj_ccc_simd(cf_t *x, cf_t *y, int len); -SRSLTE_API void srslte_vec_prod_conj_ccc_sse(cf_t *x,cf_t *y, cf_t *z, uint32_t len); +SRSLTE_API cf_t srslte_vec_dot_prod_ccc_simd(cf_t *x, cf_t *y, int len); SRSLTE_API cf_t srslte_vec_dot_prod_ccc_sse(cf_t *x, cf_t *y, uint32_t len); +SRSLTE_API c16_t srslte_vec_dot_prod_ccc_c16i_simd(c16_t *x, c16_t *y, int len); + SRSLTE_API void srslte_vec_sc_div2_sss_avx2(short *x, int k, short *z, uint32_t len); -SRSLTE_API void srslte_vec_abs_square_cf_sse(cf_t *x, float *z, uint32_t len); +SRSLTE_API void srslte_vec_abs_cf_simd(cf_t *x, float *z, int len); + +SRSLTE_API void srslte_vec_abs_square_cf_simd(cf_t *x, float *z, int len); -SRSLTE_API void srslte_vec_prod_sss_sse(short *x, short *y, short *z, uint32_t len); +SRSLTE_API void srslte_vec_prod_sss_sse(short *x, short *y, short *z, uint32_t len); SRSLTE_API void srslte_vec_prod_sss_avx(short *x, short *y, short *z, uint32_t len); @@ -93,7 +112,9 @@ SRSLTE_API void srslte_vec_lut_sss_sse(short *x, unsigned short *lut, short *y, SRSLTE_API void srslte_vec_convert_fi_sse(float *x, int16_t *z, float scale, uint32_t len); -SRSLTE_API void srslte_vec_sc_prod_cfc_avx(const cf_t *x,const float h,cf_t *y,const uint32_t len); +SRSLTE_API void srslte_vec_sc_prod_cfc_simd(const cf_t *x,const float h,cf_t *y,const int len); + +SRSLTE_API void srslte_vec_cp_simd(cf_t *src, cf_t *dst, int len); #ifdef __cplusplus } diff --git a/lib/src/phy/utils/test/CMakeLists.txt b/lib/src/phy/utils/test/CMakeLists.txt index 4dccbf2a0..76df7ac59 100644 --- a/lib/src/phy/utils/test/CMakeLists.txt +++ b/lib/src/phy/utils/test/CMakeLists.txt @@ -42,3 +42,6 @@ target_link_libraries(algebra_test srslte_phy) add_test(algebra_2x2_zf_solver_test algebra_test -z) add_test(algebra_2x2_mmse_solver_test algebra_test -m) + +add_executable(vector_test vector_test.c) +target_link_libraries(vector_test srslte_phy) \ No newline at end of file diff --git a/lib/src/phy/utils/test/vector_test.c b/lib/src/phy/utils/test/vector_test.c new file mode 100644 index 000000000..e781d05b9 --- /dev/null +++ b/lib/src/phy/utils/test/vector_test.c @@ -0,0 +1,555 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2015 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of the srsLTE library. + * + * 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/. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "srslte/phy/utils/mat.h" +#include "srslte/phy/utils/simd.h" +#include "srslte/phy/utils/vector.h" + + +bool zf_solver = false; +bool mmse_solver = false; +bool verbose = false; + +#define MAX_MSE (1e-3) +#define NOF_REPETITIONS (1024*128) +#define MAX_FUNCTIONS (64) +#define MAX_BLOCKS (16) + +#define RANDOM_F() ((float)rand())/((float)RAND_MAX) +#define RANDOM_S() ((int16_t)(rand() && 0x800F)) +#define RANDOM_CF() (RANDOM_F() + _Complex_I*RANDOM_F()) + +#define TEST_CALL(TEST_CODE) gettimeofday(&start, NULL);\ + for (int i = 0; i < NOF_REPETITIONS; i++){TEST_CODE;}\ + gettimeofday(&end, NULL); \ + *timing = elapsed_us(&start, &end); + +#define TEST(X, CODE) static bool test_##X (char *func_name, double *timing, uint32_t block_size) {\ + struct timeval start, end;\ + float mse = 0.0f;\ + bool passed;\ + strncpy(func_name, #X, 32);\ + CODE;\ + passed = (mse < MAX_MSE);\ + printf("%32s (%5d) ... %7.1f MSamp/s ... %3s Passed\n", func_name, block_size, \ + (double) block_size*NOF_REPETITIONS/ *timing, passed?"":"Not");\ + return passed;\ +} + +#define MALLOC(TYPE, NAME) TYPE *NAME = srslte_vec_malloc(sizeof(TYPE)*block_size) + + +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; + } +} + +float squared_error (cf_t a, cf_t b) { + float diff_re = __real__ a - __real__ b; + float diff_im = __imag__ a - __imag__ b; + return diff_re*diff_re + diff_im*diff_im; +} + +TEST(srslte_vec_dot_prod_sss, + MALLOC(int16_t, x); + MALLOC(int16_t, y); + int16_t z; + + cf_t gold = 0.0f; + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_S(); + y[i] = RANDOM_S(); + } + + TEST_CALL(z = srslte_vec_dot_prod_sss(x, y, block_size)) + + for (int i = 0; i < block_size; i++) { + gold += x[i] * y[i]; + } + + mse += cabsf(gold - z) / cabsf(gold); + + free(x); + free(y); +) + +TEST(srslte_vec_sum_sss, + MALLOC(int16_t, x); + MALLOC(int16_t, y); + MALLOC(int16_t, z); + + cf_t gold = 0.0f; + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_S(); + y[i] = RANDOM_S(); + } + + TEST_CALL(srslte_vec_sum_sss(x, y, z, block_size)) + + for (int i = 0; i < block_size; i++) { + gold = x[i] + y[i]; + mse += cabsf(gold - z[i]); + } + + free(x); + free(y); + free(z); +) + +TEST(srslte_vec_sub_sss, + MALLOC(int16_t, x); + MALLOC(int16_t, y); + MALLOC(int16_t, z); + + cf_t gold = 0.0f; + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_S(); + y[i] = RANDOM_S(); + } + + TEST_CALL(srslte_vec_sub_sss(x, y, z, block_size)) + + for (int i = 0; i < block_size; i++) { + gold = x[i] - y[i]; + mse += cabsf(gold - z[i]); + } + + free(x); + free(y); + free(z); +) + +TEST(srslte_vec_prod_sss, + MALLOC(int16_t, x); + MALLOC(int16_t, y); + MALLOC(int16_t, z); + + cf_t gold = 0.0f; + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_S(); + y[i] = RANDOM_S(); + } + + TEST_CALL(srslte_vec_prod_sss(x, y, z, block_size)) + + for (int i = 0; i < block_size; i++) { + gold = x[i] * y[i]; + mse += cabsf(gold - z[i]); + } + + free(x); + free(y); + free(z); +) + +TEST(srslte_vec_acc_cc, + MALLOC(cf_t, x); + cf_t z; + + cf_t gold = 0.0f; + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_F(); + } + + TEST_CALL(z = srslte_vec_acc_cc(x, block_size)) + + for (int i = 0; i < block_size; i++) { + gold += x[i]; + } + + mse += cabsf(gold - z)/cabsf(gold); + + free(x); +) + + +TEST(srslte_vec_sum_fff, + MALLOC(float, x); + MALLOC(float, y); + MALLOC(float, z); + + cf_t gold = 0.0f; + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_F(); + y[i] = RANDOM_F(); + } + + TEST_CALL(srslte_vec_sum_fff(x, y, z, block_size)) + + for (int i = 0; i < block_size; i++) { + gold = x[i] + y[i]; + mse += cabsf(gold - z[i]); + } + + free(x); + free(y); +) + +TEST(srslte_vec_sub_fff, + MALLOC(float, x); + MALLOC(float, y); + MALLOC(float, z); + + cf_t gold = 0.0f; + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_F(); + y[i] = RANDOM_F(); + } + + TEST_CALL(srslte_vec_sub_fff(x, y, z, block_size)) + + for (int i = 0; i < block_size; i++) { + gold = x[i] - y[i]; + mse += cabsf(gold - z[i]); + } + + free(x); + free(y); +) + +TEST(srslte_vec_dot_prod_ccc, + MALLOC(cf_t, x); + MALLOC(cf_t, y); + cf_t z; + + cf_t gold = 0.0f; + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_CF(); + y[i] = RANDOM_CF(); + } + + TEST_CALL(z = srslte_vec_dot_prod_ccc(x, y, block_size)) + + for (int i = 0; i < block_size; i++) { + gold += x[i] * y[i]; + } + + mse = cabsf(gold - z) / cabsf(gold); + + free(x); + free(y); +) + +TEST(srslte_vec_dot_prod_conj_ccc, + MALLOC(cf_t, x); + MALLOC(cf_t, y); + cf_t z; + + cf_t gold = 0.0f; + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_CF(); + y[i] = RANDOM_CF(); + } + + TEST_CALL(z = srslte_vec_dot_prod_conj_ccc(x, y, block_size)) + + for (int i = 0; i < block_size; i++) { + gold += x[i] * conjf(y[i]); + } + + mse = cabsf(gold - z) / cabsf(gold); + + free(x); + free(y); +) + +TEST(srslte_vec_prod_ccc, + MALLOC(cf_t, x); + MALLOC(cf_t, y); + MALLOC(cf_t, z); + + cf_t gold; + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_CF(); + y[i] = RANDOM_CF(); + } + + TEST_CALL(srslte_vec_prod_ccc(x, y, z, block_size)) + + for (int i = 0; i < block_size; i++) { + gold = x[i] * y[i]; + mse += cabsf(gold - z[i]); + } + + free(x); + free(z); +) + +TEST(srslte_vec_prod_conj_ccc, + MALLOC(cf_t, x); + MALLOC(cf_t, y); + MALLOC(cf_t, z); + + cf_t gold; + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_CF(); + y[i] = RANDOM_CF(); + } + + TEST_CALL(srslte_vec_prod_conj_ccc(x, y, z, block_size)) + + for (int i = 0; i < block_size; i++) { + gold = x[i] * conjf(y[i]); + mse += cabsf(gold - z[i]); + } + + free(x); + free(z); +) + +TEST(srslte_vec_sc_prod_ccc, + MALLOC(cf_t, x); + MALLOC(cf_t, z); + cf_t y = RANDOM_F(); + + cf_t gold; + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_CF(); + } + + TEST_CALL(srslte_vec_sc_prod_ccc(x, y, z, block_size)) + + for (int i = 0; i < block_size; i++) { + gold = x[i] * y; + mse += cabsf(gold - z[i]); + } + + free(x); + free(z); +) + +TEST(srslte_vec_prod_fff, + MALLOC(float, x); + MALLOC(float, y); + MALLOC(float, z); + + cf_t gold; + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_CF(); + y[i] = RANDOM_CF(); + } + + TEST_CALL(srslte_vec_prod_fff(x, y, z, block_size)) + + for (int i = 0; i < block_size; i++) { + gold = x[i] * y[i]; + mse += cabsf(gold - z[i]); + } + + free(x); + free(z); +) + +TEST(srslte_vec_sc_prod_fff, + MALLOC(float, x); + MALLOC(float, z); + float y = RANDOM_F(); + + float gold; + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_CF(); + } + + TEST_CALL(srslte_vec_sc_prod_fff(x, y, z, block_size)) + + for (int i = 0; i < block_size; i++) { + gold = x[i] * y; + mse += cabsf(gold - z[i]); + } + + free(x); + free(z); +) + +TEST(srslte_vec_abs_cf, + MALLOC(cf_t, x); + MALLOC(float, z); + float gold; + + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_CF(); + } + + TEST_CALL(srslte_vec_abs_cf(x, z, block_size)) + + for (int i = 0; i < block_size; i++) { + gold = sqrtf(crealf(x[i]) * crealf(x[i]) + cimagf(x[i])*cimagf(x[i])); + mse += cabsf(gold - z[i]); + } + + free(x); + free(z); +) + +TEST(srslte_vec_abs_square_cf, + MALLOC(cf_t, x); + MALLOC(float, z); + float gold; + + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_CF(); + } + + TEST_CALL(srslte_vec_abs_square_cf(x, z, block_size)) + + for (int i = 0; i < block_size; i++) { + gold = crealf(x[i]) * crealf(x[i]) + cimagf(x[i])*cimagf(x[i]); + mse += cabsf(gold - z[i]); + } + + free(x); + free(z); +) + +TEST(srslte_vec_sc_prod_cfc, + MALLOC(cf_t, x); + MALLOC(cf_t, z); + cf_t gold; + float h = RANDOM_F(); + + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_CF(); + } + + TEST_CALL(srslte_vec_sc_prod_cfc(x, h, z, block_size)) + + for (int i = 0; i < block_size; i++) { + gold = x[i] * h; + mse += cabsf(gold - z[i]); + } + + free(x); + free(z); +) + +int main(int argc, char **argv) { + char func_names[MAX_FUNCTIONS][32]; + double timmings[MAX_FUNCTIONS][MAX_BLOCKS]; + uint32_t sizes[32]; + uint32_t size_count = 0; + uint32_t func_count = 0; + bool passed = true; + + for (uint32_t block_size = 1; block_size <= 1024*16; block_size *= 2) { + func_count = 0; + + passed &= test_srslte_vec_dot_prod_sss(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed &= test_srslte_vec_sum_sss(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed &= test_srslte_vec_sub_sss(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed &= test_srslte_vec_prod_sss(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed &= test_srslte_vec_acc_cc(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed &= test_srslte_vec_sum_fff(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed &= test_srslte_vec_sub_fff(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed &= test_srslte_vec_dot_prod_ccc(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed &= test_srslte_vec_dot_prod_conj_ccc(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed &= test_srslte_vec_prod_fff(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed &= test_srslte_vec_prod_ccc(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed &= test_srslte_vec_prod_conj_ccc(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed &= test_srslte_vec_sc_prod_ccc(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed &= test_srslte_vec_sc_prod_fff(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed &= test_srslte_vec_abs_cf(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed &= test_srslte_vec_abs_square_cf(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed &= test_srslte_vec_sc_prod_cfc(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + sizes[size_count] = block_size; + size_count++; + } + + printf("\n"); + printf("%32s |", "Subroutine/MSps"); + for (int i = 0; i < size_count; i++) { + printf(" %7d", sizes[i]); + } + printf(" |\n"); + + for (int j = 0; j < 32; j++) { + printf("-"); + } + printf("-+-"); + for (int j = 0; j < size_count; j++) { + printf("--------"); + } + printf("-|\n"); + + for (int i = 0; i < func_count; i++) { + printf("%32s | ", func_names[i]); + for (int j = 0; j < size_count; j++) { + printf(" %7.1f", (double) NOF_REPETITIONS*(double)sizes[j]/timmings[i][j]); + } + printf(" |\n"); + } + + return (passed)?SRSLTE_SUCCESS:SRSLTE_ERROR; +} diff --git a/lib/src/phy/utils/vector.c b/lib/src/phy/utils/vector.c index 917810e92..cb21f24f1 100644 --- a/lib/src/phy/utils/vector.c +++ b/lib/src/phy/utils/vector.c @@ -36,25 +36,6 @@ #include "srslte/phy/utils/bit.h" -#ifdef LV_HAVE_SSE -#include -#endif - -#ifdef LV_HAVE_AVX -#include -#endif - - -#ifdef HAVE_VOLK -#include "volk/volk.h" -#endif - -#ifdef DEBUG_MODE -#warning FIXME: Disabling SSE/AVX vector code -#undef LV_HAVE_SSE -#undef LV_HAVE_AVX -#endif - int srslte_vec_acc_ii(int *x, uint32_t len) { int i; @@ -88,51 +69,25 @@ void srslte_vec_ema_filter(cf_t *new_data, cf_t *average, cf_t *output, float co } cf_t srslte_vec_acc_cc(cf_t *x, uint32_t len) { - int i; - cf_t z=0; - for (i=0;i #include #include #include #include - -#include "srslte/phy/utils/vector_simd.h" - #include #include -#ifdef LV_HAVE_SSE -#include -#endif - -#ifdef LV_HAVE_AVX -#include -#endif - - -int srslte_vec_dot_prod_sss_sse(short *x, short *y, uint32_t len) -{ - int result = 0; -#ifdef LV_HAVE_SSE - unsigned int number = 0; - const unsigned int points = len / 8; +#include +#include "srslte/phy/utils/vector_simd.h" +#include "srslte/phy/utils/simd.h" - const __m128i* xPtr = (const __m128i*) x; - const __m128i* yPtr = (const __m128i*) y; - - __m128i dotProdVal = _mm_setzero_si128(); - __m128i xVal, yVal, zVal; - for(;number < points; number++){ +int srslte_vec_dot_prod_sss_simd(int16_t *x, int16_t *y, int len) { + int i = 0; + int result = 0; +#if SRSLTE_SIMD_S_SIZE + simd_s_t simd_dotProdVal = srslte_simd_s_zero(); + if (SRSLTE_IS_ALIGNED(x) && SRSLTE_IS_ALIGNED(y)) { + for (; i < len - SRSLTE_SIMD_S_SIZE + 1; i += SRSLTE_SIMD_S_SIZE) { + simd_s_t a = srslte_simd_s_load(&x[i]); + simd_s_t b = srslte_simd_s_load(&y[i]); - xVal = _mm_load_si128(xPtr); - yVal = _mm_loadu_si128(yPtr); + simd_s_t z = srslte_simd_s_mul(a, b); - zVal = _mm_mullo_epi16(xVal, yVal); + simd_dotProdVal = srslte_simd_s_add(simd_dotProdVal, z); + } + } else { + for (; i < len - SRSLTE_SIMD_S_SIZE + 1; i += SRSLTE_SIMD_S_SIZE) { + simd_s_t a = srslte_simd_s_loadu(&x[i]); + simd_s_t b = srslte_simd_s_loadu(&y[i]); - dotProdVal = _mm_add_epi16(dotProdVal, zVal); + simd_s_t z = srslte_simd_s_mul(a, b); - xPtr ++; - yPtr ++; + simd_dotProdVal = srslte_simd_s_add(simd_dotProdVal, z); + } } - - short dotProdVector[8]; - _mm_store_si128((__m128i*) dotProdVector, dotProdVal); - for (int i=0;i<8;i++) { - result += dotProdVector[i]; + __attribute__ ((aligned (SRSLTE_SIMD_S_SIZE*2))) short dotProdVector[SRSLTE_SIMD_S_SIZE]; + srslte_simd_s_store(dotProdVector, simd_dotProdVal); + for (int k = 0; k < SRSLTE_SIMD_S_SIZE; k++) { + result += dotProdVector[k]; } +#endif /* SRSLTE_SIMD_S_SIZE */ - number = points * 8; - for(;number < len; number++){ - result += (x[number] * y[number]); + for(; i < len; i++){ + result += (x[i] * y[i]); } - -#endif - return result; -} - -int srslte_vec_dot_prod_sss_avx2(short *x, short *y, uint32_t len) -{ - int result = 0; -#ifdef LV_HAVE_AVX2 - unsigned int number = 0; - const unsigned int points = len / 16; - - const __m256i* xPtr = (const __m256i*) x; - const __m256i* yPtr = (const __m256i*) y; - - __m256i dotProdVal = _mm256_setzero_si256(); - - __m256i xVal, yVal, zVal; - for(;number < points; number++){ - - xVal = _mm256_load_si256(xPtr); - yVal = _mm256_loadu_si256(yPtr); - zVal = _mm256_mullo_epi16(xVal, yVal); - dotProdVal = _mm256_add_epi16(dotProdVal, zVal); - xPtr ++; - yPtr ++; - } - - __attribute__ ((aligned (256))) short dotProdVector[16]; - _mm256_store_si256((__m256i*) dotProdVector, dotProdVal); - for (int i=0;i<16;i++) { - result += dotProdVector[i]; - } - - number = points * 16; - for(;number < len; number++){ - result += (x[number] * y[number]); - } - -#endif return result; } +void srslte_vec_sum_sss_simd(int16_t *x, int16_t *y, int16_t *z, int len) { + int i = 0; +#ifdef SRSLTE_SIMD_S_SIZE + if (SRSLTE_IS_ALIGNED(x) && SRSLTE_IS_ALIGNED(y) && SRSLTE_IS_ALIGNED(z)) { + for (; i < len - SRSLTE_SIMD_S_SIZE + 1; i += SRSLTE_SIMD_S_SIZE) { + simd_s_t a = srslte_simd_s_load(&x[i]); + simd_s_t b = srslte_simd_s_load(&y[i]); + simd_s_t r = srslte_simd_s_add(a, b); -void srslte_vec_sum_sss_sse(short *x, short *y, short *z, uint32_t len) -{ -#ifdef LV_HAVE_SSE - unsigned int number = 0; - const unsigned int points = len / 8; - - const __m128i* xPtr = (const __m128i*) x; - const __m128i* yPtr = (const __m128i*) y; - __m128i* zPtr = (__m128i*) z; - - __m128i xVal, yVal, zVal; - for(;number < points; number++){ - - xVal = _mm_load_si128(xPtr); - yVal = _mm_load_si128(yPtr); - - zVal = _mm_add_epi16(xVal, yVal); - - _mm_store_si128(zPtr, zVal); - - xPtr ++; - yPtr ++; - zPtr ++; - } - - number = points * 8; - for(;number < len; number++){ - z[number] = x[number] + y[number]; - } -#endif - -} - -void srslte_vec_sum_sss_avx2(short *x, short *y, short *z, uint32_t len) -{ -#ifdef LV_HAVE_AVX2 - unsigned int number = 0; - const unsigned int points = len / 16; - - const __m256i* xPtr = (const __m256i*) x; - const __m256i* yPtr = (const __m256i*) y; - __m256i* zPtr = (__m256i*) z; - - __m256i xVal, yVal, zVal; - for(;number < points; number++){ - - xVal = _mm256_load_si256(xPtr); - yVal = _mm256_loadu_si256(yPtr); - - zVal = _mm256_add_epi16(xVal, yVal); - _mm256_store_si256(zPtr, zVal); - - xPtr ++; - yPtr ++; - zPtr ++; - } - - number = points * 16; - for(;number < len; number++){ - z[number] = x[number] + y[number]; - } -#endif - -} - - -void srslte_vec_sub_sss_sse(short *x, short *y, short *z, uint32_t len) -{ -#ifdef LV_HAVE_SSE - unsigned int number = 0; - const unsigned int points = len / 8; - - const __m128i* xPtr = (const __m128i*) x; - const __m128i* yPtr = (const __m128i*) y; - __m128i* zPtr = (__m128i*) z; - - __m128i xVal, yVal, zVal; - for(;number < points; number++){ - - xVal = _mm_load_si128(xPtr); - yVal = _mm_load_si128(yPtr); - - zVal = _mm_sub_epi16(xVal, yVal); - - _mm_store_si128(zPtr, zVal); - - xPtr ++; - yPtr ++; - zPtr ++; - } - - number = points * 8; - for(;number < len; number++){ - z[number] = x[number] - y[number]; - } -#endif -} - -void srslte_vec_sub_sss_avx2(short *x, short *y, short *z, uint32_t len) -{ -#ifdef LV_HAVE_AVX2 - unsigned int number = 0; - const unsigned int points = len / 16; - - const __m256i* xPtr = (const __m256i*) x; - const __m256i* yPtr = (const __m256i*) y; - __m256i* zPtr = (__m256i*) z; - - __m256i xVal, yVal, zVal; - for(;number < points; number++){ - - xVal = _mm256_load_si256(xPtr); - yVal = _mm256_loadu_si256(yPtr); - - zVal = _mm256_sub_epi16(xVal, yVal); + srslte_simd_s_store(&z[i], r); + } + } else { + for (; i < len - SRSLTE_SIMD_S_SIZE + 1; i += SRSLTE_SIMD_S_SIZE) { + simd_s_t a = srslte_simd_s_loadu(&x[i]); + simd_s_t b = srslte_simd_s_loadu(&y[i]); - _mm256_store_si256(zPtr, zVal); + simd_s_t r = srslte_simd_s_add(a, b); - xPtr ++; - yPtr ++; - zPtr ++; + srslte_simd_s_storeu(&z[i], r); + } } +#endif /* SRSLTE_SIMD_S_SIZE */ - number = points * 16; - for(;number < len; number++){ - z[number] = x[number] - y[number]; + for(; i < len; i++){ + z[i] = x[i] + y[i]; } - #endif } +void srslte_vec_sub_sss_simd(int16_t *x, int16_t *y, int16_t *z, int len) { + int i = 0; +#ifdef SRSLTE_SIMD_S_SIZE + if (SRSLTE_IS_ALIGNED(x) && SRSLTE_IS_ALIGNED(y) && SRSLTE_IS_ALIGNED(z)) { + for (; i < len - SRSLTE_SIMD_S_SIZE + 1; i += SRSLTE_SIMD_S_SIZE) { + simd_s_t a = srslte_simd_s_load(&x[i]); + simd_s_t b = srslte_simd_s_load(&y[i]); + simd_s_t r = srslte_simd_s_sub(a, b); + srslte_simd_s_store(&z[i], r); + } + } else { + for (; i < len - SRSLTE_SIMD_S_SIZE + 1; i += SRSLTE_SIMD_S_SIZE) { + simd_s_t a = srslte_simd_s_loadu(&x[i]); + simd_s_t b = srslte_simd_s_loadu(&y[i]); -void srslte_vec_prod_sss_sse(short *x, short *y, short *z, uint32_t len) -{ -#ifdef LV_HAVE_SSE - unsigned int number = 0; - const unsigned int points = len / 8; - - const __m128i* xPtr = (const __m128i*) x; - const __m128i* yPtr = (const __m128i*) y; - __m128i* zPtr = (__m128i*) z; - - __m128i xVal, yVal, zVal; - for(;number < points; number++){ - - xVal = _mm_load_si128(xPtr); - yVal = _mm_load_si128(yPtr); - - zVal = _mm_mullo_epi16(xVal, yVal); - - _mm_store_si128(zPtr, zVal); + simd_s_t r = srslte_simd_s_sub(a, b); - xPtr ++; - yPtr ++; - zPtr ++; + srslte_simd_s_storeu(&z[i], r); + } } +#endif /* SRSLTE_SIMD_S_SIZE */ - number = points * 8; - for(;number < len; number++){ - z[number] = x[number] * y[number]; + for(; i < len; i++){ + z[i] = x[i] - y[i]; } -#endif } -void srslte_vec_prod_sss_avx2(short *x, short *y, short *z, uint32_t len) -{ -#ifdef LV_HAVE_AVX2 - unsigned int number = 0; - const unsigned int points = len / 16; - - const __m256i* xPtr = (const __m256i*) x; - const __m256i* yPtr = (const __m256i*) y; - __m256i* zPtr = (__m256i*) z; +void srslte_vec_prod_sss_simd(int16_t *x, int16_t *y, int16_t *z, int len) { + int i = 0; +#ifdef SRSLTE_SIMD_S_SIZE + if (SRSLTE_IS_ALIGNED(x) && SRSLTE_IS_ALIGNED(y) && SRSLTE_IS_ALIGNED(z)) { + for (; i < len - SRSLTE_SIMD_S_SIZE + 1; i += SRSLTE_SIMD_S_SIZE) { + simd_s_t a = srslte_simd_s_load(&x[i]); + simd_s_t b = srslte_simd_s_load(&y[i]); - __m256i xVal, yVal, zVal; - for(;number < points; number++){ - - xVal = _mm256_loadu_si256(xPtr); - yVal = _mm256_loadu_si256(yPtr); + simd_s_t r = srslte_simd_s_mul(a, b); - zVal = _mm256_mullo_epi16(xVal, yVal); + srslte_simd_s_store(&z[i], r); + } + } else { + for (; i < len - SRSLTE_SIMD_S_SIZE + 1; i += SRSLTE_SIMD_S_SIZE) { + simd_s_t a = srslte_simd_s_loadu(&x[i]); + simd_s_t b = srslte_simd_s_loadu(&y[i]); - _mm256_storeu_si256(zPtr, zVal); + simd_s_t r = srslte_simd_s_mul(a, b); - xPtr ++; - yPtr ++; - zPtr ++; + srslte_simd_s_storeu(&z[i], r); + } } +#endif /* SRSLTE_SIMD_S_SIZE */ - number = points * 16; - for(;number < len; number++){ - z[number] = x[number] * y[number]; + for(; i < len; i++){ + z[i] = x[i] * y[i]; } -#endif } - - +#warning remove function if it is not used +/* void srslte_vec_sc_div2_sss_sse(short *x, int k, short *z, uint32_t len) { #ifdef LV_HAVE_SSE @@ -357,8 +195,10 @@ void srslte_vec_sc_div2_sss_sse(short *x, int k, short *z, uint32_t len) z[number] = x[number] / divn; } #endif -} +}*/ +#warning remove function if it is not used +/* void srslte_vec_sc_div2_sss_avx2(short *x, int k, short *z, uint32_t len) { #ifdef LV_HAVE_AVX2 @@ -387,7 +227,7 @@ void srslte_vec_sc_div2_sss_avx2(short *x, int k, short *z, uint32_t len) z[number] = x[number] / divn; } #endif -} +}*/ @@ -531,379 +371,527 @@ void srslte_vec_sum_fff_avx(float *x, float *y, float *z, uint32_t len) { #endif } -void srslte_vec_sub_fff_sse(float *x, float *y, float *z, uint32_t len) { -#ifdef LV_HAVE_SSE - unsigned int number = 0; - const unsigned int points = len / 4; +cf_t srslte_vec_acc_cc_simd(cf_t *x, int len) { + int i = 0; + cf_t acc_sum = 0.0f; - const float* xPtr = (const float*) x; - const float* yPtr = (const float*) y; - float* zPtr = (float*) z; +#if SRSLTE_SIMD_F_SIZE + simd_f_t simd_sum = srslte_simd_f_zero(); - __m128 xVal, yVal, zVal; - for(;number < points; number++){ + if (SRSLTE_IS_ALIGNED(x)) { + for (; i < len - SRSLTE_SIMD_F_SIZE / 2 + 1; i += SRSLTE_SIMD_F_SIZE / 2) { + simd_f_t a = srslte_simd_f_load((float *) &x[i]); - xVal = _mm_loadu_ps(xPtr); - yVal = _mm_loadu_ps(yPtr); + simd_sum = srslte_simd_f_add(simd_sum, a); + } + } else { + for (; i < len - SRSLTE_SIMD_F_SIZE / 2 + 1; i += SRSLTE_SIMD_F_SIZE / 2) { + simd_f_t a = srslte_simd_f_loadu((float *) &x[i]); - zVal = _mm_sub_ps(xVal, yVal); + simd_sum = srslte_simd_f_add(simd_sum, a); + } + } - _mm_storeu_ps(zPtr, zVal); + __attribute__((aligned(64))) cf_t sum[SRSLTE_SIMD_F_SIZE/2]; + srslte_simd_f_store((float*)&sum, simd_sum); + for (int k = 0; k < SRSLTE_SIMD_F_SIZE/2; k++) { + acc_sum += sum[k]; + } +#endif - xPtr += 4; - yPtr += 4; - zPtr += 4; + for (; i Date: Mon, 25 Sep 2017 17:08:11 +0200 Subject: [PATCH 024/242] Solved bugs and compilation error in simd and vector_simd --- lib/include/srslte/phy/utils/simd.h | 20 ++++++++++---------- lib/include/srslte/phy/utils/vector_simd.h | 2 +- lib/src/phy/utils/test/vector_test.c | 8 ++++---- lib/src/phy/utils/vector_simd.c | 10 +++++----- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/lib/include/srslte/phy/utils/simd.h b/lib/include/srslte/phy/utils/simd.h index 774dd54bd..22d8db79d 100644 --- a/lib/include/srslte/phy/utils/simd.h +++ b/lib/include/srslte/phy/utils/simd.h @@ -226,7 +226,7 @@ static inline simd_f_t srslte_simd_f_mul(simd_f_t a, simd_f_t b) { static inline simd_f_t srslte_simd_f_addsub(simd_f_t a, simd_f_t b) { #ifdef LV_HAVE_AVX512 __m512 r = _mm512_add_ps(a, b); - return _mm512_mask_sub_ps(r, 0b1010101010101010, a, b); + return _mm512_mask_sub_ps(r, 0b0101010101010101, a, b); #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_AVX2 return _mm256_addsub_ps(a, b); @@ -642,10 +642,10 @@ static inline simd_s_t srslte_simd_s_load(int16_t *ptr) { return _mm512_load_si512(ptr); #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_AVX2 - return _mm256_load_si256(ptr); + return _mm256_load_si256((__m256i*) ptr); #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE - return _mm_load_si128(ptr); + return _mm_load_si128((__m128i*) ptr); #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -653,13 +653,13 @@ static inline simd_s_t srslte_simd_s_load(int16_t *ptr) { static inline simd_s_t srslte_simd_s_loadu(int16_t *ptr) { #ifdef LV_HAVE_AVX512 - return _mm512_load_si512(ptr); + return _mm512_loadu_si512(ptr); #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_AVX2 - return _mm256_load_si256(ptr); + return _mm256_loadu_si256((__m256i*) ptr); #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE - return _mm_load_si128(ptr); + return _mm_loadu_si128((__m128i*) ptr); #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -670,10 +670,10 @@ static inline void srslte_simd_s_store(int16_t *ptr, simd_s_t simdreg) { _mm512_store_si512(ptr, simdreg); #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_AVX2 - _mm256_store_si256(ptr, simdreg); + _mm256_store_si256((__m256i*) ptr, simdreg); #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE - _mm_store_si128(ptr, simdreg); + _mm_store_si128((__m128i*) ptr, simdreg); #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -684,10 +684,10 @@ static inline void srslte_simd_s_storeu(int16_t *ptr, simd_s_t simdreg) { _mm512_storeu_si512(ptr, simdreg); #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_AVX2 - _mm256_storeu_si256(ptr, simdreg); + _mm256_storeu_si256((__m256i*) ptr, simdreg); #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE - _mm_storeu_si128(ptr, simdreg); + _mm_storeu_si128((__m128i*) ptr, simdreg); #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ diff --git a/lib/include/srslte/phy/utils/vector_simd.h b/lib/include/srslte/phy/utils/vector_simd.h index 8ea2ce9bc..4ee839fab 100644 --- a/lib/include/srslte/phy/utils/vector_simd.h +++ b/lib/include/srslte/phy/utils/vector_simd.h @@ -44,7 +44,7 @@ extern "C" { #ifdef LV_HAVE_SSE #define SRSLTE_IS_ALIGNED(PTR) (((size_t)(PTR) & 0x0F) == 0) #else /* LV_HAVE_SSE */ -#define SRSLTE_IS_ALIGNED(PTR) (true) +#define SRSLTE_IS_ALIGNED(PTR) (1) #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX */ #endif /* LV_HAVE_AVX512 */ diff --git a/lib/src/phy/utils/test/vector_test.c b/lib/src/phy/utils/test/vector_test.c index e781d05b9..05dce1d35 100644 --- a/lib/src/phy/utils/test/vector_test.c +++ b/lib/src/phy/utils/test/vector_test.c @@ -45,7 +45,7 @@ bool mmse_solver = false; bool verbose = false; #define MAX_MSE (1e-3) -#define NOF_REPETITIONS (1024*128) +#define NOF_REPETITIONS (1024) #define MAX_FUNCTIONS (64) #define MAX_BLOCKS (16) @@ -70,7 +70,7 @@ bool verbose = false; return passed;\ } -#define MALLOC(TYPE, NAME) TYPE *NAME = srslte_vec_malloc(sizeof(TYPE)*block_size) +#define MALLOC(TYPE, NAME) TYPE *NAME = malloc(sizeof(TYPE)*block_size) static double elapsed_us(struct timeval *ts_start, struct timeval *ts_end) { @@ -339,7 +339,7 @@ TEST(srslte_vec_prod_conj_ccc, TEST(srslte_vec_sc_prod_ccc, MALLOC(cf_t, x); MALLOC(cf_t, z); - cf_t y = RANDOM_F(); + cf_t y = RANDOM_CF(); cf_t gold; for (int i = 0; i < block_size; i++) { @@ -469,7 +469,7 @@ int main(int argc, char **argv) { uint32_t func_count = 0; bool passed = true; - for (uint32_t block_size = 1; block_size <= 1024*16; block_size *= 2) { + for (uint32_t block_size = 1; block_size <= 1024*8; block_size *= 2) { func_count = 0; passed &= test_srslte_vec_dot_prod_sss(func_names[func_count], &timmings[func_count][size_count], block_size); diff --git a/lib/src/phy/utils/vector_simd.c b/lib/src/phy/utils/vector_simd.c index 21132390f..2eb0428b7 100644 --- a/lib/src/phy/utils/vector_simd.c +++ b/lib/src/phy/utils/vector_simd.c @@ -77,7 +77,7 @@ int srslte_vec_dot_prod_sss_simd(int16_t *x, int16_t *y, int len) { void srslte_vec_sum_sss_simd(int16_t *x, int16_t *y, int16_t *z, int len) { int i = 0; -#ifdef SRSLTE_SIMD_S_SIZE +#if SRSLTE_SIMD_S_SIZE if (SRSLTE_IS_ALIGNED(x) && SRSLTE_IS_ALIGNED(y) && SRSLTE_IS_ALIGNED(z)) { for (; i < len - SRSLTE_SIMD_S_SIZE + 1; i += SRSLTE_SIMD_S_SIZE) { simd_s_t a = srslte_simd_s_load(&x[i]); @@ -106,7 +106,7 @@ void srslte_vec_sum_sss_simd(int16_t *x, int16_t *y, int16_t *z, int len) { void srslte_vec_sub_sss_simd(int16_t *x, int16_t *y, int16_t *z, int len) { int i = 0; -#ifdef SRSLTE_SIMD_S_SIZE +#if SRSLTE_SIMD_S_SIZE if (SRSLTE_IS_ALIGNED(x) && SRSLTE_IS_ALIGNED(y) && SRSLTE_IS_ALIGNED(z)) { for (; i < len - SRSLTE_SIMD_S_SIZE + 1; i += SRSLTE_SIMD_S_SIZE) { simd_s_t a = srslte_simd_s_load(&x[i]); @@ -135,7 +135,7 @@ void srslte_vec_sub_sss_simd(int16_t *x, int16_t *y, int16_t *z, int len) { void srslte_vec_prod_sss_simd(int16_t *x, int16_t *y, int16_t *z, int len) { int i = 0; -#ifdef SRSLTE_SIMD_S_SIZE +#if SRSLTE_SIMD_S_SIZE if (SRSLTE_IS_ALIGNED(x) && SRSLTE_IS_ALIGNED(y) && SRSLTE_IS_ALIGNED(z)) { for (; i < len - SRSLTE_SIMD_S_SIZE + 1; i += SRSLTE_SIMD_S_SIZE) { simd_s_t a = srslte_simd_s_load(&x[i]); @@ -721,14 +721,14 @@ void srslte_vec_sc_prod_ccc_simd(cf_t *x, cf_t h, cf_t *z, int len) { } } else { for (; i < len - SRSLTE_SIMD_F_SIZE / 2 + 1; i += SRSLTE_SIMD_F_SIZE / 2) { - simd_f_t temp = srslte_simd_f_load((float *) &x[i]); + simd_f_t temp = srslte_simd_f_loadu((float *) &x[i]); simd_f_t m1 = srslte_simd_f_mul(hre, temp); simd_f_t sw = srslte_simd_f_swap(temp); simd_f_t m2 = srslte_simd_f_mul(him, sw); simd_f_t r = srslte_simd_f_addsub(m1, m2); - srslte_simd_f_store((float *) &z[i], r); + srslte_simd_f_storeu((float *) &z[i], r); } } #endif From 9e5f999666a97b82fa0558b28294a7b9f62becbf Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 28 Sep 2017 11:04:26 +0200 Subject: [PATCH 025/242] Added more functions --- lib/include/srslte/phy/utils/simd.h | 237 ++++++++++ lib/include/srslte/phy/utils/vector.h | 5 +- lib/include/srslte/phy/utils/vector_simd.h | 59 +-- lib/src/phy/mimo/precoding.c | 3 +- lib/src/phy/sync/find_sss.c | 8 +- lib/src/phy/utils/test/CMakeLists.txt | 3 +- lib/src/phy/utils/test/vector_test.c | 287 +++++++++++- lib/src/phy/utils/vector.c | 134 +----- lib/src/phy/utils/vector_simd.c | 487 ++++++++++++++++----- 9 files changed, 934 insertions(+), 289 deletions(-) diff --git a/lib/include/srslte/phy/utils/simd.h b/lib/include/srslte/phy/utils/simd.h index 22d8db79d..9a5f15dbb 100644 --- a/lib/include/srslte/phy/utils/simd.h +++ b/lib/include/srslte/phy/utils/simd.h @@ -88,6 +88,8 @@ #define SRSLTE_SIMD_F_SIZE 16 #define SRSLTE_SIMD_CF_SIZE 16 +#define SRSLTE_SIMD_I_SIZE 16 + #define SRSLTE_SIMD_S_SIZE 32 #define SRSLTE_SIMD_C16_SIZE 0 @@ -97,6 +99,8 @@ #define SRSLTE_SIMD_F_SIZE 8 #define SRSLTE_SIMD_CF_SIZE 8 +#define SRSLTE_SIMD_I_SIZE 8 + #define SRSLTE_SIMD_S_SIZE 16 #define SRSLTE_SIMD_C16_SIZE 16 @@ -106,6 +110,8 @@ #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 @@ -114,6 +120,8 @@ #define SRSLTE_SIMD_F_SIZE 0 #define SRSLTE_SIMD_CF_SIZE 0 +#define SRSLTE_SIMD_I_SIZE 0 + #define SRSLTE_SIMD_S_SIZE 0 #define SRSLTE_SIMD_C16_SIZE 0 @@ -223,6 +231,20 @@ static inline simd_f_t srslte_simd_f_mul(simd_f_t a, simd_f_t b) { #endif /* LV_HAVE_AVX512 */ } +static inline simd_f_t srslte_simd_f_rcp(simd_f_t a) { +#ifdef LV_HAVE_AVX512 + return _mm512_rcp_ps(a); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_rcp_ps(a); +#else /* LV_HAVE_AVX2 */ + #ifdef LV_HAVE_SSE + return _mm_rcp_ps(a); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + static inline simd_f_t srslte_simd_f_addsub(simd_f_t a, simd_f_t b) { #ifdef LV_HAVE_AVX512 __m512 r = _mm512_add_ps(a, b); @@ -600,6 +622,61 @@ static inline simd_cf_t srslte_simd_cf_add (simd_cf_t a, simd_cf_t b) { return ret; } +static inline simd_cf_t srslte_simd_cf_mul (simd_cf_t a, simd_f_t b) { + simd_cf_t ret; +#ifdef LV_HAVE_AVX512 + b = _mm512_permutexvar_ps(b, _mm512_setr_epi32(0,4,1,5,2,6,3,7,8,12,9,13,10,14,11,15)); + ret.re = _mm512_mul_ps(a.re, b); + ret.im = _mm512_mul_ps(a.im, b); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + b = _mm256_permutevar8x32_ps(b, _mm256_setr_epi32(0,4,1,5,2,6,3,7)); + ret.re = _mm256_mul_ps(a.re, b); + ret.im = _mm256_mul_ps(a.im, b); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + ret.re = _mm_mul_ps(a.re, b); + ret.im = _mm_mul_ps(a.im, b); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ + return ret; +} + +static inline simd_cf_t srslte_simd_cf_rcp (simd_cf_t a) { + simd_cf_t ret; +#ifdef LV_HAVE_AVX512 + simd_f_t a2re = _mm512_mul_ps(a.re, a.re); + simd_f_t a2im = _mm512_mul_ps(a.im, a.im); + simd_f_t mod2 = _mm512_add_ps(a2re, a2im); + simd_f_t rcp = _mm512_rcp_ps(mod2); + simd_f_t neg_a_im = _mm512_xor_ps(_mm512_set1_ps(-0.0f), a.im); + ret.re = _mm512_mul_ps(a.re, rcp); + ret.im = _mm512_mul_ps(neg_a_im, rcp); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + simd_f_t a2re = _mm256_mul_ps(a.re, a.re); + simd_f_t a2im = _mm256_mul_ps(a.im, a.im); + simd_f_t mod2 = _mm256_add_ps(a2re, a2im); + simd_f_t rcp = _mm256_rcp_ps(mod2); + simd_f_t neg_a_im = _mm256_xor_ps(_mm256_set1_ps(-0.0f), a.im); + ret.re = _mm256_mul_ps(a.re, rcp); + ret.im = _mm256_mul_ps(neg_a_im, rcp); +#else /* LV_HAVE_AVX2 */ + #ifdef LV_HAVE_SSE + simd_f_t a2re = _mm_mul_ps(a.re, a.re); + simd_f_t a2im = _mm_mul_ps(a.im, a.im); + simd_f_t mod2 = _mm_add_ps(a2re, a2im); + simd_f_t rcp = _mm_rcp_ps(mod2); + 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); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ + return ret; +} + static inline simd_cf_t srslte_simd_cf_zero (void) { simd_cf_t ret; #ifdef LV_HAVE_AVX512 @@ -621,6 +698,106 @@ static inline simd_cf_t srslte_simd_cf_zero (void) { #endif /* SRSLTE_SIMD_CF_SIZE */ +#if SRSLTE_SIMD_I_SIZE + +#ifdef LV_HAVE_AVX512 +typedef __m512i simd_i_t; +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 +typedef __m256i simd_i_t; +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE +typedef __m128i simd_i_t; +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ + +static inline simd_i_t srslte_simd_i_load(int *x) { +#ifdef LV_HAVE_AVX512 + return _mm512_load_epi32((__m512i*)x); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_load_si256((__m256i*)x); +#else + #ifdef LV_HAVE_SSE + return _mm_load_si128((__m128i*)x); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline void srslte_simd_i_store(int *x, simd_i_t reg) { +#ifdef LV_HAVE_AVX512 + _mm512_store_epi32((__m512i*)x, reg); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + _mm256_store_si256((__m256i*)x, reg); +#else +#ifdef LV_HAVE_SSE + _mm_store_si128((__m128i*)x, reg); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline simd_i_t srslte_simd_i_set1(int x) { +#ifdef LV_HAVE_AVX512 + return _mm512_set1_epi32(x); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_set1_epi32(x); +#else + #ifdef LV_HAVE_SSE + return _mm_set1_epi32(x); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline simd_i_t srslte_simd_i_add(simd_i_t a, simd_i_t b) { +#ifdef LV_HAVE_AVX512 + return _mm512_add_epi32(a, b); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_add_epi32(a, b); +#else +#ifdef LV_HAVE_SSE + return _mm_add_epi32(a, b); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline simd_i_t srslte_simd_f_max(simd_f_t a, simd_f_t b) { +#ifdef LV_HAVE_AVX512 + return (simd_i_t) _mm512_cmp_ps_mask(a, b, _CMP_GT_OS); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return (simd_i_t) _mm256_cmp_ps(a, b, _CMP_GT_OS); +#else /* LV_HAVE_AVX2 */ + #ifdef LV_HAVE_SSE + return (simd_i_t) _mm_cmpgt_ps(a, b); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline simd_i_t srslte_simd_i_select(simd_i_t a, simd_i_t b, simd_i_t selector) { +#ifdef LV_HAVE_AVX512 + return (__m512i) _mm512_blendv_ps((__m512)a, (__m512) b, (__m512) selector); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return (__m256i) _mm256_blendv_ps((__m256) a,(__m256) b,(__m256) selector); +#else + #ifdef LV_HAVE_SSE + return (__m128i) _mm_blendv_ps((__m128)a, (__m128)b, (__m128)selector); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +#endif /* SRSLTE_SIMD_I_SIZE*/ + #if SRSLTE_SIMD_S_SIZE @@ -829,6 +1006,20 @@ static inline simd_c16_t srslte_simd_c16_load(int16_t *re, int16_t *im) { return ret; } +static inline simd_c16_t srslte_simd_c16_loadu(int16_t *re, int16_t *im) { + simd_c16_t ret; +#ifdef LV_HAVE_AVX2 + ret.re.m256 = _mm256_loadu_si256((__m256i*)(re)); + ret.im.m256 = _mm256_loadu_si256((__m256i*)(im)); +#else +#ifdef LV_HAVE_SSE + ret.re.m128 = _mm_loadu_si128((__m128i*)(re)); + ret.im.m128 = _mm_loadu_si128((__m128i*)(im)); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ + return ret; +} + static inline void srslte_simd_c16i_store(c16_t *ptr, simd_c16_t simdreg) { #ifdef LV_HAVE_AVX2 __m256i re_sw = _mm256_shufflelo_epi16(_mm256_shufflehi_epi16(simdreg.re.m256, 0b10110001), 0b10110001); @@ -845,6 +1036,22 @@ static inline void srslte_simd_c16i_store(c16_t *ptr, simd_c16_t simdreg) { #endif /* LV_HAVE_AVX2 */ } +static inline void srslte_simd_c16i_storeu(c16_t *ptr, simd_c16_t simdreg) { +#ifdef LV_HAVE_AVX2 + __m256i re_sw = _mm256_shufflelo_epi16(_mm256_shufflehi_epi16(simdreg.re.m256, 0b10110001), 0b10110001); + __m256i im_sw = _mm256_shufflelo_epi16(_mm256_shufflehi_epi16(simdreg.im.m256, 0b10110001), 0b10110001); + _mm256_storeu_si256((__m256i *) (ptr), _mm256_blend_epi16(simdreg.re.m256, im_sw, 0b10101010)); + _mm256_storeu_si256((__m256i *) (ptr + 8), _mm256_blend_epi16(re_sw, simdreg.im.m256, 0b10101010)); +#else +#ifdef LV_HAVE_SSE + __m128i re_sw = _mm_shufflelo_epi16(_mm_shufflehi_epi16(simdreg.re.m128, 0b10110001), 0b10110001); + __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)); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +} + static inline void srslte_simd_c16_store(int16_t *re, int16_t *im, simd_c16_t simdreg) { #ifdef LV_HAVE_AVX2 _mm256_store_si256((__m256i *) re, simdreg.re.m256); @@ -857,6 +1064,18 @@ static inline void srslte_simd_c16_store(int16_t *re, int16_t *im, simd_c16_t si #endif /* LV_HAVE_AVX2 */ } +static inline void srslte_simd_c16_storeu(int16_t *re, int16_t *im, simd_c16_t simdreg) { +#ifdef LV_HAVE_AVX2 + _mm256_storeu_si256((__m256i *) re, simdreg.re.m256); + _mm256_storeu_si256((__m256i *) im, simdreg.im.m256); +#else +#ifdef LV_HAVE_SSE + _mm_storeu_si128((__m128i *) re, simdreg.re.m128); + _mm_storeu_si128((__m128i *) im, simdreg.im.m128); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +} + static inline simd_c16_t srslte_simd_c16_prod (simd_c16_t a, simd_c16_t b) { simd_c16_t ret; #ifdef LV_HAVE_AVX2 @@ -905,6 +1124,24 @@ static inline simd_c16_t srslte_simd_c16_zero (void) { #endif /* SRSLTE_SIMD_C16_SIZE */ +#if SRSLTE_SIMD_F_SIZE && SRSLTE_SIMD_S_SIZE + +static inline simd_s_t srslte_simd_convert_2f_s(simd_f_t a, simd_f_t b) { +#ifdef LV_HAVE_AVX2 + __m256 aa = _mm256_permute2f128_ps(a, b, 0x20); + __m256 bb = _mm256_permute2f128_ps(a, b, 0x31); + __m256i ai = _mm256_cvttps_epi32(aa); + __m256i bi = _mm256_cvttps_epi32(bb); + return _mm256_packs_epi32(ai, bi); +#else +#ifdef LV_HAVE_SSE + __m128i ai = _mm_cvttps_epi32(a); + __m128i bi = _mm_cvttps_epi32(b); + return _mm_packs_epi32(ai, bi); +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +} +#endif /* SRSLTE_SIMD_F_SIZE && SRSLTE_SIMD_C16_SIZE */ #endif //SRSLTE_SIMD_H_H diff --git a/lib/include/srslte/phy/utils/vector.h b/lib/include/srslte/phy/utils/vector.h index 0fadfb334..9b99c6fff 100644 --- a/lib/include/srslte/phy/utils/vector.h +++ b/lib/include/srslte/phy/utils/vector.h @@ -123,6 +123,7 @@ SRSLTE_API void srslte_vec_interleave_cf(float *real, float *imag, cf_t *x, uint /* vector product (element-wise) */ SRSLTE_API void srslte_vec_prod_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len); +SRSLTE_API void srslte_vec_prod_ccc_split(float *x_re, float *x_im, float *y_re, float *y_im, float *z_re, float *z_im, uint32_t len); /* vector product (element-wise) */ SRSLTE_API void srslte_vec_prod_cfc(cf_t *x, float *y, cf_t *z, uint32_t len); @@ -142,8 +143,8 @@ SRSLTE_API float srslte_vec_dot_prod_fff(float *x, float *y, uint32_t len); SRSLTE_API int32_t srslte_vec_dot_prod_sss(int16_t *x, int16_t *y, uint32_t len); /* z=x/y vector division (element-wise) */ -SRSLTE_API void srslte_vec_div_ccc(cf_t *x, cf_t *y, float *y_mod, cf_t *z, float *z_real, float *z_imag, uint32_t len); -void srslte_vec_div_cfc(cf_t *x, float *y, cf_t *z, float *z_real, float *z_imag, uint32_t len); +SRSLTE_API void srslte_vec_div_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len); +SRSLTE_API void srslte_vec_div_cfc(cf_t *x, float *y, cf_t *z, uint32_t len); SRSLTE_API void srslte_vec_div_fff(float *x, float *y, float *z, uint32_t len); /* conjugate */ diff --git a/lib/include/srslte/phy/utils/vector_simd.h b/lib/include/srslte/phy/utils/vector_simd.h index 4ee839fab..294cff50f 100644 --- a/lib/include/srslte/phy/utils/vector_simd.h +++ b/lib/include/srslte/phy/utils/vector_simd.h @@ -36,26 +36,29 @@ extern "C" { #include "srslte/config.h" #ifdef LV_HAVE_AVX512 +#define SRSLTE_SIMD_BIT_ALIGN 512 #define SRSLTE_IS_ALIGNED(PTR) (((size_t)(PTR) & 0x3F) == 0) #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_AVX +#define SRSLTE_SIMD_BIT_ALIGN 256 #define SRSLTE_IS_ALIGNED(PTR) (((size_t)(PTR) & 0x1F) == 0) #else /* LV_HAVE_AVX */ #ifdef LV_HAVE_SSE +#define SRSLTE_SIMD_BIT_ALIGN 128 #define SRSLTE_IS_ALIGNED(PTR) (((size_t)(PTR) & 0x0F) == 0) #else /* LV_HAVE_SSE */ +#define SRSLTE_SIMD_BIT_ALIGN 64 #define SRSLTE_IS_ALIGNED(PTR) (1) #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX */ #endif /* LV_HAVE_AVX512 */ -SRSLTE_API int srslte_vec_dot_prod_sss_simd(int16_t *x, int16_t *y, int len); - +/* SIMD Basic vector math */ SRSLTE_API void srslte_vec_sum_sss_simd(int16_t *x, int16_t *y, int16_t *z, int len); SRSLTE_API void srslte_vec_sub_sss_simd(int16_t *x, int16_t *y, int16_t *z, int len); -SRSLTE_API void srslte_vec_sub_sss_avx2(short *x, short *y, short *z, uint32_t len); +SRSLTE_API float srslte_vec_acc_ff_simd(float *x, int len); SRSLTE_API cf_t srslte_vec_acc_cc_simd(cf_t *x, int len); @@ -63,58 +66,62 @@ SRSLTE_API void srslte_vec_add_fff_simd(float *x, float *y, float *z, int len); SRSLTE_API void srslte_vec_sub_fff_simd(float *x, float *y, float *z, int len); +/* SIMD Vector Scalar Product */ +SRSLTE_API void srslte_vec_sc_prod_cfc_simd(const cf_t *x,const float h,cf_t *y,const int len); + SRSLTE_API void srslte_vec_sc_prod_fff_simd(float *x, float h, float *z, int len); SRSLTE_API void srslte_vec_sc_prod_ccc_simd(cf_t *x, cf_t h, cf_t *z, int len); +/* SIMD Vector Product */ +SRSLTE_API void srslte_vec_prod_ccc_split_simd(float *a_re, float *a_im, float *b_re, float *b_im, float *r_re, float *r_im, int len); + +SRSLTE_API void srslte_vec_prod_ccc_c16_simd(int16_t *a_re, int16_t *a_im, int16_t *b_re, int16_t *b_im, int16_t *r_re, + int16_t *r_im, int len); + +SRSLTE_API void srslte_vec_prod_sss_simd(int16_t *x, int16_t *y, int16_t *z, int len); + +SRSLTE_API void srslte_vec_prod_cfc_simd(cf_t *x, float *y, cf_t *z, int len); + SRSLTE_API void srslte_vec_prod_fff_simd(float *x, float *y, float *z, int len); SRSLTE_API void srslte_vec_prod_ccc_simd(cf_t *x,cf_t *y, cf_t *z, int len); SRSLTE_API void srslte_vec_prod_conj_ccc_simd(cf_t *x,cf_t *y, cf_t *z, int len); -SRSLTE_API void srslte_vec_prod_ccc_cf_simd(float *a_re, float *a_im, float *b_re, float *b_im, float *r_re, float *r_im, int len); +/* SIMD Division */ +SRSLTE_API void srslte_vec_div_ccc_simd(cf_t *x,cf_t *y, cf_t *z, int len); -SRSLTE_API void srslte_vec_prod_ccc_c16_simd(int16_t *a_re, int16_t *a_im, int16_t *b_re, int16_t *b_im, int16_t *r_re, - int16_t *r_im, int len); +SRSLTE_API void srslte_vec_div_cfc_simd(cf_t *x, float *y, cf_t *z, int len); -SRSLTE_API void srslte_vec_prod_sss_simd(int16_t *x, int16_t *y, int16_t *z, int len); +SRSLTE_API void srslte_vec_div_fff_simd(float *x, float *y, float *z, int len); +/* SIMD Dot product */ SRSLTE_API cf_t srslte_vec_dot_prod_conj_ccc_simd(cf_t *x, cf_t *y, int len); SRSLTE_API cf_t srslte_vec_dot_prod_ccc_simd(cf_t *x, cf_t *y, int len); -SRSLTE_API cf_t srslte_vec_dot_prod_ccc_sse(cf_t *x, cf_t *y, uint32_t len); - SRSLTE_API c16_t srslte_vec_dot_prod_ccc_c16i_simd(c16_t *x, c16_t *y, int len); -SRSLTE_API void srslte_vec_sc_div2_sss_avx2(short *x, int k, short *z, uint32_t len); +SRSLTE_API int srslte_vec_dot_prod_sss_simd(int16_t *x, int16_t *y, int len); +/* SIMD Modulus functions */ SRSLTE_API void srslte_vec_abs_cf_simd(cf_t *x, float *z, int len); SRSLTE_API void srslte_vec_abs_square_cf_simd(cf_t *x, float *z, int len); -SRSLTE_API void srslte_vec_prod_sss_sse(short *x, short *y, short *z, uint32_t len); - -SRSLTE_API void srslte_vec_prod_sss_avx(short *x, short *y, short *z, uint32_t len); - -SRSLTE_API void srslte_vec_sc_div2_sss_sse(short *x, int n_rightshift, short *z, uint32_t len); +/* Other Functions */ +SRSLTE_API void srslte_vec_lut_sss_simd(short *x, unsigned short *lut, short *y, int len); -SRSLTE_API void srslte_vec_sc_div2_sss_avx(short *x, int k, short *z, uint32_t len); +SRSLTE_API void srslte_vec_convert_fi_simd(float *x, int16_t *z, float scale, int len); -SRSLTE_API void srslte_vec_lut_sss_sse(short *x, unsigned short *lut, short *y, uint32_t len); - -SRSLTE_API void srslte_vec_convert_fi_sse(float *x, int16_t *z, float scale, uint32_t len); - -SRSLTE_API void srslte_vec_mult_scalar_cf_f_avx( cf_t *z,const cf_t *x,const float h,const uint32_t len); - -SRSLTE_API void srslte_vec_lut_sss_sse(short *x, unsigned short *lut, short *y, uint32_t len); +SRSLTE_API void srslte_vec_cp_simd(cf_t *src, cf_t *dst, int len); -SRSLTE_API void srslte_vec_convert_fi_sse(float *x, int16_t *z, float scale, uint32_t len); -SRSLTE_API void srslte_vec_sc_prod_cfc_simd(const cf_t *x,const float h,cf_t *y,const int len); +/* SIMD Find Max functions */ +SRSLTE_API uint32_t srslte_vec_max_fi_simd(float *x, int len); -SRSLTE_API void srslte_vec_cp_simd(cf_t *src, cf_t *dst, int len); +SRSLTE_API uint32_t srslte_vec_max_ci_simd(cf_t *x, int len); #ifdef __cplusplus } diff --git a/lib/src/phy/mimo/precoding.c b/lib/src/phy/mimo/precoding.c index f1aab3b5d..8f8bd7737 100644 --- a/lib/src/phy/mimo/precoding.c +++ b/lib/src/phy/mimo/precoding.c @@ -36,17 +36,16 @@ #ifdef LV_HAVE_SSE #include -#include "srslte/phy/utils/mat.h" int srslte_predecoding_single_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, int nof_rxant, int nof_symbols, float noise_estimate); int srslte_predecoding_diversity2_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], int nof_rxant, int nof_symbols); #endif #ifdef LV_HAVE_AVX #include -#include "srslte/phy/utils/mat.h" int srslte_predecoding_single_avx(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, int nof_rxant, int nof_symbols, float noise_estimate); #endif +#include "srslte/phy/utils/mat.h" static srslte_mimo_decoder_t mimo_decoder = SRSLTE_MIMO_DECODER_MMSE; diff --git a/lib/src/phy/sync/find_sss.c b/lib/src/phy/sync/find_sss.c index 2afeced42..082aee52a 100644 --- a/lib/src/phy/sync/find_sss.c +++ b/lib/src/phy/sync/find_sss.c @@ -70,14 +70,12 @@ static void corr_all_sz_partial(cf_t z[SRSLTE_SSS_N], float s[SRSLTE_SSS_N][SRSL static void extract_pair_sss(srslte_sss_synch_t *q, cf_t *input, cf_t *ce, cf_t y[2][SRSLTE_SSS_N]) { cf_t input_fft[SRSLTE_SYMBOL_SZ_MAX]; - float ce_mod[2*SRSLTE_SSS_N], z_real[2*SRSLTE_SSS_N], z_imag[2*SRSLTE_SSS_N]; - + srslte_dft_run_c(&q->dftp_input, input, input_fft); if (ce) { - srslte_vec_div_ccc(&input_fft[q->fft_size/2-SRSLTE_SSS_N], ce, ce_mod, - &input_fft[q->fft_size/2-SRSLTE_SSS_N], z_real, z_imag, - 2*SRSLTE_SSS_N); + srslte_vec_div_ccc(&input_fft[q->fft_size/2-SRSLTE_SSS_N], ce, + &input_fft[q->fft_size/2-SRSLTE_SSS_N], 2*SRSLTE_SSS_N); } for (int i = 0; i < SRSLTE_SSS_N; i++) { diff --git a/lib/src/phy/utils/test/CMakeLists.txt b/lib/src/phy/utils/test/CMakeLists.txt index 76df7ac59..1f5c66827 100644 --- a/lib/src/phy/utils/test/CMakeLists.txt +++ b/lib/src/phy/utils/test/CMakeLists.txt @@ -44,4 +44,5 @@ add_test(algebra_2x2_zf_solver_test algebra_test -z) add_test(algebra_2x2_mmse_solver_test algebra_test -m) add_executable(vector_test vector_test.c) -target_link_libraries(vector_test srslte_phy) \ No newline at end of file +target_link_libraries(vector_test srslte_phy) +add_test(vector_test vector_test) diff --git a/lib/src/phy/utils/test/vector_test.c b/lib/src/phy/utils/test/vector_test.c index 05dce1d35..cf0f38926 100644 --- a/lib/src/phy/utils/test/vector_test.c +++ b/lib/src/phy/utils/test/vector_test.c @@ -89,6 +89,26 @@ float squared_error (cf_t a, cf_t b) { return diff_re*diff_re + diff_im*diff_im; } +TEST(srslte_vec_acc_ff, + MALLOC(float, x); + float z; + + cf_t gold = 0.0f; + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_F(); + } + + TEST_CALL(z = srslte_vec_acc_ff(x, block_size)) + + for (int i = 0; i < block_size; i++) { + gold += x[i]; + } + + mse += fabs(gold - z) / gold; + + free(x); +) + TEST(srslte_vec_dot_prod_sss, MALLOC(int16_t, x); MALLOC(int16_t, y); @@ -314,6 +334,37 @@ TEST(srslte_vec_prod_ccc, free(z); ) +TEST(srslte_vec_prod_ccc_split, + MALLOC(float, x_re); + MALLOC(float, x_im); + MALLOC(float, y_re); + MALLOC(float, y_im); + MALLOC(float, z_re); + MALLOC(float, z_im); + + cf_t gold; + for (int i = 0; i < block_size; i++) { + x_re[i] = RANDOM_F(); + x_im[i] = RANDOM_F(); + y_re[i] = RANDOM_F(); + y_im[i] = RANDOM_F(); + } + + TEST_CALL(srslte_vec_prod_ccc_split(x_re, x_im, y_re, y_im, z_re, z_im, block_size)) + + for (int i = 0; i < block_size; i++) { + gold = (x_re[i] + I * x_im[i]) * (y_re[i] + I * y_im[i]); + mse += cabsf(gold - (z_re[i] + I*z_im[i])); + } + + free(x_re); + free(x_im); + free(y_re); + free(y_im); + free(z_re); + free(z_im); +) + TEST(srslte_vec_prod_conj_ccc, MALLOC(cf_t, x); MALLOC(cf_t, y); @@ -357,6 +408,27 @@ TEST(srslte_vec_sc_prod_ccc, free(z); ) +TEST(srslte_vec_convert_fi, + MALLOC(float, x); + MALLOC(short, z); + float scale = 1000.0f; + + short gold; + for (int i = 0; i < block_size; i++) { + x[i] = (float) RANDOM_F(); + } + + TEST_CALL(srslte_vec_convert_fi(x, z, scale, block_size)) + + for (int i = 0; i < block_size; i++) { + gold = (short) ((x[i] * scale)); + mse += cabsf((float)gold - (float) z[i]); + } + + free(x); + free(z); +) + TEST(srslte_vec_prod_fff, MALLOC(float, x); MALLOC(float, y); @@ -376,6 +448,30 @@ TEST(srslte_vec_prod_fff, } free(x); + free(y); + free(z); +) + +TEST(srslte_vec_prod_cfc, + MALLOC(cf_t, x); + MALLOC(float, y); + MALLOC(cf_t, z); + + cf_t gold; + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_CF(); + y[i] = RANDOM_F(); + } + + TEST_CALL(srslte_vec_prod_cfc(x, y, z, block_size)) + + for (int i = 0; i < block_size; i++) { + gold = x[i] * y[i]; + mse += cabsf(gold - z[i]); + } + + free(x); + free(y); free(z); ) @@ -461,66 +557,216 @@ TEST(srslte_vec_sc_prod_cfc, free(z); ) +TEST(srslte_vec_div_ccc, + MALLOC(cf_t, x); + MALLOC(cf_t, y); + MALLOC(cf_t, z); + + cf_t gold; + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_CF(); + y[i] = RANDOM_CF(); + } + + TEST_CALL(srslte_vec_div_ccc(x, y, z, block_size)) + + for (int i = 0; i < block_size; i++) { + gold = x[i] / y[i]; + mse += cabsf(gold - z[i]); + } + mse /= block_size; + + free(x); + free(y); + free(z); +) + + +TEST(srslte_vec_div_cfc, + MALLOC(cf_t, x); + MALLOC(float, y); + MALLOC(cf_t, z); + + cf_t gold; + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_CF(); + y[i] = RANDOM_F(); + } + + TEST_CALL(srslte_vec_div_cfc(x, y, z, block_size)) + + for (int i = 0; i < block_size; i++) { + gold = x[i] / y[i]; + mse += cabsf(gold - z[i])/cabsf(gold); + } + mse /= block_size; + + free(x); + free(y); + free(z); +) + + +TEST(srslte_vec_div_fff, + MALLOC(float, x); + MALLOC(float, y); + MALLOC(float, z); + + cf_t gold; + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_F(); + y[i] = RANDOM_F(); + } + + TEST_CALL(srslte_vec_div_fff(x, y, z, block_size)) + + for (int i = 0; i < block_size; i++) { + gold = x[i] / y[i]; + mse += cabsf(gold - z[i]); + } + mse /= block_size; + + free(x); + free(y); + free(z); +) + +TEST(srslte_vec_max_fi, + MALLOC(float, x); + + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_F(); + } + + uint32_t max_index = 0; + TEST_CALL(max_index = srslte_vec_max_fi(x, block_size);) + + float gold_value = -INFINITY; + uint32_t gold_index = 0; + for (int i = 0; i < block_size; i++) { + if (gold_value < x[i]) { + gold_value = x[i]; + gold_index = i; + } + } + mse = (gold_index != max_index) ? 1:0; + + free(x); +) + +TEST(srslte_vec_max_abs_ci, + MALLOC(cf_t, x); + + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_CF(); + } + + uint32_t max_index = 0; + TEST_CALL(max_index = srslte_vec_max_abs_ci(x, block_size);) + + float gold_value = -INFINITY; + uint32_t gold_index = 0; + for (int i = 0; i < block_size; i++) { + cf_t a = x[i]; + float abs2 = __real__ a * __real__ a + __imag__ a * __imag__ a; + if (abs2 > gold_value) { + gold_value = abs2; + gold_index = (uint32_t)i; + } + } + mse = (gold_index != max_index) ? 1:0; + + free(x); +) + int main(int argc, char **argv) { char func_names[MAX_FUNCTIONS][32]; double timmings[MAX_FUNCTIONS][MAX_BLOCKS]; uint32_t sizes[32]; uint32_t size_count = 0; uint32_t func_count = 0; - bool passed = true; + bool passed[MAX_FUNCTIONS][MAX_BLOCKS]; + bool all_passed = true; for (uint32_t block_size = 1; block_size <= 1024*8; block_size *= 2) { func_count = 0; - passed &= test_srslte_vec_dot_prod_sss(func_names[func_count], &timmings[func_count][size_count], block_size); + passed[func_count][size_count] = test_srslte_vec_acc_ff(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed[func_count][size_count] = test_srslte_vec_dot_prod_sss(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed[func_count][size_count] = test_srslte_vec_sum_sss(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed[func_count][size_count] = test_srslte_vec_sub_sss(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed[func_count][size_count] = test_srslte_vec_prod_sss(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed[func_count][size_count] = test_srslte_vec_acc_cc(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed[func_count][size_count] = test_srslte_vec_sum_fff(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed[func_count][size_count] = test_srslte_vec_sub_fff(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed[func_count][size_count] = test_srslte_vec_dot_prod_ccc(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed[func_count][size_count] = test_srslte_vec_dot_prod_conj_ccc(func_names[func_count], &timmings[func_count][size_count], block_size); func_count++; - passed &= test_srslte_vec_sum_sss(func_names[func_count], &timmings[func_count][size_count], block_size); + passed[func_count][size_count] = test_srslte_vec_convert_fi(func_names[func_count], &timmings[func_count][size_count], block_size); func_count++; - passed &= test_srslte_vec_sub_sss(func_names[func_count], &timmings[func_count][size_count], block_size); + passed[func_count][size_count] = test_srslte_vec_prod_fff(func_names[func_count], &timmings[func_count][size_count], block_size); func_count++; - passed &= test_srslte_vec_prod_sss(func_names[func_count], &timmings[func_count][size_count], block_size); + passed[func_count][size_count] = test_srslte_vec_prod_cfc(func_names[func_count], &timmings[func_count][size_count], block_size); func_count++; - passed &= test_srslte_vec_acc_cc(func_names[func_count], &timmings[func_count][size_count], block_size); + passed[func_count][size_count] = test_srslte_vec_prod_ccc(func_names[func_count], &timmings[func_count][size_count], block_size); func_count++; - passed &= test_srslte_vec_sum_fff(func_names[func_count], &timmings[func_count][size_count], block_size); + passed[func_count][size_count] = test_srslte_vec_prod_ccc_split(func_names[func_count], &timmings[func_count][size_count], block_size); func_count++; - passed &= test_srslte_vec_sub_fff(func_names[func_count], &timmings[func_count][size_count], block_size); + passed[func_count][size_count] = test_srslte_vec_prod_conj_ccc(func_names[func_count], &timmings[func_count][size_count], block_size); func_count++; - passed &= test_srslte_vec_dot_prod_ccc(func_names[func_count], &timmings[func_count][size_count], block_size); + passed[func_count][size_count] = test_srslte_vec_sc_prod_ccc(func_names[func_count], &timmings[func_count][size_count], block_size); func_count++; - passed &= test_srslte_vec_dot_prod_conj_ccc(func_names[func_count], &timmings[func_count][size_count], block_size); + passed[func_count][size_count] = test_srslte_vec_sc_prod_fff(func_names[func_count], &timmings[func_count][size_count], block_size); func_count++; - passed &= test_srslte_vec_prod_fff(func_names[func_count], &timmings[func_count][size_count], block_size); + passed[func_count][size_count] = test_srslte_vec_abs_cf(func_names[func_count], &timmings[func_count][size_count], block_size); func_count++; - passed &= test_srslte_vec_prod_ccc(func_names[func_count], &timmings[func_count][size_count], block_size); + passed[func_count][size_count] = test_srslte_vec_abs_square_cf(func_names[func_count], &timmings[func_count][size_count], block_size); func_count++; - passed &= test_srslte_vec_prod_conj_ccc(func_names[func_count], &timmings[func_count][size_count], block_size); + passed[func_count][size_count] = test_srslte_vec_sc_prod_cfc(func_names[func_count], &timmings[func_count][size_count], block_size); func_count++; - passed &= test_srslte_vec_sc_prod_ccc(func_names[func_count], &timmings[func_count][size_count], block_size); + passed[func_count][size_count] = test_srslte_vec_div_ccc(func_names[func_count], &timmings[func_count][size_count], block_size); func_count++; - passed &= test_srslte_vec_sc_prod_fff(func_names[func_count], &timmings[func_count][size_count], block_size); + passed[func_count][size_count] = test_srslte_vec_div_cfc(func_names[func_count], &timmings[func_count][size_count], block_size); func_count++; - passed &= test_srslte_vec_abs_cf(func_names[func_count], &timmings[func_count][size_count], block_size); + passed[func_count][size_count] = test_srslte_vec_div_fff(func_names[func_count], &timmings[func_count][size_count], block_size); func_count++; - passed &= test_srslte_vec_abs_square_cf(func_names[func_count], &timmings[func_count][size_count], block_size); + passed[func_count][size_count] = test_srslte_vec_max_fi(func_names[func_count], &timmings[func_count][size_count], block_size); func_count++; - passed &= test_srslte_vec_sc_prod_cfc(func_names[func_count], &timmings[func_count][size_count], block_size); + passed[func_count][size_count] = test_srslte_vec_max_abs_ci(func_names[func_count], &timmings[func_count][size_count], block_size); func_count++; sizes[size_count] = block_size; @@ -546,10 +792,11 @@ int main(int argc, char **argv) { for (int i = 0; i < func_count; i++) { printf("%32s | ", func_names[i]); for (int j = 0; j < size_count; j++) { - printf(" %7.1f", (double) NOF_REPETITIONS*(double)sizes[j]/timmings[i][j]); + printf(" %s%7.1f\x1b[0m", (passed[i][j])?"":"\x1B[31m", (double) NOF_REPETITIONS*(double)sizes[j]/timmings[i][j]); + all_passed &= passed[i][j]; } printf(" |\n"); } - return (passed)?SRSLTE_SUCCESS:SRSLTE_ERROR; + return (all_passed)?SRSLTE_SUCCESS:SRSLTE_ERROR; } diff --git a/lib/src/phy/utils/vector.c b/lib/src/phy/utils/vector.c index cb21f24f1..f85dbca0a 100644 --- a/lib/src/phy/utils/vector.c +++ b/lib/src/phy/utils/vector.c @@ -48,18 +48,7 @@ int srslte_vec_acc_ii(int *x, uint32_t len) { // Used in PRACH detector, AGC and chest_dl for noise averaging float srslte_vec_acc_ff(float *x, uint32_t len) { -#ifdef HAVE_VOLK_ACC_FUNCTION - float result; - volk_32f_accumulator_s32f(&result,x,len); - return result; -#else - int i; - float z=0; - for (i=0;im) { - m=x[i]; - p=i; - } - } - return p; -#endif -#endif + return srslte_vec_max_fi_simd(x, len); } int16_t srslte_vec_max_star_si(int16_t *x, uint32_t len) { @@ -616,30 +541,7 @@ void srslte_vec_max_fff(float *x, float *y, float *z, uint32_t len) { // CP autocorr uint32_t srslte_vec_max_abs_ci(cf_t *x, uint32_t len) { -#ifdef HAVE_VOLK_MAX_ABS_FUNCTION_32 - uint32_t target=0; - volk_32fc_index_max_32u(&target,x,len); - return target; -#else -#ifdef HAVE_VOLK_MAX_ABS_FUNCTION_16 - uint32_t target=0; - volk_32fc_index_max_16u(&target,x,len); - return target; -#else - uint32_t i; - float m=-FLT_MAX; - uint32_t p=0; - float tmp; - for (i=0;im) { - m=tmp; - p=i; - } - } - return p; -#endif -#endif + return srslte_vec_max_ci_simd(x, len); } void srslte_vec_quant_fuc(float *in, uint8_t *out, float gain, float offset, float clip, uint32_t len) { diff --git a/lib/src/phy/utils/vector_simd.c b/lib/src/phy/utils/vector_simd.c index 2eb0428b7..2dd354548 100644 --- a/lib/src/phy/utils/vector_simd.c +++ b/lib/src/phy/utils/vector_simd.c @@ -232,143 +232,113 @@ void srslte_vec_sc_div2_sss_avx2(short *x, int k, short *z, uint32_t len) /* No improvement with AVX */ -void srslte_vec_lut_sss_sse(short *x, unsigned short *lut, short *y, uint32_t len) -{ -#ifdef DEBUG_MODE - for (int i=0;i max_value) { + max_value = values_buffer[k]; + max_index = (uint32_t) indexes_buffer[k]; + } + } +#endif /* SRSLTE_SIMD_I_SIZE */ + + for (; i < len; i++) { + if (x[i] > max_value) { + max_value = x[i]; + max_index = (uint32_t)i; + } + } + + return max_index; +} + +uint32_t srslte_vec_max_ci_simd(cf_t *x, int len) { + int i = 0; + + float max_value = -INFINITY; + uint32_t max_index = 0; + +#if SRSLTE_SIMD_I_SIZE + __attribute__ ((aligned (SRSLTE_SIMD_I_SIZE*sizeof(int)))) int indexes_buffer[SRSLTE_SIMD_I_SIZE] = {0}; + __attribute__ ((aligned (SRSLTE_SIMD_I_SIZE*sizeof(float)))) float values_buffer[SRSLTE_SIMD_I_SIZE] = {0}; + + for (int k = 0; k < SRSLTE_SIMD_I_SIZE; k++) indexes_buffer[k] = k; + simd_i_t simd_inc = srslte_simd_i_set1(SRSLTE_SIMD_I_SIZE); + simd_i_t simd_indexes = srslte_simd_i_load(indexes_buffer); + simd_i_t simd_max_indexes = srslte_simd_i_set1(0); + + simd_f_t simd_max_values = srslte_simd_f_set1(-INFINITY); + + if (SRSLTE_IS_ALIGNED(x)) { + for (; i < len - SRSLTE_SIMD_I_SIZE + 1; i += SRSLTE_SIMD_I_SIZE) { + simd_f_t x1 = srslte_simd_f_load((float *) &x[i]); + simd_f_t x2 = srslte_simd_f_load((float *) &x[i + SRSLTE_SIMD_F_SIZE / 2]); + + simd_f_t mul1 = srslte_simd_f_mul(x1, x1); + simd_f_t mul2 = srslte_simd_f_mul(x2, x2); + + simd_f_t z1 = srslte_simd_f_hadd(mul1, mul2); + + simd_i_t res = srslte_simd_f_max(z1, simd_max_values); + + simd_max_indexes = srslte_simd_i_select(simd_max_indexes, simd_indexes, res); + simd_max_values = (simd_f_t) srslte_simd_i_select((simd_i_t) simd_max_values, (simd_i_t) z1, res); + simd_indexes = srslte_simd_i_add(simd_indexes, simd_inc); + } + } else { + for (; i < len - SRSLTE_SIMD_I_SIZE + 1; i += SRSLTE_SIMD_I_SIZE) { + simd_f_t x1 = srslte_simd_f_loadu((float *) &x[i]); + simd_f_t x2 = srslte_simd_f_loadu((float *) &x[i + SRSLTE_SIMD_F_SIZE / 2]); + + simd_f_t mul1 = srslte_simd_f_mul(x1, x1); + simd_f_t mul2 = srslte_simd_f_mul(x2, x2); + + simd_f_t z1 = srslte_simd_f_hadd(mul1, mul2); + + simd_i_t res = srslte_simd_f_max(z1, simd_max_values); + + simd_max_indexes = srslte_simd_i_select(simd_max_indexes, simd_indexes, res); + simd_max_values = (simd_f_t) srslte_simd_i_select((simd_i_t) simd_max_values, (simd_i_t) z1, res); + simd_indexes = srslte_simd_i_add(simd_indexes, simd_inc); + } + } + + srslte_simd_i_store(indexes_buffer, simd_max_indexes); + srslte_simd_f_store(values_buffer, simd_max_values); + + for (int k = 0; k < SRSLTE_SIMD_I_SIZE; k++) { + if (values_buffer[k] > max_value) { + max_value = values_buffer[k]; + max_index = (uint32_t) indexes_buffer[k]; + } + } +#endif /* SRSLTE_SIMD_I_SIZE */ + + for (; i < len; i++) { + cf_t a = x[i]; + float abs2 = __real__ a * __real__ a + __imag__ a * __imag__ a; + if (abs2 > max_value) { + max_value = abs2; + max_index = (uint32_t)i; + } + } + + return max_index; +} From 94a06867a3c3efbb8c6eb36e1ac2fa5f1aa2dc07 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 29 Sep 2017 16:42:46 +0200 Subject: [PATCH 026/242] Optimized SIMD includes and solved AVX512 bugs --- CMakeLists.txt | 4 +- lib/include/srslte/phy/utils/mat.h | 3 - lib/include/srslte/phy/utils/simd.h | 97 ++++++++++++++++++++-------- lib/src/phy/mimo/precoding.c | 5 +- lib/src/phy/utils/test/mat_test.c | 1 - lib/src/phy/utils/test/vector_test.c | 2 - lib/src/phy/utils/vector_simd.c | 10 +-- 7 files changed, 79 insertions(+), 43 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 28afbc0d8..efaa1973a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -283,8 +283,8 @@ if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") endif (HAVE_AVX2) if (HAVE_AVX512) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mavx512f -DLV_HAVE_AVX512") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx512f -DLV_HAVE_AVX512") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mavx512f -mavx512cd -DLV_HAVE_AVX512") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx512f -mavx512cd -DLV_HAVE_AVX512") endif(HAVE_AVX512) if(NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug") diff --git a/lib/include/srslte/phy/utils/mat.h b/lib/include/srslte/phy/utils/mat.h index 942559955..339cfea23 100644 --- a/lib/include/srslte/phy/utils/mat.h +++ b/lib/include/srslte/phy/utils/mat.h @@ -60,7 +60,6 @@ SRSLTE_API float srslte_mat_2x2_cn(cf_t h00, #ifdef LV_HAVE_SSE -#include /* SSE implementation for complex reciprocal */ SRSLTE_API __m128 srslte_mat_cf_recip_sse(__m128 a); @@ -84,8 +83,6 @@ SRSLTE_API void srslte_mat_2x2_mmse_sse(__m128 y0, __m128 y1, #ifdef LV_HAVE_AVX -#include - /* AVX implementation for complex reciprocal */ SRSLTE_API __m256 srslte_mat_cf_recip_avx(__m256 a); diff --git a/lib/include/srslte/phy/utils/simd.h b/lib/include/srslte/phy/utils/simd.h index 9a5f15dbb..2590794f2 100644 --- a/lib/include/srslte/phy/utils/simd.h +++ b/lib/include/srslte/phy/utils/simd.h @@ -27,7 +27,12 @@ #ifndef SRSLTE_SIMD_H_H #define SRSLTE_SIMD_H_H +#ifdef LV_HAVE_SSE /* AVX, AVX2, FMA, AVX512 are in this group */ +#ifndef __OPTIMIZE__ +#define __OPTIMIZE__ +#endif #include +#endif /* LV_HAVE_SSE */ /* * SSE Macros @@ -233,7 +238,7 @@ static inline simd_f_t srslte_simd_f_mul(simd_f_t a, simd_f_t b) { static inline simd_f_t srslte_simd_f_rcp(simd_f_t a) { #ifdef LV_HAVE_AVX512 - return _mm512_rcp_ps(a); + return _mm512_rcp14_ps(a); #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_AVX2 return _mm256_rcp_ps(a); @@ -372,10 +377,16 @@ typedef struct { static inline simd_cf_t srslte_simd_cfi_load(cf_t *ptr) { simd_cf_t ret; #ifdef LV_HAVE_AVX512 - __m512 in1 = _mm512_permute_ps(_mm512_load_ps((float*)(ptr)), 0b11011000); - __m512 in2 = _mm512_permute_ps(_mm512_load_ps((float*)(ptr + 8)), 0b11011000); - ret.re = _mm512_unpacklo_ps(in1, in2); - ret.im = _mm512_unpackhi_ps(in1, in2); + __m512 in1 = _mm512_load_ps((float*)(ptr)); + __m512 in2 = _mm512_load_ps((float*)(ptr + SRSLTE_SIMD_CF_SIZE/2)); + ret.re = _mm512_permutex2var_ps(in1, _mm512_setr_epi32(0x00, 0x02, 0x04, 0x06, + 0x08, 0x0A, 0x0C, 0x0E, + 0x10, 0x12, 0x14, 0x16, + 0x18, 0x1A, 0x1C, 0x1E), in2); + ret.im = _mm512_permutex2var_ps(in1, _mm512_setr_epi32(0x01, 0x03, 0x05, 0x07, + 0x09, 0x0B, 0x0D, 0x0F, + 0x11, 0x13, 0x15, 0x17, + 0x19, 0x1B, 0x1D, 0x1F), in2); #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_AVX2 __m256 in1 = _mm256_permute_ps(_mm256_load_ps((float*)(ptr)), 0b11011000); @@ -398,10 +409,16 @@ static inline simd_cf_t srslte_simd_cfi_load(cf_t *ptr) { static inline simd_cf_t srslte_simd_cfi_loadu(cf_t *ptr) { simd_cf_t ret; #ifdef LV_HAVE_AVX512 - __m512 in1 = _mm512_permute_ps(_mm512_loadu_ps((float*)(ptr)), 0b11011000); - __m512 in2 = _mm512_permute_ps(_mm512_loadu_ps((float*)(ptr + 8)), 0b11011000); - ret.re = _mm512_unpacklo_ps(in1, in2); - ret.im = _mm512_unpackhi_ps(in1, in2); + __m512 in1 = _mm512_loadu_ps((float*)(ptr)); + __m512 in2 = _mm512_loadu_ps((float*)(ptr + SRSLTE_SIMD_CF_SIZE/2)); + ret.re = _mm512_permutex2var_ps(in1, _mm512_setr_epi32(0x00, 0x02, 0x04, 0x06, + 0x08, 0x0A, 0x0C, 0x0E, + 0x10, 0x12, 0x14, 0x16, + 0x18, 0x1A, 0x1C, 0x1E), in2); + ret.im = _mm512_permutex2var_ps(in1, _mm512_setr_epi32(0x01, 0x03, 0x05, 0x07, + 0x09, 0x0B, 0x0D, 0x0F, + 0x11, 0x13, 0x15, 0x17, + 0x19, 0x1B, 0x1D, 0x1F), in2); #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_AVX2 __m256 in1 = _mm256_permute_ps(_mm256_loadu_ps((float*)(ptr)), 0b11011000); @@ -460,10 +477,16 @@ static inline simd_cf_t srslte_simd_cf_loadu(float *re, float *im) { static inline void srslte_simd_cfi_store(cf_t *ptr, simd_cf_t simdreg) { #ifdef LV_HAVE_AVX512 - __m512 out1 = _mm512_permute_ps(simdreg.re, 0b11011000); - __m512 out2 = _mm512_permute_ps(simdreg.im, 0b11011000); - _mm512_store_ps((float*)(ptr), _mm512_unpacklo_ps(out1, out2)); - _mm512_store_ps((float*)(ptr + 8), _mm512_unpackhi_ps(out1, out2)); + __m512 s1 = _mm512_permutex2var_ps(simdreg.re, _mm512_setr_epi32(0x00, 0x10, 0x01, 0x11, + 0x02, 0x12, 0x03, 0x13, + 0x04, 0x14, 0x05, 0x15, + 0x06, 0x16, 0x07, 0x17), simdreg.im); + __m512 s2 = _mm512_permutex2var_ps(simdreg.re, _mm512_setr_epi32(0x08, 0x18, 0x09, 0x19, + 0x0A, 0x1A, 0x0B, 0x1B, + 0x0C, 0x1C, 0x0D, 0x1D, + 0x0E, 0x1E, 0x0F, 0x1F), simdreg.im); + _mm512_store_ps((float*)(ptr), s1); + _mm512_store_ps((float*)(ptr + 8), s2); #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_AVX2 __m256 out1 = _mm256_permute_ps(simdreg.re, 0b11011000); @@ -481,10 +504,16 @@ static inline void srslte_simd_cfi_store(cf_t *ptr, simd_cf_t simdreg) { static inline void srslte_simd_cfi_storeu(cf_t *ptr, simd_cf_t simdreg) { #ifdef LV_HAVE_AVX512 - __m512 out1 = _mm512_permute_ps(simdreg.re, 0b11011000); - __m512 out2 = _mm512_permute_ps(simdreg.im, 0b11011000); - _mm512_storeu_ps((float*)(ptr), _mm512_unpacklo_ps(out1, out2)); - _mm512_storeu_ps((float*)(ptr + 8), _mm512_unpackhi_ps(out1, out2)); + __m512 s1 = _mm512_permutex2var_ps(simdreg.re, _mm512_setr_epi32(0x00, 0x10, 0x01, 0x11, + 0x02, 0x12, 0x03, 0x13, + 0x04, 0x14, 0x05, 0x15, + 0x06, 0x16, 0x07, 0x17), simdreg.im); + __m512 s2 = _mm512_permutex2var_ps(simdreg.re, _mm512_setr_epi32(0x08, 0x18, 0x09, 0x19, + 0x0A, 0x1A, 0x0B, 0x1B, + 0x0C, 0x1C, 0x0D, 0x1D, + 0x0E, 0x1E, 0x0F, 0x1F), simdreg.im); + _mm512_storeu_ps((float*)(ptr), s1); + _mm512_storeu_ps((float*)(ptr + 8), s2); #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_AVX2 __m256 out1 = _mm256_permute_ps(simdreg.re, 0b11011000); @@ -625,7 +654,6 @@ static inline simd_cf_t srslte_simd_cf_add (simd_cf_t a, simd_cf_t b) { static inline simd_cf_t srslte_simd_cf_mul (simd_cf_t a, simd_f_t b) { simd_cf_t ret; #ifdef LV_HAVE_AVX512 - b = _mm512_permutexvar_ps(b, _mm512_setr_epi32(0,4,1,5,2,6,3,7,8,12,9,13,10,14,11,15)); ret.re = _mm512_mul_ps(a.re, b); ret.im = _mm512_mul_ps(a.im, b); #else /* LV_HAVE_AVX512 */ @@ -649,7 +677,7 @@ static inline simd_cf_t srslte_simd_cf_rcp (simd_cf_t a) { simd_f_t a2re = _mm512_mul_ps(a.re, a.re); simd_f_t a2im = _mm512_mul_ps(a.im, a.im); simd_f_t mod2 = _mm512_add_ps(a2re, a2im); - simd_f_t rcp = _mm512_rcp_ps(mod2); + simd_f_t rcp = _mm512_rcp14_ps(mod2); simd_f_t neg_a_im = _mm512_xor_ps(_mm512_set1_ps(-0.0f), a.im); ret.re = _mm512_mul_ps(a.re, rcp); ret.im = _mm512_mul_ps(neg_a_im, rcp); @@ -702,12 +730,15 @@ static inline simd_cf_t srslte_simd_cf_zero (void) { #ifdef LV_HAVE_AVX512 typedef __m512i simd_i_t; +typedef __mmask16 simd_sel_t; #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_AVX2 typedef __m256i simd_i_t; +typedef __m256 simd_sel_t; #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE typedef __m128i simd_i_t; +typedef __m128i simd_sel_t; #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -768,12 +799,12 @@ static inline simd_i_t srslte_simd_i_add(simd_i_t a, simd_i_t b) { #endif /* LV_HAVE_AVX512 */ } -static inline simd_i_t srslte_simd_f_max(simd_f_t a, simd_f_t b) { +static inline simd_sel_t srslte_simd_f_max(simd_f_t a, simd_f_t b) { #ifdef LV_HAVE_AVX512 - return (simd_i_t) _mm512_cmp_ps_mask(a, b, _CMP_GT_OS); + return _mm512_cmp_ps_mask(a, b, _CMP_GT_OS); #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_AVX2 - return (simd_i_t) _mm256_cmp_ps(a, b, _CMP_GT_OS); + return _mm256_cmp_ps(a, b, _CMP_GT_OS); #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return (simd_i_t) _mm_cmpgt_ps(a, b); @@ -782,15 +813,15 @@ static inline simd_i_t srslte_simd_f_max(simd_f_t a, simd_f_t b) { #endif /* LV_HAVE_AVX512 */ } -static inline simd_i_t srslte_simd_i_select(simd_i_t a, simd_i_t b, simd_i_t selector) { +static inline simd_i_t srslte_simd_i_select(simd_i_t a, simd_i_t b, simd_sel_t selector) { #ifdef LV_HAVE_AVX512 - return (__m512i) _mm512_blendv_ps((__m512)a, (__m512) b, (__m512) selector); + return (__m512i) _mm512_mask_blend_ps( selector, (__m512)a, (__m512) b); #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_AVX2 - return (__m256i) _mm256_blendv_ps((__m256) a,(__m256) b,(__m256) selector); + return (__m256i) _mm256_blendv_ps((__m256) a,(__m256) b, selector); #else #ifdef LV_HAVE_SSE - return (__m128i) _mm_blendv_ps((__m128)a, (__m128)b, (__m128)selector); + return (__m128i) _mm_blendv_ps((__m128)a, (__m128)b, selector); #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -1127,6 +1158,19 @@ static inline simd_c16_t srslte_simd_c16_zero (void) { #if SRSLTE_SIMD_F_SIZE && SRSLTE_SIMD_S_SIZE static inline simd_s_t srslte_simd_convert_2f_s(simd_f_t a, simd_f_t b) { +#ifdef LV_HAVE_AVX512 + __m512 aa = _mm512_permutex2var_ps(a, _mm512_setr_epi32(0x00, 0x01, 0x02, 0x03, + 0x08, 0x09, 0x0A, 0x0B, + 0x10, 0x11, 0x12, 0x13, + 0x18, 0x19, 0x1A, 0x1B), b); + __m512 bb = _mm512_permutex2var_ps(a, _mm512_setr_epi32(0x04, 0x05, 0x06, 0x07, + 0x0C, 0x0D, 0x0E, 0x0F, + 0x14, 0x15, 0x16, 0x17, + 0x1C, 0x1D, 0x1E, 0x1F), b); + __m512i ai = _mm512_cvttps_epi32(aa); + __m512i bi = _mm512_cvttps_epi32(bb); + return _mm512_packs_epi32(ai, bi); +#else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_AVX2 __m256 aa = _mm256_permute2f128_ps(a, b, 0x20); __m256 bb = _mm256_permute2f128_ps(a, b, 0x31); @@ -1140,6 +1184,7 @@ static inline simd_s_t srslte_simd_convert_2f_s(simd_f_t a, simd_f_t b) { return _mm_packs_epi32(ai, bi); #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ } #endif /* SRSLTE_SIMD_F_SIZE && SRSLTE_SIMD_C16_SIZE */ diff --git a/lib/src/phy/mimo/precoding.c b/lib/src/phy/mimo/precoding.c index 8f8bd7737..21350524b 100644 --- a/lib/src/phy/mimo/precoding.c +++ b/lib/src/phy/mimo/precoding.c @@ -33,20 +33,17 @@ #include "srslte/phy/mimo/precoding.h" #include "srslte/phy/utils/vector.h" #include "srslte/phy/utils/debug.h" +#include "srslte/phy/utils/mat.h" #ifdef LV_HAVE_SSE -#include int srslte_predecoding_single_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, int nof_rxant, int nof_symbols, float noise_estimate); int srslte_predecoding_diversity2_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], int nof_rxant, int nof_symbols); #endif #ifdef LV_HAVE_AVX -#include int srslte_predecoding_single_avx(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, int nof_rxant, int nof_symbols, float noise_estimate); #endif -#include "srslte/phy/utils/mat.h" - static srslte_mimo_decoder_t mimo_decoder = SRSLTE_MIMO_DECODER_MMSE; /************************************************ diff --git a/lib/src/phy/utils/test/mat_test.c b/lib/src/phy/utils/test/mat_test.c index 46081da98..0bfb482a9 100644 --- a/lib/src/phy/utils/test/mat_test.c +++ b/lib/src/phy/utils/test/mat_test.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include "srslte/phy/utils/mat.h" diff --git a/lib/src/phy/utils/test/vector_test.c b/lib/src/phy/utils/test/vector_test.c index cf0f38926..8d5b9f2d6 100644 --- a/lib/src/phy/utils/test/vector_test.c +++ b/lib/src/phy/utils/test/vector_test.c @@ -29,9 +29,7 @@ #include #include #include -#include #include -#include #include #include diff --git a/lib/src/phy/utils/vector_simd.c b/lib/src/phy/utils/vector_simd.c index 2dd354548..109c99717 100644 --- a/lib/src/phy/utils/vector_simd.c +++ b/lib/src/phy/utils/vector_simd.c @@ -556,7 +556,7 @@ void srslte_vec_prod_cfc_simd(cf_t *x, float *y, cf_t *z, int len) { for (; i < len - SRSLTE_SIMD_F_SIZE + 1; i += SRSLTE_SIMD_F_SIZE) { simd_f_t s = srslte_simd_f_loadu(&y[i]); - simd_cf_t a = srslte_simd_cfi_load(&x[i]); + simd_cf_t a = srslte_simd_cfi_loadu(&x[i]); simd_cf_t r = srslte_simd_cf_mul(a, s); srslte_simd_cfi_storeu(&z[i], r); } @@ -1036,7 +1036,7 @@ uint32_t srslte_vec_max_fi_simd(float *x, int len) { for (; i < len - SRSLTE_SIMD_I_SIZE + 1; i += SRSLTE_SIMD_I_SIZE) { simd_f_t a = srslte_simd_f_load(&x[i]); - simd_i_t res = srslte_simd_f_max(a, simd_max_values); + simd_sel_t res = srslte_simd_f_max(a, simd_max_values); simd_max_indexes = srslte_simd_i_select(simd_max_indexes, simd_indexes, res); simd_max_values = (simd_f_t) srslte_simd_i_select((simd_i_t) simd_max_values, (simd_i_t) a, res); @@ -1046,7 +1046,7 @@ uint32_t srslte_vec_max_fi_simd(float *x, int len) { for (; i < len - SRSLTE_SIMD_I_SIZE + 1; i += SRSLTE_SIMD_I_SIZE) { simd_f_t a = srslte_simd_f_loadu(&x[i]); - simd_i_t res = srslte_simd_f_max(a, simd_max_values); + simd_sel_t res = srslte_simd_f_max(a, simd_max_values); simd_max_indexes = srslte_simd_i_select(simd_max_indexes, simd_indexes, res); simd_max_values = (simd_f_t) srslte_simd_i_select((simd_i_t) simd_max_values, (simd_i_t) a, res); @@ -1102,7 +1102,7 @@ uint32_t srslte_vec_max_ci_simd(cf_t *x, int len) { simd_f_t z1 = srslte_simd_f_hadd(mul1, mul2); - simd_i_t res = srslte_simd_f_max(z1, simd_max_values); + simd_sel_t res = srslte_simd_f_max(z1, simd_max_values); simd_max_indexes = srslte_simd_i_select(simd_max_indexes, simd_indexes, res); simd_max_values = (simd_f_t) srslte_simd_i_select((simd_i_t) simd_max_values, (simd_i_t) z1, res); @@ -1118,7 +1118,7 @@ uint32_t srslte_vec_max_ci_simd(cf_t *x, int len) { simd_f_t z1 = srslte_simd_f_hadd(mul1, mul2); - simd_i_t res = srslte_simd_f_max(z1, simd_max_values); + simd_sel_t res = srslte_simd_f_max(z1, simd_max_values); simd_max_indexes = srslte_simd_i_select(simd_max_indexes, simd_indexes, res); simd_max_values = (simd_f_t) srslte_simd_i_select((simd_i_t) simd_max_values, (simd_i_t) z1, res); From d6bdabfdc09ddd315e5285ae46e335f59557d9fd Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 29 Sep 2017 20:38:12 +0200 Subject: [PATCH 027/242] Changed all harq delays to variables --- lib/include/srslte/common/common.h | 6 +++++ srsenb/hdr/mac/scheduler_ue.h | 2 +- srsenb/hdr/mac/ue.h | 2 +- srsenb/hdr/phy/phch_common.h | 8 +++---- srsenb/src/mac/mac.cc | 6 ++--- srsenb/src/mac/scheduler.cc | 8 +++---- srsenb/src/mac/scheduler_harq.cc | 2 +- srsenb/src/mac/scheduler_ue.cc | 4 ++-- srsenb/src/phy/phch_common.cc | 4 ++-- srsenb/src/phy/phch_worker.cc | 35 +++++++++++++++--------------- srsue/hdr/mac/mac.h | 2 +- srsue/hdr/phy/phch_common.h | 2 +- srsue/src/mac/proc_bsr.cc | 2 +- srsue/src/phy/phch_common.cc | 14 ++++++------ srsue/src/phy/phch_recv.cc | 4 ++-- srsue/src/phy/phch_worker.cc | 26 +++++++++++----------- 16 files changed, 66 insertions(+), 61 deletions(-) diff --git a/lib/include/srslte/common/common.h b/lib/include/srslte/common/common.h index 7156fbfc9..ea89cc8b7 100644 --- a/lib/include/srslte/common/common.h +++ b/lib/include/srslte/common/common.h @@ -44,6 +44,12 @@ #define SRSLTE_N_DRB 8 #define SRSLTE_N_RADIO_BEARERS 11 +#define HARQ_SFMOD 10 +#define HARQ_DELAY_MS 4 +#define MSG3_DELAY_MS 6 +#define HARQ_TX(tti) ((tti+HARQ_DELAY_MS)%10240) +#define HARQ_RX(tti) ((tti+(2*HARQ_DELAY_MS))%10240) + // Cat 3 UE - Max number of DL-SCH transport block bits received within a TTI // 3GPP 36.306 Table 4.1.1 #define SRSLTE_MAX_BUFFER_SIZE_BITS 102048 diff --git a/srsenb/hdr/mac/scheduler_ue.h b/srsenb/hdr/mac/scheduler_ue.h index b59461140..c454f1edf 100644 --- a/srsenb/hdr/mac/scheduler_ue.h +++ b/srsenb/hdr/mac/scheduler_ue.h @@ -173,7 +173,7 @@ private: // Allowed DCI locations per CFI and per subframe sched_dci_cce_t dci_locations[3][10]; - const static int SCHED_MAX_HARQ_PROC = 8; + const static int SCHED_MAX_HARQ_PROC = 2*HARQ_DELAY_MS; dl_harq_proc dl_harq[SCHED_MAX_HARQ_PROC]; ul_harq_proc ul_harq[SCHED_MAX_HARQ_PROC]; diff --git a/srsenb/hdr/mac/ue.h b/srsenb/hdr/mac/ue.h index b879d040b..0f95a1144 100644 --- a/srsenb/hdr/mac/ue.h +++ b/srsenb/hdr/mac/ue.h @@ -120,7 +120,7 @@ private: uint32_t nof_failures; - const static int NOF_HARQ_PROCESSES = 8; + const static int NOF_HARQ_PROCESSES = 2*HARQ_DELAY_MS; srslte_softbuffer_tx_t softbuffer_tx[NOF_HARQ_PROCESSES]; srslte_softbuffer_rx_t softbuffer_rx[NOF_HARQ_PROCESSES]; diff --git a/srsenb/hdr/phy/phch_common.h b/srsenb/hdr/phy/phch_common.h index 00a59d969..b6c4ceb08 100644 --- a/srsenb/hdr/phy/phch_common.h +++ b/srsenb/hdr/phy/phch_common.h @@ -78,13 +78,13 @@ public: mac_interface_phy *mac; // Common objects for schedulign grants - mac_interface_phy::ul_sched_t ul_grants[10]; - mac_interface_phy::dl_sched_t dl_grants[10]; + mac_interface_phy::ul_sched_t ul_grants[HARQ_SFMOD]; + mac_interface_phy::dl_sched_t dl_grants[HARQ_SFMOD]; // Map of pending ACKs for each user typedef struct { - bool is_pending[10]; - uint16_t n_pdcch[10]; + bool is_pending[HARQ_SFMOD]; + uint16_t n_pdcch[HARQ_SFMOD]; } pending_ack_t; std::map pending_ack; diff --git a/srsenb/src/mac/mac.cc b/srsenb/src/mac/mac.cc index 7cb30cc65..0528852be 100644 --- a/srsenb/src/mac/mac.cc +++ b/srsenb/src/mac/mac.cc @@ -406,7 +406,7 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) log_step_dl(tti); if (!started) { - return 0; + return 0; } if (!dl_sched_res) { @@ -604,7 +604,7 @@ int mac::get_ul_sched(uint32_t tti, ul_sched_t *ul_sched_res) void mac::log_step_ul(uint32_t tti) { - int tti_ul = tti-8; + int tti_ul = tti-(2*HARQ_DELAY_MS); if (tti_ul < 0) { tti_ul += 10240; } @@ -613,7 +613,7 @@ void mac::log_step_ul(uint32_t tti) void mac::log_step_dl(uint32_t tti) { - int tti_dl = tti-4; + int tti_dl = tti-HARQ_DELAY_MS; if (tti_dl < 0) { tti_dl += 10240; } diff --git a/srsenb/src/mac/scheduler.cc b/srsenb/src/mac/scheduler.cc index 79cf3f476..5de780470 100644 --- a/srsenb/src/mac/scheduler.cc +++ b/srsenb/src/mac/scheduler.cc @@ -541,7 +541,7 @@ int sched::dl_sched_rar(dl_sched_rar_t rar[MAX_RAR_LIST]) pending_rar[j].rar_tti = 0; // Save UL resources - uint32_t pending_tti=(current_tti+6)%10; + uint32_t pending_tti=(current_tti+MSG3_DELAY_MS)%10; pending_msg3[pending_tti].enabled = true; pending_msg3[pending_tti].rnti = pending_rar[j].rnti; pending_msg3[pending_tti].L = L_prb; @@ -677,7 +677,7 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched pthread_mutex_lock(&mutex); /* If dl_sched() not yet called this tti (this tti is +4ms advanced), reset CCE state */ - if ((current_tti+4)%10240 != tti) { + if (HARQ_TX(current_tti) != tti) { bzero(used_cce, MAX_CCE*sizeof(bool)); } @@ -685,9 +685,9 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched current_tti = tti; sfn = tti/10; if (tti > 4) { - sf_idx = (tti-4)%10; + sf_idx = (tti-HARQ_DELAY_MS)%10; } else { - sf_idx = (tti+10240-4)%10; + sf_idx = (tti+10240-HARQ_DELAY_MS)%10; } int nof_dci_elems = 0; int nof_phich_elems = 0; diff --git a/srsenb/src/mac/scheduler_harq.cc b/srsenb/src/mac/scheduler_harq.cc index a6ae70d19..f5209b374 100644 --- a/srsenb/src/mac/scheduler_harq.cc +++ b/srsenb/src/mac/scheduler_harq.cc @@ -177,7 +177,7 @@ void dl_harq_proc::set_rbgmask(uint32_t new_mask) bool dl_harq_proc::has_pending_retx(uint32_t current_tti) { - return srslte_tti_interval(current_tti, tti) >= 8 && has_pending_retx_common(); + return srslte_tti_interval(current_tti, tti) >= (2*HARQ_DELAY_MS) && has_pending_retx_common(); } int dl_harq_proc::get_tbs() diff --git a/srsenb/src/mac/scheduler_ue.cc b/srsenb/src/mac/scheduler_ue.cc index 1534d12ef..567711cbe 100644 --- a/srsenb/src/mac/scheduler_ue.cc +++ b/srsenb/src/mac/scheduler_ue.cc @@ -247,7 +247,7 @@ bool sched_ue::get_pucch_sched(uint32_t current_tti, uint32_t prb_idx[2], uint32 // First check if it has pending ACKs for (int i=0;iul_grants[i].nof_grants;j++) { if (phy->ul_grants[i].sched_grants[j].rnti == rnti) { phy->ul_grants[i].sched_grants[j].rnti = 0; @@ -266,7 +266,7 @@ void phch_worker::rem_rnti(uint16_t rnti) void phch_worker::work_imp() { uint32_t sf_ack; - + if (!running) { return; } @@ -326,12 +326,12 @@ void phch_worker::work_imp() encode_phich(ul_grants[sf_sched_ul].phich, ul_grants[sf_sched_ul].nof_phich, sf_tx); // Prepare for receive ACK for DL grants in sf_tx+4 - sf_ack = (sf_tx+4)%10; + sf_ack = HARQ_RX(sf_tx)%HARQ_SFMOD; phy->ack_clear(sf_ack); for (uint32_t i=0;i= SRSLTE_CRNTI_START && dl_grants[sf_tx].sched_grants[i].rnti <= SRSLTE_CRNTI_END) { - phy->ack_set_pending(sf_ack, dl_grants[sf_tx].sched_grants[i].rnti, dl_grants[sf_tx].sched_grants[i].location.ncce); + phy->ack_set_pending(sf_ack, dl_grants[sf_tx].sched_grants[i].rnti, dl_grants[sf_tx].sched_grants[i].location.ncce); } } @@ -504,8 +504,7 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch, int phch_worker::decode_pucch(uint32_t tti_rx) { - uint32_t sf_rx = tti_rx%10; - srslte_uci_data_t uci_data; + srslte_uci_data_t uci_data; for(std::map::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) { uint16_t rnti = (uint16_t) iter->first; @@ -523,7 +522,7 @@ int phch_worker::decode_pucch(uint32_t tti_rx) uci_data.scheduling_request = true; } } - if (phy->ack_is_pending(sf_rx, rnti, &last_n_pdcch)) { + if (phy->ack_is_pending(tti_rx%HARQ_SFMOD, rnti, &last_n_pdcch)) { needs_pucch = true; needs_ack = true; uci_data.uci_ack_len = 1; @@ -589,7 +588,7 @@ int phch_worker::encode_phich(srslte_enb_dl_phich_t *acks, uint32_t nof_acks, ui srslte_enb_dl_put_phich(&enb_dl, acks[i].ack, ue_db[rnti].phich_info.n_prb_lowest, ue_db[rnti].phich_info.n_dmrs, - sf_idx); + sf_idx%10); Info("PHICH: rnti=0x%x, hi=%d, I_lowest=%d, n_dmrs=%d, tti_tx=%d\n", rnti, acks[i].ack, @@ -606,13 +605,13 @@ int phch_worker::encode_pdcch_ul(srslte_enb_ul_pusch_t *grants, uint32_t nof_gra for (uint32_t i=0;iinfo_hex(ptr, len, - "PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tbs=%d, mcs=%d, rv=%d, tti_tx=%d\n", + "PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tbs=%d, mcs=%d, rv=%d, tti_tx=%d\n", rnti, phy_grant.nof_prb, grant_str, grants[i].grant.harq_process, phy_grant.mcs[0].tbs/8, phy_grant.mcs[0].idx, grants[i].grant.rv_idx, tti_tx); } diff --git a/srsue/hdr/mac/mac.h b/srsue/hdr/mac/mac.h index a306af187..d19f668bf 100644 --- a/srsue/hdr/mac/mac.h +++ b/srsue/hdr/mac/mac.h @@ -109,7 +109,7 @@ private: static const int MAC_MAIN_THREAD_PRIO = 5; static const int MAC_PDU_THREAD_PRIO = 6; - static const int MAC_NOF_HARQ_PROC = 8; + static const int MAC_NOF_HARQ_PROC = 2*HARQ_DELAY_MS; // Interaction with PHY srslte::tti_sync_cv ttisync; diff --git a/srsue/hdr/phy/phch_common.h b/srsue/hdr/phy/phch_common.h index aa64fe9ea..fb077e733 100644 --- a/srsue/hdr/phy/phch_common.h +++ b/srsue/hdr/phy/phch_common.h @@ -138,7 +138,7 @@ namespace srsue { uint32_t I_lowest; uint32_t n_dmrs; } pending_ack_t; - pending_ack_t pending_ack[10]; + pending_ack_t pending_ack[HARQ_SFMOD]; bool is_first_tx; diff --git a/srsue/src/mac/proc_bsr.cc b/srsue/src/mac/proc_bsr.cc index 898943ab9..43694c1bc 100644 --- a/srsue/src/mac/proc_bsr.cc +++ b/srsue/src/mac/proc_bsr.cc @@ -368,7 +368,7 @@ bool bsr_proc::need_to_reset_sr() { bool bsr_proc::need_to_send_sr(uint32_t tti) { if (!sr_is_sent && triggered_bsr_type == REGULAR) { - if (srslte_tti_interval(tti,next_tx_tti)>0 && srslte_tti_interval(tti,next_tx_tti) < 10240-4) { + if (srslte_tti_interval(tti,next_tx_tti)>0 && srslte_tti_interval(tti,next_tx_tti) < 10240-HARQ_DELAY_MS) { reset_sr = false; sr_is_sent = true; Debug("BSR: Need to send sr: sr_is_sent=true, reset_sr=false, tti=%d, next_tx_tti=%d\n", tti, next_tx_tti); diff --git a/srsue/src/phy/phch_common.cc b/srsue/src/phy/phch_common.cc index d49b1ced2..cce1857f1 100644 --- a/srsue/src/phy/phch_common.cc +++ b/srsue/src/phy/phch_common.cc @@ -195,13 +195,13 @@ void phch_common::set_dl_rnti(srslte_rnti_type_t type, uint16_t rnti_value, int } void phch_common::reset_pending_ack(uint32_t tti) { - pending_ack[tti%10].enabled = false; + pending_ack[tti%HARQ_SFMOD].enabled = false; } void phch_common::set_pending_ack(uint32_t tti, uint32_t I_lowest, uint32_t n_dmrs) { - pending_ack[tti%10].enabled = true; - pending_ack[tti%10].I_lowest = I_lowest; - pending_ack[tti%10].n_dmrs = n_dmrs; + pending_ack[tti%HARQ_SFMOD].enabled = true; + pending_ack[tti%HARQ_SFMOD].I_lowest = I_lowest; + pending_ack[tti%HARQ_SFMOD].n_dmrs = n_dmrs; Debug("Set pending ACK for tti=%d I_lowest=%d, n_dmrs=%d\n", tti, I_lowest, n_dmrs); } @@ -211,12 +211,12 @@ bool phch_common::get_pending_ack(uint32_t tti) { bool phch_common::get_pending_ack(uint32_t tti, uint32_t *I_lowest, uint32_t *n_dmrs) { if (I_lowest) { - *I_lowest = pending_ack[tti%10].I_lowest; + *I_lowest = pending_ack[tti%HARQ_SFMOD].I_lowest; } if (n_dmrs) { - *n_dmrs = pending_ack[tti%10].n_dmrs; + *n_dmrs = pending_ack[tti%HARQ_SFMOD].n_dmrs; } - return pending_ack[tti%10].enabled; + return pending_ack[tti%HARQ_SFMOD].enabled; } /* The transmisison of UL subframes must be in sequence. Each worker uses this function to indicate diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index dad2c82b8..647226384 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -715,11 +715,11 @@ void phch_recv::run_thread() { worker->set_sample_offset(srslte_ue_sync_get_sfo(&ue_sync)/1000); - /* Compute TX time: Any transmission happens in TTI4 thus advance 4 ms the reception time */ + /* Compute TX time: Any transmission happens in TTI+4 thus advance 4 ms the reception time */ srslte_timestamp_t rx_time, tx_time, tx_time_prach; srslte_ue_sync_get_last_timestamp(&ue_sync, &rx_time); srslte_timestamp_copy(&tx_time, &rx_time); - srslte_timestamp_add(&tx_time, 0, 4e-3 - time_adv_sec); + srslte_timestamp_add(&tx_time, 0, HARQ_DELAY_MS*1e-3 - time_adv_sec); worker->set_tx_time(tx_time, next_offset); next_offset = 0; diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 1c9abc1ca..1c52568af 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -335,7 +335,7 @@ void phch_worker::work_imp() &ul_action.softbuffers[0], ul_action.rv[0], ul_action.rnti, ul_mac_grant.is_from_rar); signal_ready = true; if (ul_action.expect_ack) { - phy->set_pending_ack(tti + 8, ue_ul.pusch_cfg.grant.n_prb_tilde[0], ul_action.phy_grant.ul.ncs_dmrs); + phy->set_pending_ack(tti + 2*HARQ_DELAY_MS, ue_ul.pusch_cfg.grant.n_prb_tilde[0], ul_action.phy_grant.ul.ncs_dmrs); } } else if (dl_action.generate_ack || uci_data.scheduling_request || uci_data.uci_cqi_len > 0) { @@ -663,7 +663,7 @@ bool phch_worker::decode_pdcch_ul(mac_interface_phy::mac_grant_t* grant) char timestr[64]; timestr[0]='\0'; - phy->reset_pending_ack(tti + 8); + phy->reset_pending_ack(tti + 2*HARQ_DELAY_MS); srslte_dci_msg_t dci_msg; srslte_ra_ul_dci_t dci_unpacked; @@ -776,7 +776,7 @@ void phch_worker::set_uci_sr() { uci_data.scheduling_request = false; if (phy->sr_enabled) { - uint32_t sr_tx_tti = (tti+4)%10240; + uint32_t sr_tx_tti = HARQ_TX(tti); // Get I_sr parameter if (srslte_ue_ul_sr_send_tti(I_sr, sr_tx_tti)) { Info("PUCCH: SR transmission at TTI=%d, I_sr=%d\n", sr_tx_tti, I_sr); @@ -793,7 +793,7 @@ void phch_worker::set_uci_periodic_cqi() int cqi_max = phy->args->cqi_max; if (period_cqi.configured && rnti_is_set) { - if (period_cqi.ri_idx_present && srslte_ri_send(period_cqi.pmi_idx, period_cqi.ri_idx, (tti+4)%10240)) { + if (period_cqi.ri_idx_present && srslte_ri_send(period_cqi.pmi_idx, period_cqi.ri_idx, HARQ_TX(tti))) { if (uci_data.uci_ri_len) { uci_data.uci_cqi[0] = uci_data.uci_ri; uci_data.uci_cqi_len = uci_data.uci_ri_len; @@ -802,7 +802,7 @@ void phch_worker::set_uci_periodic_cqi() uci_data.uci_pmi_len = 0; Info("PUCCH: Periodic RI=%d\n", uci_data.uci_cqi[0]); } - } else if (srslte_cqi_send(period_cqi.pmi_idx, (tti+4)%10240)) { + } else if (srslte_cqi_send(period_cqi.pmi_idx, HARQ_TX(tti))) { srslte_cqi_value_t cqi_report; if (period_cqi.format_is_subband) { // TODO: Implement subband periodic reports @@ -868,8 +868,8 @@ void phch_worker::set_uci_aperiodic_cqi() bool phch_worker::srs_is_ready_to_send() { if (srs_cfg.configured) { - if (srslte_refsignal_srs_send_cs(srs_cfg.subframe_config, (tti+4)%10) == 1 && - srslte_refsignal_srs_send_ue(srs_cfg.I_srs, (tti+4)%10240) == 1) + if (srslte_refsignal_srs_send_cs(srs_cfg.subframe_config, HARQ_RX(tti)%10) == 1 && + srslte_refsignal_srs_send_ue(srs_cfg.I_srs, HARQ_TX(tti)) == 1) { return true; } @@ -889,7 +889,7 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui char timestr[64]; timestr[0]='\0'; - if (srslte_ue_ul_cfg_grant(&ue_ul, grant, (tti+4)%10240, rv, current_tx_nb)) { + if (srslte_ue_ul_cfg_grant(&ue_ul, grant, HARQ_TX(tti), rv, current_tx_nb)) { Error("Configuring UL grant\n"); } @@ -919,7 +919,7 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui #endif Info("PUSCH: tti_tx=%d, n_prb=%d, rb_start=%d, tbs=%d, mod=%d, mcs=%d, rv_idx=%d, ack=%s, ri=%s, cfo=%.1f Hz%s\n", - (tti+4)%10240, + HARQ_TX(tti), grant->L_prb, grant->n_prb[0], grant->mcs.tbs/8, grant->mcs.mod, grant->mcs.idx, rv, uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no", @@ -950,7 +950,7 @@ void phch_worker::encode_pucch() gettimeofday(&t[1], NULL); #endif - if (srslte_ue_ul_pucch_encode(&ue_ul, uci_data, last_dl_pdcch_ncce, (tti+4)%10240, signal_buffer[0])) { + if (srslte_ue_ul_pucch_encode(&ue_ul, uci_data, last_dl_pdcch_ncce, HARQ_TX(tti), signal_buffer[0])) { Error("Encoding PUCCH\n"); } @@ -966,7 +966,7 @@ void phch_worker::encode_pucch() float gain = set_power(tx_power); Info("PUCCH: tti_tx=%d, n_cce=%3d, n_pucch=%d, n_prb=%d, ack=%s%s, ri=%s, pmi=%s%s, sr=%s, cfo=%.1f Hz%s\n", - (tti+4)%10240, + HARQ_TX(tti), last_dl_pdcch_ncce, ue_ul.pucch.last_n_pucch, ue_ul.pucch.last_n_prb, uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no", uci_data.uci_ack_len>1?(uci_data.uci_ack_2?"1":"0"):"", @@ -987,7 +987,7 @@ void phch_worker::encode_srs() char timestr[64]; timestr[0]='\0'; - if (srslte_ue_ul_srs_encode(&ue_ul, (tti+4)%10240, signal_buffer[0])) + if (srslte_ue_ul_srs_encode(&ue_ul, HARQ_TX(tti), signal_buffer[0])) { Error("Encoding SRS\n"); } @@ -1002,7 +1002,7 @@ void phch_worker::encode_srs() float gain = set_power(tx_power); uint32_t fi = srslte_vec_max_fi((float*) signal_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb)); float *f = (float*) signal_buffer; - Info("SRS: power=%.2f dBm, tti_tx=%d%s\n", tx_power, (tti+4)%10240, timestr); + Info("SRS: power=%.2f dBm, tti_tx=%d%s\n", tx_power, HARQ_TX(tti), timestr); } From dbae016b003c69f651e2c0fe885281ca61b9cb7c Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Mon, 2 Oct 2017 18:16:03 +0100 Subject: [PATCH 028/242] Removed unused vector functions --- lib/include/srslte/phy/utils/vector.h | 35 +---- lib/src/phy/utils/vector.c | 182 +------------------------- lib/src/phy/utils/vector_simd.c | 69 ---------- 3 files changed, 2 insertions(+), 284 deletions(-) diff --git a/lib/include/srslte/phy/utils/vector.h b/lib/include/srslte/phy/utils/vector.h index 9b99c6fff..4a5daefb3 100644 --- a/lib/include/srslte/phy/utils/vector.h +++ b/lib/include/srslte/phy/utils/vector.h @@ -54,7 +54,6 @@ extern "C" { #define SRSLTE_VEC_EMA(data, average, alpha) ((alpha)*(data)+(1-alpha)*(average)) /** Return the sum of all the elements */ -SRSLTE_API int srslte_vec_acc_ii(int *x, uint32_t len); SRSLTE_API float srslte_vec_acc_ff(float *x, uint32_t len); SRSLTE_API cf_t srslte_vec_acc_cc(cf_t *x, uint32_t len); @@ -77,7 +76,6 @@ SRSLTE_API void srslte_vec_save_file(char *filename, void *buffer, uint32_t len) SRSLTE_API void srslte_vec_load_file(char *filename, void *buffer, uint32_t len); /* sum two vectors */ -SRSLTE_API void srslte_vec_sum_ch(uint8_t *x, uint8_t *y, char *z, uint32_t len); SRSLTE_API void srslte_vec_sum_fff(float *x, float *y, float *z, uint32_t len); SRSLTE_API void srslte_vec_sum_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len); SRSLTE_API void srslte_vec_sub_sss(int16_t *x, int16_t *y, int16_t *z, uint32_t len); @@ -87,39 +85,16 @@ SRSLTE_API void srslte_vec_sum_sss(int16_t *x, int16_t *y, int16_t *z, uint32_t SRSLTE_API void srslte_vec_sub_fff(float *x, float *y, float *z, uint32_t len); SRSLTE_API void srslte_vec_sub_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len); -/* EMA filter: output=coeff*new_data + (1-coeff)*average */ -SRSLTE_API void srslte_vec_ema_filter(cf_t *new_data, cf_t *average, cf_t *output, float coeff, uint32_t len); - -/* Square distance */ -//SRSLTE_API void srslte_vec_square_dist(cf_t symbol, cf_t *points, float *distance, uint32_t npoints); - -/* scalar addition */ -SRSLTE_API void srslte_vec_sc_add_fff(float *x, float h, float *z, uint32_t len); -SRSLTE_API void srslte_vec_sc_add_cfc(cf_t *x, float h, cf_t *z, uint32_t len); -SRSLTE_API void srslte_vec_sc_add_ccc(cf_t *x, cf_t h, cf_t *z, uint32_t len); -SRSLTE_API void srslte_vec_sc_add_sss(int16_t *x, int16_t h, int16_t *z, uint32_t len); - /* scalar product */ SRSLTE_API void srslte_vec_sc_prod_cfc(cf_t *x, float h, cf_t *z, uint32_t len); SRSLTE_API void srslte_vec_sc_prod_ccc(cf_t *x, cf_t h, cf_t *z, uint32_t len); SRSLTE_API void srslte_vec_sc_prod_fff(float *x, float h, float *z, uint32_t len); -SRSLTE_API void srslte_vec_sc_prod_sfs(short *x, float h, short *z, uint32_t len); -SRSLTE_API void srslte_vec_sc_div2_sss(short *x, int pow2_div, short *z, uint32_t len); -/* Normalization */ -SRSLTE_API void srslte_vec_norm_cfc(cf_t *x, float amplitude, cf_t *y, uint32_t len); SRSLTE_API void srslte_vec_convert_fi(float *x, int16_t *z, float scale, uint32_t len); SRSLTE_API void srslte_vec_convert_if(int16_t *x, float *z, float scale, uint32_t len); -SRSLTE_API void srslte_vec_convert_ci(int8_t *x, int16_t *z, uint32_t len); - -SRSLTE_API void srslte_vec_lut_fuf(float *x, uint32_t *lut, float *y, uint32_t len); -SRSLTE_API void srslte_vec_lut_sss(short *x, unsigned short *lut, short *y, uint32_t len); -SRSLTE_API void srslte_vec_deinterleave_cf(cf_t *x, float *real, float *imag, uint32_t len); -SRSLTE_API void srslte_vec_deinterleave_real_cf(cf_t *x, float *real, uint32_t len); - -SRSLTE_API void srslte_vec_interleave_cf(float *real, float *imag, cf_t *x, uint32_t len); +SRSLTE_API void srslte_vec_lut_sss(short *x, unsigned short *lut, short *y, uint32_t len); /* vector product (element-wise) */ SRSLTE_API void srslte_vec_prod_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len); @@ -159,11 +134,6 @@ SRSLTE_API float srslte_vec_corr_ccc(cf_t *x, cf_t *y, uint32_t len); /* return the index of the maximum value in the vector */ SRSLTE_API uint32_t srslte_vec_max_fi(float *x, uint32_t len); SRSLTE_API uint32_t srslte_vec_max_abs_ci(cf_t *x, uint32_t len); -SRSLTE_API int16_t srslte_vec_max_star_si(int16_t *x, uint32_t len); -SRSLTE_API int16_t srslte_vec_max_abs_star_si(int16_t *x, uint32_t len); - -/* maximum between two vectors */ -SRSLTE_API void srslte_vec_max_fff(float *x, float *y, float *z, uint32_t len); /* quantify vector of floats or int16 and convert to uint8_t */ SRSLTE_API void srslte_vec_quant_fuc(float *in, uint8_t *out, float gain, float offset, float clip, uint32_t len); @@ -173,9 +143,6 @@ SRSLTE_API void srslte_vec_quant_suc(int16_t *in, uint8_t *out, float gain, int1 SRSLTE_API void srslte_vec_abs_cf(cf_t *x, float *abs, uint32_t len); SRSLTE_API void srslte_vec_abs_square_cf(cf_t *x, float *abs_square, uint32_t len); -/* argument of each vector element */ -SRSLTE_API void srslte_vec_arg_cf(cf_t *x, float *arg, uint32_t len); - /* Copy 256 bit aligned vector */ SRSLTE_API void srs_vec_cf_cpy(cf_t *src, cf_t *dst, int len); diff --git a/lib/src/phy/utils/vector.c b/lib/src/phy/utils/vector.c index f85dbca0a..3bb7fb08f 100644 --- a/lib/src/phy/utils/vector.c +++ b/lib/src/phy/utils/vector.c @@ -37,15 +37,6 @@ -int srslte_vec_acc_ii(int *x, uint32_t len) { - int i; - int z=0; - for (i=0;im) { - m=x[i]; - } - } - return m; -} - -int16_t srslte_vec_max_abs_star_si(int16_t *x, uint32_t len) { - uint32_t i; - int16_t m=-INT16_MIN; - for (i=0;im) { - m=abs(x[i]); - } - } - return m; -} - -void srslte_vec_max_fff(float *x, float *y, float *z, uint32_t len) { - uint32_t i; - for (i=0;i y[i]) { - z[i] = x[i]; - } else { - z[i] = y[i]; - } - } -} - - // CP autocorr uint32_t srslte_vec_max_abs_ci(cf_t *x, uint32_t len) { return srslte_vec_max_ci_simd(x, len); diff --git a/lib/src/phy/utils/vector_simd.c b/lib/src/phy/utils/vector_simd.c index 109c99717..0294bd1af 100644 --- a/lib/src/phy/utils/vector_simd.c +++ b/lib/src/phy/utils/vector_simd.c @@ -162,75 +162,6 @@ void srslte_vec_prod_sss_simd(int16_t *x, int16_t *y, int16_t *z, int len) { } } - - - -#warning remove function if it is not used -/* -void srslte_vec_sc_div2_sss_sse(short *x, int k, short *z, uint32_t len) -{ -#ifdef LV_HAVE_SSE - unsigned int number = 0; - const unsigned int points = len / 8; - - const __m128i* xPtr = (const __m128i*) x; - __m128i* zPtr = (__m128i*) z; - - __m128i xVal, zVal; - for(;number < points; number++){ - - xVal = _mm_load_si128(xPtr); - - zVal = _mm_srai_epi16(xVal, k); - - _mm_store_si128(zPtr, zVal); - - xPtr ++; - zPtr ++; - } - - number = points * 8; - short divn = (1< Date: Thu, 5 Oct 2017 16:52:02 +0200 Subject: [PATCH 029/242] Now working with variable HARQ scheduling --- lib/include/srslte/common/common.h | 14 +- srsenb/hdr/phy/phch_worker.h | 4 +- srsenb/src/mac/scheduler.cc | 4 +- srsenb/src/mac/scheduler_metric.cc | 18 +- srsenb/src/mac/scheduler_ue.cc | 12 +- srsenb/src/phy/phch_common.cc | 10 +- srsenb/src/phy/phch_worker.cc | 367 +++++++++++++++-------------- srsenb/src/phy/txrx.cc | 2 +- srsue/hdr/mac/mux.h | 3 +- srsue/src/phy/phch_common.cc | 12 +- srsue/src/phy/phch_worker.cc | 41 ++-- 11 files changed, 260 insertions(+), 227 deletions(-) diff --git a/lib/include/srslte/common/common.h b/lib/include/srslte/common/common.h index c6ad06402..9d3d56569 100644 --- a/lib/include/srslte/common/common.h +++ b/lib/include/srslte/common/common.h @@ -44,13 +44,15 @@ #define SRSLTE_N_DRB 8 #define SRSLTE_N_RADIO_BEARERS 11 -#define HARQ_DELAY_MS 4 -#define MSG3_DELAY_MS 6 -#define HARQ_TX(tti) ((tti+HARQ_DELAY_MS)%10240) -#define HARQ_RX(tti) ((tti+(2*HARQ_DELAY_MS))%10240) +#define HARQ_DELAY_MS 6 +#define MSG3_DELAY_MS 6 +#define TTI_TX(tti) ((tti+HARQ_DELAY_MS)%10240) +#define TTI_RX_ACK(tti) ((tti+(2*HARQ_DELAY_MS))%10240) -#define TTIMOD_SZ 10 -#define TTIMOD(tti) (tti%TTIMOD_SZ) +#define TTIMOD_SZ 20 +#define TTIMOD(tti) (tti%TTIMOD_SZ) + +#define ASYNC_DL_SCHED (HARQ_DELAY_MS <= 4) // Cat 3 UE - Max number of DL-SCH transport block bits received within a TTI // 3GPP 36.306 Table 4.1.1 diff --git a/srsenb/hdr/phy/phch_worker.h b/srsenb/hdr/phy/phch_worker.h index a84045920..3194751e8 100644 --- a/srsenb/hdr/phy/phch_worker.h +++ b/srsenb/hdr/phy/phch_worker.h @@ -89,9 +89,9 @@ private: cf_t *signal_buffer_rx; cf_t *signal_buffer_tx; - uint32_t tti_rx, tti_tx, tti_sched_ul; + uint32_t tti_rx, tti_tx_dl, tti_tx_ul; uint32_t sf_rx, sf_tx, tx_mutex_cnt; - uint32_t t_rx, t_tx, t_sched_ul; + uint32_t t_rx, t_tx_dl, t_tx_ul; srslte_enb_dl_t enb_dl; srslte_enb_ul_t enb_ul; diff --git a/srsenb/src/mac/scheduler.cc b/srsenb/src/mac/scheduler.cc index 73f121424..ab499efb0 100644 --- a/srsenb/src/mac/scheduler.cc +++ b/srsenb/src/mac/scheduler.cc @@ -677,14 +677,14 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched pthread_mutex_lock(&mutex); /* If dl_sched() not yet called this tti (this tti is +4ms advanced), reset CCE state */ - if (HARQ_TX(current_tti) != tti) { + if (TTI_TX(current_tti) != tti) { bzero(used_cce, MAX_CCE*sizeof(bool)); } /* Initialize variables */ current_tti = tti; sfn = tti/10; - if (tti > 4) { + if (tti > HARQ_DELAY_MS) { sf_idx = (tti-HARQ_DELAY_MS)%10; } else { sf_idx = (tti+10240-HARQ_DELAY_MS)%10; diff --git a/srsenb/src/mac/scheduler_metric.cc b/srsenb/src/mac/scheduler_metric.cc index 708ab2dd8..6c50009f7 100644 --- a/srsenb/src/mac/scheduler_metric.cc +++ b/srsenb/src/mac/scheduler_metric.cc @@ -142,8 +142,12 @@ dl_harq_proc* dl_metric_rr::get_user_allocation(sched_ue *user) dl_harq_proc *h = user->get_pending_dl_harq(current_tti); // Time-domain RR scheduling +#if ASYNC_DL_SCHED if (pending_data || h) { - if (nof_users_with_data) { +#else + if (pending_data || (h && !h->is_empty())) { +#endif + if (nof_users_with_data) { if (nof_users_with_data == 2) { } if ((current_tti%nof_users_with_data) != user->ue_idx) { @@ -153,7 +157,11 @@ dl_harq_proc* dl_metric_rr::get_user_allocation(sched_ue *user) } // Schedule retx if we have space +#if ASYNC_DL_SCHED if (h) { +#else + if (h && !h->is_empty()) { +#endif uint32_t retx_mask = h->get_rbgmask(); // If can schedule the same mask, do it if (!allocation_is_valid(retx_mask)) { @@ -170,10 +178,14 @@ dl_harq_proc* dl_metric_rr::get_user_allocation(sched_ue *user) } } } - // If could not schedule the reTx, or there wasn't any pending retx, find an empty PID + // If could not schedule the reTx, or there wasn't any pending retx, find an empty PID +#if ASYNC_DL_SCHED h = user->get_empty_dl_harq(); if (h) { - // Allocate resources based on pending data +#else + if (h && h->is_empty()) { +#endif + // Allocate resources based on pending data if (pending_data) { uint32_t pending_rb = user->get_required_prb_dl(pending_data, nof_ctrl_symbols); uint32_t newtx_mask = 0; diff --git a/srsenb/src/mac/scheduler_ue.cc b/srsenb/src/mac/scheduler_ue.cc index 525494ad2..7f4042849 100644 --- a/srsenb/src/mac/scheduler_ue.cc +++ b/srsenb/src/mac/scheduler_ue.cc @@ -248,7 +248,7 @@ bool sched_ue::get_pucch_sched(uint32_t current_tti, uint32_t prb_idx[2]) // First check if it has pending ACKs for (int i=0;iN_pucch_1 = phy->pucch_cfg.n1_pucch_an; srslte_enb_ul_cfg_ue(&enb_ul, rnti, uci_cfg, pucch_sched, srs_cfg); - - ue_db[rnti].I_sr = I_sr; + + ue_db[rnti].I_sr = I_sr; ue_db[rnti].I_sr_en = true; if (pucch_cqi) { - ue_db[rnti].pmi_idx = pmi_idx; - ue_db[rnti].cqi_en = true; - ue_db[rnti].pucch_cqi_ack = pucch_cqi_ack; + ue_db[rnti].pmi_idx = pmi_idx; + ue_db[rnti].cqi_en = true; + ue_db[rnti].pucch_cqi_ack = pucch_cqi_ack; } else { - ue_db[rnti].pmi_idx = 0; - ue_db[rnti].cqi_en = false; + ue_db[rnti].pmi_idx = 0; + ue_db[rnti].cqi_en = false; } - + } else { Error("Setting config dedicated: rnti=0x%x does not exist\n"); } - pthread_mutex_unlock(&mutex); + pthread_mutex_unlock(&mutex); } void phch_worker::rem_rnti(uint16_t rnti) { - pthread_mutex_lock(&mutex); + pthread_mutex_lock(&mutex); if (ue_db.count(rnti)) { ue_db.erase(rnti); - - srslte_enb_dl_rem_rnti(&enb_dl, rnti); + + srslte_enb_dl_rem_rnti(&enb_dl, rnti); srslte_enb_ul_rem_rnti(&enb_ul, rnti); - - // remove any pending grant for each subframe + + // remove any pending grant for each subframe for (uint32_t i=0;iul_grants[i].nof_grants;j++) { if (phy->ul_grants[i].sched_grants[j].rnti == rnti) { - phy->ul_grants[i].sched_grants[j].rnti = 0; + phy->ul_grants[i].sched_grants[j].rnti = 0; } } for (uint32_t j=0;jdl_grants[i].nof_grants;j++) { if (phy->dl_grants[i].sched_grants[j].rnti == rnti) { - phy->dl_grants[i].sched_grants[j].rnti = 0; + phy->dl_grants[i].sched_grants[j].rnti = 0; } } } } else { Error("Removing user: rnti=0x%x does not exist\n", rnti); } - pthread_mutex_unlock(&mutex); + pthread_mutex_unlock(&mutex); } void phch_worker::work_imp() @@ -275,18 +275,18 @@ void phch_worker::work_imp() } pthread_mutex_lock(&mutex); - + mac_interface_phy::ul_sched_t *ul_grants = phy->ul_grants; - mac_interface_phy::dl_sched_t *dl_grants = phy->dl_grants; - mac_interface_phy *mac = phy->mac; - + mac_interface_phy::dl_sched_t *dl_grants = phy->dl_grants; + mac_interface_phy *mac = phy->mac; + log_h->step(tti_rx); - + Debug("Worker %d running\n", get_id()); - + for(std::map::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) { uint16_t rnti = (uint16_t) iter->first; - ue_db[rnti].has_grant_tti = -1; + ue_db[rnti].has_grant_tti = -1; } // Process UL signal @@ -294,51 +294,51 @@ void phch_worker::work_imp() // Decode pending UL grants for the tti they were scheduled decode_pusch(ul_grants[t_rx].sched_grants, ul_grants[t_rx].nof_grants); - + // Decode remaining PUCCH ACKs not associated with PUSCH transmission and SR signals decode_pucch(); - + // Get DL scheduling for the TX TTI from MAC - if (mac->get_dl_sched(tti_tx, &dl_grants[t_tx]) < 0) { + if (mac->get_dl_sched(tti_tx_dl, &dl_grants[t_tx_dl]) < 0) { Error("Getting DL scheduling from MAC\n"); goto unlock; - } - - if (dl_grants[t_tx].cfi < 1 || dl_grants[t_tx].cfi > 3) { - Error("Invalid CFI=%d\n", dl_grants[t_tx].cfi); + } + + if (dl_grants[t_tx_dl].cfi < 1 || dl_grants[t_tx_dl].cfi > 3) { + Error("Invalid CFI=%d\n", dl_grants[t_tx_dl].cfi); goto unlock; } - + // Get UL scheduling for the TX TTI from MAC - if (mac->get_ul_sched(tti_sched_ul, &ul_grants[t_sched_ul]) < 0) { + if (mac->get_ul_sched(tti_tx_ul, &ul_grants[t_tx_ul]) < 0) { Error("Getting UL scheduling from MAC\n"); goto unlock; - } - + } + // Put base signals (references, PBCH, PCFICH and PSS/SSS) into the resource grid srslte_enb_dl_clear_sf(&enb_dl); - srslte_enb_dl_set_cfi(&enb_dl, dl_grants[t_tx].cfi); - srslte_enb_dl_put_base(&enb_dl, tti_tx); + srslte_enb_dl_set_cfi(&enb_dl, dl_grants[t_tx_dl].cfi); + srslte_enb_dl_put_base(&enb_dl, tti_tx_dl); + + // Put UL/DL grants to resource grid. PDSCH data will be encoded as well. + encode_pdcch_dl(dl_grants[t_tx_dl].sched_grants, dl_grants[t_tx_dl].nof_grants); + encode_pdcch_ul(ul_grants[t_tx_ul].sched_grants, ul_grants[t_tx_ul].nof_grants); + encode_pdsch(dl_grants[t_tx_dl].sched_grants, dl_grants[t_tx_dl].nof_grants); - // Put UL/DL grants to resource grid. PDSCH data will be encoded as well. - encode_pdcch_dl(dl_grants[t_tx].sched_grants, dl_grants[t_tx].nof_grants); - encode_pdcch_ul(ul_grants[t_sched_ul].sched_grants, ul_grants[t_sched_ul].nof_grants); - encode_pdsch(dl_grants[t_tx].sched_grants, dl_grants[t_tx].nof_grants); - // Put pending PHICH HARQ ACK/NACK indications into subframe - encode_phich(ul_grants[t_sched_ul].phich, ul_grants[t_sched_ul].nof_phich); - - // Prepare for receive ACK for DL grants in t_tx+4 - phy->ack_clear(TTIMOD(HARQ_TX(sf_tx))); - for (uint32_t i=0;iack_clear(TTIMOD(TTI_TX(t_tx_dl))); + for (uint32_t i=0;i= SRSLTE_CRNTI_START && dl_grants[t_tx].sched_grants[i].rnti <= SRSLTE_CRNTI_END) { - phy->ack_set_pending(TTIMOD(HARQ_TX(sf_tx)), dl_grants[t_tx].sched_grants[i].rnti, dl_grants[t_tx].sched_grants[i].location.ncce); + if (dl_grants[t_tx_dl].sched_grants[i].rnti >= SRSLTE_CRNTI_START && dl_grants[t_tx_dl].sched_grants[i].rnti <= SRSLTE_CRNTI_END) { + phy->ack_set_pending(TTIMOD(TTI_TX(t_tx_dl)), dl_grants[t_tx_dl].sched_grants[i].rnti, dl_grants[t_tx_dl].sched_grants[i].location.ncce); } } - + // Generate signal and transmit - srslte_enb_dl_gen_signal(&enb_dl, signal_buffer_tx); + srslte_enb_dl_gen_signal(&enb_dl, signal_buffer_tx); Debug("Sending to radio\n"); phy->worker_end(tx_mutex_cnt, signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->cell.nof_prb), tx_time); @@ -347,35 +347,35 @@ void phch_worker::work_imp() #endif #ifdef DEBUG_WRITE_FILE - if (tti_tx == 10) { + if (tti_tx_dl == 10) { fclose(f); exit(-1); } -#endif - +#endif + /* Tell the plotting thread to draw the plots */ #ifdef ENABLE_GUI if ((int) get_id() == plot_worker_id) { - sem_post(&plot_sem); + sem_post(&plot_sem); } #endif unlock: - pthread_mutex_unlock(&mutex); + pthread_mutex_unlock(&mutex); } int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) { - srslte_uci_data_t uci_data; + srslte_uci_data_t uci_data; bzero(&uci_data, sizeof(srslte_uci_data_t)); - - uint32_t wideband_cqi_value = 0; - - uint32_t n_rb_ho = 0; + + uint32_t wideband_cqi_value = 0; + + uint32_t n_rb_ho = 0; for (uint32_t i=0;iack_is_pending(t_rx, rnti)) { - uci_data.uci_ack_len = 1; + uci_data.uci_ack_len = 1; } - // Configure PUSCH CQI channel + // Configure PUSCH CQI channel srslte_cqi_value_t cqi_value; - bool cqi_enabled = false; + bool cqi_enabled = false; if (ue_db[rnti].cqi_en && srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) { cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND; - cqi_enabled = true; + cqi_enabled = true; } else if (grants[i].grant.cqi_request) { cqi_value.type = SRSLTE_CQI_TYPE_SUBBAND_HL; cqi_value.subband_hl.N = (phy->cell.nof_prb > 7) ? srslte_cqi_hl_get_no_subbands(phy->cell.nof_prb) : 0; - cqi_enabled = true; + cqi_enabled = true; } if (cqi_enabled) { uci_data.uci_cqi_len = srslte_cqi_size(&cqi_value); } - - // mark this tti as having an ul grant to avoid pucch - ue_db[rnti].has_grant_tti = tti_rx; - - srslte_ra_ul_grant_t phy_grant; + + // mark this tti as having an ul grant to avoid pucch + ue_db[rnti].has_grant_tti = tti_rx; + + 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 (phy_grant.mcs.mod == SRSLTE_MOD_64QAM) { @@ -414,27 +414,27 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) } phy_grant.Qm = SRSLTE_MIN(phy_grant.Qm, 4); res = srslte_enb_ul_get_pusch(&enb_ul, &phy_grant, grants[i].softbuffer, - rnti, grants[i].rv_idx, - grants[i].current_tx_nb, - grants[i].data, - &uci_data, + rnti, grants[i].rv_idx, + grants[i].current_tx_nb, + grants[i].data, + &uci_data, sf_rx); } else { Error("Computing PUSCH grant\n"); - return SRSLTE_ERROR; + return SRSLTE_ERROR; } - + #ifdef LOG_EXECTIME gettimeofday(&t[2], NULL); get_time_interval(t); snprintf(timestr, 64, ", dec_time=%4d us", (int) t[0].tv_usec); #endif - - bool crc_res = (res == 0); - + + bool crc_res = (res == 0); + // Save PHICH scheduling for this user. Each user can have just 1 PUSCH grant per TTI - ue_db[rnti].phich_info.n_prb_lowest = enb_ul.pusch_cfg.grant.n_prb_tilde[0]; - ue_db[rnti].phich_info.n_dmrs = phy_grant.ncs_dmrs; + ue_db[rnti].phich_info.n_prb_lowest = enb_ul.pusch_cfg.grant.n_prb_tilde[0]; + ue_db[rnti].phich_info.n_dmrs = phy_grant.ncs_dmrs; char cqi_str[64]; if (cqi_enabled) { @@ -446,8 +446,8 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) } snprintf(cqi_str, 64, ", cqi=%d", wideband_cqi_value); } - - float snr_db = 10*log10(srslte_chest_ul_get_snr(&enb_ul.chest)); + + float snr_db = 10*log10(srslte_chest_ul_get_snr(&enb_ul.chest)); /* if (!crc_res && enb_ul.pusch_cfg.grant.L_prb == 1 && enb_ul.pusch_cfg.grant.n_prb[0] == 0 && snr_db > 5) { @@ -456,8 +456,8 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) srslte_vec_save_file("d", enb_ul.pusch.d, sizeof(cf_t)*enb_ul.pusch_cfg.nbits.nof_re); srslte_vec_save_file("ce2", enb_ul.pusch.ce, sizeof(cf_t)*enb_ul.pusch_cfg.nbits.nof_re); srslte_vec_save_file("z", enb_ul.pusch.z, sizeof(cf_t)*enb_ul.pusch_cfg.nbits.nof_re); - printf("saved sf_idx=%d, mcs=%d, tbs=%d, rnti=%d, rv=%d, snr=%.1f\n", tti%10, - grants[i].grant.mcs_idx, enb_ul.pusch_cfg.cb_segm.tbs, rnti, grants[i].rv_idx, snr_db); + printf("saved sf_idx=%d, mcs=%d, tbs=%d, rnti=%d, rv=%d, snr=%.1f\n", tti%10, + grants[i].grant.mcs_idx, enb_ul.pusch_cfg.cb_segm.tbs, rnti, grants[i].rv_idx, snr_db); exit(-1); } */ @@ -465,120 +465,121 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) "PUSCH: rnti=0x%x, prb=(%d,%d), tbs=%d, mcs=%d, rv=%d, snr=%.1f dB, n_iter=%d, crc=%s%s%s%s\n", rnti, phy_grant.n_prb[0], phy_grant.n_prb[0]+phy_grant.L_prb, phy_grant.mcs.tbs/8, phy_grant.mcs.idx, grants[i].grant.rv_idx, - snr_db, + snr_db, srslte_pusch_last_noi(&enb_ul.pusch), crc_res?"OK":"KO", uci_data.uci_ack_len>0?(uci_data.uci_ack?", ack=1":", ack=0"):"", - uci_data.uci_cqi_len>0?cqi_str:"", - timestr); - - // Notify MAC of RL status + uci_data.uci_cqi_len>0?cqi_str:"", + timestr); + + // Notify MAC of RL status if (grants[i].grant.rv_idx == 0) { if (res && snr_db < PUSCH_RL_SNR_DB_TH) { Debug("PUSCH: Radio-Link failure snr=%.1f dB\n", snr_db); phy->mac->rl_failure(rnti); } else { phy->mac->rl_ok(rnti); - } + } } - + // Notify MAC new received data and HARQ Indication value - phy->mac->crc_info(tti_rx, rnti, phy_grant.mcs.tbs/8, crc_res); + phy->mac->crc_info(tti_rx, rnti, phy_grant.mcs.tbs/8, crc_res); if (uci_data.uci_ack_len) { phy->mac->ack_info(tti_rx, rnti, uci_data.uci_ack && (crc_res || snr_db > PUSCH_RL_SNR_DB_TH)); } - - // Notify MAC of UL SNR and DL CQI + + // Notify MAC of UL SNR and DL CQI if (snr_db >= PUSCH_RL_SNR_DB_TH) { phy->mac->snr_info(tti_rx, rnti, snr_db); } if (uci_data.uci_cqi_len>0 && crc_res) { phy->mac->cqi_info(tti_rx, rnti, wideband_cqi_value); } - - // Save metrics stats + + // Save metrics stats ue_db[rnti].metrics_ul(phy_grant.mcs.idx, 0, snr_db, srslte_pusch_last_noi(&enb_ul.pusch)); - } + } } - return SRSLTE_SUCCESS; + return SRSLTE_SUCCESS; } int phch_worker::decode_pucch() { srslte_uci_data_t uci_data; - + for(std::map::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) { uint16_t rnti = (uint16_t) iter->first; if (rnti >= SRSLTE_CRNTI_START && rnti <= SRSLTE_CRNTI_END && ue_db[rnti].has_grant_tti != (int) tti_rx) { - // Check if user needs to receive PUCCH - bool needs_pucch = false, needs_ack=false, needs_sr=false, needs_cqi=false; + // Check if user needs to receive PUCCH + bool needs_pucch = false, needs_ack=false, needs_sr=false, needs_cqi=false; uint32_t last_n_pdcch = 0; bzero(&uci_data, sizeof(srslte_uci_data_t)); - + if (ue_db[rnti].I_sr_en) { if (srslte_ue_ul_sr_send_tti(ue_db[rnti].I_sr, tti_rx)) { - needs_pucch = true; - needs_sr = true; - uci_data.scheduling_request = true; + needs_pucch = true; + needs_sr = true; + uci_data.scheduling_request = true; } - } + } + if (phy->ack_is_pending(t_rx, rnti, &last_n_pdcch)) { - needs_pucch = true; - needs_ack = true; - uci_data.uci_ack_len = 1; + needs_pucch = true; + needs_ack = true; + uci_data.uci_ack_len = 1; } srslte_cqi_value_t cqi_value; if (ue_db[rnti].cqi_en && (ue_db[rnti].pucch_cqi_ack || !needs_ack)) { if (srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) { - needs_pucch = true; - needs_cqi = true; - cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND; + needs_pucch = true; + needs_cqi = true; + cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND; uci_data.uci_cqi_len = srslte_cqi_size(&cqi_value); } } - + if (needs_pucch) { - if (srslte_enb_ul_get_pucch(&enb_ul, rnti, last_n_pdcch, t_rx, &uci_data)) { + if (srslte_enb_ul_get_pucch(&enb_ul, rnti, last_n_pdcch, sf_rx, &uci_data)) { fprintf(stderr, "Error getting PUCCH\n"); - return SRSLTE_ERROR; + return SRSLTE_ERROR; } if (uci_data.uci_ack_len > 0) { - phy->mac->ack_info(tti_rx, rnti, uci_data.uci_ack && (srslte_pucch_get_last_corr(&enb_ul.pucch) >= PUCCH_RL_CORR_TH)); + phy->mac->ack_info(tti_rx, rnti, uci_data.uci_ack && (srslte_pucch_get_last_corr(&enb_ul.pucch) >= PUCCH_RL_CORR_TH)); } if (uci_data.scheduling_request) { - phy->mac->sr_detected(tti_rx, rnti); + phy->mac->sr_detected(tti_rx, rnti); } - + char cqi_str[64]; if (uci_data.uci_cqi_len) { srslte_cqi_value_unpack(uci_data.uci_cqi, &cqi_value); phy->mac->cqi_info(tti_rx, rnti, cqi_value.wideband.wideband_cqi); sprintf(cqi_str, ", cqi=%d", cqi_value.wideband.wideband_cqi); } - log_h->info("PUCCH: rnti=0x%x, corr=%.2f, n_pucch=%d, n_prb=%d%s%s%s\n", - rnti, + log_h->info("PUCCH: rnti=0x%x, corr=%.2f, n_pucch=%d, n_prb=%d%s%s%s\n", + rnti, srslte_pucch_get_last_corr(&enb_ul.pucch), enb_ul.pucch.last_n_pucch, enb_ul.pucch.last_n_prb, - needs_ack?(uci_data.uci_ack?", ack=1":", ack=0"):"", - needs_sr?(uci_data.scheduling_request?", sr=yes":", sr=no"):"", - needs_cqi?cqi_str:""); + needs_ack?(uci_data.uci_ack?", ack=1":", ack=0"):"", + needs_sr?(uci_data.scheduling_request?", sr=yes":", sr=no"):"", + needs_cqi?cqi_str:""); - // Notify MAC of RL status + // Notify MAC of RL status if (!needs_sr) { if (srslte_pucch_get_last_corr(&enb_ul.pucch) < PUCCH_RL_CORR_TH) { Debug("PUCCH: Radio-Link failure corr=%.1f\n", srslte_pucch_get_last_corr(&enb_ul.pucch)); phy->mac->rl_failure(rnti); } else { phy->mac->rl_ok(rnti); - } - } + } + } } } - } - return 0; + } + return 0; } @@ -587,15 +588,15 @@ int phch_worker::encode_phich(srslte_enb_dl_phich_t *acks, uint32_t nof_acks) for (uint32_t i=0;iinfo_hex(ptr, len, - "PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tbs=%d, mcs=%d, rv=%d, tti_tx=%d\n", - rnti, phy_grant.nof_prb, grant_str, grants[i].grant.harq_process, - phy_grant.mcs[0].tbs/8, phy_grant.mcs[0].idx, grants[i].grant.rv_idx, tti_tx); + "PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tbs=%d, mcs=%d, rv=%d, tti_tx_dl=%d\n", + rnti, phy_grant.nof_prb, grant_str, grants[i].grant.harq_process, + phy_grant.mcs[0].tbs/8, phy_grant.mcs[0].idx, grants[i].grant.rv_idx, tti_tx_dl); } srslte_softbuffer_tx_t *sb[SRSLTE_MAX_CODEWORDS] = {grants[i].softbuffer, NULL}; diff --git a/srsenb/src/phy/txrx.cc b/srsenb/src/phy/txrx.cc index 9427e3459..fa14b0b82 100644 --- a/srsenb/src/phy/txrx.cc +++ b/srsenb/src/phy/txrx.cc @@ -115,7 +115,7 @@ void txrx::run_thread() /* Compute TX time: Any transmission happens in TTI+4 thus advance 4 ms the reception time */ srslte_timestamp_copy(&tx_time, &rx_time); - srslte_timestamp_add(&tx_time, 0, 4e-3); + srslte_timestamp_add(&tx_time, 0, HARQ_DELAY_MS*1e-3); Debug("Settting TTI=%d, tx_mutex=%d, tx_time=%d:%f to worker %d\n", tti, tx_mutex_cnt, diff --git a/srsue/hdr/mac/mux.h b/srsue/hdr/mac/mux.h index 1167af752..ab081070c 100644 --- a/srsue/hdr/mac/mux.h +++ b/srsue/hdr/mac/mux.h @@ -82,8 +82,7 @@ private: const static int MIN_RLC_SDU_LEN = 0; const static int MAX_NOF_SUBHEADERS = 20; - const static int MAX_HARQ_PROC = 8; - + std::vector lch; // Keep track of the PIDs that transmitted BSR reports diff --git a/srsue/src/phy/phch_common.cc b/srsue/src/phy/phch_common.cc index 489d27197..549783fd9 100644 --- a/srsue/src/phy/phch_common.cc +++ b/srsue/src/phy/phch_common.cc @@ -136,12 +136,16 @@ srslte::radio* phch_common::get_radio() void phch_common::set_rar_grant(uint32_t tti, uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN]) { srslte_dci_rar_grant_unpack(&rar_grant, grant_payload); - rar_grant_pending = true; - // PUSCH is at n+6 or n+7 and phch_worker assumes default delay of 4 ttis + rar_grant_pending = true; + int delay = MSG3_DELAY_MS-HARQ_DELAY_MS; + if (delay < 0) { + fprintf(stderr, "Error MSG3_DELAY_MS can't be lower than HARQ_DELAY_MS\n"); + delay = 0; + } if (rar_grant.ul_delay) { - rar_grant_tti = (tti + 3) % 10240; + rar_grant_tti = (tti + delay + 1) % 10240; } else { - rar_grant_tti = (tti + 2) % 10240; + rar_grant_tti = (tti + delay) % 10240; } } diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index e6c0050e2..adeb41603 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -292,6 +292,13 @@ void phch_worker::work_imp() } } } + + // Process RAR before UL to enable zero-delay Msg3 + bool rar_delivered = false; + if (HARQ_DELAY_MS == MSG3_DELAY_MS && dl_mac_grant.rnti_type == SRSLTE_RNTI_RAR) { + rar_delivered = true; + phy->mac->tb_decoded(dl_ack[0], 0, dl_mac_grant.rnti_type, dl_mac_grant.pid); + } // Decode PHICH bool ul_ack = false; @@ -313,8 +320,8 @@ void phch_worker::work_imp() set_uci_periodic_cqi(); } - /* TTI offset for UL is always 4 for LTE */ - ul_action.tti_offset = 4; + /* TTI offset for UL */ + ul_action.tti_offset = HARQ_DELAY_MS; /* Send UL grant or HARQ information (from PHICH) to MAC */ if (ul_grant_available && ul_ack_available) { @@ -335,7 +342,7 @@ void phch_worker::work_imp() &ul_action.softbuffers[0], ul_action.rv[0], ul_action.rnti, ul_mac_grant.is_from_rar); signal_ready = true; if (ul_action.expect_ack) { - phy->set_pending_ack(HARQ_RX(tti), ue_ul.pusch_cfg.grant.n_prb_tilde[0], ul_action.phy_grant.ul.ncs_dmrs); + phy->set_pending_ack(TTI_RX_ACK(tti), ue_ul.pusch_cfg.grant.n_prb_tilde[0], ul_action.phy_grant.ul.ncs_dmrs); } } else if (dl_action.generate_ack || uci_data.scheduling_request || uci_data.uci_cqi_len > 0) { @@ -357,7 +364,7 @@ void phch_worker::work_imp() if (!dl_action.generate_ack_callback) { if (dl_mac_grant.rnti_type == SRSLTE_RNTI_PCH && dl_action.decode_enabled[0]) { phy->mac->pch_decoded_ok(dl_mac_grant.n_bytes[0]); - } else { + } else if (!rar_delivered) { for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { if (dl_action.decode_enabled[tb]) { phy->mac->tb_decoded(dl_ack[tb], tb, dl_mac_grant.rnti_type, dl_mac_grant.pid); @@ -475,7 +482,7 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant) /* Fill MAC grant structure */ grant->ndi[0] = dci_unpacked.ndi; grant->ndi[1] = dci_unpacked.ndi_1; - grant->pid = dci_unpacked.harq_process; + 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; @@ -663,7 +670,7 @@ bool phch_worker::decode_pdcch_ul(mac_interface_phy::mac_grant_t* grant) char timestr[64]; timestr[0]='\0'; - phy->reset_pending_ack(HARQ_RX(tti)); + phy->reset_pending_ack(TTI_RX_ACK(tti)); srslte_dci_msg_t dci_msg; srslte_ra_ul_dci_t dci_unpacked; @@ -776,7 +783,7 @@ void phch_worker::set_uci_sr() { uci_data.scheduling_request = false; if (phy->sr_enabled) { - uint32_t sr_tx_tti = HARQ_TX(tti); + uint32_t sr_tx_tti = TTI_TX(tti); // Get I_sr parameter if (srslte_ue_ul_sr_send_tti(I_sr, sr_tx_tti)) { Info("PUCCH: SR transmission at TTI=%d, I_sr=%d\n", sr_tx_tti, I_sr); @@ -793,7 +800,7 @@ void phch_worker::set_uci_periodic_cqi() int cqi_max = phy->args->cqi_max; if (period_cqi.configured && rnti_is_set) { - if (period_cqi.ri_idx_present && srslte_ri_send(period_cqi.pmi_idx, period_cqi.ri_idx, HARQ_TX(tti))) { + if (period_cqi.ri_idx_present && srslte_ri_send(period_cqi.pmi_idx, period_cqi.ri_idx, TTI_TX(tti))) { if (uci_data.uci_ri_len) { uci_data.uci_cqi[0] = uci_data.uci_ri; uci_data.uci_cqi_len = uci_data.uci_ri_len; @@ -802,7 +809,7 @@ void phch_worker::set_uci_periodic_cqi() uci_data.uci_pmi_len = 0; Info("PUCCH: Periodic RI=%d\n", uci_data.uci_cqi[0]); } - } else if (srslte_cqi_send(period_cqi.pmi_idx, HARQ_TX(tti))) { + } else if (srslte_cqi_send(period_cqi.pmi_idx, TTI_TX(tti))) { srslte_cqi_value_t cqi_report; if (period_cqi.format_is_subband) { // TODO: Implement subband periodic reports @@ -868,8 +875,8 @@ void phch_worker::set_uci_aperiodic_cqi() bool phch_worker::srs_is_ready_to_send() { if (srs_cfg.configured) { - if (srslte_refsignal_srs_send_cs(srs_cfg.subframe_config, HARQ_RX(tti)%10) == 1 && - srslte_refsignal_srs_send_ue(srs_cfg.I_srs, HARQ_TX(tti)) == 1) + if (srslte_refsignal_srs_send_cs(srs_cfg.subframe_config, TTI_TX(tti)%10) == 1 && + srslte_refsignal_srs_send_ue(srs_cfg.I_srs, TTI_TX(tti)) == 1) { return true; } @@ -889,7 +896,7 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui char timestr[64]; timestr[0]='\0'; - if (srslte_ue_ul_cfg_grant(&ue_ul, grant, HARQ_TX(tti), rv, current_tx_nb)) { + if (srslte_ue_ul_cfg_grant(&ue_ul, grant, TTI_TX(tti), rv, current_tx_nb)) { Error("Configuring UL grant\n"); } @@ -919,7 +926,7 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui #endif Info("PUSCH: tti_tx=%d, n_prb=%d, rb_start=%d, tbs=%d, mod=%d, mcs=%d, rv_idx=%d, ack=%s, ri=%s, cfo=%.1f Hz%s\n", - HARQ_TX(tti), + TTI_TX(tti), grant->L_prb, grant->n_prb[0], grant->mcs.tbs/8, grant->mcs.mod, grant->mcs.idx, rv, uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no", @@ -950,7 +957,7 @@ void phch_worker::encode_pucch() gettimeofday(&t[1], NULL); #endif - if (srslte_ue_ul_pucch_encode(&ue_ul, uci_data, last_dl_pdcch_ncce, HARQ_TX(tti), signal_buffer[0])) { + if (srslte_ue_ul_pucch_encode(&ue_ul, uci_data, last_dl_pdcch_ncce, TTI_TX(tti), signal_buffer[0])) { Error("Encoding PUCCH\n"); } @@ -966,7 +973,7 @@ void phch_worker::encode_pucch() float gain = set_power(tx_power); Info("PUCCH: tti_tx=%d, n_cce=%3d, n_pucch=%d, n_prb=%d, ack=%s%s, ri=%s, pmi=%s%s, sr=%s, cfo=%.1f Hz%s\n", - HARQ_TX(tti), + TTI_TX(tti), last_dl_pdcch_ncce, ue_ul.pucch.last_n_pucch, ue_ul.pucch.last_n_prb, uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no", uci_data.uci_ack_len>1?(uci_data.uci_ack_2?"1":"0"):"", @@ -987,7 +994,7 @@ void phch_worker::encode_srs() char timestr[64]; timestr[0]='\0'; - if (srslte_ue_ul_srs_encode(&ue_ul, HARQ_TX(tti), signal_buffer[0])) + if (srslte_ue_ul_srs_encode(&ue_ul, TTI_TX(tti), signal_buffer[0])) { Error("Encoding SRS\n"); } @@ -1002,7 +1009,7 @@ void phch_worker::encode_srs() float gain = set_power(tx_power); uint32_t fi = srslte_vec_max_fi((float*) signal_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb)); float *f = (float*) signal_buffer; - Info("SRS: power=%.2f dBm, tti_tx=%d%s\n", tx_power, HARQ_TX(tti), timestr); + Info("SRS: power=%.2f dBm, tti_tx=%d%s\n", tx_power, TTI_TX(tti), timestr); } From cfc9432ee20b63b377fd0a7b2fa835fd4e592d4e Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 6 Oct 2017 16:14:16 +0200 Subject: [PATCH 030/242] fix warning --- lib/src/phy/rf/rf_soapy_imp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/phy/rf/rf_soapy_imp.c b/lib/src/phy/rf/rf_soapy_imp.c index ee646c2c2..fef533ffc 100644 --- a/lib/src/phy/rf/rf_soapy_imp.c +++ b/lib/src/phy/rf/rf_soapy_imp.c @@ -492,7 +492,7 @@ int rf_soapy_send_timed_multi(void *h, rf_soapy_handler_t *handler = (rf_soapy_handler_t *) h; int flags = 0; const long timeoutUs = 2000; // arbitrarily chosen - long long timeNs; + long long timeNs = 0; int trials = 0; int ret = 0; int n = 0; From 270a15fe1af8de1944eab1639a8db0188ef51499 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 6 Oct 2017 16:14:58 +0200 Subject: [PATCH 031/242] update version --- cmake/modules/SRSLTEVersion.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/modules/SRSLTEVersion.cmake b/cmake/modules/SRSLTEVersion.cmake index d2ab204f5..b52e47fe5 100644 --- a/cmake/modules/SRSLTEVersion.cmake +++ b/cmake/modules/SRSLTEVersion.cmake @@ -18,7 +18,7 @@ # and at http://www.gnu.org/licenses/. # -SET(SRSLTE_VERSION_MAJOR 002) -SET(SRSLTE_VERSION_MINOR 000) -SET(SRSLTE_VERSION_PATCH 000) +SET(SRSLTE_VERSION_MAJOR 17) +SET(SRSLTE_VERSION_MINOR 9) +SET(SRSLTE_VERSION_PATCH 0) SET(SRSLTE_VERSION_STRING "${SRSLTE_VERSION_MAJOR}.${SRSLTE_VERSION_MINOR}.${SRSLTE_VERSION_PATCH}") From 24f2375dcd459545ccc0705785075ee8661ea4fa Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 6 Oct 2017 16:20:35 +0200 Subject: [PATCH 032/242] update changelog --- CHANGELOG | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 7dfff7d89..2acd0c4a3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,11 @@ Change Log for Releases ============================== +## 17.09 + * Added MIMO 2x2 in the PHY layer and srsUE (i.e. TM3/TM4) + * eMBMS support in the PHY layer + * Many bug-fixes and improved stability and performance in srsUE/srsENB + ## 002.000.000 * Added fully functional srsENB to srsLTE code * Merged srsUE code into srsLTE and reestructured PHY code From 1fc4f8ef07953b6e470a6316e8c22c22c456dee4 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 6 Oct 2017 16:26:22 +0200 Subject: [PATCH 033/242] Update README.md --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c891ab219..ad87ad149 100644 --- a/README.md +++ b/README.md @@ -18,10 +18,10 @@ Common Features * LTE Release 8 compliant (with selected features of Release 9) * FDD configuration * Tested bandwidths: 1.4, 3, 5, 10, 15 and 20 MHz - * Transmission mode 1 (single antenna), 2 (transmit diversity), 3 (transmit diversity/CCD) and 4 (closed-loop spatial multiplexing) + * Transmission mode 1 (single antenna), 2 (transmit diversity), 3 (CCD) and 4 (closed-loop spatial multiplexing) * Frequency-based ZF and MMSE equalizer * Evolved multimedia broadcast and multicast service (eMBMS) - * Highly optimized Turbo Decoder available in Intel SSE4.1/AVX (+100 Mbps) and standard C (+25 Mbps) + * Highly optimized Turbo Decoder available in Intel SSE4.1/AVX2 (+100 Mbps) and standard C (+25 Mbps) * MAC, RLC, PDCP, RRC, NAS, S1AP and GW layers * Detailed log system with per-layer log levels and hex dumps * MAC layer wireshark packet capture @@ -57,6 +57,8 @@ srsENB has been tested and validated with the following handsets: * LG Nexus 5 * LG Nexus 4 * Motorola Moto G4 plus + * Huawei P9/P9lite + * Huawei dongles: E3276 and E398 Hardware -------- From a5b384da4acdfedd2cb561e278dc264ccf2ed37c Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 7 Oct 2017 21:31:13 +0200 Subject: [PATCH 034/242] Added support for roaming PLMN --- lib/include/srslte/common/bcd_helpers.h | 2 +- lib/include/srslte/interfaces/ue_interfaces.h | 2 ++ srsue/hdr/upper/nas.h | 1 + srsue/hdr/upper/rrc.h | 2 +- srsue/src/phy/phch_recv.cc | 1 + srsue/src/upper/nas.cc | 34 ++++++++++++++++--- srsue/src/upper/rrc.cc | 15 ++++++-- 7 files changed, 48 insertions(+), 9 deletions(-) diff --git a/lib/include/srslte/common/bcd_helpers.h b/lib/include/srslte/common/bcd_helpers.h index 55411ae33..b696954c2 100644 --- a/lib/include/srslte/common/bcd_helpers.h +++ b/lib/include/srslte/common/bcd_helpers.h @@ -113,7 +113,7 @@ inline bool mnc_to_string(uint16_t mnc, std::string *str) *str += (mnc & 0x000F) + '0'; return true; } -inline std::string plmn_id_to_c_str(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) { +inline std::string plmn_id_to_string(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) { std::string mcc_str, mnc_str; mnc_to_string(plmn_id.mnc, &mnc_str); mcc_to_string(plmn_id.mcc, &mcc_str); diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index 2c29bd4d4..15ef48568 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -104,6 +104,7 @@ public: virtual uint32_t get_ul_count() = 0; virtual bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) = 0; virtual void plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) = 0; + virtual void plmn_search_end() = 0; }; // NAS interface for UE @@ -140,6 +141,7 @@ class rrc_interface_phy public: virtual void in_sync() = 0; virtual void out_of_sync() = 0; + virtual void earfcn_end() = 0; virtual void cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) = 0; }; diff --git a/srsue/hdr/upper/nas.h b/srsue/hdr/upper/nas.h index 68d00ba06..7c1420128 100644 --- a/srsue/hdr/upper/nas.h +++ b/srsue/hdr/upper/nas.h @@ -91,6 +91,7 @@ public: bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi); void plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code); + void plmn_search_end(); // UE interface void attach_request(); diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index 8dfa7f70d..3643f76c3 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -177,8 +177,8 @@ private: // PHY interface void in_sync(); - void out_of_sync(); + void earfcn_end(); void cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp); // MAC interface diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 718b15b81..c14141257 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -479,6 +479,7 @@ void phch_recv::cell_search_inc() if (cur_earfcn_index >= 0) { if (cur_earfcn_index >= (int) earfcn.size() - 1) { cur_earfcn_index = 0; + rrc->earfcn_end(); } } Info("SYNC: Cell Search idx %d/%d\n", cur_earfcn_index, earfcn.size()); diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index 91b35ce01..2d9da4c2e 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -72,7 +72,7 @@ void nas::attach_request() { nas_log->info("Starting PLMN Search...\n"); rrc->plmn_search(); } else if (plmn_selection == PLMN_SELECTED) { - nas_log->info("Selecting PLMN %s\n", plmn_id_to_c_str(current_plmn).c_str()); + nas_log->info("Selecting PLMN %s\n", plmn_id_to_string(current_plmn).c_str()); rrc->plmn_select(current_plmn); selecting_plmn = current_plmn; } @@ -96,25 +96,49 @@ RRC interface void nas::plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) { - // Store PLMN if not registered + // Check if already registered for (uint32_t i=0;iinfo("Detected known PLMN %s\n", plmn_id_to_c_str(plmn_id).c_str()); + nas_log->info("Found known PLMN Id=%s\n", plmn_id_to_string(plmn_id).c_str()); if (plmn_id.mcc == home_plmn.mcc && plmn_id.mnc == home_plmn.mnc) { + nas_log->info("Connecting Home PLMN Id=%s\n", plmn_id_to_string(plmn_id).c_str()); rrc->plmn_select(plmn_id); selecting_plmn = plmn_id; } return; } } - nas_log->info("Found PLMN: Id=%s, TAC=%d\n", plmn_id_to_c_str(plmn_id).c_str(), + + // Save if new PLMN + known_plmns.push_back(plmn_id); + + nas_log->info("Found PLMN: Id=%s, TAC=%d\n", plmn_id_to_string(plmn_id).c_str(), tracking_area_code); - nas_log->console("Found PLMN: Id=%s, TAC=%d\n", plmn_id_to_c_str(plmn_id).c_str(), + nas_log->console("Found PLMN: Id=%s, TAC=%d\n", plmn_id_to_string(plmn_id).c_str(), tracking_area_code); + if (plmn_id.mcc == home_plmn.mcc && plmn_id.mnc == home_plmn.mnc) { rrc->plmn_select(plmn_id); selecting_plmn = plmn_id; } + +} + +// RRC indicates that the UE has gone through all EARFCN and finished PLMN selection +void nas::plmn_search_end() { + if (known_plmns.size() > 0) { + nas_log->info("Could not find Home PLMN Id=%s, trying to connect to PLMN Id=%s\n", + plmn_id_to_string(home_plmn).c_str(), + plmn_id_to_string(known_plmns[0]).c_str()); + + nas_log->console("Could not find Home PLMN Id=%s, trying to connect to PLMN Id=%s\n", + plmn_id_to_string(home_plmn).c_str(), + plmn_id_to_string(known_plmns[0]).c_str()); + + rrc->plmn_select(known_plmns[0]); + } else { + nas_log->info("Finished searching PLMN in current EARFCN set but no networks were found.\n"); + } } bool nas::is_attached() { diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 1d614aed4..3ebeb97dd 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -177,7 +177,7 @@ void rrc::run_thread() { case RRC_STATE_PLMN_SELECTION: plmn_select_timeout++; if (plmn_select_timeout >= RRC_PLMN_SELECT_TIMEOUT) { - rrc_log->info("RRC PLMN Search: timeout expired. Searching again\n"); + rrc_log->info("RRC PLMN Search: timeout expired\n"); phy->cell_search_stop(); sleep(1); rrc_log->console("\nRRC PLMN Search: timeout expired. Searching again\n"); @@ -369,7 +369,7 @@ void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) { state = RRC_STATE_CELL_SELECTING; select_cell_timeout = 0; } else { - rrc_log->info("PLMN %s selected\n", plmn_id_to_c_str(plmn_id).c_str()); + rrc_log->info("PLMN Id=%s selected\n", plmn_id_to_string(plmn_id).c_str()); // Sort cells according to RSRP selected_plmn_id = plmn_id; @@ -431,6 +431,8 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { for (uint32_t i = 0; i < current_cell->sib1.N_plmn_ids; i++) { nas->plmn_found(current_cell->sib1.plmn_id[i].id, current_cell->sib1.tracking_area_code); } + usleep(5000); + phy->cell_search_next(); } return; } @@ -454,6 +456,15 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { cell.earfcn, cell.rsrp); } +// PHY indicates that has gone through all known EARFCN +void rrc::earfcn_end() { + rrc_log->info("Finished searching cells in EARFCN set while in state %s\n", rrc_state_text[state]); + + // If searching for PLMN, indicate NAS we scanned all frequencies + if (state == RRC_STATE_PLMN_SELECTION) { + nas->plmn_search_end(); + } +} From c7d5231251c235a6244c1dcc4bcd198b281c363f Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 7 Oct 2017 21:58:08 +0200 Subject: [PATCH 035/242] Read Home PLMN from IMSI --- lib/include/srslte/interfaces/ue_interfaces.h | 1 + srsue/hdr/upper/nas.h | 1 - srsue/hdr/upper/usim.h | 3 + srsue/src/ue.cc | 3 +- srsue/src/upper/nas.cc | 11 +++- srsue/src/upper/rrc.cc | 2 +- srsue/src/upper/usim.cc | 60 +++++++++++++++++-- 7 files changed, 69 insertions(+), 12 deletions(-) diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index 15ef48568..8561ba55c 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -54,6 +54,7 @@ class usim_interface_nas public: virtual void get_imsi_vec(uint8_t* imsi_, uint32_t n) = 0; virtual void get_imei_vec(uint8_t* imei_, uint32_t n) = 0; + virtual int get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id) = 0; virtual void generate_authentication_response(uint8_t *rand, uint8_t *autn_enb, uint16_t mcc, diff --git a/srsue/hdr/upper/nas.h b/srsue/hdr/upper/nas.h index 7c1420128..e743165fb 100644 --- a/srsue/hdr/upper/nas.h +++ b/srsue/hdr/upper/nas.h @@ -95,7 +95,6 @@ public: // UE interface void attach_request(); - void deattach_request(); private: diff --git a/srsue/hdr/upper/usim.h b/srsue/hdr/upper/usim.h index bb4e394bd..fea15ba68 100644 --- a/srsue/hdr/upper/usim.h +++ b/srsue/hdr/upper/usim.h @@ -61,6 +61,7 @@ public: // NAS interface void get_imsi_vec(uint8_t* imsi_, uint32_t n); void get_imei_vec(uint8_t* imei_, uint32_t n); + int get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id); void generate_authentication_response(uint8_t *rand, uint8_t *autn_enb, @@ -119,6 +120,8 @@ private: uint8_t k_asme[32]; uint8_t k_enb[32]; + bool initiated; + }; } // namespace srsue diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index 03e4b6546..92adaf8dd 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -181,11 +181,10 @@ bool ue::init(all_args_t *args_) rlc.init(&pdcp, &rrc, this, &rlc_log, &mac, 0 /* RB_ID_SRB0 */); pdcp.init(&rlc, &rrc, &gw, &pdcp_log, 0 /* RB_ID_SRB0 */, SECURITY_DIRECTION_UPLINK); + usim.init(&args->usim, &usim_log); nas.init(&usim, &rrc, &gw, &nas_log, 1 /* RB_ID_SRB1 */); gw.init(&pdcp, &nas, &gw_log, 3 /* RB_ID_DRB1 */); - usim.init(&args->usim, &usim_log); - 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/nas.cc b/srsue/src/upper/nas.cc index 2d9da4c2e..f0fd8cf54 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -50,8 +50,12 @@ void nas::init(usim_interface_nas *usim_, nas_log = nas_log_; state = EMM_STATE_DEREGISTERED; plmn_selection = PLMN_NOT_SELECTED; - home_plmn.mcc = 61441; // This is 001 - home_plmn.mnc = 65281; // This is 01 + + if (usim->get_home_plmn_id(&home_plmn)) { + nas_log->error("Getting Home PLMN Id from USIM. Defaulting to 001-01\n"); + home_plmn.mcc = 61441; // This is 001 + home_plmn.mnc = 65281; // This is 01 + } cfg = cfg_; } @@ -64,6 +68,7 @@ emm_state_t nas::get_state() { /******************************************************************************* UE interface *******************************************************************************/ + void nas::attach_request() { nas_log->info("Attach Request\n"); if (state == EMM_STATE_DEREGISTERED) { @@ -137,7 +142,7 @@ void nas::plmn_search_end() { rrc->plmn_select(known_plmns[0]); } else { - nas_log->info("Finished searching PLMN in current EARFCN set but no networks were found.\n"); + nas_log->debug("Finished searching PLMN in current EARFCN set but no networks were found.\n"); } } diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 3ebeb97dd..7b78bd774 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -458,7 +458,7 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { // PHY indicates that has gone through all known EARFCN void rrc::earfcn_end() { - rrc_log->info("Finished searching cells in EARFCN set while in state %s\n", rrc_state_text[state]); + rrc_log->debug("Finished searching cells in EARFCN set while in state %s\n", rrc_state_text[state]); // If searching for PLMN, indicate NAS we scanned all frequencies if (state == RRC_STATE_PLMN_SELECTION) { diff --git a/srsue/src/upper/usim.cc b/srsue/src/upper/usim.cc index 7b1f92896..418bb6f78 100644 --- a/srsue/src/upper/usim.cc +++ b/srsue/src/upper/usim.cc @@ -25,13 +25,15 @@ */ +#include #include "upper/usim.h" +#include "srslte/common/bcd_helpers.h" using namespace srslte; namespace srsue{ -usim::usim() +usim::usim() : initiated(false) {} void usim::init(usim_args_t *args, srslte::log *usim_log_) @@ -91,6 +93,7 @@ void usim::init(usim_args_t *args, srslte::log *usim_log_) if("xor" == args->algo) { auth_algo = auth_algo_xor; } + initiated = true; } void usim::stop() @@ -102,6 +105,11 @@ void usim::stop() void usim::get_imsi_vec(uint8_t* imsi_, uint32_t n) { + if (!initiated) + { + usim_log->error("Getting IMSI: USIM not initiated\n"); + return; + } if(NULL == imsi_ || n < 15) { usim_log->error("Invalid parameters to get_imsi_vec"); @@ -111,13 +119,18 @@ void usim::get_imsi_vec(uint8_t* imsi_, uint32_t n) uint64_t temp = imsi; for(int i=14;i>=0;i--) { - imsi_[i] = temp % 10; - temp /= 10; + imsi_[i] = temp % 10; + temp /= 10; } } void usim::get_imei_vec(uint8_t* imei_, uint32_t n) { + if (!initiated) + { + usim_log->error("Getting IMEI: USIM not initiated\n"); + return; + } if(NULL == imei_ || n < 15) { usim_log->error("Invalid parameters to get_imei_vec"); @@ -127,9 +140,46 @@ void usim::get_imei_vec(uint8_t* imei_, uint32_t n) uint64 temp = imei; for(int i=14;i>=0;i--) { - imei_[i] = temp % 10; - temp /= 10; + imei_[i] = temp % 10; + temp /= 10; + } +} + +int usim::get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id) +{ + if (!initiated) + { + usim_log->error("Getting Home PLMN Id: USIM not initiated\n"); + return -1; } + + uint32_t mcc_len = 3; + uint32_t mnc_len = 2; + + uint8_t imsi_vec[15]; + get_imsi_vec(imsi_vec, 15); + + std::ostringstream mcc_str, mnc_str; + + for (int i=0;imcc); + string_to_mnc(mnc_str.str(), &home_plmn_id->mnc); + + usim_log->info("Read Home PLMN Id=%s\n", + plmn_id_to_string(*home_plmn_id).c_str()); + + return 0; } void usim::generate_authentication_response(uint8_t *rand, From 7a14e2883748bf48cf1accb7222f79c2be0f2497 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 7 Oct 2017 22:17:39 +0200 Subject: [PATCH 036/242] Extened to all US MCC codes --- srsue/src/upper/usim.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/srsue/src/upper/usim.cc b/srsue/src/upper/usim.cc index 418bb6f78..9be69383e 100644 --- a/srsue/src/upper/usim.cc +++ b/srsue/src/upper/usim.cc @@ -153,8 +153,8 @@ int usim::get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id) return -1; } - uint32_t mcc_len = 3; - uint32_t mnc_len = 2; + int mcc_len = 3; + int mnc_len = 2; uint8_t imsi_vec[15]; get_imsi_vec(imsi_vec, 15); @@ -166,7 +166,12 @@ int usim::get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id) } // US MCC uses 3 MNC digits - if (!mcc_str.str().compare("310")) { + if (!mcc_str.str().compare("310") || + !mcc_str.str().compare("311") || + !mcc_str.str().compare("312") || + !mcc_str.str().compare("313") || + !mcc_str.str().compare("316")) + { mnc_len = 3; } for (int i=mcc_len;i Date: Sat, 7 Oct 2017 23:40:59 +0200 Subject: [PATCH 037/242] Update enb.conf.example --- srsenb/enb.conf.example | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srsenb/enb.conf.example b/srsenb/enb.conf.example index d88b63bb7..44e546116 100644 --- a/srsenb/enb.conf.example +++ b/srsenb/enb.conf.example @@ -123,8 +123,8 @@ enable = false #pdsch_mcs = -1 #pdsch_max_mcs = -1 #pusch_mcs = -1 -#pusch_max_mcs = -1 -nof_ctrl_symbols = 2 +pusch_max_mcs = 16 +nof_ctrl_symbols = 3 ##################################################################### # Expert configuration options From 5208c4c1602b63b814aee04b058f7e2119cf7d8f Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sun, 8 Oct 2017 00:41:39 +0200 Subject: [PATCH 038/242] Removed unused code --- srsenb/src/phy/phch_common.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/srsenb/src/phy/phch_common.cc b/srsenb/src/phy/phch_common.cc index c4b94153c..061743274 100644 --- a/srsenb/src/phy/phch_common.cc +++ b/srsenb/src/phy/phch_common.cc @@ -128,10 +128,6 @@ bool phch_common::ack_is_pending(uint32_t sf_idx, uint16_t rnti, uint32_t *last_ bool ret = pending_ack[rnti].is_pending[sf_idx]; pending_ack[rnti].is_pending[sf_idx] = false; - if (ret) { - - } - if (ret && last_n_pdcch) { *last_n_pdcch = pending_ack[rnti].n_pdcch[sf_idx]; } From 1a5cf45ddacb16271bf70df002ff7ad881a84690 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 9 Oct 2017 16:30:32 +0200 Subject: [PATCH 039/242] Solved compilation error for SSE (Tested in Atom) --- lib/include/srslte/phy/utils/simd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/include/srslte/phy/utils/simd.h b/lib/include/srslte/phy/utils/simd.h index 2590794f2..08eed115f 100644 --- a/lib/include/srslte/phy/utils/simd.h +++ b/lib/include/srslte/phy/utils/simd.h @@ -738,7 +738,7 @@ typedef __m256 simd_sel_t; #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE typedef __m128i simd_i_t; -typedef __m128i simd_sel_t; +typedef __m128 simd_sel_t; #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -807,7 +807,7 @@ static inline simd_sel_t srslte_simd_f_max(simd_f_t a, simd_f_t b) { return _mm256_cmp_ps(a, b, _CMP_GT_OS); #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE - return (simd_i_t) _mm_cmpgt_ps(a, b); + return (simd_sel_t) _mm_cmpgt_ps(a, b); #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ From a180b5ebacfdfa8f90add5f764608ee57be3a8fd Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 10 Oct 2017 12:06:24 +0200 Subject: [PATCH 040/242] Msg3 delay is added to harq delay --- lib/include/srslte/common/common.h | 2 +- srsenb/src/mac/scheduler.cc | 2 +- srsue/src/phy/phch_common.cc | 10 ++++------ 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/include/srslte/common/common.h b/lib/include/srslte/common/common.h index fd785fbca..6372af73e 100644 --- a/lib/include/srslte/common/common.h +++ b/lib/include/srslte/common/common.h @@ -45,7 +45,7 @@ #define SRSLTE_N_RADIO_BEARERS 11 #define HARQ_DELAY_MS 4 -#define MSG3_DELAY_MS 6 +#define MSG3_DELAY_MS 2 // Delay added to HARQ_DELAY_MS #define TTI_TX(tti) ((tti+HARQ_DELAY_MS)%10240) #define TTI_RX_ACK(tti) ((tti+(2*HARQ_DELAY_MS))%10240) diff --git a/srsenb/src/mac/scheduler.cc b/srsenb/src/mac/scheduler.cc index 21d60652d..a7e3d12d6 100644 --- a/srsenb/src/mac/scheduler.cc +++ b/srsenb/src/mac/scheduler.cc @@ -541,7 +541,7 @@ int sched::dl_sched_rar(dl_sched_rar_t rar[MAX_RAR_LIST]) pending_rar[j].rar_tti = 0; // Save UL resources - uint32_t pending_tti=(current_tti+MSG3_DELAY_MS)%10; + uint32_t pending_tti=(current_tti+MSG3_DELAY_MS+HARQ_DELAY_MS)%10; pending_msg3[pending_tti].enabled = true; pending_msg3[pending_tti].rnti = pending_rar[j].rnti; pending_msg3[pending_tti].L = L_prb; diff --git a/srsue/src/phy/phch_common.cc b/srsue/src/phy/phch_common.cc index 549783fd9..7d2948c1a 100644 --- a/srsue/src/phy/phch_common.cc +++ b/srsue/src/phy/phch_common.cc @@ -137,15 +137,13 @@ void phch_common::set_rar_grant(uint32_t tti, uint8_t grant_payload[SRSLTE_RAR_G { srslte_dci_rar_grant_unpack(&rar_grant, grant_payload); rar_grant_pending = true; - int delay = MSG3_DELAY_MS-HARQ_DELAY_MS; - if (delay < 0) { - fprintf(stderr, "Error MSG3_DELAY_MS can't be lower than HARQ_DELAY_MS\n"); - delay = 0; + if (MSG3_DELAY_MS < 0) { + fprintf(stderr, "Error MSG3_DELAY_MS can't be negative\n"); } if (rar_grant.ul_delay) { - rar_grant_tti = (tti + delay + 1) % 10240; + rar_grant_tti = (tti + MSG3_DELAY_MS + 1) % 10240; } else { - rar_grant_tti = (tti + delay) % 10240; + rar_grant_tti = (tti + MSG3_DELAY_MS) % 10240; } } From fda886407b7bebe2537ee608687f74f5dae9cf81 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 10 Oct 2017 12:33:10 +0200 Subject: [PATCH 041/242] Added option to force the DL/UL frequency at the UE --- srsenb/enb.conf.example | 4 +++- srsue/hdr/phy/phch_recv.h | 5 +++++ srsue/hdr/phy/phy.h | 3 ++- srsue/src/main.cc | 2 ++ srsue/src/phy/phch_recv.cc | 29 ++++++++++++++++++++++------- srsue/src/phy/phy.cc | 5 +++++ srsue/src/ue.cc | 4 ++++ srsue/ue.conf.example | 2 ++ 8 files changed, 45 insertions(+), 9 deletions(-) diff --git a/srsenb/enb.conf.example b/srsenb/enb.conf.example index 44e546116..7f023d0c6 100644 --- a/srsenb/enb.conf.example +++ b/srsenb/enb.conf.example @@ -45,7 +45,9 @@ drb_config = drb.conf # tx_gain: Transmit gain (dB). # rx_gain: Optional receive gain (dB). If disabled, AGC if enabled # -# Optional parameters: +# Optional parameters: +# dl_freq: Override DL frequency corresponding to dl_earfcn +# ul_freq: Override UL frequency corresponding to dl_earfcn (must be set if dl_freq is set) # device_name: Device driver family. Supported options: "auto" (uses first found), "UHD" or "bladeRF" # device_args: Arguments for the device driver. Options are "auto" or any string. # Default for UHD: "recv_frame_size=9232,send_frame_size=9232" diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index 044960760..c51622e53 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -53,6 +53,7 @@ public: void set_agc_enable(bool enable); void set_earfcn(std::vector earfcn); + void force_freq(float dl_freq, float ul_freq); void reset_sync(); void cell_search_start(); @@ -171,6 +172,10 @@ private: int cell_meas_rsrp(); int cell_search(int force_N_id_2 = -1); bool set_cell(); + + float dl_freq; + float ul_freq; + }; } // namespace srsue diff --git a/srsue/hdr/phy/phy.h b/srsue/hdr/phy/phy.h index 0c77360b2..07a2713fa 100644 --- a/srsue/hdr/phy/phy.h +++ b/srsue/hdr/phy/phy.h @@ -76,6 +76,7 @@ public: void write_trace(std::string filename); void set_earfcn(std::vector earfcns); + void force_freq(float dl_freq, float ul_freq); /********** RRC INTERFACE ********************/ void reset(); @@ -167,7 +168,7 @@ private: /* Current time advance */ uint32_t n_ta; - + bool init_(srslte::radio *radio_handler, mac_interface_phy *mac, srslte::log *log_h, bool do_agc, uint32_t nof_workers); void set_default_args(phy_args_t *args); bool check_args(phy_args_t *args); diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 569083998..47d5f807e 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -65,6 +65,8 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { common.add_options() ("rf.dl_earfcn", bpo::value(&args->rf.dl_earfcn)->default_value(3400), "Downlink EARFCN") ("rf.freq_offset", bpo::value(&args->rf.freq_offset)->default_value(0), "(optional) Frequency offset") + ("rf.dl_freq", bpo::value(&args->rf.dl_freq)->default_value(-1), "Downlink Frequency (if positive overrides EARFCN)") + ("rf.ul_freq", bpo::value(&args->rf.ul_freq)->default_value(-1), "Uplink Frequency (if positive overrides EARFCN)") ("rf.rx_gain", bpo::value(&args->rf.rx_gain)->default_value(-1), "Front-end receiver gain") ("rf.tx_gain", bpo::value(&args->rf.tx_gain)->default_value(-1), "Front-end transmitter gain") ("rf.nof_rx_ant", bpo::value(&args->rf.nof_rx_ant)->default_value(1), "Number of RX antennas") diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index e10c013fe..8642460aa 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -63,6 +63,8 @@ double callback_set_rx_gain(void *h, double gain) { phch_recv::phch_recv() { + dl_freq = -1; + ul_freq = -1; bzero(&cell, sizeof(srslte_cell_t)); running = false; } @@ -445,6 +447,11 @@ void phch_recv::set_earfcn(std::vector earfcn) { this->earfcn = earfcn; } +void phch_recv::force_freq(float dl_freq, float ul_freq) { + this->dl_freq = dl_freq; + this->ul_freq = ul_freq; +} + bool phch_recv::stop_sync() { wait_radio_reset(); @@ -568,17 +575,25 @@ bool phch_recv::cell_select(uint32_t earfcn, srslte_cell_t cell) { bool phch_recv::set_frequency() { - double dl_freq = 1e6*srslte_band_fd(current_earfcn); - double ul_freq = 1e6*srslte_band_fu(srslte_band_ul_earfcn(current_earfcn)); - if (dl_freq > 0 && ul_freq > 0) { + double set_dl_freq = 0; + double set_ul_freq = 0; + + if (this->dl_freq > 0 && this->ul_freq > 0) { + set_dl_freq = this->dl_freq; + set_ul_freq = this->ul_freq; + } else { + set_dl_freq = 1e6*srslte_band_fd(current_earfcn); + set_ul_freq = 1e6*srslte_band_fu(srslte_band_ul_earfcn(current_earfcn)); + } + if (set_dl_freq > 0 && set_ul_freq > 0) { log_h->info("SYNC: Set DL EARFCN=%d, f_dl=%.1f MHz, f_ul=%.1f MHz\n", - current_earfcn, dl_freq / 1e6, ul_freq / 1e6); + current_earfcn, set_dl_freq / 1e6, set_ul_freq / 1e6); log_h->console("Searching cell in DL EARFCN=%d, f_dl=%.1f MHz, f_ul=%.1f MHz\n", - current_earfcn, dl_freq / 1e6, ul_freq / 1e6); + current_earfcn, set_dl_freq / 1e6, set_ul_freq / 1e6); - radio_h->set_rx_freq(dl_freq); - radio_h->set_tx_freq(ul_freq); + radio_h->set_rx_freq(set_dl_freq); + radio_h->set_tx_freq(set_ul_freq); ul_dl_factor = radio_h->get_tx_freq()/radio_h->get_rx_freq(); srslte_ue_sync_reset(&ue_sync); diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index e74107661..df29726d5 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -332,6 +332,11 @@ void phy::set_earfcn(vector< uint32_t > earfcns) sf_recv.set_earfcn(earfcns); } +void phy::force_freq(float dl_freq, float ul_freq) +{ + sf_recv.force_freq(dl_freq, ul_freq); +} + bool phy::sync_status() { return sf_recv.status_is_sync(); diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index 92adaf8dd..3560a78fe 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -193,6 +193,10 @@ bool ue::init(all_args_t *args_) earfcn_list.push_back(args->rf.dl_earfcn); phy.set_earfcn(earfcn_list); + if (args->rf.dl_freq > 0 && args->rf.ul_freq > 0) { + phy.force_freq(args->rf.dl_freq, args->rf.ul_freq); + } + printf("Waiting PHY to initialize...\n"); phy.wait_initialize(); phy.configure_ul_params(); diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index 30c05069a..5d14d3c3c 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -9,6 +9,8 @@ # rx_gain: Optional receive gain (dB). If disabled, AGC if enabled # # Optional parameters: +# dl_freq: Override DL frequency corresponding to dl_earfcn +# ul_freq: Override UL frequency corresponding to dl_earfcn # nof_rx_ant: Number of RX antennas (Default 1, supported 1 or 2) # device_name: Device driver family. Supported options: "auto" (uses first found), "UHD" or "bladeRF" # device_args: Arguments for the device driver. Options are "auto" or any string. From e8da7160f09b5b00d5f7de4e6432d440fc9a775a Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 10 Oct 2017 13:24:23 +0200 Subject: [PATCH 042/242] eNB transmits diversity by default if two cell ports are configured --- lib/include/srslte/phy/enb/enb_dl.h | 6 ++--- lib/include/srslte/phy/rf/rf.h | 10 +++---- lib/include/srslte/radio/radio.h | 8 +++--- lib/src/phy/enb/enb_dl.c | 11 ++++---- lib/src/phy/rf/rf_imp.c | 12 +++------ lib/src/radio/radio.cc | 30 +++++++++++++-------- lib/src/radio/radio_multi.cc | 2 +- srsenb/hdr/enb.h | 2 ++ srsenb/hdr/phy/phch_common.h | 2 +- srsenb/hdr/phy/phch_worker.h | 6 ++--- srsenb/hdr/upper/rrc.h | 1 + srsenb/src/enb.cc | 2 +- srsenb/src/enb_cfg_parser.cc | 26 +++++++++++++++++- srsenb/src/mac/mac.cc | 24 ++++++++--------- srsenb/src/main.cc | 6 +++-- srsenb/src/phy/phch_common.cc | 6 ++--- srsenb/src/phy/phch_worker.cc | 41 +++++++++++++++-------------- srsenb/src/phy/txrx.cc | 12 +++++---- srsue/hdr/phy/prach.h | 4 +-- srsue/src/phy/phch_common.cc | 4 +-- srsue/src/phy/prach.cc | 22 +++++++++------- 21 files changed, 137 insertions(+), 100 deletions(-) diff --git a/lib/include/srslte/phy/enb/enb_dl.h b/lib/include/srslte/phy/enb/enb_dl.h index 7c3166e5c..b63cb6416 100644 --- a/lib/include/srslte/phy/enb/enb_dl.h +++ b/lib/include/srslte/phy/enb/enb_dl.h @@ -97,8 +97,8 @@ typedef struct { uint16_t rnti; srslte_ra_dl_dci_t grant; srslte_dci_location_t location; - srslte_softbuffer_tx_t *softbuffer; - uint8_t *data; + srslte_softbuffer_tx_t *softbuffers[SRSLTE_MAX_TB]; + uint8_t *data[SRSLTE_MAX_TB]; } srslte_enb_dl_pdsch_t; typedef struct { @@ -147,7 +147,7 @@ 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); + cf_t *signal_buffer[SRSLTE_MAX_PORTS]); SRSLTE_API int srslte_enb_dl_add_rnti(srslte_enb_dl_t *q, uint16_t rnti); diff --git a/lib/include/srslte/phy/rf/rf.h b/lib/include/srslte/phy/rf/rf.h index 860e0a257..c171e69d1 100644 --- a/lib/include/srslte/phy/rf/rf.h +++ b/lib/include/srslte/phy/rf/rf.h @@ -73,16 +73,12 @@ SRSLTE_API int srslte_rf_open(srslte_rf_t *h, SRSLTE_API int srslte_rf_open_multi(srslte_rf_t *h, char *args, - uint32_t nof_rx_antennas); + uint32_t nof_channels); SRSLTE_API int srslte_rf_open_devname(srslte_rf_t *h, char *devname, - char *args); - -SRSLTE_API int srslte_rf_open_devname_multi(srslte_rf_t *h, - char *devname, - char *args, - uint32_t nof_rx_antennas); + char *args, + uint32_t nof_channels); SRSLTE_API const char *srslte_rf_name(srslte_rf_t *h); diff --git a/lib/include/srslte/radio/radio.h b/lib/include/srslte/radio/radio.h index 329dd825a..2a34bd9a9 100644 --- a/lib/include/srslte/radio/radio.h +++ b/lib/include/srslte/radio/radio.h @@ -74,7 +74,7 @@ namespace srslte { agc_enabled = false; }; - bool init(char *args = NULL, char *devname = NULL); + bool init(char *args = NULL, char *devname = NULL, uint32_t nof_channels = 1); void stop(); void reset(); bool start_agc(bool tx_gain_same_rx); @@ -86,9 +86,10 @@ namespace srslte { void set_manual_calibration(rf_cal_t *calibration); void get_time(srslte_timestamp_t *now); - bool tx(void *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time); + bool tx_single(void *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time); + bool tx(void *buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t tx_time); void tx_end(); - bool rx_now(void *buffer, uint32_t nof_samples, srslte_timestamp_t *rxd_time); + bool rx_now(void *buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t *rxd_time); bool rx_at(void *buffer, uint32_t nof_samples, srslte_timestamp_t rx_time); void set_tx_gain(float gain); @@ -166,6 +167,7 @@ namespace srslte { uint32_t tti; bool agc_enabled; + uint32_t saved_nof_channels; char saved_args[128]; char saved_devname[128]; diff --git a/lib/src/phy/enb/enb_dl.c b/lib/src/phy/enb/enb_dl.c index 2ba179399..7b2723765 100644 --- a/lib/src/phy/enb/enb_dl.c +++ b/lib/src/phy/enb/enb_dl.c @@ -264,14 +264,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, cf_t *signal_buffer[SRSLTE_MAX_PORTS]) { - - 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)); + + for (int p = 0; p < SRSLTE_MAX_PORTS; p++) { + srslte_ofdm_tx_sf(&q->ifft, q->sf_symbols[p], signal_buffer[p]); + srslte_vec_sc_prod_cfc(signal_buffer[p], q->tx_amp*norm_factor, signal_buffer[p], (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/rf/rf_imp.c b/lib/src/phy/rf/rf_imp.c index c1074ebc5..7149cec9d 100644 --- a/lib/src/phy/rf/rf_imp.c +++ b/lib/src/phy/rf/rf_imp.c @@ -98,11 +98,7 @@ const char* srslte_rf_get_devname(srslte_rf_t *rf) { return ((rf_dev_t*) rf->dev)->name; } -int srslte_rf_open_devname(srslte_rf_t *rf, char *devname, char *args) { - return srslte_rf_open_devname_multi(rf, devname, args, 1); -} - -int srslte_rf_open_devname_multi(srslte_rf_t *rf, char *devname, char *args, uint32_t nof_channels) { +int srslte_rf_open_devname(srslte_rf_t *rf, char *devname, char *args, uint32_t nof_channels) { /* Try to open the device if name is provided */ if (devname) { if (devname[0] != '\0') { @@ -186,12 +182,12 @@ void srslte_rf_register_error_handler(srslte_rf_t *rf, srslte_rf_error_handler_t int srslte_rf_open(srslte_rf_t *h, char *args) { - return srslte_rf_open_devname_multi(h, NULL, args, 1); + return srslte_rf_open_devname(h, NULL, args, 1); } -int srslte_rf_open_multi(srslte_rf_t *h, char *args, uint32_t nof_rx_antennas) +int srslte_rf_open_multi(srslte_rf_t *h, char *args, uint32_t nof_channels) { - return srslte_rf_open_devname_multi(h, NULL, args, nof_rx_antennas); + return srslte_rf_open_devname(h, NULL, args, nof_channels); } int srslte_rf_close(srslte_rf_t *rf) diff --git a/lib/src/radio/radio.cc b/lib/src/radio/radio.cc index b393a3ff4..c6abb8642 100644 --- a/lib/src/radio/radio.cc +++ b/lib/src/radio/radio.cc @@ -34,9 +34,9 @@ extern "C" { namespace srslte { -bool radio::init(char *args, char *devname) +bool radio::init(char *args, char *devname, uint32_t nof_channels) { - if (srslte_rf_open_devname(&rf_device, devname, args)) { + if (srslte_rf_open_devname(&rf_device, devname, args, nof_channels)) { fprintf(stderr, "Error opening RF device\n"); return false; } @@ -68,6 +68,7 @@ bool radio::init(char *args, char *devname) if (devname) { strncpy(saved_devname, devname, 128); } + saved_nof_channels = nof_channels; return true; } @@ -82,7 +83,7 @@ void radio::reset() printf("Resetting Radio...\n"); srslte_rf_close(&rf_device); sleep(3); - if (srslte_rf_open_devname(&rf_device, saved_devname, saved_args)) { + if (srslte_rf_open_devname(&rf_device, saved_devname, saved_args, saved_nof_channels)) { fprintf(stderr, "Error opening RF device\n"); } } @@ -137,9 +138,9 @@ bool radio::rx_at(void* buffer, uint32_t nof_samples, srslte_timestamp_t rx_time return false; } -bool radio::rx_now(void* buffer, uint32_t nof_samples, srslte_timestamp_t* rxd_time) +bool radio::rx_now(void* buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t* rxd_time) { - if (srslte_rf_recv_with_time(&rf_device, buffer, nof_samples, true, + if (srslte_rf_recv_with_time_multi(&rf_device, buffer, nof_samples, true, rxd_time?&rxd_time->full_secs:NULL, rxd_time?&rxd_time->frac_secs:NULL) > 0) { return true; } else { @@ -186,10 +187,18 @@ bool radio::is_first_of_burst() { #define BLOCKING_TX true -bool radio::tx(void* buffer, uint32_t nof_samples, srslte_timestamp_t tx_time) -{ - void *iq_samples[4] = {(void *) zeros, (void *) zeros, (void *) zeros, (void *) zeros}; +bool radio::tx_single(void *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time) { + void *_buffer[SRSLTE_MAX_PORTS]; + + _buffer[0] = buffer; + for (int p = 1; p < SRSLTE_MAX_PORTS; p++) { + _buffer[p] = zeros; + } + + return this->tx(_buffer, nof_samples, tx_time); +} +bool radio::tx(void *buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t tx_time) { if (!tx_adv_negative) { srslte_timestamp_sub(&tx_time, 0, tx_adv_sec); } else { @@ -202,7 +211,7 @@ bool radio::tx(void* buffer, uint32_t nof_samples, srslte_timestamp_t tx_time) srslte_timestamp_copy(&tx_time_pad, &tx_time); srslte_timestamp_sub(&tx_time_pad, 0, burst_preamble_time_rounded); save_trace(1, &tx_time_pad); - srslte_rf_send_timed_multi(&rf_device, iq_samples, burst_preamble_samples, tx_time_pad.full_secs, tx_time_pad.frac_secs, true, true, false); + srslte_rf_send_timed_multi(&rf_device, buffer, burst_preamble_samples, tx_time_pad.full_secs, tx_time_pad.frac_secs, true, true, false); is_start_of_burst = false; } } @@ -212,8 +221,7 @@ bool radio::tx(void* buffer, uint32_t nof_samples, srslte_timestamp_t tx_time) srslte_timestamp_add(&end_of_burst_time, 0, (double) nof_samples/cur_tx_srate); save_trace(0, &tx_time); - iq_samples[0] = buffer; - int ret = srslte_rf_send_timed_multi(&rf_device, (void**) iq_samples, nof_samples, + int ret = srslte_rf_send_timed_multi(&rf_device, buffer, nof_samples, tx_time.full_secs, tx_time.frac_secs, BLOCKING_TX, is_start_of_burst, false); is_start_of_burst = false; diff --git a/lib/src/radio/radio_multi.cc b/lib/src/radio/radio_multi.cc index 018a675ac..2ec7f891c 100644 --- a/lib/src/radio/radio_multi.cc +++ b/lib/src/radio/radio_multi.cc @@ -4,7 +4,7 @@ namespace srslte { bool radio_multi::init_multi(uint32_t nof_rx_antennas, char* args, char* devname) { - if (srslte_rf_open_devname_multi(&rf_device, devname, args, nof_rx_antennas)) { + if (srslte_rf_open_devname(&rf_device, devname, args, nof_rx_antennas)) { fprintf(stderr, "Error opening RF device\n"); return false; } diff --git a/srsenb/hdr/enb.h b/srsenb/hdr/enb.h index 7b1681cd6..c40fcebf4 100644 --- a/srsenb/hdr/enb.h +++ b/srsenb/hdr/enb.h @@ -66,6 +66,8 @@ typedef struct { s1ap_args_t s1ap; uint32_t n_prb; uint32_t pci; + uint32_t nof_ports; + uint32_t transmission_mode; }enb_args_t; typedef struct { diff --git a/srsenb/hdr/phy/phch_common.h b/srsenb/hdr/phy/phch_common.h index 00a59d969..391d8932e 100644 --- a/srsenb/hdr/phy/phch_common.h +++ b/srsenb/hdr/phy/phch_common.h @@ -65,7 +65,7 @@ public: void set_nof_mutex(uint32_t nof_mutex); - void worker_end(uint32_t tx_mutex_cnt, cf_t *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time); + void worker_end(uint32_t tx_mutex_cnt, cf_t *buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t tx_time); // Common objects srslte_cell_t cell; diff --git a/srsenb/hdr/phy/phch_worker.h b/srsenb/hdr/phy/phch_worker.h index 906e8b9d0..42e36113d 100644 --- a/srsenb/hdr/phy/phch_worker.h +++ b/srsenb/hdr/phy/phch_worker.h @@ -45,7 +45,7 @@ public: void stop(); void reset(); - cf_t *get_buffer_rx(); + cf_t *get_buffer_rx(uint32_t antenna_idx); void set_time(uint32_t tti, uint32_t tx_mutex_cnt, srslte_timestamp_t tx_time); int add_rnti(uint16_t rnti); @@ -87,8 +87,8 @@ private: bool initiated; bool running; - cf_t *signal_buffer_rx; - cf_t *signal_buffer_tx; + cf_t *signal_buffer_rx[SRSLTE_MAX_PORTS]; + cf_t *signal_buffer_tx[SRSLTE_MAX_PORTS]; uint32_t tti_rx, tti_tx, tti_sched_ul, sf_rx, sf_tx, sf_sched_ul, tx_mutex_cnt; srslte_enb_dl_t enb_dl; diff --git a/srsenb/hdr/upper/rrc.h b/srsenb/hdr/upper/rrc.h index e0b9dd158..2ea07a749 100644 --- a/srsenb/hdr/upper/rrc.h +++ b/srsenb/hdr/upper/rrc.h @@ -79,6 +79,7 @@ typedef struct { LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_STRUCT sibs[LIBLTE_RRC_MAX_SIB]; LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT mac_cnfg; LIBLTE_RRC_PUSCH_CONFIG_DEDICATED_STRUCT pusch_cfg; + LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT antenna_info; rrc_cfg_sr_t sr_cfg; rrc_cfg_cqi_t cqi_cfg; rrc_cfg_qci_t qci_cfg[MAX_NOF_QCI]; diff --git a/srsenb/src/enb.cc b/srsenb/src/enb.cc index 82b4e8145..fad7e1528 100644 --- a/srsenb/src/enb.cc +++ b/srsenb/src/enb.cc @@ -136,7 +136,7 @@ bool enb::init(all_args_t *args_) dev_args = (char*) args->rf.device_args.c_str(); } - if(!radio.init(dev_args, dev_name)) + if(!radio.init(dev_args, dev_name, args->enb.nof_ports)) { printf("Failed to find device %s with args %s\n", args->rf.device_name.c_str(), args->rf.device_args.c_str()); diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 3beb85a65..a7734cd0c 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -37,7 +37,7 @@ namespace srsenb { int enb::parse_cell_cfg(all_args_t *args, srslte_cell_t *cell) { cell->id = args->enb.pci; cell->cp = SRSLTE_CP_NORM; - cell->nof_ports = 1; + cell->nof_ports = args->enb.nof_ports; cell->nof_prb = args->enb.n_prb; LIBLTE_RRC_PHICH_CONFIG_STRUCT phichcfg; @@ -842,6 +842,30 @@ bool enb::sib_is_present(LIBLTE_RRC_SCHEDULING_INFO_STRUCT *sched_info, uint32_t int enb::parse_rr(all_args_t* args, rrc_cfg_t* rrc_cfg) { + + /* Transmission mode config section */ + if (args->enb.transmission_mode < 0 || args->enb.transmission_mode > LIBLTE_RRC_TRANSMISSION_MODE_N_ITEMS) { + ERROR("Invalid transmission mode (%d). Only indexes 1-4 are implemented.\n", args->enb.transmission_mode); + return SRSLTE_ERROR; + } + + bzero(&rrc_cfg->antenna_info, sizeof(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT)); + rrc_cfg->antenna_info.tx_mode = (LIBLTE_RRC_TRANSMISSION_MODE_ENUM) (args->enb.transmission_mode - 1); + + if (rrc_cfg->antenna_info.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) { + rrc_cfg->antenna_info.ue_tx_antenna_selection_setup = LIBLTE_RRC_UE_TX_ANTENNA_SELECTION_OPEN_LOOP; + rrc_cfg->antenna_info.ue_tx_antenna_selection_setup_present = true; + + rrc_cfg->antenna_info.codebook_subset_restriction_choice = LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N2_TM3; + } else if (rrc_cfg->antenna_info.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { + rrc_cfg->antenna_info.ue_tx_antenna_selection_setup = LIBLTE_RRC_UE_TX_ANTENNA_SELECTION_CLOSED_LOOP; + rrc_cfg->antenna_info.ue_tx_antenna_selection_setup_present = true; + + rrc_cfg->antenna_info.codebook_subset_restriction_choice = LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N2_TM4; + rrc_cfg->antenna_info.codebook_subset_restriction = 0b111111; + rrc_cfg->antenna_info.codebook_subset_restriction_present = true; + } + /* MAC config section */ parser::section mac_cnfg("mac_cnfg"); diff --git a/srsenb/src/mac/mac.cc b/srsenb/src/mac/mac.cc index 6c8458540..796d08025 100644 --- a/srsenb/src/mac/mac.cc +++ b/srsenb/src/mac/mac.cc @@ -434,20 +434,20 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) memcpy(&dl_sched_res->sched_grants[n].grant, &sched_result.data[i].dci, sizeof(srslte_ra_dl_dci_t)); memcpy(&dl_sched_res->sched_grants[n].location, &sched_result.data[i].dci_location, sizeof(srslte_dci_location_t)); - dl_sched_res->sched_grants[n].softbuffer = ue_db[rnti]->get_tx_softbuffer(sched_result.data[i].dci.harq_process); + dl_sched_res->sched_grants[n].softbuffers[0] = ue_db[rnti]->get_tx_softbuffer(sched_result.data[i].dci.harq_process); // Get PDU if it's a new transmission if (sched_result.data[i].nof_pdu_elems > 0) { - dl_sched_res->sched_grants[n].data = ue_db[rnti]->generate_pdu(sched_result.data[i].pdu, + dl_sched_res->sched_grants[n].data[0] = ue_db[rnti]->generate_pdu(sched_result.data[i].pdu, sched_result.data[i].nof_pdu_elems, sched_result.data[i].tbs); if (pcap) { - pcap->write_dl_crnti(dl_sched_res->sched_grants[n].data, sched_result.data[i].tbs, rnti, true, tti); + pcap->write_dl_crnti(dl_sched_res->sched_grants[n].data[0], sched_result.data[i].tbs, rnti, true, tti); } } else { - dl_sched_res->sched_grants[n].data = NULL; + dl_sched_res->sched_grants[n].data[0] = NULL; } n++; } @@ -460,14 +460,14 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) memcpy(&dl_sched_res->sched_grants[n].location, &sched_result.rar[i].dci_location, sizeof(srslte_dci_location_t)); // Set softbuffer (there are no retx in RAR but a softbuffer is required) - dl_sched_res->sched_grants[n].softbuffer = &rar_softbuffer_tx; + dl_sched_res->sched_grants[n].softbuffers[0] = &rar_softbuffer_tx; // Assemble PDU - dl_sched_res->sched_grants[n].data = assemble_rar(sched_result.rar[i].grants, sched_result.rar[i].nof_grants, i, sched_result.rar[i].tbs); + dl_sched_res->sched_grants[n].data[0] = assemble_rar(sched_result.rar[i].grants, sched_result.rar[i].nof_grants, i, sched_result.rar[i].tbs); if (pcap) { - pcap->write_dl_ranti(dl_sched_res->sched_grants[n].data, sched_result.data[i].tbs, dl_sched_res->sched_grants[n].rnti, true, tti); + pcap->write_dl_ranti(dl_sched_res->sched_grants[n].data[0], sched_result.data[i].tbs, dl_sched_res->sched_grants[n].rnti, true, tti); } n++; @@ -482,20 +482,20 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) // Set softbuffer if (sched_result.bc[i].type == sched_interface::dl_sched_bc_t::BCCH) { - dl_sched_res->sched_grants[n].softbuffer = &bcch_softbuffer_tx[sched_result.bc[i].index]; - dl_sched_res->sched_grants[n].data = assemble_si(sched_result.bc[i].index); + dl_sched_res->sched_grants[n].softbuffers[0] = &bcch_softbuffer_tx[sched_result.bc[i].index]; + dl_sched_res->sched_grants[n].data[0] = assemble_si(sched_result.bc[i].index); #ifdef WRITE_SIB_PCAP if (pcap) { pcap->write_dl_sirnti(dl_sched_res->sched_grants[n].data, sched_result.bc[i].tbs, true, tti); } #endif } else { - dl_sched_res->sched_grants[n].softbuffer = &pcch_softbuffer_tx; - dl_sched_res->sched_grants[n].data = pcch_payload_buffer; + dl_sched_res->sched_grants[n].softbuffers[0] = &pcch_softbuffer_tx; + dl_sched_res->sched_grants[n].data[0] = pcch_payload_buffer; rlc_h->read_pdu_pcch(pcch_payload_buffer, pcch_payload_buffer_len); if (pcap) { - pcap->write_dl_pch(dl_sched_res->sched_grants[n].data, sched_result.bc[i].tbs, true, tti); + pcap->write_dl_pch(dl_sched_res->sched_grants[n].data[0], sched_result.bc[i].tbs, true, tti); } } diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 528878388..7978e6ddc 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -75,9 +75,11 @@ void parse_args(all_args_t *args, int argc, char* argv[]) { ("enb.mnc", bpo::value(&mnc)->default_value("01"), "Mobile Network Code") ("enb.mme_addr", bpo::value(&args->enb.s1ap.mme_addr)->default_value("127.0.0.1"),"IP address of MME for S1 connnection") ("enb.gtp_bind_addr", bpo::value(&args->enb.s1ap.gtp_bind_addr)->default_value("192.168.3.1"), "Local IP address to bind for GTP connection") - ("enb.phy_cell_id", bpo::value(&args->enb.pci)->default_value(0), "Physical Cell Identity (PCI)") + ("enb.phy_cell_id", bpo::value(&args->enb.pci)->default_value(0), "Physical Cell Identity (PCI)") ("enb.n_prb", bpo::value(&args->enb.n_prb)->default_value(25), "Number of PRB") - + ("enb.nof_ports", bpo::value(&args->enb.nof_ports)->default_value(1), "Number of ports") + ("enb.tm", bpo::value(&args->enb.transmission_mode)->default_value(1), "Transmission mode (1-8)") + ("enb_files.sib_config", bpo::value(&args->enb_files.sib_config)->default_value("sib.conf"), "SIB configuration files") ("enb_files.rr_config", bpo::value(&args->enb_files.rr_config)->default_value("rr.conf"), "RR configuration files") ("enb_files.drb_config", bpo::value(&args->enb_files.drb_config)->default_value("drb.conf"), "DRB configuration files") diff --git a/srsenb/src/phy/phch_common.cc b/srsenb/src/phy/phch_common.cc index e4d91581e..545ad576e 100644 --- a/srsenb/src/phy/phch_common.cc +++ b/srsenb/src/phy/phch_common.cc @@ -74,7 +74,7 @@ void phch_common::stop() { } } -void phch_common::worker_end(uint32_t tx_mutex_cnt, cf_t* buffer, uint32_t nof_samples, srslte_timestamp_t tx_time) +void phch_common::worker_end(uint32_t tx_mutex_cnt, cf_t* buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t tx_time) { // Wait previous TTIs to be transmitted @@ -84,8 +84,8 @@ void phch_common::worker_end(uint32_t tx_mutex_cnt, cf_t* buffer, uint32_t nof_s pthread_mutex_lock(&tx_mutex[tx_mutex_cnt%nof_mutex]); } - radio->set_tti(tx_mutex_cnt); - radio->tx(buffer, nof_samples, tx_time); + radio->set_tti(tx_mutex_cnt); + radio->tx((void **) buffer, nof_samples, tx_time); // Trigger next transmission pthread_mutex_unlock(&tx_mutex[(tx_mutex_cnt+1)%nof_mutex]); diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index 3a1fb8ca4..7b547c944 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -88,15 +88,17 @@ void phch_worker::init(phch_common* phy_, srslte::log *log_h_) pthread_mutex_init(&mutex, NULL); // Init cell here - signal_buffer_rx = (cf_t*) srslte_vec_malloc(2*SRSLTE_SF_LEN_PRB(phy->cell.nof_prb)*sizeof(cf_t)); - if (!signal_buffer_rx) { - 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) { - fprintf(stderr, "Error allocating memory\n"); - return; + for(int p = 0; p < SRSLTE_MAX_PORTS; p++) { + signal_buffer_rx[p] = (cf_t *) srslte_vec_malloc(2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t)); + if (!signal_buffer_rx) { + fprintf(stderr, "Error allocating memory\n"); + return; + } + signal_buffer_tx[p] = (cf_t *) srslte_vec_malloc(2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t)); + if (!signal_buffer_tx) { + fprintf(stderr, "Error allocating memory\n"); + return; + } } if (srslte_enb_dl_init(&enb_dl, phy->cell.nof_prb)) { fprintf(stderr, "Error initiating ENB DL\n"); @@ -168,9 +170,9 @@ void phch_worker::reset() ue_db.clear(); } -cf_t* phch_worker::get_buffer_rx() +cf_t* phch_worker::get_buffer_rx(uint32_t antenna_idx) { - return signal_buffer_rx; + return signal_buffer_rx[antenna_idx]; } void phch_worker::set_time(uint32_t tti_, uint32_t tx_mutex_cnt_, srslte_timestamp_t tx_time_) @@ -287,7 +289,7 @@ void phch_worker::work_imp() } // Process UL signal - srslte_enb_ul_fft(&enb_ul, signal_buffer_rx); + srslte_enb_ul_fft(&enb_ul, signal_buffer_rx[0]); // Decode pending UL grants for the tti they were scheduled decode_pusch(ul_grants[sf_rx].sched_grants, ul_grants[sf_rx].nof_grants, sf_rx); @@ -649,6 +651,9 @@ int phch_worker::encode_pdcch_dl(srslte_enb_dl_pdsch_t *grants, uint32_t nof_gra int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants, uint32_t sf_idx) { + /* FIXME: currently, it assumes TM1, TM2 or TM3 */ + srslte_mimo_type_t mimo_type = (enb_dl.cell.nof_ports == 1) ? SRSLTE_MIMO_TYPE_SINGLE_ANTENNA : SRSLTE_MIMO_TYPE_TX_DIVERSITY; + for (uint32_t i=0;iinfo_hex(ptr, len, - "PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tbs=%d, mcs=%d, rv=%d, tti_tx=%d\n", + "PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tbs=%d, mcs=%d, rv=%d, tti_tx=%d\n", rnti, phy_grant.nof_prb, grant_str, grants[i].grant.harq_process, phy_grant.mcs[0].tbs/8, phy_grant.mcs[0].idx, grants[i].grant.rv_idx, tti_tx); } - srslte_softbuffer_tx_t *sb[SRSLTE_MAX_CODEWORDS] = {grants[i].softbuffer, NULL}; - uint8_t *d[SRSLTE_MAX_CODEWORDS] = {grants[i].data, NULL}; - int rv[SRSLTE_MAX_CODEWORDS] = {grants[i].grant.rv_idx, 0}; - + int rv[SRSLTE_MAX_CODEWORDS] = {grants[i].grant.rv_idx, grants[i].grant.rv_idx_1}; - if (srslte_enb_dl_put_pdsch(&enb_dl, &phy_grant, sb, rnti, rv, sf_idx, d, SRSLTE_MIMO_TYPE_SINGLE_ANTENNA, 0)) - { + if (srslte_enb_dl_put_pdsch(&enb_dl, &phy_grant, grants[i].softbuffers, rnti, rv, sf_idx, grants[i].data, mimo_type, 0)) { fprintf(stderr, "Error putting PDSCH %d\n",i); return SRSLTE_ERROR; } diff --git a/srsenb/src/phy/txrx.cc b/srsenb/src/phy/txrx.cc index 9427e3459..2a6929a20 100644 --- a/srsenb/src/phy/txrx.cc +++ b/srsenb/src/phy/txrx.cc @@ -77,7 +77,7 @@ void txrx::stop() void txrx::run_thread() { phch_worker *worker = NULL; - cf_t *buffer = NULL; + cf_t *buffer[SRSLTE_MAX_PORTS] = {NULL}; srslte_timestamp_t rx_time, tx_time; uint32_t sf_len = SRSLTE_SF_LEN_PRB(worker_com->cell.nof_prb); @@ -108,10 +108,12 @@ void txrx::run_thread() while (running) { tti = (tti+1)%10240; worker = (phch_worker*) workers_pool->wait_worker(tti); - if (worker) { - buffer = worker->get_buffer_rx(); + if (worker) { + for (int p = 0; p < SRSLTE_MAX_PORTS; p++){ + buffer[p] = worker->get_buffer_rx(p); + } - radio_h->rx_now(buffer, sf_len, &rx_time); + radio_h->rx_now((void **) buffer, sf_len, &rx_time); /* Compute TX time: Any transmission happens in TTI+4 thus advance 4 ms the reception time */ srslte_timestamp_copy(&tx_time, &rx_time); @@ -129,7 +131,7 @@ void txrx::run_thread() workers_pool->start_worker(worker); // Trigger prach worker execution - prach->new_tti(tti, buffer); + prach->new_tti(tti, buffer[0]); } else { // wait_worker() only returns NULL if it's being closed. Quit now to avoid unnecessary loops here diff --git a/srsue/hdr/phy/prach.h b/srsue/hdr/phy/prach.h index 67ccc0c94..2872c374c 100644 --- a/srsue/hdr/phy/prach.h +++ b/srsue/hdr/phy/prach.h @@ -45,11 +45,11 @@ namespace srsue { args = NULL; config = NULL; - signal_buffer = NULL; transmitted_tti = 0; target_power_dbm = 0; mem_initiated = false; cell_initiated = false; + bzero(signal_buffer, sizeof(signal_buffer)); } ~prach(); void init(LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT *config, uint32_t max_prb, phy_args_t *args, srslte::log *log_h); @@ -78,7 +78,7 @@ namespace srsue { srslte_prach_t prach_obj; int transmitted_tti; srslte_cell_t cell; - cf_t *signal_buffer; + cf_t *signal_buffer[SRSLTE_MAX_PORTS]; srslte_cfo_t cfo_h; float target_power_dbm; diff --git a/srsue/src/phy/phch_common.cc b/srsue/src/phy/phch_common.cc index d49b1ced2..4a2f8a441 100644 --- a/srsue/src/phy/phch_common.cc +++ b/srsue/src/phy/phch_common.cc @@ -237,12 +237,12 @@ void phch_common::worker_end(uint32_t tti, bool tx_enable, radio_h->set_tti(tti); if (tx_enable) { - radio_h->tx(buffer, nof_samples, tx_time); + radio_h->tx_single(buffer, nof_samples, tx_time); is_first_of_burst = false; } else { if (TX_MODE_CONTINUOUS) { if (!is_first_of_burst) { - radio_h->tx(zeros, nof_samples, tx_time); + radio_h->tx_single(zeros, nof_samples, tx_time); } } else { if (!is_first_of_burst) { diff --git a/srsue/src/phy/prach.cc b/srsue/src/phy/prach.cc index 7c693fe7a..bd7550457 100644 --- a/srsue/src/phy/prach.cc +++ b/srsue/src/phy/prach.cc @@ -75,10 +75,12 @@ void prach::init(LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT *config_, uint32_t max_prb, return; } srslte_cfo_set_tol(&cfo_h, 0); - signal_buffer = (cf_t*) srslte_vec_malloc(SRSLTE_PRACH_MAX_LEN*sizeof(cf_t)); - if (!signal_buffer) { - perror("malloc"); - return; + for (int p = 0; p < SRSLTE_MAX_PORTS; p++) { + signal_buffer[p] = (cf_t *) srslte_vec_malloc(SRSLTE_PRACH_MAX_LEN * sizeof(cf_t)); + if (!signal_buffer[p]) { + perror("malloc"); + return; + } } if (srslte_prach_init(&prach_obj, srslte_symbol_sz(max_prb))) { Error("Initiating PRACH library\n"); @@ -181,8 +183,8 @@ void prach::send(srslte::radio *radio_handler, float cfo, float pathloss, srslte // Get current TX gain float old_gain = radio_handler->get_tx_gain(); - // Correct CFO before transmission - srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer, cfo / srslte_symbol_sz(cell.nof_prb)); + // Correct CFO before transmission FIXME: UL SISO Only + srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer[0], cfo / srslte_symbol_sz(cell.nof_prb)); // If power control is enabled, choose amplitude and power if (args->ul_pwr_ctrl_en) { @@ -193,10 +195,10 @@ void prach::send(srslte::radio *radio_handler, float cfo, float pathloss, srslte radio_handler->set_tx_power(tx_power); // Scale signal - float digital_power = srslte_vec_avg_power_cf(signal_buffer, len); + float digital_power = srslte_vec_avg_power_cf(signal_buffer[0], len); float scale = sqrtf(pow(10,tx_power/10)/digital_power); - srslte_vec_sc_prod_cfc(signal_buffer, scale, signal_buffer, len); + srslte_vec_sc_prod_cfc(signal_buffer[0], scale, signal_buffer[0], len); log_h->console("PRACH: Pathloss=%.2f dB, Target power %.2f dBm, TX_power %.2f dBm, TX_gain %.1f dB\n", pathloss, target_power_dbm, tx_power, radio_handler->get_tx_gain(), scale); @@ -207,8 +209,8 @@ void prach::send(srslte::radio *radio_handler, float cfo, float pathloss, srslte } Debug("TX PRACH: Power control for PRACH is disabled, setting gain to %.0f dB\n", prach_gain); } - - radio_handler->tx(signal_buffer, len, tx_time); + + radio_handler->tx((void **) signal_buffer, len, tx_time); radio_handler->tx_end(); Info("PRACH: Transmitted preamble=%d, CFO=%.2f KHz, tx_time=%f\n", From f4e883d24f50c775034d8ee10b7a72bd37d3cddd Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 10 Oct 2017 16:42:24 +0200 Subject: [PATCH 043/242] Divided phch_recv in subclasses --- lib/include/srslte/phy/utils/ringbuffer.h | 4 +- lib/include/srslte/srslte.h | 1 + lib/src/phy/utils/ringbuffer.c | 8 +- srsue/hdr/phy/phch_recv.h | 182 +++-- srsue/src/phy/phch_recv.cc | 895 +++++++++++++++------- 5 files changed, 746 insertions(+), 344 deletions(-) diff --git a/lib/include/srslte/phy/utils/ringbuffer.h b/lib/include/srslte/phy/utils/ringbuffer.h index 9cbe0ddd6..c9276d5a9 100644 --- a/lib/include/srslte/phy/utils/ringbuffer.h +++ b/lib/include/srslte/phy/utils/ringbuffer.h @@ -24,11 +24,11 @@ SRSLTE_API void srslte_ringbuffer_free(srslte_ringbuffer_t *q, int capacity); SRSLTE_API int srslte_ringbuffer_write(srslte_ringbuffer_t *q, - uint8_t *ptr, + void *ptr, int nof_bytes); SRSLTE_API int srslte_ringbuffer_read(srslte_ringbuffer_t *q, - uint8_t *ptr, + void *ptr, int nof_bytes); diff --git a/lib/include/srslte/srslte.h b/lib/include/srslte/srslte.h index f44f5325d..f4806b36d 100644 --- a/lib/include/srslte/srslte.h +++ b/lib/include/srslte/srslte.h @@ -39,6 +39,7 @@ #include "srslte/version.h" #include "srslte/phy/utils/bit.h" +#include "srslte/phy/utils/ringbuffer.h" #include "srslte/phy/utils/convolution.h" #include "srslte/phy/utils/debug.h" #include "srslte/phy/utils/cexptab.h" diff --git a/lib/src/phy/utils/ringbuffer.c b/lib/src/phy/utils/ringbuffer.c index 86578b3ea..02faaeb9a 100644 --- a/lib/src/phy/utils/ringbuffer.c +++ b/lib/src/phy/utils/ringbuffer.c @@ -34,8 +34,9 @@ void srslte_ringbuffer_free(srslte_ringbuffer_t *q, int capacity) } } -int srslte_ringbuffer_write(srslte_ringbuffer_t *q, uint8_t *ptr, int nof_bytes) -{ +int srslte_ringbuffer_write(srslte_ringbuffer_t *q, void *p, int nof_bytes) +{ + uint8_t *ptr = (uint8_t*) p; int w_bytes = nof_bytes; pthread_mutex_lock(&q->mutex); if (q->count + w_bytes >= q->capacity) { @@ -59,8 +60,9 @@ int srslte_ringbuffer_write(srslte_ringbuffer_t *q, uint8_t *ptr, int nof_bytes) return w_bytes; } -int srslte_ringbuffer_read(srslte_ringbuffer_t *q, uint8_t *ptr, int nof_bytes) +int srslte_ringbuffer_read(srslte_ringbuffer_t *q, void *p, int nof_bytes) { + uint8_t *ptr = (uint8_t*) p; pthread_mutex_lock(&q->mutex); while(q->count < nof_bytes) { pthread_cond_wait(&q->cvar, &q->mutex); diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index c51622e53..781603be1 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -70,11 +70,8 @@ public: const static int MUTEX_X_WORKER = 4; - // public variables needed by callback function - uint32_t current_sflen; - srslte::radio_multi *radio_h; - int next_offset; - + int radio_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time); + int scell_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time); private: @@ -83,49 +80,156 @@ private: void reset(); void radio_error(); bool wait_radio_reset(); - void set_ue_sync_opts(srslte_ue_sync_t *q); + void set_ue_sync_opts(srslte_ue_sync_t *q); void run_thread(); void set_sampling_rate(); bool set_frequency(); - void resync_sfn(bool is_connected = false); - bool stop_sync(); + bool set_cell(); void cell_search_inc(); - - bool init_cell(); - void free_cell(); + void resync_sfn(bool is_connected = false); + bool stop_sync(); void stop_rx(); void start_rx(); bool radio_is_rx; bool radio_is_resetting; + bool running; + + // Class to run cell search + class search { + public: + typedef enum {CELL_NOT_FOUND, CELL_FOUND, ERROR, TIMEOUT} ret_code; + + ~search(); + void init(cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, uint32_t nof_rx_antennas, phch_recv *parent); + void reset(); + float get_last_gain(); + float get_last_cfo(); + void set_N_id_2(int N_id_2); + ret_code run(srslte_cell_t *cell); + + private: + phch_recv *p; + srslte::log *log_h; + cf_t *buffer[SRSLTE_MAX_PORTS]; + srslte_ue_cellsearch_t cs; + srslte_ue_mib_sync_t ue_mib_sync; + int force_N_id_2; + }; + + // Class to synchronize system frame number + class sfn_sync { + public: + typedef enum {IDLE, SFN_FOUND, ERROR, TIMEOUT} ret_code; + + ~sfn_sync(); + void init(srslte_ue_sync_t *ue_sync, cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, uint32_t timeout = SYNC_SFN_TIMEOUT); + void reset(); + bool set_cell(srslte_cell_t cell); + ret_code run_subframe(srslte_cell_t *cell, uint32_t *tti_cnt); + + private: + srslte::log *log_h; + srslte_ue_sync_t *ue_sync; + cf_t *buffer[SRSLTE_MAX_PORTS]; + srslte_ue_mib_t ue_mib; + uint32_t cnt; + uint32_t timeout; + const static uint32_t SYNC_SFN_TIMEOUT = 200; + }; + + // Class to perform cell measurements + class measure { + public: + typedef enum {IDLE, MEASURE_OK, ERROR} ret_code; + + ~measure(); + void init(srslte_ue_sync_t *ue_sync, cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, + uint32_t nof_rx_antennas, uint32_t nof_subframes = RSRP_MEASURE_NOF_FRAMES); + void reset(); + void set_cell(srslte_cell_t cell); + ret_code run_subframe(uint32_t sf_idx); + float rsrp(); + float rsrq(); + float snr(); + private: + srslte::log *log_h; + srslte_ue_dl_t ue_dl; + srslte_ue_sync_t *ue_sync; + cf_t *buffer[SRSLTE_MAX_PORTS]; + uint32_t cnt; + uint32_t nof_subframes; + float mean_rsrp, mean_rsrq, mean_snr; + const static int RSRP_MEASURE_NOF_FRAMES = 5; + }; + + + // Class to receive secondary cell + class scell_recv : public thread { + public: + void init(phch_recv *parent, srslte::log *log_h, uint32_t nof_rx_antennas, uint32_t prio, int cpu_affinity = -1); + void stop(); + int recv(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time); + void write(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time); + bool is_enabled(); + private: + void run_thread(); + + enum { + IDLE = 0, + SCELL_SELECT, + SCELL_MEASURE, + SCELL_CAMPING + } scell_state; + + srslte::log *log_h; + phch_recv *p; + bool running; + srslte_ringbuffer_t ring_buffer[SRSLTE_MAX_PORTS]; + cf_t *sf_buffer[SRSLTE_MAX_PORTS]; + srslte_ue_sync_t ue_sync; + srslte_cell_t cell; + + measure measure_p; + sfn_sync sfn_p; + uint32_t tti; + }; + + + + + // Objects for internal use + scell_recv scell; + measure measure_p; + search search_p; + sfn_sync sfn_p; - bool running; - + uint32_t current_sflen; + int next_offset; + uint32_t nof_rx_antennas; + + // Pointers to other classes mac_interface_phy *mac; rrc_interface_phy *rrc; srslte::log *log_h; srslte::thread_pool *workers_pool; + srslte::radio_multi *radio_h; phch_common *worker_com; prach *prach_buffer; - // Structures for Cell Camp - srslte_ue_sync_t ue_sync; - srslte_ue_mib_t ue_mib; - - // Structures for Cell Search - srslte_ue_cellsearch_t cs; - srslte_ue_mib_sync_t ue_mib_sync; + // Object for synchronization of the primary cell + srslte_ue_sync_t ue_sync; - uint32_t nof_rx_antennas; - - cf_t *sf_buffer[SRSLTE_MAX_PORTS]; + // Buffer for primary cell samples + cf_t *sf_buffer[SRSLTE_MAX_PORTS]; // Sync metrics - sync_metrics_t metrics; + sync_metrics_t metrics; + // State for primary cell enum { IDLE = 0, CELL_SEARCH, @@ -137,44 +241,30 @@ private: bool is_in_idle; + // Sampling rate mode (find is 1.96 MHz, camp is the full cell BW) enum { SRATE_NONE=0, SRATE_FIND, SRATE_CAMP } srate_mode; float current_srate; + // This is the primary cell srslte_cell_t cell; bool cell_is_set; - bool is_sfn_synched; - bool started; + bool started; float time_adv_sec; uint32_t tti; bool do_agc; - float last_gain; - float cellsearch_cfo; uint32_t nof_tx_mutex; uint32_t tx_mutex_cnt; + float ul_dl_factor; uint32_t current_earfcn; + int cur_earfcn_index; + bool cell_search_in_progress; - uint32_t sync_sfn_cnt; - const static uint32_t SYNC_SFN_TIMEOUT = 200; - float ul_dl_factor; - int cur_earfcn_index; - bool cell_search_in_progress; - uint32_t measure_cnt; - float measure_rsrp; - srslte_ue_dl_t ue_dl_measure; - - const static int RSRP_MEASURE_NOF_FRAMES = 5; - - int cell_sync_sfn(); - int cell_meas_rsrp(); - int cell_search(int force_N_id_2 = -1); - bool set_cell(); - - float dl_freq; - float ul_freq; + float dl_freq; + float ul_freq; }; diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 8642460aa..2249a0913 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -39,23 +39,15 @@ namespace srsue { -int radio_recv_wrapper_cs(void *obj, cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time) { - phch_recv *h = (phch_recv*) obj; - srslte::radio_multi *radio_h = h->radio_h; +int radio_recv_callback(void *obj, cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time) { + return ((phch_recv*) obj)->radio_recv_fnc(data, nsamples, rx_time); - if (radio_h->rx_now(data, nsamples, rx_time)) { - int offset = nsamples - h->current_sflen; - if (abs(offset) < 10 && offset != 0) { - h->next_offset = offset; - } else if (nsamples < 10) { - h->next_offset = nsamples; - } - return nsamples; - } else { - return -1; - } } +int scell_recv_callback(void *obj, cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time) { + return ((phch_recv*) obj)->scell_recv_fnc(data, nsamples, rx_time); +} + double callback_set_rx_gain(void *h, double gain) { srslte::radio_multi *radio_handler = (srslte::radio_multi *) h; return radio_handler->set_rx_gain_th(gain); @@ -69,68 +61,52 @@ phch_recv::phch_recv() { running = false; } -void phch_recv:: init(srslte::radio_multi *_radio_handler, mac_interface_phy *_mac, rrc_interface_phy *_rrc, +void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_mac, rrc_interface_phy *_rrc, prach *_prach_buffer, srslte::thread_pool *_workers_pool, phch_common *_worker_com, srslte::log *_log_h, uint32_t nof_rx_antennas_, uint32_t prio, int sync_cpu_affinity) { radio_h = _radio_handler; - log_h = _log_h; - mac = _mac; - rrc = _rrc; - workers_pool = _workers_pool; - worker_com = _worker_com; - prach_buffer = _prach_buffer; + log_h = _log_h; + mac = _mac; + rrc = _rrc; + workers_pool = _workers_pool; + worker_com = _worker_com; + prach_buffer = _prach_buffer; nof_rx_antennas = nof_rx_antennas_; - reset(); - for (uint32_t i = 0; i < nof_rx_antennas; i++) { sf_buffer[i] = (cf_t *) srslte_vec_malloc(sizeof(cf_t) * 3 * SRSLTE_SF_LEN_PRB(100)); } - - if (srslte_ue_cellsearch_init_multi(&cs, 5, radio_recv_wrapper_cs, nof_rx_antennas, - this)) { - Error("SYNC: Initiating UE cell search\n"); + if (srslte_ue_sync_init_multi(&ue_sync, SRSLTE_MAX_PRB, false, radio_recv_callback, nof_rx_antennas, this)) { + Error("SYNC: Initiating ue_sync\n"); return; } - srslte_ue_cellsearch_set_nof_valid_frames(&cs, 2); - - // Set options defined in expert section - set_ue_sync_opts(&cs.ue_sync); + nof_tx_mutex = MUTEX_X_WORKER * workers_pool->get_nof_workers(); + worker_com->set_nof_mutex(nof_tx_mutex); - if (do_agc) { - srslte_ue_sync_start_agc(&cs.ue_sync, callback_set_rx_gain, last_gain); - } + // Initialize cell searcher + search_p.init(sf_buffer, log_h, nof_rx_antennas, this); - if (srslte_ue_dl_init(&ue_dl_measure, SRSLTE_MAX_PRB, nof_rx_antennas)) { - Error("SYNC: Initiating ue_dl_measure\n"); - return; - } + // Initialize SFN synchronizer + sfn_p.init(&ue_sync, sf_buffer, log_h); - if (srslte_ue_mib_init(&ue_mib, SRSLTE_MAX_PRB)) { - Error("SYNC: Initiating UE MIB decoder\n"); - return; - } + // Initialize measurement class for the primary cell + measure_p.init(&ue_sync, sf_buffer, log_h, nof_rx_antennas); - if (srslte_ue_sync_init_multi(&ue_sync, SRSLTE_MAX_PRB, false, radio_recv_wrapper_cs, nof_rx_antennas, this)) { - Error("SYNC: Initiating ue_sync\n"); - return; - } + // Start scell + scell.init(this, log_h, nof_rx_antennas_, prio, sync_cpu_affinity); - if (srslte_ue_mib_sync_init_multi(&ue_mib_sync, radio_recv_wrapper_cs, nof_rx_antennas, this)) { - Error("SYNC: Initiating UE MIB synchronization\n"); - return; - } + reset(); - nof_tx_mutex = MUTEX_X_WORKER * workers_pool->get_nof_workers(); - worker_com->set_nof_mutex(nof_tx_mutex); + // Start main thread if (sync_cpu_affinity < 0) { start(prio); } else { start_cpu(prio, sync_cpu_affinity); } + } phch_recv::~phch_recv() { @@ -140,10 +116,6 @@ phch_recv::~phch_recv() { } } srslte_ue_sync_free(&ue_sync); - srslte_ue_dl_free(&ue_dl_measure); - srslte_ue_mib_free(&ue_mib); - srslte_ue_mib_sync_free(&ue_mib_sync); - srslte_ue_cellsearch_free(&cs); } void phch_recv::stop() { @@ -159,11 +131,14 @@ void phch_recv::reset() { time_adv_sec = 0; next_offset = 0; cell_is_set = false; - sync_sfn_cnt = 0; srate_mode = SRATE_NONE; cell_search_in_progress = false; current_earfcn = 0; radio_is_resetting = false; + sfn_p.reset(); + measure_p.reset(); + search_p.reset(); + } void phch_recv::radio_error() { @@ -232,23 +207,14 @@ void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q) { bool phch_recv::set_cell() { cell_is_set = false; - if (srslte_ue_mib_set_cell(&ue_mib, cell)) { - Error("SYNC: Setting cell: initiating ue_mib\n"); - return false; - } + + // Set cell in all objects if (srslte_ue_sync_set_cell(&ue_sync, cell)) { Error("SYNC: Setting cell: initiating ue_sync"); return false; } - - // Set options defined in expert section - set_ue_sync_opts(&ue_sync); - - if (srslte_ue_dl_set_cell(&ue_dl_measure, cell)) { - Error("SYNC: Setting cell: initiating ue_dl_measure\n"); - return false; - } - + measure_p.set_cell(cell); + sfn_p.set_cell(cell); worker_com->set_cell(cell); for (uint32_t i = 0; i < workers_pool->get_nof_workers(); i++) { @@ -257,178 +223,20 @@ bool phch_recv::set_cell() { return false; } } - if (do_agc) { - srslte_ue_sync_start_agc(&ue_sync, callback_set_rx_gain, last_gain); - } - cell_is_set = true; - - return cell_is_set; -} - -int phch_recv::cell_search(int force_N_id_2) { - uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; - - srslte_ue_cellsearch_result_t found_cells[3]; - - bzero(&cell, sizeof(srslte_cell_t)); - bzero(found_cells, 3 * sizeof(srslte_ue_cellsearch_result_t)); - - if (srate_mode != SRATE_FIND) { - srate_mode = SRATE_FIND; - radio_h->set_rx_srate(1.92e6); - } - start_rx(); - - /* Find a cell in the given N_id_2 or go through the 3 of them to find the strongest */ - uint32_t max_peak_cell = 0; - int ret = SRSLTE_ERROR; - - Info("SYNC: Searching for cell...\n"); - printf("."); fflush(stdout); - - if (force_N_id_2 >= 0 && force_N_id_2 < 3) { - ret = srslte_ue_cellsearch_scan_N_id_2(&cs, force_N_id_2, &found_cells[force_N_id_2]); - max_peak_cell = force_N_id_2; - } else { - ret = srslte_ue_cellsearch_scan(&cs, found_cells, &max_peak_cell); - } - - last_gain = srslte_agc_get_gain(&cs.ue_sync.agc); - - if (ret < 0) { - Error("SYNC: Error decoding MIB: Error searching PSS\n"); - return -1; - } else if (ret == 0) { - stop_rx(); - Info("SYNC: Could not find any cell in this frequency\n"); - return 0; - } - // Save result - cell.id = found_cells[max_peak_cell].cell_id; - cell.cp = found_cells[max_peak_cell].cp; - cellsearch_cfo = found_cells[max_peak_cell].cfo; - - printf("\n"); - Info("SYNC: PSS/SSS detected: PCI=%d, CFO=%.1f KHz, CP=%s\n", - cell.id, cellsearch_cfo/1000, srslte_cp_string(cell.cp)); - - if (srslte_ue_mib_sync_set_cell(&ue_mib_sync, cell.id, cell.cp)) { - Error("SYNC: Setting UE MIB cell\n"); - return false; - } // Set options defined in expert section - set_ue_sync_opts(&ue_mib_sync.ue_sync); - - if (do_agc) { - srslte_ue_sync_start_agc(&ue_mib_sync.ue_sync, callback_set_rx_gain, last_gain); - } - - srslte_ue_sync_reset(&ue_mib_sync.ue_sync); - srslte_ue_sync_set_cfo(&ue_mib_sync.ue_sync, cellsearch_cfo); - - /* Find and decode MIB */ - int sfn_offset; - ret = srslte_ue_mib_sync_decode(&ue_mib_sync, - 40, - bch_payload, &cell.nof_ports, &sfn_offset); - stop_rx(); - last_gain = srslte_agc_get_gain(&ue_mib_sync.ue_sync.agc); - cellsearch_cfo = srslte_ue_sync_get_cfo(&ue_mib_sync.ue_sync); + set_ue_sync_opts(&ue_sync); + // Reset ue_sync and set CFO/gain from search procedure srslte_ue_sync_reset(&ue_sync); - srslte_ue_sync_set_cfo(&ue_sync, cellsearch_cfo); - - if (ret == 1) { - srslte_pbch_mib_unpack(bch_payload, &cell, NULL); - - fprintf(stdout, "Found Cell: PCI=%d, PRB=%d, Ports=%d, CFO=%.1f KHz\n", - cell.id, cell.nof_prb, cell.nof_ports, cellsearch_cfo/1000); - - Info("SYNC: MIB Decoded: PCI=%d, PRB=%d, Ports=%d, CFO=%.1f KHz\n", - cell.id, cell.nof_prb, cell.nof_ports, cellsearch_cfo/1000); - - return true; - } else if (ret == 0) { - Warning("SYNC: Found PSS but could not decode PBCH\n"); - return 0; - } else { - Error("SYNC: Receiving MIB\n"); - return -1; - } -} - - -int phch_recv::cell_sync_sfn(void) { - - int ret = SRSLTE_ERROR; - uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; - - srslte_ue_sync_decode_sss_on_track(&ue_sync, true); - ret = srslte_ue_sync_zerocopy_multi(&ue_sync, sf_buffer); - if (ret < 0) { - Error("SYNC: Error calling ue_sync_get_buffer"); - return -1; - } - - if (ret == 1) { - if (srslte_ue_sync_get_sfidx(&ue_sync) == 0) { - int sfn_offset = 0; - Info("SYNC: Trying to decode MIB... SNR=%.1f dB\n", - 10*log10(srslte_chest_dl_get_snr(&ue_mib.chest))); - int n = srslte_ue_mib_decode(&ue_mib, sf_buffer[0], bch_payload, NULL, &sfn_offset); - if (n < 0) { - Error("SYNC: Error decoding MIB while synchronising SFN"); - return -1; - } else if (n == SRSLTE_UE_MIB_FOUND) { - uint32_t sfn; - srslte_pbch_mib_unpack(bch_payload, &cell, &sfn); - - sfn = (sfn+sfn_offset)%1024; - tti = sfn * 10; - - srslte_ue_sync_decode_sss_on_track(&ue_sync, true); - Info("SYNC: DONE, TTI=%d, sfn_offset=%d\n", tti, sfn_offset); - srslte_ue_mib_reset(&ue_mib); - return 1; - } - } - } else { - Debug("SYNC: PSS/SSS not found...\n"); + srslte_ue_sync_set_cfo(&ue_sync, search_p.get_last_cfo()); + if (do_agc) { + srslte_ue_sync_start_agc(&ue_sync, callback_set_rx_gain, search_p.get_last_gain()); } - return 0; -} - -int phch_recv::cell_meas_rsrp() { - - uint32_t cfi = 0; - tti = (tti+1) % 10240; - log_h->step(tti); - - uint32_t sf_idx = tti%10; - - int sync_res = srslte_ue_sync_zerocopy_multi(&ue_sync, sf_buffer); - if (sync_res == 1) { - if (srslte_ue_dl_decode_fft_estimate(&ue_dl_measure, sf_buffer, sf_idx, &cfi)) { - log_h->error("SYNC: Measuring RSRP: Estimating channel\n"); - return -1; - } - float rsrp = srslte_chest_dl_get_rsrp(&ue_dl_measure.chest); - float snr = srslte_chest_dl_get_snr(&ue_dl_measure.chest); - measure_rsrp = SRSLTE_VEC_CMA(rsrp, measure_rsrp, measure_cnt); - measure_cnt++; - log_h->info("SYNC: Measuring RSRP %d/%d, sf_idx=%d, RSRP=%.1f dBm, SNR=%.1f dB\n", - measure_cnt, RSRP_MEASURE_NOF_FRAMES, sf_idx, 10 * log10(rsrp / 1000), 10*log10(snr)); - if (measure_cnt >= RSRP_MEASURE_NOF_FRAMES) { - return 1; - } - } else { - log_h->error("SYNC: Measuring RSRP: Sync error\n"); - return -1; - } + cell_is_set = true; - return 0; + return cell_is_set; } void phch_recv::resync_sfn(bool is_connected) { @@ -437,9 +245,9 @@ void phch_recv::resync_sfn(bool is_connected) { stop_rx(); start_rx(); - srslte_ue_mib_reset(&ue_mib); + sfn_p.reset(); Info("SYNC: Starting SFN synchronization\n"); - sync_sfn_cnt = 0; + phy_state = is_connected?CELL_RESELECT:CELL_SELECT; } @@ -475,7 +283,7 @@ void phch_recv::reset_sync() { wait_radio_reset(); Warning("SYNC: Resetting sync, cell_search_in_progress=%s\n", cell_search_in_progress?"yes":"no"); - srslte_ue_sync_reset(&ue_mib_sync.ue_sync); + search_p.reset(); srslte_ue_sync_reset(&ue_sync); resync_sfn(true); } @@ -625,22 +433,96 @@ void phch_recv::set_sampling_rate() } } -void phch_recv::run_thread() { +void phch_recv::stop_rx() { + if (radio_is_rx) { + Info("SYNC: Stopping RX streaming\n"); + radio_h->stop_rx(); + } + radio_is_rx = false; +} + +void phch_recv::start_rx() { + if (!radio_is_rx) { + Info("SYNC: Starting RX streaming\n"); + radio_h->start_rx(); + } + radio_is_rx = true; +} + +uint32_t phch_recv::get_current_tti() { + return tti; +} + +bool phch_recv::status_is_sync() { + return phy_state == CELL_CAMP; +} + +void phch_recv::get_current_cell(srslte_cell_t *cell_) { + if (cell_) { + memcpy(cell_, &cell, sizeof(srslte_cell_t)); + } +} + +int phch_recv::radio_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time) +{ + if (radio_h->rx_now(data, nsamples, rx_time)) { + int offset = nsamples - current_sflen; + if (abs(offset) < 10 && offset != 0) { + next_offset = offset; + } else if (nsamples < 10) { + next_offset = nsamples; + } + + if (offset == 0) { + scell.write(data, nsamples, rx_time); + } + return nsamples; + } else { + return -1; + } +} + +int phch_recv::scell_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time) +{ + return scell.recv(data, nsamples, rx_time); +} + + + + + + + +/** + * MAIN THREAD + */ + +void phch_recv::run_thread() +{ phch_worker *worker = NULL; - cf_t *buffer[SRSLTE_MAX_PORTS]; + cf_t *buffer[SRSLTE_MAX_PORTS] = {NULL}; + uint32_t sf_idx = 0; phy_state = IDLE; is_in_idle = true; - while (running) { + while (running) + { if (phy_state != IDLE) { is_in_idle = false; Debug("SYNC: state=%d\n", phy_state); } + + tti = (tti+1) % 10240; + log_h->step(tti); + sf_idx = tti%10; + switch (phy_state) { case CELL_SEARCH: - if (cell_search_in_progress) { - switch(cell_search()) { - case 1: + if (cell_search_in_progress) + { + switch(search_p.run(&cell)) + { + case search::CELL_FOUND: if (!srslte_cell_isvalid(&cell)) { Error("SYNC: Detected invalid cell\n"); phy_state = IDLE; @@ -651,7 +533,7 @@ void phch_recv::run_thread() { resync_sfn(); } break; - case 0: + case search::CELL_NOT_FOUND: if (cell_search_in_progress) { cell_search_inc(); } @@ -664,46 +546,40 @@ void phch_recv::run_thread() { break; case CELL_RESELECT: case CELL_SELECT: - - srslte_ue_sync_decode_sss_on_track(&ue_sync, true); - - switch (cell_sync_sfn()) { - case 1: - srslte_ue_sync_set_agc_period(&ue_sync, 20); + switch (sfn_p.run_subframe(&cell, &tti)) + { + case sfn_sync::SFN_FOUND: if (!cell_search_in_progress) { - phy_state = CELL_CAMP; log_h->info("Sync OK. Camping on cell PCI=%d...\n", cell.id); + phy_state = CELL_CAMP; + } else { + measure_p.reset(); + phy_state = CELL_MEASURE; + } + break; + case sfn_sync::TIMEOUT: + if (phy_state == CELL_SELECT) { + phy_state = CELL_SEARCH; } else { - measure_cnt = 0; - measure_rsrp = 0; - phy_state = CELL_MEASURE; + phy_state = IDLE; } break; - case 0: + case sfn_sync::IDLE: break; default: radio_error(); break; } - sync_sfn_cnt++; - if (sync_sfn_cnt >= SYNC_SFN_TIMEOUT) { - sync_sfn_cnt = 0; - log_h->warning("SYNC: Timeout while synchronizing SFN\n"); - if (phy_state == CELL_SELECT) { - phy_state = CELL_SEARCH; - } else { - phy_state = IDLE; - } - } break; case CELL_MEASURE: - switch(cell_meas_rsrp()) { - case 1: + switch(measure_p.run_subframe(sf_idx)) + { + case measure::MEASURE_OK: log_h->info("SYNC: Measured OK. Camping on cell PCI=%d...\n", cell.id); phy_state = CELL_CAMP; - rrc->cell_found(earfcn[cur_earfcn_index], cell, 10*log10(measure_rsrp/1000)); + rrc->cell_found(earfcn[cur_earfcn_index], cell, measure_p.rsrp()); break; - case 0: + case measure::IDLE: break; default: radio_error(); @@ -711,7 +587,7 @@ void phch_recv::run_thread() { } break; case CELL_CAMP: - tti = (tti+1) % 10240; + worker = (phch_worker *) workers_pool->wait_worker(tti); if (worker) { for (uint32_t i = 0; i < nof_rx_antennas; i++) { @@ -721,8 +597,6 @@ void phch_recv::run_thread() { switch(srslte_ue_sync_zerocopy_multi(&ue_sync, buffer)) { case 1: - log_h->step(tti); - Debug("SYNC: Worker %d synchronized\n", worker->get_id()); metrics.sfo = srslte_ue_sync_get_sfo(&ue_sync); @@ -786,33 +660,468 @@ void phch_recv::run_thread() { } } -void phch_recv::stop_rx() { - if (radio_is_rx) { - Info("SYNC: Stopping RX streaming\n"); - radio_h->stop_rx(); - } - radio_is_rx = false; -} -void phch_recv::start_rx() { - if (!radio_is_rx) { - Info("SYNC: Starting RX streaming\n"); - radio_h->start_rx(); - } - radio_is_rx = true; + + + + + + + + + + + + + +/********* + * Cell search class + */ +phch_recv::search::~search() +{ + srslte_ue_mib_sync_free(&ue_mib_sync); + srslte_ue_cellsearch_free(&cs); } -uint32_t phch_recv::get_current_tti() { - return tti; +void phch_recv::search::init(cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, uint32_t nof_rx_antennas, phch_recv *parent) +{ + this->log_h = log_h; + this->p = parent; + + for (int i=0;ibuffer[i] = buffer[i]; + } + + if (srslte_ue_cellsearch_init_multi(&cs, 5, radio_recv_callback, nof_rx_antennas, parent)) { + Error("SYNC: Initiating UE cell search\n"); + } + + if (srslte_ue_mib_sync_init_multi(&ue_mib_sync, radio_recv_callback, nof_rx_antennas, parent)) { + Error("SYNC: Initiating UE MIB synchronization\n"); + } + + srslte_ue_cellsearch_set_nof_valid_frames(&cs, 2); + + // Set options defined in expert section + p->set_ue_sync_opts(&cs.ue_sync); + + if (p->do_agc) { + srslte_ue_sync_start_agc(&cs.ue_sync, callback_set_rx_gain, 40); + } + + force_N_id_2 = -1; } -bool phch_recv::status_is_sync() { - return phy_state == CELL_CAMP; +void phch_recv::search::set_N_id_2(int N_id_2) { + force_N_id_2 = N_id_2; } -void phch_recv::get_current_cell(srslte_cell_t *cell_) { - if (cell_) { - memcpy(cell_, &cell, sizeof(srslte_cell_t)); +void phch_recv::search::reset() +{ + srslte_ue_sync_reset(&ue_mib_sync.ue_sync); +} + +float phch_recv::search::get_last_gain() +{ + return srslte_agc_get_gain(&ue_mib_sync.ue_sync.agc); +} + +float phch_recv::search::get_last_cfo() +{ + return srslte_ue_sync_get_cfo(&ue_mib_sync.ue_sync); +} + +phch_recv::search::ret_code phch_recv::search::run(srslte_cell_t *cell) +{ + + if (!cell) { + return ERROR; + } + + uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; + + srslte_ue_cellsearch_result_t found_cells[3]; + + bzero(cell, sizeof(srslte_cell_t)); + bzero(found_cells, 3 * sizeof(srslte_ue_cellsearch_result_t)); + + if (p->srate_mode != SRATE_FIND) { + p->srate_mode = SRATE_FIND; + p->radio_h->set_rx_srate(1.92e6); + } + p->start_rx(); + + /* Find a cell in the given N_id_2 or go through the 3 of them to find the strongest */ + uint32_t max_peak_cell = 0; + int ret = SRSLTE_ERROR; + + Info("SYNC: Searching for cell...\n"); + printf("."); fflush(stdout); + + if (force_N_id_2 >= 0 && force_N_id_2 < 3) { + ret = srslte_ue_cellsearch_scan_N_id_2(&cs, force_N_id_2, &found_cells[force_N_id_2]); + max_peak_cell = force_N_id_2; + } else { + ret = srslte_ue_cellsearch_scan(&cs, found_cells, &max_peak_cell); + } + + if (ret < 0) { + Error("SYNC: Error decoding MIB: Error searching PSS\n"); + return ERROR; + } else if (ret == 0) { + p->stop_rx(); + Info("SYNC: Could not find any cell in this frequency\n"); + return CELL_NOT_FOUND; + } + // Save result + cell->id = found_cells[max_peak_cell].cell_id; + cell->cp = found_cells[max_peak_cell].cp; + float cfo = found_cells[max_peak_cell].cfo; + + printf("\n"); + Info("SYNC: PSS/SSS detected: PCI=%d, CFO=%.1f KHz, CP=%s\n", + cell->id, cfo/1000, srslte_cp_string(cell->cp)); + + if (srslte_ue_mib_sync_set_cell(&ue_mib_sync, cell->id, cell->cp)) { + Error("SYNC: Setting UE MIB cell\n"); + return ERROR; + } + + // Set options defined in expert section + p->set_ue_sync_opts(&ue_mib_sync.ue_sync); + + if (p->do_agc) { + srslte_ue_sync_start_agc(&ue_mib_sync.ue_sync, callback_set_rx_gain, srslte_agc_get_gain(&cs.ue_sync.agc)); + } + + srslte_ue_sync_reset(&ue_mib_sync.ue_sync); + srslte_ue_sync_set_cfo(&ue_mib_sync.ue_sync, cfo); + + /* Find and decode MIB */ + int sfn_offset; + ret = srslte_ue_mib_sync_decode(&ue_mib_sync, + 40, + bch_payload, &cell->nof_ports, &sfn_offset); + p->stop_rx(); + + if (ret == 1) { + srslte_pbch_mib_unpack(bch_payload, cell, NULL); + + fprintf(stdout, "Found Cell: PCI=%d, PRB=%d, Ports=%d, CFO=%.1f KHz\n", + cell->id, cell->nof_prb, cell->nof_ports, cfo/1000); + + Info("SYNC: MIB Decoded: PCI=%d, PRB=%d, Ports=%d, CFO=%.1f KHz\n", + cell->id, cell->nof_prb, cell->nof_ports, cfo/1000); + + return CELL_FOUND; + } else if (ret == 0) { + Warning("SYNC: Found PSS but could not decode PBCH\n"); + return CELL_NOT_FOUND; + } else { + Error("SYNC: Receiving MIB\n"); + return ERROR; + } +} + + + + + + + + +/********* + * SFN synchronizer class + */ + +phch_recv::sfn_sync::~sfn_sync() +{ + srslte_ue_mib_free(&ue_mib); +} + +void phch_recv::sfn_sync::init(srslte_ue_sync_t *ue_sync, cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, uint32_t timeout) +{ + this->log_h = log_h; + this->ue_sync = ue_sync; + this->timeout = timeout; + + for (int i=0;ibuffer[i] = buffer[i]; + } + + if (srslte_ue_mib_init(&ue_mib, SRSLTE_MAX_PRB)) { + Error("SYNC: Initiating UE MIB decoder\n"); + } +} + +bool phch_recv::sfn_sync::set_cell(srslte_cell_t cell) +{ + if (srslte_ue_mib_set_cell(&ue_mib, cell)) { + Error("SYNC: Setting cell: initiating ue_mib\n"); + return false; } + return true; } + +void phch_recv::sfn_sync::reset() +{ + srslte_ue_mib_reset(&ue_mib); + cnt = 0; +} + +phch_recv::sfn_sync::ret_code phch_recv::sfn_sync::run_subframe(srslte_cell_t *cell, uint32_t *tti_cnt) +{ + + uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; + + srslte_ue_sync_decode_sss_on_track(ue_sync, true); + int ret = srslte_ue_sync_zerocopy_multi(ue_sync, buffer); + if (ret < 0) { + Error("SYNC: Error calling ue_sync_get_buffer"); + return ERROR; + } + + if (ret == 1) { + if (srslte_ue_sync_get_sfidx(ue_sync) == 0) { + int sfn_offset = 0; + Info("SYNC: Trying to decode MIB... SNR=%.1f dB\n", 10*log10(srslte_chest_dl_get_snr(&ue_mib.chest))); + + int n = srslte_ue_mib_decode(&ue_mib, buffer[0], bch_payload, NULL, &sfn_offset); + if (n < 0) { + Error("SYNC: Error decoding MIB while synchronising SFN"); + return ERROR; + } else if (n == SRSLTE_UE_MIB_FOUND) { + uint32_t sfn; + srslte_pbch_mib_unpack(bch_payload, cell, &sfn); + + sfn = (sfn+sfn_offset)%1024; + if (tti_cnt) { + *tti_cnt = 10*sfn; + Info("SYNC: DONE, TTI=%d, sfn_offset=%d\n", *tti_cnt, sfn_offset); + } + + srslte_ue_sync_set_agc_period(ue_sync, 20); + srslte_ue_sync_decode_sss_on_track(ue_sync, true); + reset(); + return SFN_FOUND; + } + } + } else { + Debug("SYNC: PSS/SSS not found...\n"); + } + + cnt++; + if (cnt >= timeout) { + cnt = 0; + log_h->warning("SYNC: Timeout while synchronizing SFN\n"); + return TIMEOUT; + } + + return IDLE; +} + + + + + + +/********* + * Measurement class + */ +void phch_recv::measure::init(srslte_ue_sync_t *ue_sync, cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, uint32_t nof_rx_antennas, uint32_t nof_subrames) +{ + this->log_h = log_h; + this->nof_subframes = nof_subrames; + this->ue_sync = ue_sync; + for (int i=0;ibuffer[i] = buffer[i]; + } + + if (srslte_ue_dl_init(&ue_dl, SRSLTE_MAX_PRB, nof_rx_antennas)) { + Error("SYNC: Initiating ue_dl_measure\n"); + return; + } + reset(); +} + +phch_recv::measure::~measure() { + srslte_ue_dl_free(&ue_dl); +} + +void phch_recv::measure::reset() { + cnt = 0; + mean_rsrp = 0; + mean_rsrq = 0; + mean_snr = 0; +} + +void phch_recv::measure::set_cell(srslte_cell_t cell) +{ + if (srslte_ue_dl_set_cell(&ue_dl, cell)) { + Error("SYNC: Setting cell: initiating ue_dl_measure\n"); + } +} + +float phch_recv::measure::rsrp() { + return 10*log10(mean_rsrp/1000); +} + +float phch_recv::measure::rsrq() { + return 10*log10(mean_rsrq); +} + +float phch_recv::measure::snr() { + return 10*log10(mean_snr); +} + +phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx) +{ + int sync_res = srslte_ue_sync_zerocopy_multi(ue_sync, buffer); + if (sync_res == 1) { + uint32_t cfi = 0; + + if (srslte_ue_dl_decode_fft_estimate(&ue_dl, buffer, sf_idx, &cfi)) { + log_h->error("SYNC: Measuring RSRP: Estimating channel\n"); + return ERROR; + } + + float rsrp = srslte_chest_dl_get_rsrp(&ue_dl.chest); + float rsrq = srslte_chest_dl_get_rsrq(&ue_dl.chest); + float snr = srslte_chest_dl_get_snr(&ue_dl.chest); + + mean_rsrp = SRSLTE_VEC_CMA(rsrp, mean_rsrp, cnt); + mean_rsrq = SRSLTE_VEC_CMA(rsrq, mean_rsrq, cnt); + mean_snr = SRSLTE_VEC_CMA(rsrq, mean_snr, cnt); + cnt++; + + log_h->info("SYNC: Measuring RSRP %d/%d, sf_idx=%d, RSRP=%.1f dBm, SNR=%.1f dB\n", + cnt, RSRP_MEASURE_NOF_FRAMES, sf_idx, + 10*log10(rsrp/1000), 10*log10(snr)); + + if (cnt >= nof_subframes) { + return MEASURE_OK; + } + } else { + log_h->error("SYNC: Measuring RSRP: Sync error\n"); + return ERROR; + } + + return IDLE; +} + + + + + + + + +/********** + * Secondary cell receiver + */ + +void phch_recv::scell_recv::init(phch_recv *parent, srslte::log *log_h, uint32_t nof_rx_antennas, uint32_t prio, int cpu_affinity) +{ + this->p = parent; + this->log_h = log_h; + + // Create the ringbuffer for secondary cell reception + for (int i=0;iinfo("SFN Sync OK. Camping on cell PCI=%d...\n", cell.id); + break; + case sfn_sync::TIMEOUT: + log_h->info("SFN sync timeout\n"); + break; + case sfn_sync::IDLE: + break; + default: + p->radio_error(); + break; + } + break; + case SCELL_MEASURE: + switch (measure_p.run_subframe(tti%10)) { + case measure::MEASURE_OK: + log_h->info("SYNC: Measured OK\n"); + break; + case measure::IDLE: + break; + default: + p->radio_error(); + break; + } + break; + } + } +} + } From 95897ceb719c519490818feba4220732cc03b92d Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 10 Oct 2017 17:01:40 +0200 Subject: [PATCH 044/242] Added TM2 (Tx diversity) support for eNB --- lib/src/phy/enb/enb_dl.c | 14 +++++++++----- srsenb/src/phy/phch_worker.cc | 16 +++++++++------- srsenb/src/upper/rrc.cc | 3 +++ 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/lib/src/phy/enb/enb_dl.c b/lib/src/phy/enb/enb_dl.c index 7b2723765..d0db1f553 100644 --- a/lib/src/phy/enb/enb_dl.c +++ b/lib/src/phy/enb/enb_dl.c @@ -219,15 +219,19 @@ void srslte_enb_dl_clear_sf(srslte_enb_dl_t *q) void srslte_enb_dl_put_sync(srslte_enb_dl_t *q, uint32_t sf_idx) { if (sf_idx == 0 || sf_idx == 5) { - srslte_pss_put_slot(q->pss_signal, q->sf_symbols[0], q->cell.nof_prb, q->cell.cp); - srslte_sss_put_slot(sf_idx ? q->sss_signal5 : q->sss_signal0, q->sf_symbols[0], - q->cell.nof_prb, SRSLTE_CP_NORM); + for (int p = 0; p < q->cell.nof_ports; p++) { + srslte_pss_put_slot(q->pss_signal, q->sf_symbols[p], q->cell.nof_prb, q->cell.cp); + srslte_sss_put_slot(sf_idx ? q->sss_signal5 : q->sss_signal0, q->sf_symbols[p], + q->cell.nof_prb, SRSLTE_CP_NORM); + } } } void srslte_enb_dl_put_refs(srslte_enb_dl_t *q, uint32_t sf_idx) { - srslte_refsignal_cs_put_sf(q->cell, 0, q->csr_signal.pilots[0][sf_idx], q->sf_symbols[0]); + for (int p = 0; p < q->cell.nof_ports; p++) { + srslte_refsignal_cs_put_sf(q->cell, (uint32_t) p, q->csr_signal.pilots[p / 2][sf_idx], q->sf_symbols[p]); + } } void srslte_enb_dl_put_mib(srslte_enb_dl_t *q, uint32_t tti) @@ -256,7 +260,7 @@ void srslte_enb_dl_put_phich(srslte_enb_dl_t *q, uint8_t ack, uint32_t n_prb_low void srslte_enb_dl_put_base(srslte_enb_dl_t *q, uint32_t tti) { uint32_t sf_idx = tti%10; - + srslte_enb_dl_put_sync(q, sf_idx); srslte_enb_dl_put_refs(q, sf_idx); srslte_enb_dl_put_mib(q, tti); diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index 7b547c944..73d284c2c 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -90,12 +90,12 @@ void phch_worker::init(phch_common* phy_, srslte::log *log_h_) // Init cell here for(int p = 0; p < SRSLTE_MAX_PORTS; p++) { signal_buffer_rx[p] = (cf_t *) srslte_vec_malloc(2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t)); - if (!signal_buffer_rx) { + if (!signal_buffer_rx[p]) { fprintf(stderr, "Error allocating memory\n"); return; } signal_buffer_tx[p] = (cf_t *) srslte_vec_malloc(2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t)); - if (!signal_buffer_tx) { + if (!signal_buffer_tx[p]) { fprintf(stderr, "Error allocating memory\n"); return; } @@ -155,11 +155,13 @@ void phch_worker::stop() srslte_enb_dl_free(&enb_dl); srslte_enb_ul_free(&enb_ul); - if (signal_buffer_rx) { - free(signal_buffer_rx); - } - if (signal_buffer_tx) { - free(signal_buffer_tx); + for (int p = 0; p < SRSLTE_MAX_PORTS; p++) { + if (signal_buffer_rx[p]) { + free(signal_buffer_rx[p]); + } + if (signal_buffer_tx[p]) { + free(signal_buffer_tx[p]); + } } pthread_mutex_unlock(&mutex); pthread_mutex_destroy(&mutex); diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index 4a432b394..6d8ec168f 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -1114,6 +1114,9 @@ void rrc::ue::send_connection_setup(bool is_setup) phy_cfg->sched_request_cnfg_present = true; phy_cfg->sched_request_cnfg.setup_present = true; phy_cfg->sched_request_cnfg.dsr_trans_max = parent->cfg.sr_cfg.dsr_max; + memcpy(&phy_cfg->antenna_info_explicit_value, &parent->cfg.antenna_info, sizeof(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT)); + phy_cfg->antenna_info_present = true; + phy_cfg->antenna_info_default_value = false; if (is_setup) { if (sr_allocate(parent->cfg.sr_cfg.period, &phy_cfg->sched_request_cnfg.sr_cnfg_idx, &phy_cfg->sched_request_cnfg.sr_pucch_resource_idx)) { From 21355de77e5eb429312609aa5d2e6c41780223a1 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 11 Oct 2017 17:00:49 +0200 Subject: [PATCH 045/242] Added TM3 (1 layer only) eNB support at RRC --- .../srslte/interfaces/enb_interfaces.h | 3 +- srsenb/hdr/phy/phch_worker.h | 11 ++++-- srsenb/hdr/phy/phy.h | 1 + srsenb/src/phy/phch_worker.cc | 38 ++++++++++++++++--- srsenb/src/phy/phy.cc | 13 ++++--- srsenb/src/upper/rrc.cc | 4 ++ srsue/src/upper/rrc.cc | 4 +- 7 files changed, 59 insertions(+), 15 deletions(-) diff --git a/lib/include/srslte/interfaces/enb_interfaces.h b/lib/include/srslte/interfaces/enb_interfaces.h index 9c85814f8..0cb3d18d6 100644 --- a/lib/include/srslte/interfaces/enb_interfaces.h +++ b/lib/include/srslte/interfaces/enb_interfaces.h @@ -93,7 +93,8 @@ public: class phy_interface_rrc { public: - virtual void set_config_dedicated(uint16_t rnti, LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT* dedicated) = 0; + virtual void set_conf_dedicated_ack(uint16_t rnti, bool rrc_completed) = 0; + virtual void set_config_dedicated(uint16_t rnti, LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT* dedicated) = 0; }; diff --git a/srsenb/hdr/phy/phch_worker.h b/srsenb/hdr/phy/phch_worker.h index 42e36113d..2d773345c 100644 --- a/srsenb/hdr/phy/phch_worker.h +++ b/srsenb/hdr/phy/phch_worker.h @@ -56,13 +56,15 @@ public: int read_ce_abs(float *ce_abs); int read_pusch_d(cf_t *pusch_d); void start_plot(); - + + void set_conf_dedicated_ack(uint16_t rnti, + bool rrc_completed); void set_config_dedicated(uint16_t rnti, srslte_uci_cfg_t *uci_cfg, srslte_pucch_sched_t *pucch_sched, srslte_refsignal_srs_cfg_t *srs_cfg, - uint32_t I_sr, bool pucch_cqi, uint32_t pmi_idx, bool pucch_cqi_ack); + LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT* dedicated); uint32_t get_metrics(phy_metrics_t metrics[ENB_METRICS_MAX_USERS]); @@ -99,13 +101,16 @@ private: // Class to store user information class ue { public: - ue() : I_sr(0), I_sr_en(false), cqi_en(false), pucch_cqi_ack(false), pmi_idx(0), has_grant_tti(0) {bzero(&metrics, sizeof(phy_metrics_t));} + ue() : I_sr(0), I_sr_en(false), cqi_en(false), pucch_cqi_ack(false), pmi_idx(0), has_grant_tti(0), + dedicated_ack(false) {bzero(&metrics, sizeof(phy_metrics_t));} uint32_t I_sr; uint32_t pmi_idx; bool I_sr_en; bool cqi_en; bool pucch_cqi_ack; int has_grant_tti; + LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT dedicated; + bool dedicated_ack; uint32_t rnti; srslte_enb_ul_phich_info_t phich_info; void metrics_read(phy_metrics_t *metrics); diff --git a/srsenb/hdr/phy/phy.h b/srsenb/hdr/phy/phy.h index 9ab1efd74..a1616c268 100644 --- a/srsenb/hdr/phy/phy.h +++ b/srsenb/hdr/phy/phy.h @@ -66,6 +66,7 @@ public: static uint32_t tti_to_subf(uint32_t tti); void start_plot(); + void set_conf_dedicated_ack(uint16_t rnti, bool dedicated_ack); void set_config_dedicated(uint16_t rnti, LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT* dedicated); void get_metrics(phy_metrics_t metrics[ENB_METRICS_MAX_USERS]); diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index 73d284c2c..d38242782 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -210,13 +210,28 @@ uint32_t phch_worker::get_nof_rnti() { return ue_db.size(); } +void phch_worker::set_conf_dedicated_ack(uint16_t rnti, bool ack){ + pthread_mutex_lock(&mutex); + if (ue_db.count(rnti)) { + ue_db[rnti].dedicated_ack = ack; + } else { + Error("Setting dedicated ack: rnti=0x%x does not exist\n"); + } + pthread_mutex_unlock(&mutex); +} + void phch_worker::set_config_dedicated(uint16_t rnti, srslte_uci_cfg_t *uci_cfg, srslte_pucch_sched_t *pucch_sched, srslte_refsignal_srs_cfg_t *srs_cfg, - uint32_t I_sr, bool pucch_cqi, uint32_t pmi_idx, bool pucch_cqi_ack) + LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT* dedicated) { - pthread_mutex_lock(&mutex); + uint32_t I_sr = dedicated->sched_request_cnfg.sr_cnfg_idx; + bool pucch_cqi = dedicated->cqi_report_cnfg.report_periodic_setup_present; + uint32_t pmi_idx = dedicated->cqi_report_cnfg.report_periodic.pmi_cnfg_idx; + bool pucch_cqi_ack = dedicated->cqi_report_cnfg.report_periodic.simult_ack_nack_and_cqi; + + pthread_mutex_lock(&mutex); if (ue_db.count(rnti)) { pucch_sched->N_pucch_1 = phy->pucch_cfg.n1_pucch_an; srslte_enb_ul_cfg_ue(&enb_ul, rnti, uci_cfg, pucch_sched, srs_cfg); @@ -232,7 +247,9 @@ void phch_worker::set_config_dedicated(uint16_t rnti, ue_db[rnti].pmi_idx = 0; ue_db[rnti].cqi_en = false; } - + + /* Copy all dedicated RRC configuration to UE */ + memcpy(&ue_db[rnti].dedicated, dedicated, sizeof(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT)); } else { Error("Setting config dedicated: rnti=0x%x does not exist\n"); } @@ -624,14 +641,25 @@ int phch_worker::encode_pdcch_ul(srslte_enb_ul_pusch_t *grants, uint32_t nof_gra int phch_worker::encode_pdcch_dl(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants, uint32_t sf_idx) { + /* For each grant... */ for (uint32_t i=0;iPHY interface **********/ +void phy::set_conf_dedicated_ack(uint16_t rnti, bool ack) +{ + for (uint32_t i = 0; i < nof_workers; i++) { + workers[i].set_conf_dedicated_ack(rnti, ack); + } +} + void phy::set_config_dedicated(uint16_t rnti, LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT* dedicated) { // Parse RRC config @@ -225,11 +232,7 @@ void phy::set_config_dedicated(uint16_t rnti, LIBLTE_RRC_PHYSICAL_CONFIG_DEDICAT pucch_sched.n_pucch_sr = dedicated->sched_request_cnfg.sr_pucch_resource_idx; for (uint32_t i=0;isched_request_cnfg.sr_cnfg_idx, - dedicated->cqi_report_cnfg.report_periodic_setup_present, - dedicated->cqi_report_cnfg.report_periodic.pmi_cnfg_idx, - dedicated->cqi_report_cnfg.report_periodic.simult_ack_nack_and_cqi); + workers[i].set_config_dedicated(rnti, &uci_cfg, &pucch_sched, NULL, dedicated); } } diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index 6d8ec168f..7b20209a5 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -862,6 +862,9 @@ void rrc::ue::handle_rrc_con_setup_complete(LIBLTE_RRC_CONNECTION_SETUP_COMPLETE memcpy(pdu->msg, msg->dedicated_info_nas.msg, msg->dedicated_info_nas.N_bytes); pdu->N_bytes = msg->dedicated_info_nas.N_bytes; + // Acknowledge Dedicated Configuration + parent->phy->set_conf_dedicated_ack(rnti, true); + if(has_tmsi) { parent->s1ap->initial_ue(rnti, pdu, m_tmsi, mmec); } else { @@ -1197,6 +1200,7 @@ void rrc::ue::send_connection_setup(bool is_setup) // Configure PHY layer parent->phy->set_config_dedicated(rnti, phy_cfg); + parent->phy->set_conf_dedicated_ack(rnti, false); parent->mac->phy_config_enabled(rnti, true); rr_cfg->drb_to_add_mod_list_size = 0; diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 7b78bd774..679cd29ee 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -1438,7 +1438,9 @@ void rrc::apply_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT if (phy_cnfg->antenna_info_present) { if (!phy_cnfg->antenna_info_default_value) { if (phy_cnfg->antenna_info_explicit_value.tx_mode != LIBLTE_RRC_TRANSMISSION_MODE_1 && - phy_cnfg->antenna_info_explicit_value.tx_mode != LIBLTE_RRC_TRANSMISSION_MODE_2) { + phy_cnfg->antenna_info_explicit_value.tx_mode != LIBLTE_RRC_TRANSMISSION_MODE_2 && + phy_cnfg->antenna_info_explicit_value.tx_mode != LIBLTE_RRC_TRANSMISSION_MODE_3 && + phy_cnfg->antenna_info_explicit_value.tx_mode != LIBLTE_RRC_TRANSMISSION_MODE_4) { rrc_log->error("Transmission mode TM%s not currently supported by srsUE\n", liblte_rrc_transmission_mode_text[phy_cnfg->antenna_info_explicit_value.tx_mode]); } From eec7b27b890bd6d41be23390d980a2742c1c0192 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 11 Oct 2017 17:09:51 +0200 Subject: [PATCH 046/242] Added check for msg3 buffer overflow. Increased msg3 buffer. Fixes #103 --- srsue/hdr/mac/mux.h | 2 +- srsue/src/mac/mux.cc | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/srsue/hdr/mac/mux.h b/srsue/hdr/mac/mux.h index 1167af752..0d04c99cb 100644 --- a/srsue/hdr/mac/mux.h +++ b/srsue/hdr/mac/mux.h @@ -100,7 +100,7 @@ private: uint8_t nof_harq_proc; /* Msg3 Buffer */ - static const uint32_t MSG3_BUFF_SZ = 128; + static const uint32_t MSG3_BUFF_SZ = 1024; uint8_t msg3_buff[MSG3_BUFF_SZ]; /* PDU Buffer */ diff --git a/srsue/src/mac/mux.cc b/srsue/src/mac/mux.cc index 5ab58fb50..e38300b87 100644 --- a/srsue/src/mac/mux.cc +++ b/srsue/src/mac/mux.cc @@ -349,14 +349,19 @@ bool mux::msg3_is_transmitted() /* Returns a pointer to the Msg3 buffer */ uint8_t* mux::msg3_get(uint8_t *payload, uint32_t pdu_sz) { - uint8_t* msg3_buff_start_pdu = pdu_get(msg3_buff, pdu_sz, 0, 0); - if (!msg3_buff_start_pdu) { - Error("Moving PDU from Mux unit to Msg3 buffer\n"); + if (pdu_sz < MSG3_BUFF_SZ - 32) { + uint8_t* msg3_buff_start_pdu = pdu_get(msg3_buff, pdu_sz, 0, 0); + if (!msg3_buff_start_pdu) { + Error("Moving PDU from Mux unit to Msg3 buffer\n"); + return NULL; + } + memcpy(payload, msg3_buff_start_pdu, sizeof(uint8_t)*pdu_sz); + msg3_has_been_transmitted = true; + return payload; + } else { + Error("Msg3 size (%d) is longer than internal msg3_buff size=%d, (see mux.h)\n", pdu_sz, MSG3_BUFF_SZ-32); return NULL; - } - memcpy(payload, msg3_buff_start_pdu, sizeof(uint8_t)*pdu_sz); - msg3_has_been_transmitted = true; - return payload; + } } From db5d747c661a19ceaba18aa085d3578e7b5d8084 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 12 Oct 2017 10:31:08 +0200 Subject: [PATCH 047/242] Fix coverty issues --- lib/include/srslte/common/metrics_hub.h | 15 ++++++++++----- lib/src/phy/ch_estimation/refsignal_dl.c | 6 +----- lib/src/phy/phch/pmch.c | 11 ++++------- lib/src/phy/phch/pusch.c | 2 +- lib/src/phy/phch/test/phich_file_test.c | 6 +++++- lib/src/phy/phch/test/pmch_file_test.c | 2 +- lib/src/phy/phch/test/pmch_test.c | 2 +- lib/src/phy/ue/ue_mib.c | 8 ++++---- lib/src/radio/radio.cc | 4 ++-- lib/src/radio/radio_multi.cc | 4 ++-- srsenb/src/mac/scheduler_ue.cc | 14 +++++++------- srsenb/src/upper/gtpu.cc | 6 +++++- srsenb/src/upper/rrc.cc | 6 +++++- 13 files changed, 48 insertions(+), 38 deletions(-) diff --git a/lib/include/srslte/common/metrics_hub.h b/lib/include/srslte/common/metrics_hub.h index 7ea3c3190..687722bcc 100644 --- a/lib/include/srslte/common/metrics_hub.h +++ b/lib/include/srslte/common/metrics_hub.h @@ -31,6 +31,9 @@ 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_; start_periodic(report_period_secs*1e6); @@ -47,11 +50,13 @@ public: private: void run_period() { - metrics_t metric; - bzero(&metric, sizeof(metrics_t)); - m->get_metrics(metric); - for (uint32_t i=0;iset_metrics(metric); + if (m) { + metrics_t metric; + bzero(&metric, sizeof(metrics_t)); + m->get_metrics(metric); + for (uint32_t i=0;iset_metrics(metric); + } } } metrics_interface *m; diff --git a/lib/src/phy/ch_estimation/refsignal_dl.c b/lib/src/phy/ch_estimation/refsignal_dl.c index 9adbc6c18..308be6877 100644 --- a/lib/src/phy/ch_estimation/refsignal_dl.c +++ b/lib/src/phy/ch_estimation/refsignal_dl.c @@ -86,11 +86,7 @@ uint32_t srslte_refsignal_cs_nof_symbols(uint32_t port_id) uint32_t srslte_refsignal_mbsfn_nof_symbols() { - if(false){ - return 3; - }else{ - return 3; - } + return 3; } diff --git a/lib/src/phy/phch/pmch.c b/lib/src/phy/phch/pmch.c index 99e40d50f..aa7fd77b1 100644 --- a/lib/src/phy/phch/pmch.c +++ b/lib/src/phy/phch/pmch.c @@ -381,11 +381,11 @@ int srslte_pmch_decode_multi(srslte_pmch_t *q, srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, q->nof_rx_antennas, cfg->nbits[0].nof_re, noise_estimate); if (SRSLTE_VERBOSE_ISDEBUG()) { - DEBUG("SAVED FILE subframe.dat: received subframe symbols\n",0); + DEBUG("SAVED FILE subframe.dat: received subframe symbols\n"); srslte_vec_save_file("subframe.dat", sf_symbols, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t)); - DEBUG("SAVED FILE hest0.dat: channel estimates for port 4\n",0); + DEBUG("SAVED FILE hest0.dat: channel estimates for port 4\n"); srslte_vec_save_file("hest0.dat", ce[0], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t)); - DEBUG("SAVED FILE pmch_symbols.dat: symbols after equalization\n",0); + DEBUG("SAVED FILE pmch_symbols.dat: symbols after equalization\n"); srslte_vec_save_file("pmch_symbols.bin", q->d, cfg->nbits[0].nof_re*sizeof(cf_t)); } @@ -393,16 +393,13 @@ int srslte_pmch_decode_multi(srslte_pmch_t *q, * The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation, * thus we don't need tot set it in thde LLRs normalization */ - - - srslte_demod_soft_demodulate_s(cfg->grant.mcs[0].mod, q->d, q->e, cfg->nbits[0].nof_re); /* descramble */ srslte_scrambling_s_offset(&q->seqs[area_id]->seq[cfg->sf_idx], q->e, 0, cfg->nbits[0].nof_bits); if (SRSLTE_VERBOSE_ISDEBUG()) { - DEBUG("SAVED FILE llr.dat: LLR estimates after demodulation and descrambling\n",0); + DEBUG("SAVED FILE llr.dat: LLR estimates after demodulation and descrambling\n"); srslte_vec_save_file("llr.dat", q->e, cfg->nbits[0].nof_bits*sizeof(int16_t)); } return srslte_dlsch_decode(&q->dl_sch, cfg, softbuffer, q->e, data); diff --git a/lib/src/phy/phch/pusch.c b/lib/src/phy/phch/pusch.c index f52bbbb42..ba1195507 100644 --- a/lib/src/phy/phch/pusch.c +++ b/lib/src/phy/phch/pusch.c @@ -323,7 +323,7 @@ int srslte_pusch_set_cell(srslte_pusch_t *q, srslte_cell_t cell) { q->max_re = cell.nof_prb * MAX_PUSCH_RE(q->cell.cp); - INFO("PUSCH: Cell config PCI=5d, %d ports %d PRBs, max_symbols: %d\n", + INFO("PUSCH: Cell config PCI=%d, %d ports %d PRBs, max_symbols: %d\n", q->cell.id, q->cell.nof_ports, q->cell.nof_prb, q->max_re); if (q->cell.id != cell.id || q->cell.nof_prb == 0) { diff --git a/lib/src/phy/phch/test/phich_file_test.c b/lib/src/phy/phch/test/phich_file_test.c index 968aa5cbc..d7078f933 100644 --- a/lib/src/phy/phch/test/phich_file_test.c +++ b/lib/src/phy/phch/test/phich_file_test.c @@ -263,7 +263,11 @@ int main(int argc, char **argv) { for (ngroup=0;ngroupue_sync, q->sf_buffer); diff --git a/lib/src/radio/radio.cc b/lib/src/radio/radio.cc index b393a3ff4..42d4143f9 100644 --- a/lib/src/radio/radio.cc +++ b/lib/src/radio/radio.cc @@ -63,10 +63,10 @@ bool radio::init(char *args, char *devname) } if (args) { - strncpy(saved_args, args, 128); + strncpy(saved_args, args, 127); } if (devname) { - strncpy(saved_devname, devname, 128); + strncpy(saved_devname, devname, 127); } return true; diff --git a/lib/src/radio/radio_multi.cc b/lib/src/radio/radio_multi.cc index 018a675ac..3888a77f3 100644 --- a/lib/src/radio/radio_multi.cc +++ b/lib/src/radio/radio_multi.cc @@ -31,10 +31,10 @@ bool radio_multi::init_multi(uint32_t nof_rx_antennas, char* args, char* devname } if (args) { - strncpy(saved_args, args, 128); + strncpy(saved_args, args, 127); } if (devname) { - strncpy(saved_devname, devname, 128); + strncpy(saved_devname, devname, 127); } return true; diff --git a/srsenb/src/mac/scheduler_ue.cc b/srsenb/src/mac/scheduler_ue.cc index 38058415f..004808976 100644 --- a/srsenb/src/mac/scheduler_ue.cc +++ b/srsenb/src/mac/scheduler_ue.cc @@ -252,13 +252,13 @@ bool sched_ue::get_pucch_sched(uint32_t current_tti, uint32_t prb_idx[2]) if (((dl_harq[i].get_tti()+4)%10240) == current_tti) { uint32_t n_pucch = srslte_pucch_get_npucch(dl_harq[i].get_n_cce(), SRSLTE_PUCCH_FORMAT_1A, has_sr, &pucch_sched); if (prb_idx) { - for (int i=0;i<2;i++) { - prb_idx[i] = srslte_pucch_n_prb(&cfg.pucch_cfg, SRSLTE_PUCCH_FORMAT_1A, n_pucch, cell.nof_prb, cell.cp, i); + for (int j=0;j<2;j++) { + prb_idx[j] = srslte_pucch_n_prb(&cfg.pucch_cfg, SRSLTE_PUCCH_FORMAT_1A, n_pucch, cell.nof_prb, cell.cp, j); } + Debug("SCHED: Reserved Format1A PUCCH for rnti=0x%x, n_prb=%d,%d, n_pucch=%d, ncce=%d, has_sr=%d, n_pucch_1=%d\n", + rnti, prb_idx[0], prb_idx[1], n_pucch, dl_harq[i].get_n_cce(), has_sr, pucch_sched.N_pucch_1); } - Debug("SCHED: Reserved Format1A PUCCH for rnti=0x%x, n_prb=%d,%d, n_pucch=%d, ncce=%d, has_sr=%d, n_pucch_1=%d\n", - rnti, prb_idx[0], prb_idx[1], n_pucch, dl_harq[i].get_n_cce(), has_sr, pucch_sched.N_pucch_1); - return true; + return true; } } // If there is no Format1A/B, then check if it's expecting Format1 @@ -277,9 +277,9 @@ bool sched_ue::get_pucch_sched(uint32_t current_tti, uint32_t prb_idx[2]) for (int i=0;i<2;i++) { prb_idx[i] = srslte_pucch_n_prb(&cfg.pucch_cfg, SRSLTE_PUCCH_FORMAT_2, cfg.cqi_pucch, cell.nof_prb, cell.cp, i); } + Debug("SCHED: Reserved Format2 PUCCH for rnti=0x%x, n_prb=%d,%d, n_pucch=%d, pmi_idx=%d\n", + rnti, prb_idx[0], prb_idx[1], cfg.cqi_pucch, cfg.cqi_idx); } - Debug("SCHED: Reserved Format2 PUCCH for rnti=0x%x, n_prb=%d,%d, n_pucch=%d, pmi_idx=%d\n", - rnti, prb_idx[0], prb_idx[1], cfg.cqi_pucch, cfg.cqi_idx); return true; } diff --git a/srsenb/src/upper/gtpu.cc b/srsenb/src/upper/gtpu.cc index d8f53d662..5d64cb4e5 100644 --- a/srsenb/src/upper/gtpu.cc +++ b/srsenb/src/upper/gtpu.cc @@ -82,6 +82,7 @@ bool gtpu::init(std::string gtp_bind_addr_, std::string mme_addr_, srsenb::pdcp_ #endif struct sockaddr_in bindaddr; + bzero(&bindaddr, sizeof(struct sockaddr_in)); bindaddr.sin_family = AF_INET; bindaddr.sin_addr.s_addr = inet_addr(gtp_bind_addr.c_str()); bindaddr.sin_port = htons(GTPU_PORT); @@ -137,7 +138,10 @@ void gtpu::write_pdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* pdu) servaddr.sin_port = htons(GTPU_PORT); gtpu_write_header(&header, pdu); - sendto(snk_fd, pdu->msg, pdu->N_bytes, MSG_EOR, (struct sockaddr*)&servaddr, sizeof(struct sockaddr_in)); + if (sendto(snk_fd, pdu->msg, pdu->N_bytes, MSG_EOR, (struct sockaddr*)&servaddr, sizeof(struct sockaddr_in))<0) { + perror("sendto"); + } + pool->deallocate(pdu); } diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index 4a432b394..35abda80a 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -223,9 +223,13 @@ void rrc::rem_user(uint16_t rnti) if (users.count(rnti) == 1) { rrc_log->console("Disconnecting rnti=0x%x.\n", rnti); rrc_log->info("Disconnecting rnti=0x%x.\n", rnti); - /* **Caution** order of removal here is imporant: from bottom to top */ + /* **Caution** order of removal here is important: from bottom to top */ mac->ue_rem(rnti); // MAC handles PHY + + pthread_mutex_unlock(&user_mutex); usleep(50000); + pthread_mutex_lock(&user_mutex); + rlc->rem_user(rnti); pdcp->rem_user(rnti); gtpu->rem_user(rnti); From 4b223ba729ef8dfb810d0c25bbe48f1ce55a333b Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 12 Oct 2017 11:50:51 +0200 Subject: [PATCH 048/242] add newline in error message --- lib/src/common/logger_file.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/common/logger_file.cc b/lib/src/common/logger_file.cc index 94e5e8405..739eded8b 100644 --- a/lib/src/common/logger_file.cc +++ b/lib/src/common/logger_file.cc @@ -55,7 +55,7 @@ void logger_file::init(std::string file) { filename = file; logfile = fopen(filename.c_str(), "w"); if(logfile==NULL) { - printf("Error: could not create log file, no messages will be logged"); + printf("Error: could not create log file, no messages will be logged!\n"); } start(); inited = true; From f5bc1049dc1e00c88f367f72872d926912a76918 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 12 Oct 2017 11:52:14 +0200 Subject: [PATCH 049/242] don't use log if USIM isn't initialized --- srsue/src/upper/usim.cc | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/srsue/src/upper/usim.cc b/srsue/src/upper/usim.cc index 9be69383e..e1d2c204f 100644 --- a/srsue/src/upper/usim.cc +++ b/srsue/src/upper/usim.cc @@ -105,20 +105,18 @@ void usim::stop() void usim::get_imsi_vec(uint8_t* imsi_, uint32_t n) { - if (!initiated) - { - usim_log->error("Getting IMSI: USIM not initiated\n"); + if (!initiated) { + fprintf(stderr, "USIM not initiated!\n"); return; } - if(NULL == imsi_ || n < 15) - { + + if(NULL == imsi_ || n < 15) { usim_log->error("Invalid parameters to get_imsi_vec"); return; } uint64_t temp = imsi; - for(int i=14;i>=0;i--) - { + for(int i=14;i>=0;i--) { imsi_[i] = temp % 10; temp /= 10; } @@ -126,13 +124,12 @@ void usim::get_imsi_vec(uint8_t* imsi_, uint32_t n) void usim::get_imei_vec(uint8_t* imei_, uint32_t n) { - if (!initiated) - { - usim_log->error("Getting IMEI: USIM not initiated\n"); + if (!initiated) { + fprintf(stderr, "USIM not initiated!\n"); return; } - if(NULL == imei_ || n < 15) - { + + if(NULL == imei_ || n < 15) { usim_log->error("Invalid parameters to get_imei_vec"); return; } @@ -147,9 +144,8 @@ void usim::get_imei_vec(uint8_t* imei_, uint32_t n) int usim::get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id) { - if (!initiated) - { - usim_log->error("Getting Home PLMN Id: USIM not initiated\n"); + if (!initiated) { + fprintf(stderr, "USIM not initiated!\n"); return -1; } From 21d9cb61423ec9ce95ff3328adb394c18eeb8c2a Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 12 Oct 2017 20:52:31 +0200 Subject: [PATCH 050/242] fix UL harq statistic printing --- srsue/src/mac/mac.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsue/src/mac/mac.cc b/srsue/src/mac/mac.cc index b54ea5be6..04b7c4750 100644 --- a/srsue/src/mac/mac.cc +++ b/srsue/src/mac/mac.cc @@ -417,7 +417,7 @@ void mac::get_metrics(mac_metrics_t &m) metrics.rx_pkts?((float) 100*metrics.rx_errors/metrics.rx_pkts):0.0, dl_harq.get_average_retx(), metrics.tx_pkts?((float) 100*metrics.tx_errors/metrics.tx_pkts):0.0, - dl_harq.get_average_retx()); + ul_harq.get_average_retx()); metrics.ul_buffer = (int) bsr_procedure.get_buffer_state(); m = metrics; From d38475d6d0f5bd37ec187b8cf25dfb3e936696d4 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 13 Oct 2017 09:35:53 +0200 Subject: [PATCH 051/242] Fixed % log in buffer pool capacity warning --- lib/include/srslte/common/buffer_pool.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/include/srslte/common/buffer_pool.h b/lib/include/srslte/common/buffer_pool.h index 94439387a..1c6dfc53a 100644 --- a/lib/include/srslte/common/buffer_pool.h +++ b/lib/include/srslte/common/buffer_pool.h @@ -93,7 +93,7 @@ public: available.pop(); if (available.size() < capacity/20) { - printf("Warning buffer pool capacity is %f %%\n", (float) available.size()/capacity); + printf("Warning buffer pool capacity is %f %%\n", (float) 100*available.size()/capacity); } #ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED if (debug_name) { From 4fe29049391ad4091fb64a1e9e227b6cbaac7c38 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 13 Oct 2017 10:23:25 +0200 Subject: [PATCH 052/242] Removed unnecessary T311 timer start --- srsue/src/upper/rrc.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 7b78bd774..94c2e449a 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -233,7 +233,6 @@ void rrc::run_thread() { set_phy_default(); set_mac_default(); mac->pcch_start_rx(); - mac_timers->timer_get(t311)->run(); mac_timers->timer_get(t310)->stop(); mac_timers->timer_get(t311)->stop(); state = RRC_STATE_IDLE; From 5509262f544a1bef9e78a25901e65c34ab219a45 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 13 Oct 2017 10:25:51 +0200 Subject: [PATCH 053/242] Fixed possible bug in rx_metadata --- lib/src/phy/rf/rf_uhd_imp.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/src/phy/rf/rf_uhd_imp.c b/lib/src/phy/rf/rf_uhd_imp.c index 95287a628..29aec5b44 100644 --- a/lib/src/phy/rf/rf_uhd_imp.c +++ b/lib/src/phy/rf/rf_uhd_imp.c @@ -649,12 +649,14 @@ int rf_uhd_recv_with_time_multi(void *h, fprintf(stderr, "Error receiving from UHD: %d\n", error); return -1; } - md = &handler->rx_md; + + uhd_rx_metadata_error_code_t error_code = 0; + uhd_rx_metadata_error_code(*md, &error_code); + + md = &handler->rx_md; n += rxd_samples; trials++; - - uhd_rx_metadata_error_code_t error_code; - uhd_rx_metadata_error_code(*md, &error_code); + if (error_code == UHD_RX_METADATA_ERROR_CODE_OVERFLOW) { log_overflow(handler); } else if (error_code == UHD_RX_METADATA_ERROR_CODE_LATE_COMMAND) { From 2019ca31eff3b7190cb6b2f3cf53734f95be9486 Mon Sep 17 00:00:00 2001 From: yagoda Date: Fri, 13 Oct 2017 15:35:48 +0100 Subject: [PATCH 054/242] adding neon support for new kernel structure --- lib/include/srslte/phy/utils/simd.h | 319 +++++++++++++++++++++++++--- 1 file changed, 292 insertions(+), 27 deletions(-) diff --git a/lib/include/srslte/phy/utils/simd.h b/lib/include/srslte/phy/utils/simd.h index 08eed115f..6e4185788 100644 --- a/lib/include/srslte/phy/utils/simd.h +++ b/lib/include/srslte/phy/utils/simd.h @@ -121,7 +121,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 @@ -147,6 +157,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 simd_f_t; +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -161,6 +175,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 */ @@ -175,12 +193,16 @@ static inline simd_f_t srslte_simd_f_loadu(float *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 */ } -static inline void srslte_simd_f_store(float *ptr, simd_f_t simdreg) { +static inline void srslte_simd_f_store(float *ptr, simd_f_t simdreg) {vst1q_f32 #ifdef LV_HAVE_AVX512 _mm512_store_ps(ptr, simdreg); #else /* LV_HAVE_AVX512 */ @@ -189,6 +211,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 +229,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 +247,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 +265,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 */ @@ -245,6 +283,10 @@ static inline simd_f_t srslte_simd_f_rcp(simd_f_t a) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_rcp_ps(a); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vrecpeq_f32(a); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -265,6 +307,9 @@ static inline simd_f_t srslte_simd_f_addsub(simd_f_t a, simd_f_t b) { #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 +319,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 +335,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 +353,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 */ @@ -344,6 +401,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 +419,10 @@ 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 + return vrecpeq_f32(vrsqrteq_f32(a)); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -368,10 +433,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 +469,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 +505,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 +528,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(ptr); + ret.val[1] = vld1q_f32(ptr); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -469,6 +552,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(ptr); + ret.val[1] = vld1q_f32(ptr); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -497,6 +585,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 +616,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 +637,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 +659,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 +682,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 + re.val[0] = vdupq_n_f32(__real__ x); + im.val[1] = vdupq_n_f32(__imag__ x); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -601,6 +712,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 +744,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 +770,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],a.val[0]); + ret.val[1] = vaddq_f32(a.val[1],a.val[1]); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -665,6 +795,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 +834,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 = vrecpeq_f32(mod2); + simd_f_t neg_a_im = vnegq_f32(vdupq_n_f32(-0.0f), 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 +863,11 @@ 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 /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ return ret; @@ -739,6 +888,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 LV_HAVE_SSE +typedef int32x4_t simd_i_t; +typedef __m128 simd_sel_t; +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -752,6 +906,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 vld1_s32((int32x4_t*)x); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -780,6 +938,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,10 +956,14 @@ 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 */ -} +}vcgtq_f32 static inline simd_sel_t srslte_simd_f_max(simd_f_t a, simd_f_t b) { #ifdef LV_HAVE_AVX512 @@ -808,6 +974,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 */ @@ -841,6 +1011,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 +1028,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((int16x8_t*) ptr); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -867,7 +1045,11 @@ static inline simd_s_t srslte_simd_s_loadu(int16_t *ptr) { return _mm256_loadu_si256((__m256i*) ptr); #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE - return _mm_loadu_si128((__m128i*) ptr); + return _mm_loadu_si128((__m128i*) ptr) +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vld1q_s16((int16x8_t*) ptr); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -882,6 +1064,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((int16x8_t*) ptr, simdreg); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -896,11 +1082,15 @@ 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((int16x8_t*) ptr, simdreg); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ } - +vdupq_n_s16 static inline simd_s_t srslte_simd_s_zero(void) { #ifdef LV_HAVE_AVX512 return _mm512_setzero_si512(); @@ -910,10 +1100,14 @@ 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 */ -} +}vmulq_s16 static inline simd_s_t srslte_simd_s_mul(simd_s_t a, simd_s_t b) { #ifdef LV_HAVE_AVX512 @@ -924,6 +1118,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 +1136,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 +1154,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 +1168,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 +1181,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 +1232,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 +1251,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 +1270,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 +1292,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_f32((float*)(ptr) ,simdreg); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ } @@ -1079,6 +1312,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_f32((float*)(ptr) ,simdreg); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ } @@ -1091,6 +1328,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_f32((int16_t *) re, simdreg.m128.val[0]); + vst1q_f32((int16_t *) im, simdreg.m128.val[1]); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ } @@ -1103,10 +1345,17 @@ 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_f32((int16_t *) re, simdreg.m128.val[0]); + vst1q_f32((int16_t *) im, simdreg.m128.val[1]); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ } + +//TODO static inline simd_c16_t srslte_simd_c16_prod (simd_c16_t a, simd_c16_t b) { simd_c16_t ret; #ifdef LV_HAVE_AVX2 @@ -1134,11 +1383,16 @@ 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_s32(a.m127.val[0],a.m127.val[0]); + ret.m128.val[1] = vaddq_s32(a.m127.val[1],a.m127.val[1]); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ return ret; } - +vdupq_n_s16 static inline simd_c16_t srslte_simd_c16_zero (void) { simd_c16_t ret; #ifdef LV_HAVE_AVX2 @@ -1148,7 +1402,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 +1441,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 */ From c4c1c62360ccbede6bb85dbfd7575e545d1aa96e Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 13 Oct 2017 17:59:12 +0200 Subject: [PATCH 055/242] stable connection. Runs out of samples in ringbuffer if clock differences --- lib/include/srslte/phy/utils/ringbuffer.h | 8 +- lib/src/phy/utils/ringbuffer.c | 5 + srsue/hdr/phy/phch_recv.h | 11 +- srsue/hdr/phy/phy.h | 2 + srsue/hdr/ue.h | 1 + srsue/src/main.cc | 6 + srsue/src/phy/phch_recv.cc | 147 +++++++++++++++++----- srsue/src/phy/phy.cc | 5 + srsue/src/ue.cc | 5 + 9 files changed, 152 insertions(+), 38 deletions(-) diff --git a/lib/include/srslte/phy/utils/ringbuffer.h b/lib/include/srslte/phy/utils/ringbuffer.h index c9276d5a9..acd2ae5e6 100644 --- a/lib/include/srslte/phy/utils/ringbuffer.h +++ b/lib/include/srslte/phy/utils/ringbuffer.h @@ -17,17 +17,19 @@ typedef struct { } srslte_ringbuffer_t; -SRSLTE_API int srslte_ringbuffer_init(srslte_ringbuffer_t *q, +SRSLTE_API int srslte_ringbuffer_init(srslte_ringbuffer_t *q, int capacity); SRSLTE_API void srslte_ringbuffer_free(srslte_ringbuffer_t *q, int capacity); -SRSLTE_API int srslte_ringbuffer_write(srslte_ringbuffer_t *q, +SRSLTE_API int srslte_ringbuffer_status(srslte_ringbuffer_t *q); + +SRSLTE_API int srslte_ringbuffer_write(srslte_ringbuffer_t *q, void *ptr, int nof_bytes); -SRSLTE_API int srslte_ringbuffer_read(srslte_ringbuffer_t *q, +SRSLTE_API int srslte_ringbuffer_read(srslte_ringbuffer_t *q, void *ptr, int nof_bytes); diff --git a/lib/src/phy/utils/ringbuffer.c b/lib/src/phy/utils/ringbuffer.c index 02faaeb9a..f7a10e2c5 100644 --- a/lib/src/phy/utils/ringbuffer.c +++ b/lib/src/phy/utils/ringbuffer.c @@ -34,6 +34,11 @@ void srslte_ringbuffer_free(srslte_ringbuffer_t *q, int capacity) } } +int srslte_ringbuffer_status(srslte_ringbuffer_t *q) +{ + return q->count; +} + int srslte_ringbuffer_write(srslte_ringbuffer_t *q, void *p, int nof_bytes) { uint8_t *ptr = (uint8_t*) p; diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index 781603be1..bb23bb5b5 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -67,7 +67,9 @@ public: void set_time_adv_sec(float time_adv_sec); void get_current_cell(srslte_cell_t *cell); - + + void scell_enable(bool enable); + const static int MUTEX_X_WORKER = 4; int radio_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time); @@ -155,6 +157,7 @@ private: float rsrp(); float rsrq(); float snr(); + float cfo(); private: srslte::log *log_h; srslte_ue_dl_t ue_dl; @@ -162,7 +165,7 @@ private: cf_t *buffer[SRSLTE_MAX_PORTS]; uint32_t cnt; uint32_t nof_subframes; - float mean_rsrp, mean_rsrq, mean_snr; + float mean_rsrp, mean_rsrq, mean_snr, mean_cfo; const static int RSRP_MEASURE_NOF_FRAMES = 5; }; @@ -172,9 +175,11 @@ private: public: void init(phch_recv *parent, srslte::log *log_h, uint32_t nof_rx_antennas, uint32_t prio, int cpu_affinity = -1); void stop(); + void reset(); int recv(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time); void write(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time); bool is_enabled(); + void set_cell(srslte_cell_t scell); private: void run_thread(); @@ -192,6 +197,8 @@ private: cf_t *sf_buffer[SRSLTE_MAX_PORTS]; srslte_ue_sync_t ue_sync; srslte_cell_t cell; + uint32_t nof_rx_antennas; + uint32_t current_sflen; measure measure_p; sfn_sync sfn_p; diff --git a/srsue/hdr/phy/phy.h b/srsue/hdr/phy/phy.h index 07a2713fa..c75fbb90d 100644 --- a/srsue/hdr/phy/phy.h +++ b/srsue/hdr/phy/phy.h @@ -78,6 +78,8 @@ public: void set_earfcn(std::vector earfcns); void force_freq(float dl_freq, float ul_freq); + void scell_enable(bool enable); + /********** RRC INTERFACE ********************/ void reset(); void sync_reset(); diff --git a/srsue/hdr/ue.h b/srsue/hdr/ue.h index 4e48f6b6d..fa461d1c9 100644 --- a/srsue/hdr/ue.h +++ b/srsue/hdr/ue.h @@ -80,6 +80,7 @@ public: void pregenerate_signals(bool enable); + void test_scell(); private: virtual ~ue(); diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 47d5f807e..0b67cecc1 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -387,14 +387,20 @@ int main(int argc, char *argv[]) pthread_t input; pthread_create(&input, NULL, &input_loop, &args); + bool scell_done = false; bool plot_started = false; bool signals_pregenerated = false; + while (running) { if (ue->is_attached()) { if (!signals_pregenerated && args.expert.pregenerate_signals) { ue->pregenerate_signals(true); signals_pregenerated = true; } + if (!scell_done) { + ((srsue::ue*) ue)->test_scell(); + scell_done = true; + } if (!plot_started && args.gui.enable) { ue->start_plot(); plot_started = true; diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 2249a0913..91d2cd482 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -64,7 +64,8 @@ phch_recv::phch_recv() { void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_mac, rrc_interface_phy *_rrc, prach *_prach_buffer, srslte::thread_pool *_workers_pool, phch_common *_worker_com, srslte::log *_log_h, uint32_t nof_rx_antennas_, uint32_t prio, - int sync_cpu_affinity) { + int sync_cpu_affinity) +{ radio_h = _radio_handler; log_h = _log_h; mac = _mac; @@ -96,7 +97,7 @@ void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_ma measure_p.init(&ue_sync, sf_buffer, log_h, nof_rx_antennas); // Start scell - scell.init(this, log_h, nof_rx_antennas_, prio, sync_cpu_affinity); + scell.init(this, log_h, nof_rx_antennas_, prio-1, sync_cpu_affinity); reset(); @@ -106,7 +107,6 @@ void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_ma } else { start_cpu(prio, sync_cpu_affinity); } - } phch_recv::~phch_recv() { @@ -118,13 +118,15 @@ phch_recv::~phch_recv() { srslte_ue_sync_free(&ue_sync); } -void phch_recv::stop() { +void phch_recv::stop() +{ running = false; wait_thread_finish(); } -void phch_recv::reset() { +void phch_recv::reset() +{ tx_mutex_cnt = 0; running = true; phy_state = IDLE; @@ -141,7 +143,8 @@ void phch_recv::reset() { } -void phch_recv::radio_error() { +void phch_recv::radio_error() +{ log_h->error("SYNC: Receiving from radio.\n"); phy_state = IDLE; radio_is_resetting=true; @@ -157,7 +160,8 @@ void phch_recv::radio_error() { radio_is_resetting=false; } -bool phch_recv::wait_radio_reset() { +bool phch_recv::wait_radio_reset() +{ int cnt=0; while(cnt < 20 && radio_is_resetting) { sleep(1); @@ -166,11 +170,13 @@ bool phch_recv::wait_radio_reset() { return radio_is_resetting; } -void phch_recv::set_agc_enable(bool enable) { +void phch_recv::set_agc_enable(bool enable) +{ do_agc = enable; } -void phch_recv::set_time_adv_sec(float _time_adv_sec) { +void phch_recv::set_time_adv_sec(float _time_adv_sec) +{ if (TX_MODE_CONTINUOUS && !radio_h->is_first_of_burst()) { int nsamples = ceil(current_srate*_time_adv_sec); next_offset = -nsamples; @@ -179,7 +185,8 @@ void phch_recv::set_time_adv_sec(float _time_adv_sec) { } } -void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q) { +void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q) +{ if (worker_com->args->cfo_integer_enabled) { srslte_ue_sync_cfo_i_detec_en(q, true); } @@ -473,9 +480,12 @@ int phch_recv::radio_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, s next_offset = nsamples; } - if (offset == 0) { + if (offset <= 0) { scell.write(data, nsamples, rx_time); } + + log_h->debug("SYNC: received %d samples from radio\n", nsamples); + return nsamples; } else { return -1; @@ -487,7 +497,13 @@ int phch_recv::scell_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, s return scell.recv(data, nsamples, rx_time); } - +void phch_recv::scell_enable(bool enable) +{ + srslte_cell_t target_cell; + memcpy(&target_cell, &cell, sizeof(srslte_cell_t)); + target_cell.id++; + scell.set_cell(target_cell); +} @@ -512,7 +528,6 @@ void phch_recv::run_thread() Debug("SYNC: state=%d\n", phy_state); } - tti = (tti+1) % 10240; log_h->step(tti); sf_idx = tti%10; @@ -635,7 +650,6 @@ void phch_recv::run_thread() rrc->out_of_sync(); worker->release(); worker_com->reset_ul(); - mac->tti_clock(tti); break; default: radio_error(); @@ -652,11 +666,12 @@ void phch_recv::run_thread() } is_in_idle = true; usleep(1000); - // Keep running MAC timer from system clock - tti = (tti+1) % 10240; - mac->tti_clock(tti); break; } + + // Increase TTI counter and trigger MAC clock (lower priority) + tti = (tti+1) % 10240; + mac->tti_clock(tti); } } @@ -860,6 +875,7 @@ bool phch_recv::sfn_sync::set_cell(srslte_cell_t cell) Error("SYNC: Setting cell: initiating ue_mib\n"); return false; } + reset(); return true; } @@ -952,7 +968,8 @@ void phch_recv::measure::reset() { cnt = 0; mean_rsrp = 0; mean_rsrq = 0; - mean_snr = 0; + mean_snr = 0; + mean_cfo = 0; } void phch_recv::measure::set_cell(srslte_cell_t cell) @@ -960,6 +977,7 @@ void phch_recv::measure::set_cell(srslte_cell_t cell) if (srslte_ue_dl_set_cell(&ue_dl, cell)) { Error("SYNC: Setting cell: initiating ue_dl_measure\n"); } + reset(); } float phch_recv::measure::rsrp() { @@ -974,6 +992,10 @@ float phch_recv::measure::snr() { return 10*log10(mean_snr); } +float phch_recv::measure::cfo() { + return mean_cfo; +} + phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx) { int sync_res = srslte_ue_sync_zerocopy_multi(ue_sync, buffer); @@ -988,10 +1010,12 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx) float rsrp = srslte_chest_dl_get_rsrp(&ue_dl.chest); float rsrq = srslte_chest_dl_get_rsrq(&ue_dl.chest); float snr = srslte_chest_dl_get_snr(&ue_dl.chest); + float cfo = srslte_ue_sync_get_cfo(ue_sync); mean_rsrp = SRSLTE_VEC_CMA(rsrp, mean_rsrp, cnt); mean_rsrq = SRSLTE_VEC_CMA(rsrq, mean_rsrq, cnt); - mean_snr = SRSLTE_VEC_CMA(rsrq, mean_snr, cnt); + mean_snr = SRSLTE_VEC_CMA(snr, mean_snr, cnt); + mean_cfo = SRSLTE_VEC_CMA(cfo, mean_cfo, cnt); cnt++; log_h->info("SYNC: Measuring RSRP %d/%d, sf_idx=%d, RSRP=%.1f dBm, SNR=%.1f dB\n", @@ -1022,19 +1046,20 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx) void phch_recv::scell_recv::init(phch_recv *parent, srslte::log *log_h, uint32_t nof_rx_antennas, uint32_t prio, int cpu_affinity) { - this->p = parent; - this->log_h = log_h; + this->p = parent; + this->log_h = log_h; + this->nof_rx_antennas = nof_rx_antennas; // Create the ringbuffer for secondary cell reception for (int i=0;i current_sflen) { + read_samples = current_sflen; + } + if (nsamples < 10) { + read_samples = 0; + } + int n = 0; + for (uint32_t i=0;idebug("SCELL: tti=%d, read %d/%d samples from buffer, buffer size=%d\n", + tti, read_samples,nsamples, srslte_ringbuffer_status(&ring_buffer[0])); + return nsamples; } else { - Error("SYNC: SCell reception not enabled\n"); + Error("SCELL: Reception not enabled\n"); return -1; } } @@ -1079,7 +1151,7 @@ int phch_recv::scell_recv::recv(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, void phch_recv::scell_recv::write(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time) { if (is_enabled()) { - for (int i = 0; i < SRSLTE_MAX_PORTS; i++) { + for (uint32_t i = 0; i < nof_rx_antennas; i++) { srslte_ringbuffer_write(&ring_buffer[i], data[i], sizeof(cf_t) * nsamples); } } @@ -1090,16 +1162,19 @@ void phch_recv::scell_recv::run_thread() while(running) { switch(scell_state) { case IDLE: + usleep(1000); break; case SCELL_SELECT: switch (sfn_p.run_subframe(&cell, &tti)) { case sfn_sync::SFN_FOUND: - log_h->info("SFN Sync OK. Camping on cell PCI=%d...\n", cell.id); + log_h->info("SCELL: SFN Sync OK. Camping on cell PCI=%d...\n", cell.id); + sfn_p.reset(); + scell_state = SCELL_MEASURE; break; case sfn_sync::TIMEOUT: - log_h->info("SFN sync timeout\n"); + log_h->info("SCELL: SFN sync timeout\n"); break; case sfn_sync::IDLE: break; @@ -1107,11 +1182,15 @@ void phch_recv::scell_recv::run_thread() p->radio_error(); break; } + break; case SCELL_MEASURE: switch (measure_p.run_subframe(tti%10)) { case measure::MEASURE_OK: - log_h->info("SYNC: Measured OK\n"); + log_h->info("SCELL: Measured OK TTI=%5d, RSRP=%.1f dBm, RSRQ=%.1f dB, SNR=%3.1f dB, CFO=%.1f KHz, Buff=%d\n", + tti, measure_p.rsrp(), measure_p.rsrq(), measure_p.snr(), measure_p.cfo()/1000, + srslte_ringbuffer_status(&ring_buffer[0])); + measure_p.reset(); break; case measure::IDLE: break; @@ -1121,6 +1200,8 @@ void phch_recv::scell_recv::run_thread() } break; } + // Increase TTI counter + tti = (tti+1) % 10240; } } diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index df29726d5..0e4bcdc5f 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -243,6 +243,11 @@ void phy::cell_search_next() sf_recv.cell_search_next(); } +void phy::scell_enable(bool enable) +{ + sf_recv.scell_enable(enable); +} + void phy::sync_reset() { sf_recv.reset_sync(); } diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index 3560a78fe..ee00d8876 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -213,6 +213,11 @@ void ue::pregenerate_signals(bool enable) phy.enable_pregen_signals(enable); } +void ue::test_scell() +{ + phy.scell_enable(true); +}; + void ue::stop() { if(started) From 2a381c109c9b5a21a9d6699bffb86ed5b7f918d3 Mon Sep 17 00:00:00 2001 From: ilshatDesu <32833109+ilshatDesu@users.noreply.github.com> Date: Mon, 16 Oct 2017 10:59:37 +0300 Subject: [PATCH 056/242] Update enb_cfg_parser.cc Non critical error in SIB1. CellIdentity is constucted from eNBID and SectorID. --- srsenb/src/enb_cfg_parser.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 3beb85a65..00f01d498 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -749,7 +749,7 @@ int enb::parse_sibs(all_args_t *args, rrc_cfg_t *rrc_cfg, phy_cfg_t *phy_config_ } // Fill rest of data from enb config - sib1->cell_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; From 6657892b80c026855724524bc2f38340fd967efd Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 16 Oct 2017 17:33:30 +0200 Subject: [PATCH 057/242] Added UCI CQI decoder for variable number of bits --- lib/include/srslte/phy/phch/uci.h | 9 ++++- lib/src/phy/phch/test/pucch_test.c | 64 +++++++++++++++++++++++++++++- lib/src/phy/phch/uci.c | 52 ++++++++++++++++-------- 3 files changed, 106 insertions(+), 19 deletions(-) diff --git a/lib/include/srslte/phy/phch/uci.h b/lib/include/srslte/phy/phch/uci.h index ff315384e..dc2030517 100644 --- a/lib/include/srslte/phy/phch/uci.h +++ b/lib/include/srslte/phy/phch/uci.h @@ -57,8 +57,8 @@ typedef struct SRSLTE_API { } srslte_uci_cqi_pusch_t; typedef struct SRSLTE_API { - uint8_t *cqi_table[16]; - int16_t *cqi_table_s[16]; + uint8_t **cqi_table; + int16_t **cqi_table_s; } srslte_uci_cqi_pucch_t; typedef struct SRSLTE_API { @@ -95,6 +95,11 @@ SRSLTE_API int srslte_uci_encode_cqi_pucch(uint8_t *cqi_data, uint32_t cqi_len, uint8_t b_bits[SRSLTE_UCI_CQI_CODED_PUCCH_B]); +SRSLTE_API int srslte_uci_encode_cqi_pucch_from_table(srslte_uci_cqi_pucch_t *q, + uint8_t *cqi_data, + uint32_t cqi_len, + uint8_t b_bits[SRSLTE_UCI_CQI_CODED_PUCCH_B]); + SRSLTE_API int16_t srslte_uci_decode_cqi_pucch(srslte_uci_cqi_pucch_t *q, int16_t b_bits[32], // aligned for simd uint8_t *cqi_data, diff --git a/lib/src/phy/phch/test/pucch_test.c b/lib/src/phy/phch/test/pucch_test.c index 43aaca953..b1d66c013 100644 --- a/lib/src/phy/phch/test/pucch_test.c +++ b/lib/src/phy/phch/test/pucch_test.c @@ -43,18 +43,20 @@ srslte_cell_t cell = { }; uint32_t subframe = 0; +bool test_cqi_only = false; void usage(char *prog) { printf("Usage: %s [csNnv]\n", prog); printf("\t-c cell id [Default %d]\n", cell.id); printf("\t-s subframe [Default %d]\n", subframe); printf("\t-n nof_prb [Default %d]\n", cell.nof_prb); + printf("\t-q Test CQI encoding/decoding only [Default %s].\n", test_cqi_only?"yes":"no"); printf("\t-v [set verbose to debug, default none]\n"); } void parse_args(int argc, char **argv) { int opt; - while ((opt = getopt(argc, argv, "csNnv")) != -1) { + while ((opt = getopt(argc, argv, "csNnqv")) != -1) { switch(opt) { case 's': subframe = atoi(argv[optind]); @@ -65,6 +67,9 @@ void parse_args(int argc, char **argv) { case 'c': cell.id = atoi(argv[optind]); break; + case 'q': + test_cqi_only = true; + break; case 'v': srslte_verbose++; break; @@ -75,6 +80,59 @@ void parse_args(int argc, char **argv) { } } +int test_uci_cqi_pucch(void) { + int ret = SRSLTE_SUCCESS; + __attribute__((aligned(256))) uint8_t o_bits[SRSLTE_UCI_MAX_CQI_LEN_PUCCH] = {0}; + __attribute__((aligned(256))) uint8_t e_bits[SRSLTE_UCI_CQI_CODED_PUCCH_B] = {0}; + __attribute__((aligned(256))) int16_t e_symb[SRSLTE_UCI_CQI_CODED_PUCCH_B] = {0}; + __attribute__((aligned(256))) uint8_t d_bits[SRSLTE_UCI_MAX_CQI_LEN_PUCCH] = {0}; + + srslte_uci_cqi_pucch_t uci_cqi_pucch = {0}; + + srslte_uci_cqi_pucch_init(&uci_cqi_pucch); + + for (uint32_t nof_bits = 1; nof_bits <= SRSLTE_UCI_MAX_CQI_LEN_PUCCH-1; nof_bits++) { + for (uint32_t cqi = 0; cqi < (1 <cqi_table[w] = srslte_vec_malloc(SRSLTE_UCI_CQI_CODED_PUCCH_B*sizeof(int8_t)); - q->cqi_table_s[w] = srslte_vec_malloc(SRSLTE_UCI_CQI_CODED_PUCCH_B*sizeof(int16_t)); + uint8_t word[16]; + + uint32_t nwords = 1 << SRSLTE_UCI_MAX_CQI_LEN_PUCCH; + q->cqi_table = srslte_vec_malloc(nwords * sizeof(int8_t *)); + q->cqi_table_s = srslte_vec_malloc(nwords * sizeof(int16_t *)); + + for (uint32_t w = 0; w < nwords; w++) { + q->cqi_table[w] = srslte_vec_malloc(SRSLTE_UCI_CQI_CODED_PUCCH_B * sizeof(int8_t)); + q->cqi_table_s[w] = srslte_vec_malloc(SRSLTE_UCI_CQI_CODED_PUCCH_B * sizeof(int16_t)); uint8_t *ptr = word; - srslte_bit_unpack(w, &ptr, 4); - srslte_uci_encode_cqi_pucch(word, 4, q->cqi_table[w]); - for (int j=0;jcqi_table_s[w][j] = 2*q->cqi_table[w][j]-1; + srslte_bit_unpack(w, &ptr, SRSLTE_UCI_MAX_CQI_LEN_PUCCH); + srslte_uci_encode_cqi_pucch(word, SRSLTE_UCI_MAX_CQI_LEN_PUCCH, q->cqi_table[w]); + for (int j = 0; j < SRSLTE_UCI_CQI_CODED_PUCCH_B; j++) { + q->cqi_table_s[w][j] = (int16_t)(2 * q->cqi_table[w][j] - 1); } } } void srslte_uci_cqi_pucch_free(srslte_uci_cqi_pucch_t *q) { - uint32_t nwords = 16; + uint32_t nwords = 1 << SRSLTE_UCI_MAX_CQI_LEN_PUCCH; for (uint32_t w=0;wcqi_table[w]) { free(q->cqi_table[w]); @@ -131,6 +134,8 @@ void srslte_uci_cqi_pucch_free(srslte_uci_cqi_pucch_t *q) { free(q->cqi_table_s[w]); } } + free(q->cqi_table); + free(q->cqi_table_s); } /* Encode UCI CQI/PMI as described in 5.2.3.3 of 36.212 @@ -151,17 +156,32 @@ int srslte_uci_encode_cqi_pucch(uint8_t *cqi_data, uint32_t cqi_len, uint8_t b_b } } +int srslte_uci_encode_cqi_pucch_from_table(srslte_uci_cqi_pucch_t *q, uint8_t *cqi_data, uint32_t cqi_len, uint8_t b_bits[SRSLTE_UCI_CQI_CODED_PUCCH_B]) +{ + if (cqi_len <= SRSLTE_UCI_MAX_CQI_LEN_PUCCH) { + bzero(&cqi_data[cqi_len], SRSLTE_UCI_MAX_CQI_LEN_PUCCH - cqi_len); + uint8_t *ptr = cqi_data; + uint32_t packed = srslte_bit_pack(&ptr, SRSLTE_UCI_MAX_CQI_LEN_PUCCH); + memcpy(b_bits, q->cqi_table[packed], SRSLTE_UCI_CQI_CODED_PUCCH_B); + + return SRSLTE_SUCCESS; + } else { + return SRSLTE_ERROR_INVALID_INPUTS; + } +} + /* Decode UCI CQI/PMI over PUCCH */ int16_t srslte_uci_decode_cqi_pucch(srslte_uci_cqi_pucch_t *q, int16_t b_bits[32], uint8_t *cqi_data, uint32_t cqi_len) { - if (cqi_len == 4 && + if (cqi_len < SRSLTE_UCI_MAX_CQI_LEN_PUCCH && b_bits != NULL && cqi_data != NULL) { uint32_t max_w = 0; - int32_t max_corr = INT32_MIN; - for (uint32_t w=0;w<16;w++) { + int32_t max_corr = INT32_MIN; + uint32_t nwords = 1 << SRSLTE_UCI_MAX_CQI_LEN_PUCCH; + for (uint32_t w=0;wcqi_table_s[w], b_bits, SRSLTE_UCI_CQI_CODED_PUCCH_B); @@ -172,7 +192,7 @@ int16_t srslte_uci_decode_cqi_pucch(srslte_uci_cqi_pucch_t *q, int16_t b_bits[32 } // Convert word to bits again uint8_t *ptr = cqi_data; - srslte_bit_unpack(max_w, &ptr, cqi_len); + srslte_bit_unpack(max_w, &ptr, SRSLTE_UCI_MAX_CQI_LEN_PUCCH); INFO("Decoded CQI: w=%d, corr=%d\n", max_w, max_corr); return max_corr; From f4b9e7311a1daa4b306c9e8bebd3c956db3e6cad Mon Sep 17 00:00:00 2001 From: yagoda Date: Tue, 17 Oct 2017 15:51:27 +0000 Subject: [PATCH 058/242] adding neon support to new vector structure --- lib/include/srslte/phy/utils/simd.h | 123 +++++++++++++++++++--------- lib/src/phy/utils/vector_simd.c | 37 +++++++-- 2 files changed, 116 insertions(+), 44 deletions(-) diff --git a/lib/include/srslte/phy/utils/simd.h b/lib/include/srslte/phy/utils/simd.h index 6e4185788..e7820c307 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 @@ -140,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 */ @@ -159,7 +165,7 @@ typedef __m256 simd_f_t; typedef __m128 simd_f_t; #else /* HAVE_NEON */ #ifdef HAVE_NEON -typedef float32x4 simd_f_t; +typedef float32x4_t simd_f_t; #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -188,7 +194,7 @@ 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 @@ -202,7 +208,7 @@ static inline simd_f_t srslte_simd_f_loadu(float *ptr) { #endif /* LV_HAVE_AVX512 */ } -static inline void srslte_simd_f_store(float *ptr, simd_f_t simdreg) {vst1q_f32 +static inline void srslte_simd_f_store(float *ptr, simd_f_t simdreg) { #ifdef LV_HAVE_AVX512 _mm512_store_ps(ptr, simdreg); #else /* LV_HAVE_AVX512 */ @@ -281,11 +287,11 @@ 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 vrecpeq_f32(a); + return vmulq_f32(vrecpeq_f32(a), vrecpsq_f32(vrecpeq_f32(a), a)); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -302,6 +308,22 @@ 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 = &a; + float* b_ptr = &b; + simd_f_t ret; + float* c_ptr = &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 */ @@ -373,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 */ @@ -421,7 +447,9 @@ static inline simd_f_t srslte_simd_f_sqrt(simd_f_t a) { return _mm_sqrt_ps(a); #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON - return vrecpeq_f32(vrsqrteq_f32(a)); + 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 */ @@ -530,8 +558,8 @@ static inline simd_cf_t srslte_simd_cf_load(float *re, float *im) { ret.im = _mm_load_ps(im); #else /*HAVE_NEON*/ #ifdef HAVE_NEON - ret.val[0] = vld1q_f32(ptr); - ret.val[1] = vld1q_f32(ptr); + ret.val[0] = vld1q_f32(re); + ret.val[1] = vld1q_f32(im); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -554,8 +582,8 @@ static inline simd_cf_t srslte_simd_cf_loadu(float *re, float *im) { ret.im = _mm_loadu_ps(im); #else /*HAVE_NEON*/ #ifdef HAVE_NEON - ret.val[0] = vld1q_f32(ptr); - ret.val[1] = vld1q_f32(ptr); + ret.val[0] = vld1q_f32(re); + ret.val[1] = vld1q_f32(im); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -684,8 +712,8 @@ static inline simd_cf_t srslte_simd_cf_set1 (cf_t x) { ret.im = _mm_set1_ps(__imag__ x); #else /*HAVE_NEON*/ #ifdef HAVE_NEON - re.val[0] = vdupq_n_f32(__real__ x); - im.val[1] = vdupq_n_f32(__imag__ x); + 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 */ @@ -772,8 +800,8 @@ static inline simd_cf_t srslte_simd_cf_add (simd_cf_t a, simd_cf_t b) { ret.im = _mm_add_ps(a.im, b.im); #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON - ret.val[0] = vaddq_f32(a.val[0],a.val[0]); - ret.val[1] = vaddq_f32(a.val[1],a.val[1]); + 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 */ @@ -839,8 +867,8 @@ static inline simd_cf_t srslte_simd_cf_rcp (simd_cf_t a) { 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 = vrecpeq_f32(mod2); - simd_f_t neg_a_im = vnegq_f32(vdupq_n_f32(-0.0f), a.val[1]); + 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 */ @@ -868,6 +896,7 @@ static inline simd_cf_t srslte_simd_cf_zero (void) { 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; @@ -889,9 +918,9 @@ typedef __m256 simd_sel_t; typedef __m128i simd_i_t; typedef __m128 simd_sel_t; #else /* LV_HAVE_AVX2 */ -#ifdef LV_HAVE_SSE +#ifdef HAVE_NEON typedef int32x4_t simd_i_t; -typedef __m128 simd_sel_t; +typedef int32x4_t simd_sel_t; #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -908,7 +937,7 @@ static inline simd_i_t srslte_simd_i_load(int *x) { return _mm_load_si128((__m128i*)x); #else #ifdef HAVE_NEON - return vld1_s32((int32x4_t*)x); + return vld1q_s32((int*)x); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -924,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 */ @@ -963,7 +996,7 @@ static inline simd_i_t srslte_simd_i_add(simd_i_t a, simd_i_t b) { #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ -}vcgtq_f32 +} static inline simd_sel_t srslte_simd_f_max(simd_f_t a, simd_f_t b) { #ifdef LV_HAVE_AVX512 @@ -992,6 +1025,25 @@ 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 = &a; + int* b_ptr = &b; + simd_i_t ret; + int* sel = &selector; + + int* c_ptr = &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 */ @@ -1030,7 +1082,7 @@ static inline simd_s_t srslte_simd_s_load(int16_t *ptr) { return _mm_load_si128((__m128i*) ptr); #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON - return vld1q_s16((int16x8_t*) ptr); + return vld1q_s16(ptr); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -1048,7 +1100,7 @@ static inline simd_s_t srslte_simd_s_loadu(int16_t *ptr) { return _mm_loadu_si128((__m128i*) ptr) #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON - return vld1q_s16((int16x8_t*) ptr); + return vld1q_s16(ptr); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -1066,7 +1118,7 @@ static inline void srslte_simd_s_store(int16_t *ptr, simd_s_t simdreg) { _mm_store_si128((__m128i*) ptr, simdreg); #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON - vst1q_s16((int16x8_t*) ptr, simdreg); + vst1q_s16( ptr, simdreg); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -1084,13 +1136,12 @@ static inline void srslte_simd_s_storeu(int16_t *ptr, simd_s_t simdreg) { _mm_storeu_si128((__m128i*) ptr, simdreg); #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON - vst1q_s16((int16x8_t*) ptr, simdreg); + vst1q_s16(ptr, simdreg); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ } -vdupq_n_s16 static inline simd_s_t srslte_simd_s_zero(void) { #ifdef LV_HAVE_AVX512 return _mm512_setzero_si512(); @@ -1107,7 +1158,7 @@ static inline simd_s_t srslte_simd_s_zero(void) { #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ -}vmulq_s16 +} static inline simd_s_t srslte_simd_s_mul(simd_s_t a, simd_s_t b) { #ifdef LV_HAVE_AVX512 @@ -1294,7 +1345,7 @@ static inline void srslte_simd_c16i_store(c16_t *ptr, simd_c16_t simdreg) { _mm_store_si128((__m128i *) (ptr + 8), _mm_blend_epi16(re_sw, simdreg.im.m128, 0b10101010)); #else /*HAVE_NEON*/ #ifdef HAVE_NEON - vst2q_f32((float*)(ptr) ,simdreg); + vst2q_s16((int16_t*)(ptr) ,simdreg.m128); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -1314,7 +1365,7 @@ static inline void srslte_simd_c16i_storeu(c16_t *ptr, simd_c16_t simdreg) { _mm_storeu_si128((__m128i *) (ptr + 8), _mm_blend_epi16(re_sw, simdreg.im.m128, 0b10101010)); #else /*HAVE_NEON*/ #ifdef HAVE_NEON - vst2q_f32((float*)(ptr) ,simdreg); + vst2q_s16((int16_t*)(ptr) ,simdreg.m128); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -1330,8 +1381,8 @@ static inline void srslte_simd_c16_store(int16_t *re, int16_t *im, simd_c16_t si _mm_store_si128((__m128i *) im, simdreg.im.m128); #else #ifdef HAVE_NEON - vst1q_f32((int16_t *) re, simdreg.m128.val[0]); - vst1q_f32((int16_t *) im, simdreg.m128.val[1]); + 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 */ @@ -1347,15 +1398,13 @@ static inline void srslte_simd_c16_storeu(int16_t *re, int16_t *im, simd_c16_t s _mm_storeu_si128((__m128i *) im, simdreg.im.m128); #else #ifdef HAVE_NEON - vst1q_f32((int16_t *) re, simdreg.m128.val[0]); - vst1q_f32((int16_t *) im, simdreg.m128.val[1]); + 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 */ } - -//TODO static inline simd_c16_t srslte_simd_c16_prod (simd_c16_t a, simd_c16_t b) { simd_c16_t ret; #ifdef LV_HAVE_AVX2 @@ -1385,14 +1434,14 @@ static inline simd_c16_t srslte_simd_c16_add (simd_c16_t a, simd_c16_t b) { ret.im.m128 = _mm_add_epi16(a.im.m128, b.im.m128); #else #ifdef HAVE_NEON - ret.m128.val[0] = vaddq_s32(a.m127.val[0],a.m127.val[0]); - ret.m128.val[1] = vaddq_s32(a.m127.val[1],a.m127.val[1]); + 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; } -vdupq_n_s16 + static inline simd_c16_t srslte_simd_c16_zero (void) { simd_c16_t ret; #ifdef LV_HAVE_AVX2 diff --git a/lib/src/phy/utils/vector_simd.c b/lib/src/phy/utils/vector_simd.c index 0294bd1af..ab281a653 100644 --- a/lib/src/phy/utils/vector_simd.c +++ b/lib/src/phy/utils/vector_simd.c @@ -751,10 +751,37 @@ void srslte_vec_div_fff_simd(float *x, float *y, float *z, int len) { } } + + +int srslte_vec_sc_prod_ccc_simd2(cf_t *x, cf_t h, cf_t *z, int len) +{ + int i = 0; + const unsigned int loops = len / 4; +#ifdef HAVE_NEON + simd_cf_t h_vec; + h_vec.val[0] = srslte_simd_f_set1(__real__ h); + h_vec.val[1] = srslte_simd_f_set1(__imag__ h); + for (; i < loops; i++) { + + simd_cf_t in = srslte_simd_cfi_load(&x[i*4]); + simd_cf_t temp = srslte_simd_cf_prod(in, h_vec); + srslte_simd_cfi_store(&z[i*4], temp); + } + +#endif + i = loops * 4; +return i; +} + void srslte_vec_sc_prod_ccc_simd(cf_t *x, cf_t h, cf_t *z, int len) { int i = 0; #if SRSLTE_SIMD_F_SIZE + + +#ifdef HAVE_NEON + i = srslte_vec_sc_prod_ccc_simd2(x, h, z, len); +#else const simd_f_t hre = srslte_simd_f_set1(__real__ h); const simd_f_t him = srslte_simd_f_set1(__imag__ h); @@ -766,8 +793,8 @@ void srslte_vec_sc_prod_ccc_simd(cf_t *x, cf_t h, cf_t *z, int len) { simd_f_t sw = srslte_simd_f_swap(temp); simd_f_t m2 = srslte_simd_f_mul(him, sw); simd_f_t r = srslte_simd_f_addsub(m1, m2); - srslte_simd_f_store((float *) &z[i], r); + } } else { for (; i < len - SRSLTE_SIMD_F_SIZE / 2 + 1; i += SRSLTE_SIMD_F_SIZE / 2) { @@ -782,10 +809,11 @@ void srslte_vec_sc_prod_ccc_simd(cf_t *x, cf_t h, cf_t *z, int len) { } } #endif - +#endif for (; i < len; i++) { z[i] = x[i] * h; } + } void srslte_vec_sc_prod_fff_simd(float *x, float h, float *z, int len) { @@ -831,7 +859,6 @@ void srslte_vec_abs_cf_simd(cf_t *x, float *z, int len) { simd_f_t z1 = srslte_simd_f_hadd(mul1, mul2); z1 = srslte_simd_f_sqrt(z1); - srslte_simd_f_store(&z[i], z1); } } else { @@ -966,9 +993,7 @@ uint32_t srslte_vec_max_fi_simd(float *x, int len) { if (SRSLTE_IS_ALIGNED(x)) { for (; i < len - SRSLTE_SIMD_I_SIZE + 1; i += SRSLTE_SIMD_I_SIZE) { simd_f_t a = srslte_simd_f_load(&x[i]); - simd_sel_t res = srslte_simd_f_max(a, simd_max_values); - simd_max_indexes = srslte_simd_i_select(simd_max_indexes, simd_indexes, res); simd_max_values = (simd_f_t) srslte_simd_i_select((simd_i_t) simd_max_values, (simd_i_t) a, res); simd_indexes = srslte_simd_i_add(simd_indexes, simd_inc); @@ -976,9 +1001,7 @@ uint32_t srslte_vec_max_fi_simd(float *x, int len) { } else { for (; i < len - SRSLTE_SIMD_I_SIZE + 1; i += SRSLTE_SIMD_I_SIZE) { simd_f_t a = srslte_simd_f_loadu(&x[i]); - simd_sel_t res = srslte_simd_f_max(a, simd_max_values); - simd_max_indexes = srslte_simd_i_select(simd_max_indexes, simd_indexes, res); simd_max_values = (simd_f_t) srslte_simd_i_select((simd_i_t) simd_max_values, (simd_i_t) a, res); simd_indexes = srslte_simd_i_add(simd_indexes, simd_inc); From 2b0b57176f08b00ffac338742e931fbc35ccde69 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 17 Oct 2017 12:10:31 -0400 Subject: [PATCH 059/242] Removed pid from demux --- srsue/hdr/mac/demux.h | 14 ++++++------ srsue/hdr/mac/dl_harq.h | 13 +++++------ srsue/src/mac/demux.cc | 48 +++++++++++++++++++---------------------- srsue/src/mac/mac.cc | 1 - 4 files changed, 37 insertions(+), 39 deletions(-) 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..442a534d5 100644 --- a/srsue/hdr/mac/dl_harq.h +++ b/srsue/hdr/mac/dl_harq.h @@ -262,8 +262,11 @@ private: if (!ack) { // 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) { action->decode_enabled[tid] = false; @@ -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, diff --git a/srsue/src/mac/demux.cc b/srsue/src/mac/demux.cc index 75bafd1b4..14c524165 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) { } @@ -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..1a2c909ae 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; From 0504e7a51b42288cd9e7f9b113b7d8bc4cc2f30d Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 18 Oct 2017 12:49:43 +0200 Subject: [PATCH 060/242] Fixed test for abs value. Solved compilation Neon warnings and SSE errors --- lib/include/srslte/phy/utils/simd.h | 16 +++++++-------- lib/src/phy/utils/test/vector_test.c | 30 ++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/lib/include/srslte/phy/utils/simd.h b/lib/include/srslte/phy/utils/simd.h index e7820c307..0c378591e 100644 --- a/lib/include/srslte/phy/utils/simd.h +++ b/lib/include/srslte/phy/utils/simd.h @@ -310,10 +310,10 @@ static inline simd_f_t srslte_simd_f_addsub(simd_f_t a, simd_f_t b) { return _mm_addsub_ps(a, b); #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON // CURRENTLY USES GENERIC IMPLEMENTATION FOR NEON - float* a_ptr = &a; - float* b_ptr = &b; + float* a_ptr = (float*) &a; + float* b_ptr = (float*) &b; simd_f_t ret; - float* c_ptr = &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]; @@ -1028,12 +1028,12 @@ static inline simd_i_t srslte_simd_i_select(simd_i_t a, simd_i_t b, simd_sel_t s #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON // CURRENTLY USES GENERIC IMPLEMENTATION FOR NEON - int* a_ptr = &a; - int* b_ptr = &b; + int* a_ptr = (int*) &a; + int* b_ptr = (int*) &b; simd_i_t ret; - int* sel = &selector; + int* sel = (int*) &selector; - int* c_ptr = &ret; + int* c_ptr = (int*) &ret; for(int i = 0;i<4;i++) { if(sel[i] == -1){ @@ -1097,7 +1097,7 @@ static inline simd_s_t srslte_simd_s_loadu(int16_t *ptr) { return _mm256_loadu_si256((__m256i*) ptr); #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE - return _mm_loadu_si128((__m128i*) ptr) + return _mm_loadu_si128((__m128i*) ptr); #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON return vld1q_s16(ptr); diff --git a/lib/src/phy/utils/test/vector_test.c b/lib/src/phy/utils/test/vector_test.c index 8d5b9f2d6..4ebed9862 100644 --- a/lib/src/phy/utils/test/vector_test.c +++ b/lib/src/phy/utils/test/vector_test.c @@ -63,12 +63,12 @@ bool verbose = false; strncpy(func_name, #X, 32);\ CODE;\ passed = (mse < MAX_MSE);\ - printf("%32s (%5d) ... %7.1f MSamp/s ... %3s Passed\n", func_name, block_size, \ - (double) block_size*NOF_REPETITIONS/ *timing, passed?"":"Not");\ + printf("%32s (%5d) ... %7.1f MSamp/s ... %3s Passed (%.6f)\n", func_name, block_size, \ + (double) block_size*NOF_REPETITIONS/ *timing, passed?"":"Not", mse);\ return passed;\ } -#define MALLOC(TYPE, NAME) TYPE *NAME = malloc(sizeof(TYPE)*block_size) +#define MALLOC(TYPE, NAME) TYPE *NAME = srslte_vec_malloc(sizeof(TYPE)*block_size) static double elapsed_us(struct timeval *ts_start, struct timeval *ts_end) { @@ -507,7 +507,7 @@ TEST(srslte_vec_abs_cf, for (int i = 0; i < block_size; i++) { gold = sqrtf(crealf(x[i]) * crealf(x[i]) + cimagf(x[i])*cimagf(x[i])); - mse += cabsf(gold - z[i]); + mse += cabsf(gold - z[i])/block_size; } free(x); @@ -771,12 +771,27 @@ int main(int argc, char **argv) { size_count++; } + char fname[68]; + FILE *f = NULL; + void * p = popen("(date +%g%m%d && hostname) | tr '\\r\\n' '__'", "r"); + if (p) { + fgets(fname, 64, p); + strncpy(fname + strnlen(fname, 64) - 1, ".tsv", 4); + f = fopen(fname, "w"); + if (f) printf("Saving benchmark results in '%s'\n", fname); + } + pclose(p); + + printf("\n"); printf("%32s |", "Subroutine/MSps"); + if (f) fprintf(f, "Subroutine/MSps Vs Vector size\t"); for (int i = 0; i < size_count; i++) { printf(" %7d", sizes[i]); + if (f) fprintf(f, "%d\t", sizes[i]); } printf(" |\n"); + if (f) fprintf(f, "\n"); for (int j = 0; j < 32; j++) { printf("-"); @@ -789,12 +804,19 @@ int main(int argc, char **argv) { for (int i = 0; i < func_count; i++) { printf("%32s | ", func_names[i]); + if (f) fprintf(f, "%s\t", func_names[i]); + for (int j = 0; j < size_count; j++) { printf(" %s%7.1f\x1b[0m", (passed[i][j])?"":"\x1B[31m", (double) NOF_REPETITIONS*(double)sizes[j]/timmings[i][j]); + if (f) fprintf(f, "%.1f\t", (double) NOF_REPETITIONS*(double)sizes[j]/timmings[i][j]); + all_passed &= passed[i][j]; } printf(" |\n"); + if (f) fprintf(f, "\n"); } + if (f) fclose(f); + return (all_passed)?SRSLTE_SUCCESS:SRSLTE_ERROR; } From 29b9b6001b114009ae72dee94e441c6a39f622b9 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 18 Oct 2017 15:00:07 +0200 Subject: [PATCH 061/242] fix metric hub when called with periodicity other than 1s --- lib/include/srslte/common/metrics_hub.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/include/srslte/common/metrics_hub.h b/lib/include/srslte/common/metrics_hub.h index 687722bcc..67f0cdbc6 100644 --- a/lib/include/srslte/common/metrics_hub.h +++ b/lib/include/srslte/common/metrics_hub.h @@ -34,8 +34,9 @@ public: metrics_hub() { m = NULL; } - bool init(metrics_interface *m_, float report_period_secs=1.0) { - m = m_; + 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; } @@ -55,13 +56,13 @@ private: bzero(&metric, sizeof(metrics_t)); m->get_metrics(metric); for (uint32_t i=0;iset_metrics(metric); + listeners[i]->set_metrics(metric, report_period_secs); } } } metrics_interface *m; - std::vector*> listeners; - + std::vector*> listeners; + float report_period_secs; }; } // namespace srslte From ab11a80c6f0c331f415df4a86cc68d8ba4b72e08 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 18 Oct 2017 15:00:47 +0200 Subject: [PATCH 062/242] fix bug in tti interval calculation now returning 0 when called with the same value --- lib/src/phy/common/phy_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; From 5ee2a37c2bef57653d996c02b2fe590998287abe Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 18 Oct 2017 15:01:36 +0200 Subject: [PATCH 063/242] fix bug in dl_harq where if always returned true --- srsue/hdr/mac/dl_harq.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsue/hdr/mac/dl_harq.h b/srsue/hdr/mac/dl_harq.h index ee925596f..75e80fd95 100644 --- a/srsue/hdr/mac/dl_harq.h +++ b/srsue/hdr/mac/dl_harq.h @@ -265,7 +265,7 @@ private: payload_buffer_ptr = harq_entity->demux_unit->request_buffer(pid * SRSLTE_MAX_TB + tid, 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; From aa5a3bfdae9f636de8a15d091b489fafda1500e2 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 18 Oct 2017 15:41:36 +0200 Subject: [PATCH 064/242] fix bug reported by coverity --- lib/include/srslte/common/metrics_hub.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/include/srslte/common/metrics_hub.h b/lib/include/srslte/common/metrics_hub.h index 67f0cdbc6..66cc4acbd 100644 --- a/lib/include/srslte/common/metrics_hub.h +++ b/lib/include/srslte/common/metrics_hub.h @@ -31,9 +31,10 @@ template class metrics_hub : public periodic_thread { public: - metrics_hub() { - m = NULL; - } + 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_; From 12877fe2960a64fb371f6bd8060bd94475d9abdf Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 18 Oct 2017 16:33:19 -0400 Subject: [PATCH 065/242] Missing ip_netmask configuration file --- srsue/src/main.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 47d5f807e..3b0cad2d0 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)") From 739b8fc457f3588f0d9d580c43de978d31329390 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 18 Oct 2017 16:34:18 -0400 Subject: [PATCH 066/242] Restored TA commands --- srsue/src/phy/phy.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index df29726d5..9760ab374 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() @@ -308,7 +308,8 @@ void phy::reset() pdcch_dl_search_reset(); for(uint32_t i=0;i Date: Wed, 18 Oct 2017 16:49:36 -0400 Subject: [PATCH 067/242] Fix for async dl scheduling --- lib/include/srslte/common/common.h | 1 + srsue/hdr/mac/mac.h | 2 +- srsue/src/phy/phch_worker.cc | 11 +++++++---- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/include/srslte/common/common.h b/lib/include/srslte/common/common.h index 6372af73e..fbc703486 100644 --- a/lib/include/srslte/common/common.h +++ b/lib/include/srslte/common/common.h @@ -52,6 +52,7 @@ #define TTIMOD_SZ (((2*HARQ_DELAY_MS) < 10)?10:20) #define TTIMOD(tti) (tti%TTIMOD_SZ) +#define MOD_N_PROC (2*HARQ_DELAY_MS-8) #define ASYNC_DL_SCHED (HARQ_DELAY_MS <= 4) // Cat 3 UE - Max number of DL-SCH transport block bits received within a TTI diff --git a/srsue/hdr/mac/mac.h b/srsue/hdr/mac/mac.h index d19f668bf..87bb764e1 100644 --- a/srsue/hdr/mac/mac.h +++ b/srsue/hdr/mac/mac.h @@ -135,7 +135,7 @@ private: demux demux_unit; /* DL/UL HARQ */ - dl_harq_entity dl_harq; + dl_harq_entity dl_harq; ul_harq_entity ul_harq; /* MAC Uplink-related Procedures */ diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index f89696015..a32bb7537 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; } @@ -482,7 +481,11 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant) /* 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)); + if (tti < MOD_N_PROC) { + grant->pid = ASYNC_DL_SCHED?dci_unpacked.harq_process:tti+(2*HARQ_DELAY_MS); + } else { + 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; From 177f36fc8c1fa7c31667cd3bc8baa3d2c5548af9 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 18 Oct 2017 16:50:22 -0400 Subject: [PATCH 068/242] Improved cell reestablishment procedure timers (still not working the authentication) --- srsue/hdr/phy/phch_recv.h | 4 ++-- srsue/hdr/upper/rrc.h | 5 ++++- srsue/src/mac/mac.cc | 3 ++- srsue/src/phy/phch_common.cc | 1 + srsue/src/upper/rrc.cc | 28 ++++++++++++++++------------ 5 files changed, 25 insertions(+), 16 deletions(-) diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index c51622e53..01a296094 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -158,7 +158,7 @@ private: uint32_t current_earfcn; uint32_t sync_sfn_cnt; - const static uint32_t SYNC_SFN_TIMEOUT = 200; + const static uint32_t SYNC_SFN_TIMEOUT = 1000; float ul_dl_factor; int cur_earfcn_index; bool cell_search_in_progress; @@ -166,7 +166,7 @@ private: float measure_rsrp; srslte_ue_dl_t ue_dl_measure; - const static int RSRP_MEASURE_NOF_FRAMES = 5; + const static int RSRP_MEASURE_NOF_FRAMES = 10; int cell_sync_sfn(); int cell_meas_rsrp(); 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/mac.cc b/srsue/src/mac/mac.cc index 1a2c909ae..f8d10bb34 100644 --- a/srsue/src/mac/mac.cc +++ b/srsue/src/mac/mac.cc @@ -117,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/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/upper/rrc.cc b/srsue/src/upper/rrc.cc index 94c2e449a..4ed20deeb 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(); @@ -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) { From b8d5b5b6a92807ebee34ebb698c2f190a79b3efb Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Wed, 18 Oct 2017 21:54:52 +0100 Subject: [PATCH 069/242] count_dl fix --- srsue/src/upper/nas.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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(); From f1ec1b2f3c07bdf3bb0c09bb86e7996204742637 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 18 Oct 2017 19:33:43 -0400 Subject: [PATCH 070/242] disable attempt to resync after N310 (too soon if N310 is low) --- srsue/src/upper/rrc.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 4ed20deeb..10373dcf2 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -489,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(); From 3292f9c2694ce5b5a75501427b5a2fd09fc38189 Mon Sep 17 00:00:00 2001 From: yagoda Date: Thu, 19 Oct 2017 16:38:58 +0000 Subject: [PATCH 071/242] simd.h tidy up & small fix for eMBMS --- lib/include/srslte/phy/utils/simd.h | 2 -- lib/src/phy/ue/ue_dl.c | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/include/srslte/phy/utils/simd.h b/lib/include/srslte/phy/utils/simd.h index 0c378591e..09e9cff8e 100644 --- a/lib/include/srslte/phy/utils/simd.h +++ b/lib/include/srslte/phy/utils/simd.h @@ -1027,12 +1027,10 @@ static inline simd_i_t srslte_simd_i_select(simd_i_t a, simd_i_t b, simd_sel_t s 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++) { diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index c4e2d3f6c..c11a29b8b 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -603,7 +603,8 @@ int srslte_ue_dl_decode_mbsfn(srslte_ue_dl_t * q, 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); From 494802ba9b0299a5ddb02000240ea47236836ece Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 19 Oct 2017 14:33:05 -0400 Subject: [PATCH 072/242] Fixed bug in RLC UM when TX large number of segments in a PDU --- lib/src/upper/rlc_um.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/upper/rlc_um.cc b/lib/src/upper/rlc_um.cc index b2697178c..045fb0b7e 100644 --- a/lib/src/upper/rlc_um.cc +++ b/lib/src/upper/rlc_um.cc @@ -309,7 +309,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) From 399f1cdbd1352aad215f2baaf8386f335334e70b Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 19 Oct 2017 14:47:14 -0400 Subject: [PATCH 073/242] Force retx for mcs>29 and new tb if rv=0 && mcs<29 --- lib/include/srslte/common/common.h | 1 - srsue/hdr/mac/dl_harq.h | 9 +++++---- srsue/hdr/mac/mac.h | 2 +- srsue/src/phy/phch_worker.cc | 6 +----- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/lib/include/srslte/common/common.h b/lib/include/srslte/common/common.h index fbc703486..6372af73e 100644 --- a/lib/include/srslte/common/common.h +++ b/lib/include/srslte/common/common.h @@ -52,7 +52,6 @@ #define TTIMOD_SZ (((2*HARQ_DELAY_MS) < 10)?10:20) #define TTIMOD(tti) (tti%TTIMOD_SZ) -#define MOD_N_PROC (2*HARQ_DELAY_MS-8) #define ASYNC_DL_SCHED (HARQ_DELAY_MS <= 4) // Cat 3 UE - Max number of DL-SCH transport block bits received within a TTI diff --git a/srsue/hdr/mac/dl_harq.h b/srsue/hdr/mac/dl_harq.h index 278dbc6dc..9abcf0922 100644 --- a/srsue/hdr/mac/dl_harq.h +++ b/srsue/hdr/mac/dl_harq.h @@ -259,7 +259,7 @@ 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 if (pid == HARQ_BCCH_PID) { @@ -347,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/mac/mac.h b/srsue/hdr/mac/mac.h index 87bb764e1..d19f668bf 100644 --- a/srsue/hdr/mac/mac.h +++ b/srsue/hdr/mac/mac.h @@ -135,7 +135,7 @@ private: demux demux_unit; /* DL/UL HARQ */ - dl_harq_entity dl_harq; + dl_harq_entity dl_harq; ul_harq_entity ul_harq; /* MAC Uplink-related Procedures */ diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index a32bb7537..1d86461cd 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -481,11 +481,7 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant) /* Fill MAC grant structure */ grant->ndi[0] = dci_unpacked.ndi; grant->ndi[1] = dci_unpacked.ndi_1; - if (tti < MOD_N_PROC) { - grant->pid = ASYNC_DL_SCHED?dci_unpacked.harq_process:tti+(2*HARQ_DELAY_MS); - } else { - grant->pid = ASYNC_DL_SCHED?dci_unpacked.harq_process:(tti%(2*HARQ_DELAY_MS)); - } + 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; From 2f44e2bf3a4082211a4f57f3d99e778af103e8ec Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 19 Oct 2017 16:10:27 -0400 Subject: [PATCH 074/242] Refactored cases mcs>29 for ul/dl --- lib/include/srslte/phy/common/phy_common.h | 3 +- lib/include/srslte/phy/phch/ra.h | 3 +- lib/src/phy/modem/demod_hard.c | 1 + lib/src/phy/modem/modem_table.c | 1 + lib/src/phy/phch/dci.c | 4 +- lib/src/phy/phch/ra.c | 182 ++++++++------------- lib/src/phy/phch/test/pusch_test.c | 2 +- srsenb/src/phy/phch_worker.cc | 2 +- srsue/hdr/phy/phch_worker.h | 7 +- srsue/src/phy/phch_worker.cc | 47 ++++-- 10 files changed, 123 insertions(+), 129 deletions(-) diff --git a/lib/include/srslte/phy/common/phy_common.h b/lib/include/srslte/phy/common/phy_common.h index 148a12974..0b71ad82e 100644 --- a/lib/include/srslte/phy/common/phy_common.h +++ b/lib/include/srslte/phy/common/phy_common.h @@ -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/phch/ra.h b/lib/include/srslte/phy/phch/ra.h index 3039455ed..680d80dd6 100644 --- a/lib/include/srslte/phy/phch/ra.h +++ b/lib/include/srslte/phy/phch/ra.h @@ -226,8 +226,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/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..471429145 100644 --- a/lib/src/phy/phch/dci.c +++ b/lib/src/phy/phch/dci.c @@ -111,7 +111,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 +177,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; } diff --git a/lib/src/phy/phch/ra.c b/lib/src/phy/phch/ra.c index be10c304c..8cae9fe65 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,23 @@ 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; + 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->mcs[0].tbs = srslte_dl_fill_ra_mcs(&grant->mcs[0], n_prb); grant->nof_tb++; } 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; } diff --git a/lib/src/phy/phch/test/pusch_test.c b/lib/src/phy/phch/test/pusch_test.c index 9d048e680..cf0be75c3 100644 --- a/lib/src/phy/phch/test/pusch_test.c +++ b/lib/src/phy/phch/test/pusch_test.c @@ -136,7 +136,7 @@ int main(int argc, char **argv) { dci.mcs_idx = mcs_idx; srslte_ra_ul_grant_t grant; - if (srslte_ra_ul_dci_to_grant(&dci, cell.nof_prb, 0, &grant, 0)) { + if (srslte_ra_ul_dci_to_grant(&dci, cell.nof_prb, 0, &grant)) { fprintf(stderr, "Error computing resource allocation\n"); return ret; } diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index 52b617fd5..b80467f4d 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -408,7 +408,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/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/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 1d86461cd..9fa3ff669 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -478,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; @@ -718,14 +728,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; } @@ -898,7 +923,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, @@ -925,12 +950,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; From 9dbbe9731a472d54e2a2a7f47186a04f5f02bb5a Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 19 Oct 2017 16:18:40 -0400 Subject: [PATCH 075/242] missing netmaks string after merge --- srsue/hdr/ue_base.h | 1 + 1 file changed, 1 insertion(+) diff --git a/srsue/hdr/ue_base.h b/srsue/hdr/ue_base.h index 411896f70..634219083 100644 --- a/srsue/hdr/ue_base.h +++ b/srsue/hdr/ue_base.h @@ -109,6 +109,7 @@ typedef struct { std::string ue_cateogry; bool metrics_csv_enable; std::string metrics_csv_filename; + std::string ip_netmask; }expert_args_t; typedef struct { From 05d6a1c82927859f183230243dbf1fd8f6c245ad Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 19 Oct 2017 16:26:00 -0400 Subject: [PATCH 076/242] added option to configure netmask (rules out previous commit) --- srsue/hdr/ue_base.h | 2 +- srsue/hdr/upper/gw.h | 5 +++++ srsue/src/ue.cc | 2 ++ srsue/src/upper/gw.cc | 13 ++++++++++++- srsue/ue.conf.example | 4 +++- 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/srsue/hdr/ue_base.h b/srsue/hdr/ue_base.h index 634219083..b547945a9 100644 --- a/srsue/hdr/ue_base.h +++ b/srsue/hdr/ue_base.h @@ -103,13 +103,13 @@ typedef struct { }gui_args_t; typedef struct { + std::string ip_netmask; phy_args_t phy; float metrics_period_secs; bool pregenerate_signals; std::string ue_cateogry; bool metrics_csv_enable; std::string metrics_csv_filename; - std::string ip_netmask; }expert_args_t; typedef struct { 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/src/ue.cc b/srsue/src/ue.cc index 3560a78fe..a99281e6f 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -185,6 +185,8 @@ bool ue::init(all_args_t *args_) nas.init(&usim, &rrc, &gw, &nas_log, 1 /* RB_ID_SRB1 */); gw.init(&pdcp, &nas, &gw_log, 3 /* RB_ID_DRB1 */); + gw.set_netmask(args->expert.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/ue.conf.example b/srsue/ue.conf.example index 5d14d3c3c..d0dc67952 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -98,7 +98,8 @@ enable = false ##################################################################### # Expert configuration options # -# ue_category: Sets UE category (range 1-5). Default: 4 +# ip_netmask: Netmask of the tun_srsue device. Default: 255.255.255.0 +# 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. @@ -138,6 +139,7 @@ enable = false # ##################################################################### [expert] +#ip_netmask = 255.255.255.0 #ue_category = 4 #prach_gain = 30 #cqi_max = 15 From 49a105baed23e14fcac95e23a005837477b6b41c Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Thu, 19 Oct 2017 22:21:18 +0100 Subject: [PATCH 077/242] Fix for tests, minor fix for RLC UM --- lib/src/upper/rlc_um.cc | 2 +- lib/test/upper/rlc_um_test.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/upper/rlc_um.cc b/lib/src/upper/rlc_um.cc index 045fb0b7e..d95e186e7 100644 --- a/lib/src/upper/rlc_um.cc +++ b/lib/src/upper/rlc_um.cc @@ -277,7 +277,7 @@ 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) { 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); diff --git a/lib/test/upper/rlc_um_test.cc b/lib/test/upper/rlc_um_test.cc index 0894a2a8b..8abcfae3c 100644 --- a/lib/test/upper/rlc_um_test.cc +++ b/lib/test/upper/rlc_um_test.cc @@ -123,7 +123,7 @@ void basic_test() byte_buffer_t pdu_bufs[NBUFS]; for(int i=0;i Date: Thu, 19 Oct 2017 18:10:17 -0400 Subject: [PATCH 078/242] coverty uninitialized member --- srsue/src/mac/demux.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsue/src/mac/demux.cc b/srsue/src/mac/demux.cc index 14c524165..171e7bf45 100644 --- a/srsue/src/mac/demux.cc +++ b/srsue/src/mac/demux.cc @@ -36,7 +36,7 @@ namespace srsue { -demux::demux() : mac_msg(20), pending_mac_msg(20) +demux::demux() : mac_msg(20), pending_mac_msg(20), rlc(NULL) { } From c14393b24f874b4e12d3bbfb883133fedda4f6f1 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 19 Oct 2017 19:39:54 -0400 Subject: [PATCH 079/242] Disable RSSI sensor by default --- srsue/src/main.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 3b0cad2d0..1b146a9f3 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -155,7 +155,7 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { "Pregenerate uplink signals after attach. Improves CPU performance.") ("expert.rssi_sensor_enabled", - bpo::value(&args->expert.phy.rssi_sensor_enabled)->default_value(true), + bpo::value(&args->expert.phy.rssi_sensor_enabled)->default_value(false), "Enable or disable RF frontend RSSI sensor. In some USRP devices can cause segmentation fault") ("expert.prach_gain", From a570e63c5b8977a8f864cde6d7103a2233ae8c83 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 20 Oct 2017 15:05:04 +0200 Subject: [PATCH 080/242] Corrected bug in RA --- lib/include/srslte/phy/phch/ra.h | 2 -- lib/src/phy/phch/ra.c | 14 ++++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/include/srslte/phy/phch/ra.h b/lib/include/srslte/phy/phch/ra.h index 680d80dd6..aef8f4751 100644 --- a/lib/include/srslte/phy/phch/ra.h +++ b/lib/include/srslte/phy/phch/ra.h @@ -103,9 +103,7 @@ 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]; diff --git a/lib/src/phy/phch/ra.c b/lib/src/phy/phch/ra.c index 8cae9fe65..913bd9548 100644 --- a/lib/src/phy/phch/ra.c +++ b/lib/src/phy/phch/ra.c @@ -549,7 +549,7 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr } grant->pinfo = dci->pinfo; - if (tbs < 0) { + if (grant->mcs[0].tbs < 0 || grant->mcs[1].tbs < 0) { return SRSLTE_ERROR; } else { return SRSLTE_SUCCESS; @@ -584,10 +584,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) @@ -869,4 +871,4 @@ void srslte_ra_prb_fprint(FILE *f, srslte_ra_dl_grant_t *grant) { } } -} \ No newline at end of file +} From 3b4649b9f730786d010962b33b924693137d8925 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 20 Oct 2017 09:29:56 -0400 Subject: [PATCH 081/242] Fixed bug in calc_new_transmission --- srsue/hdr/mac/dl_harq.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsue/hdr/mac/dl_harq.h b/srsue/hdr/mac/dl_harq.h index 9abcf0922..521018d73 100644 --- a/srsue/hdr/mac/dl_harq.h +++ b/srsue/hdr/mac/dl_harq.h @@ -347,7 +347,7 @@ private: // Determine if it's a new transmission 5.3.2.2 bool calc_is_new_transmission(Tgrant grant) { - if (grant.phy_grant.dl.mcs[tid].idx < 28 && // mcs 29,30,31 always retx regardless of rest + 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)) From c8bba2f4d07ada34376ff19c19c10a9cf50f7a17 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 20 Oct 2017 16:09:27 +0200 Subject: [PATCH 082/242] DFT optimization. memcpy removal (#76) * Solved PHICH Segmentation fault for MIMO * Initial Guru FFT optimitzation * Guru (i)FFT implemented. All test passed! * Integrated new DFT into pdsch_enodeb and pdsch_ue. Solved more DFT bugs. * Solved Merge Errors and bugs * Solved UL Guru bug (DC missing). Updated Init and OFDM calls for enb and ue (cell measurement too). --- lib/examples/cell_measurement.c | 28 +- lib/examples/pdsch_enodeb.c | 26 +- lib/examples/pdsch_ue.c | 13 +- lib/include/srslte/phy/common/phy_common.h | 4 +- lib/include/srslte/phy/dft/dft.h | 24 ++ lib/include/srslte/phy/dft/ofdm.h | 40 +-- lib/include/srslte/phy/enb/enb_dl.h | 8 +- lib/include/srslte/phy/enb/enb_ul.h | 1 + lib/include/srslte/phy/ue/ue_dl.h | 3 +- lib/include/srslte/phy/ue/ue_mib.h | 2 +- lib/include/srslte/phy/ue/ue_ul.h | 1 + lib/src/phy/dft/dft_fftw.c | 62 +++- lib/src/phy/dft/ofdm.c | 271 +++++++++++++++--- lib/src/phy/dft/test/ofdm_test.c | 63 +++- lib/src/phy/enb/enb_dl.c | 57 ++-- lib/src/phy/enb/enb_ul.c | 31 +- lib/src/phy/phch/test/pbch_file_test.c | 4 +- lib/src/phy/phch/test/pcfich_file_test.c | 10 +- lib/src/phy/phch/test/pdcch_file_test.c | 6 +- lib/src/phy/phch/test/pdsch_pdcch_file_test.c | 4 +- lib/src/phy/phch/test/phich_file_test.c | 6 +- lib/src/phy/phch/test/pmch_file_test.c | 2 +- lib/src/phy/phch/test/pmch_test.c | 122 ++++---- lib/src/phy/sync/test/sync_test.c | 12 +- lib/src/phy/ue/ue_dl.c | 77 ++--- lib/src/phy/ue/ue_mib.c | 13 +- lib/src/phy/ue/ue_ul.c | 22 +- srsenb/hdr/phy/phch_worker.h | 2 +- srsenb/src/phy/phch_worker.cc | 19 +- srsue/src/phy/phch_recv.cc | 8 +- srsue/src/phy/phch_worker.cc | 4 +- 31 files changed, 647 insertions(+), 298 deletions(-) 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;iout = 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 +128,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 +170,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 +280,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 +311,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..54a63bc2a 100644 --- a/lib/src/phy/enb/enb_dl.c +++ b/lib/src/phy/enb/enb_dl.c @@ -41,7 +41,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 +53,26 @@ 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)]; + } + + 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; + } } - srslte_ofdm_set_normalize(&q->ifft, true); + for (int i = 0; i < q->cell.nof_ports; i++) { + srslte_ofdm_set_normalize(&q->ifft[i], true); + } if (srslte_pbch_init(&q->pbch)) { fprintf(stderr, "Error creating PBCH object\n"); @@ -89,15 +102,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 +118,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 +158,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 +272,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)); + + 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/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/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..a9c29ef64 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; @@ -169,10 +169,10 @@ int main(int argc, char **argv) { 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 +181,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;isample_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)); + } + } + + 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, max_prb)) { + + 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); } } } 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_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/srsenb/hdr/phy/phch_worker.h b/srsenb/hdr/phy/phch_worker.h index 906e8b9d0..48878a879 100644 --- a/srsenb/hdr/phy/phch_worker.h +++ b/srsenb/hdr/phy/phch_worker.h @@ -88,7 +88,7 @@ private: bool running; cf_t *signal_buffer_rx; - cf_t *signal_buffer_tx; + cf_t *signal_buffer_tx[SRSLTE_MAX_PORTS]; uint32_t tti_rx, tti_tx, tti_sched_ul, sf_rx, sf_tx, sf_sched_ul, tx_mutex_cnt; srslte_enb_dl_t enb_dl; diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index 3a1fb8ca4..8a6173347 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); @@ -336,9 +339,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); diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index c14141257..041418b5a 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -101,13 +101,13 @@ void phch_recv:: init(srslte::radio_multi *_radio_handler, mac_interface_phy *_ if (do_agc) { srslte_ue_sync_start_agc(&cs.ue_sync, callback_set_rx_gain, last_gain); } - - if (srslte_ue_dl_init(&ue_dl_measure, SRSLTE_MAX_PRB, nof_rx_antennas)) { + + if (srslte_ue_dl_init(&ue_dl_measure, sf_buffer, SRSLTE_MAX_PRB, nof_rx_antennas)) { Error("SYNC: Initiating ue_dl_measure\n"); return; } - if (srslte_ue_mib_init(&ue_mib, SRSLTE_MAX_PRB)) { + if (srslte_ue_mib_init(&ue_mib, sf_buffer, SRSLTE_MAX_PRB)) { Error("SYNC: Initiating UE MIB decoder\n"); return; } @@ -374,7 +374,7 @@ int phch_recv::cell_sync_sfn(void) { int sfn_offset = 0; Info("SYNC: Trying to decode MIB... SNR=%.1f dB\n", 10*log10(srslte_chest_dl_get_snr(&ue_mib.chest))); - int n = srslte_ue_mib_decode(&ue_mib, sf_buffer[0], bch_payload, NULL, &sfn_offset); + int n = srslte_ue_mib_decode(&ue_mib, bch_payload, NULL, &sfn_offset); if (n < 0) { Error("SYNC: Error decoding MIB while synchronising SFN"); return -1; diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index c0fec2ba2..ee1011aea 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -118,12 +118,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; } From b0157cb4f870b330c6b2daa737c9335a43aaa17e Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 20 Oct 2017 10:40:59 -0400 Subject: [PATCH 083/242] Removed error when can't save fft wisdom (prints in mkl) --- lib/src/phy/dft/dft_fftw.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/src/phy/dft/dft_fftw.c b/lib/src/phy/dft/dft_fftw.c index a06dd397f..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 } From 7e3fbbc63918f049ad5eca2560d5ff4db19920bc Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Fri, 20 Oct 2017 16:18:26 +0100 Subject: [PATCH 084/242] Adding ASN support for RRC measurement report messages --- lib/include/srslte/asn1/liblte_rrc.h | 97 ++++++++++- lib/src/asn1/liblte_rrc.cc | 249 ++++++++++++++++++++++++++- lib/test/CMakeLists.txt | 1 + lib/test/asn1/CMakeLists.txt | 23 +++ lib/test/asn1/rrc_meas_test.cc | 91 ++++++++++ 5 files changed, 451 insertions(+), 10 deletions(-) create mode 100644 lib/test/asn1/CMakeLists.txt create mode 100644 lib/test/asn1/rrc_meas_test.cc diff --git a/lib/include/srslte/asn1/liblte_rrc.h b/lib/include/srslte/asn1/liblte_rrc.h index 5a8515dbb..c5c3b60e2 100644 --- a/lib/include/srslte/asn1/liblte_rrc.h +++ b/lib/include/srslte/asn1/liblte_rrc.h @@ -6435,11 +6435,102 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_mobility_from_eutra_command_msg(LIBLTE_BIT_M Document Reference: 36.331 v10.0.0 Section 6.2.2 *********************************************************************/ -// Defines -// Enums +typedef struct{ + LIBLTE_RRC_CELL_GLOBAL_ID_EUTRA_STRUCT cell_global_id; + uint16 tracking_area_code; + LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_identity_list[5]; + uint32 n_plmn_identity_list; + bool have_plmn_identity_list; +}LIBLTE_RRC_CGI_INFO_STRUCT; +LIBLTE_ERROR_ENUM liblte_rrc_pack_cgi_info_ie(LIBLTE_RRC_CGI_INFO_STRUCT *cgi_info, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_cgi_info_ie(uint8 **ie_ptr, + LIBLTE_RRC_CGI_INFO_STRUCT *cgi_info); + +typedef struct{ + uint8 rsrp_result; + bool have_rsrp; + uint8 rsrq_result; + bool have_rsrq; +}LIBLTE_RRC_MEAS_RESULT_STRUCT; +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_result_ie(LIBLTE_RRC_MEAS_RESULT_STRUCT *meas_result, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_result_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_RESULT_STRUCT *meas_result); + +typedef struct{ + uint16 phys_cell_id; + LIBLTE_RRC_CGI_INFO_STRUCT cgi_info; + bool have_cgi_info; + LIBLTE_RRC_MEAS_RESULT_STRUCT meas_result; +}LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT; +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 liblte_rrc_unpack_meas_result_eutra_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT *meas_result_eutra); + +typedef struct{ + //FIXME +}LIBLTE_RRC_MEAS_RESULT_UTRA_STRUCT; +typedef struct{ + //FIXME +}LIBLTE_RRC_MEAS_RESULT_GERAN_STRUCT; +typedef struct{ + //FIXME +}LIBLTE_RRC_MEAS_RESULT_CDMA2000_STRUCT; + + + +typedef struct{ + LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT result_eutra_list[8]; + uint8 n_result; +}LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA_STRUCT; + +typedef struct{ + LIBLTE_RRC_MEAS_RESULT_UTRA_STRUCT result_utra_list[8]; + uint8 n_result; +}LIBLTE_RRC_MEAS_RESULT_LIST_UTRA_STRUCT; + +typedef struct{ + LIBLTE_RRC_MEAS_RESULT_GERAN_STRUCT result_geran_list[8]; + uint8 n_result; +}LIBLTE_RRC_MEAS_RESULT_LIST_GERAN_STRUCT; + + +typedef struct{ + bool pre_registration_status_HRPD; + LIBLTE_RRC_MEAS_RESULT_CDMA2000_STRUCT cdma2000[8]; +}LIBLTE_RRC_MEAS_RESULTS_CDMA2000_STRUCT; + +typedef enum{ + LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA = 0, + LIBLTE_RRC_MEAS_RESULT_LIST_UTRA, + LIBLTE_RRC_MEAS_RESULT_LIST_GERAN, + LIBLTE_RRC_MEAS_RESULTS_CDMA2000, + LIBLTE_RRC_MEAS_RESULT_N_ITEMS, +}LIBLTE_RRC_MEAS_RESULT_NEIGH_CELLS_ENUM; +static const char liblte_rrc_meas_reult_neigh_cells_text[LIBLTE_RRC_MEAS_RESULT_N_ITEMS][32] = { "measResultListEUTRA", "measResultListUTRA", "measResultListGERAN", "measResultsCDMA2000"}; + + +typedef union{ + LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA_STRUCT eutra; + LIBLTE_RRC_MEAS_RESULT_LIST_UTRA_STRUCT utra; + LIBLTE_RRC_MEAS_RESULT_LIST_GERAN_STRUCT geran; + LIBLTE_RRC_MEAS_RESULTS_CDMA2000_STRUCT cdma2000; +}LIBLTE_RRC_MEAS_RESULT_NEIGH_CELLS_UNION; + +//TODO: pack/unpack for the result lists + + // Structs typedef struct{ - // FIXME + uint8 meas_id; + uint8 pcell_rsrp_result; + uint8 pcell_rsrq_result; + + LIBLTE_RRC_MEAS_RESULT_NEIGH_CELLS_UNION meas_result_neigh_cells; + LIBLTE_RRC_MEAS_RESULT_NEIGH_CELLS_ENUM meas_result_neigh_cells_choice; + bool have_meas_result_neigh_cells; }LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT; // Functions LIBLTE_ERROR_ENUM liblte_rrc_pack_measurement_report_msg(LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *meas_report, 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/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; i Date: Fri, 20 Oct 2017 18:17:07 +0200 Subject: [PATCH 085/242] SSE optimization for srslte_bit_interleave_w_offset --- lib/src/phy/utils/bit.c | 126 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) 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;i Date: Fri, 20 Oct 2017 12:34:34 -0400 Subject: [PATCH 086/242] Added option to ue.conf to configure CFO EMA (set default to 0.4) --- lib/include/srslte/interfaces/ue_interfaces.h | 3 ++- lib/include/srslte/phy/ue/ue_sync.h | 5 ++++- lib/src/phy/ue/ue_sync.c | 5 +++++ srsue/src/main.cc | 5 +++++ srsue/src/phy/phch_recv.cc | 1 + srsue/ue.conf.example | 9 ++++++++- 6 files changed, 25 insertions(+), 3 deletions(-) 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/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/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/srsue/src/main.cc b/srsue/src/main.cc index 1b146a9f3..52d4b13c9 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -202,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.") diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index cf8bd6786..8a69a7f76 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -209,6 +209,7 @@ void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q) { srslte_ue_sync_cfo_i_detec_en(q, true); } + srslte_ue_sync_set_cfo_ema(q, worker_com->args->cfo_ema); srslte_ue_sync_set_cfo_tol(q, worker_com->args->cfo_correct_tol_hz); int time_correct_period = worker_com->args->time_correct_period; diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index d0dc67952..5b3559ae9 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -98,7 +98,10 @@ enable = false ##################################################################### # Expert configuration options # +# 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., @@ -116,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 @@ -140,6 +145,7 @@ enable = false ##################################################################### [expert] #ip_netmask = 255.255.255.0 +#rssi_sensor_enabled = false #ue_category = 4 #prach_gain = 30 #cqi_max = 15 @@ -150,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 From 3cbe526cbc7fbaad9cb1febfcba4fa2c47783671 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 20 Oct 2017 12:43:04 -0400 Subject: [PATCH 087/242] Revert "Disable RSSI sensor by default" This reverts commit c14393b24f874b4e12d3bbfb883133fedda4f6f1. --- srsue/src/main.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 52d4b13c9..b933b66f3 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -155,7 +155,7 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { "Pregenerate uplink signals after attach. Improves CPU performance.") ("expert.rssi_sensor_enabled", - bpo::value(&args->expert.phy.rssi_sensor_enabled)->default_value(false), + bpo::value(&args->expert.phy.rssi_sensor_enabled)->default_value(true), "Enable or disable RF frontend RSSI sensor. In some USRP devices can cause segmentation fault") ("expert.prach_gain", From 15e75b2c65b35c573bab2fd68c7fb1d553741307 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 23 Oct 2017 14:23:03 +0200 Subject: [PATCH 088/242] Created Bit interleaver object and SSE optimised interleaver --- lib/include/srslte/phy/fec/rm_turbo.h | 2 + lib/include/srslte/phy/utils/bit.h | 19 +++ lib/src/phy/fec/rm_turbo.c | 19 ++- lib/src/phy/fec/test/rm_turbo_test.c | 1 + lib/src/phy/fec/turbocoder.c | 10 +- lib/src/phy/phch/sch.c | 2 + lib/src/phy/utils/bit.c | 173 +++++++++++++++++++++++++- 7 files changed, 221 insertions(+), 5 deletions(-) diff --git a/lib/include/srslte/phy/fec/rm_turbo.h b/lib/include/srslte/phy/fec/rm_turbo.h index df0720b95..182b49fb8 100644 --- a/lib/include/srslte/phy/fec/rm_turbo.h +++ b/lib/include/srslte/phy/fec/rm_turbo.h @@ -58,6 +58,8 @@ SRSLTE_API int srslte_rm_turbo_tx(uint8_t *w_buff, SRSLTE_API void srslte_rm_turbo_gentables(); +SRSLTE_API void srslte_rm_turbo_free_tables(); + SRSLTE_API int srslte_rm_turbo_tx_lut(uint8_t *w_buff, uint8_t *systematic, uint8_t *parity, diff --git a/lib/include/srslte/phy/utils/bit.h b/lib/include/srslte/phy/utils/bit.h index c02ecd6bb..e4289b790 100644 --- a/lib/include/srslte/phy/utils/bit.h +++ b/lib/include/srslte/phy/utils/bit.h @@ -40,6 +40,25 @@ #include "srslte/config.h" +typedef struct { + uint32_t nof_bits; + uint16_t *interleaver; + uint16_t *byte_idx; + uint8_t *bit_mask; + uint8_t n_128; +} srslte_bit_interleaver_t; + +SRSLTE_API void srslte_bit_interleaver_init(srslte_bit_interleaver_t *q, + uint16_t *interleaver, + uint32_t nof_bits); + +SRSLTE_API void srslte_bit_interleaver_free(srslte_bit_interleaver_t *q); + +SRSLTE_API void srslte_bit_interleaver_run(srslte_bit_interleaver_t *q, + uint8_t *input, + uint8_t *output, + uint16_t w_offset); + SRSLTE_API void srslte_bit_interleave(uint8_t *input, uint8_t *output, uint16_t *interleaver, diff --git a/lib/src/phy/fec/rm_turbo.c b/lib/src/phy/fec/rm_turbo.c index cdc8ac88d..b1cc95a8c 100644 --- a/lib/src/phy/fec/rm_turbo.c +++ b/lib/src/phy/fec/rm_turbo.c @@ -61,7 +61,9 @@ static uint8_t RM_PERM_TC[NCOLS] = { 0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, /* Align tables to 16-byte boundary */ static uint16_t interleaver_systematic_bits[192][6160]; // 4 tail bits +static srslte_bit_interleaver_t bit_interleavers_systematic_bits[192]; static uint16_t interleaver_parity_bits[192][2*6160]; +static srslte_bit_interleaver_t bit_interleavers_parity_bits[192]; static uint16_t deinterleaver[192][4][18448]; static int k0_vec[SRSLTE_NOF_TC_CB_SIZES][4][2]; static bool rm_turbo_tables_generated = false; @@ -235,7 +237,12 @@ void srslte_rm_turbo_gentables() { k0_vec[cb_idx][i][1] = -1; } srslte_rm_turbo_gentable_systematic(interleaver_systematic_bits[cb_idx], k0_vec[cb_idx], nrows, ndummy); + srslte_bit_interleaver_init(&bit_interleavers_systematic_bits[cb_idx], interleaver_systematic_bits[cb_idx], + (uint32_t) srslte_cbsegm_cbsize(cb_idx)+4); + srslte_rm_turbo_gentable_parity(interleaver_parity_bits[cb_idx], k0_vec[cb_idx], in_len/3, nrows, ndummy); + srslte_bit_interleaver_init(&bit_interleavers_parity_bits[cb_idx], interleaver_parity_bits[cb_idx], + (uint32_t) (srslte_cbsegm_cbsize(cb_idx)+4)*2); for (int i=0;i<4;i++) { srslte_rm_turbo_gentable_receive(deinterleaver[cb_idx][i], in_len, i); @@ -244,6 +251,12 @@ void srslte_rm_turbo_gentables() { } } +void srslte_rm_turbo_free_tables () { + for (int i = 0; i < SRSLTE_NOF_TC_CB_SIZES; i++) { + srslte_bit_interleaver_free(&bit_interleavers_systematic_bits[i]); + srslte_bit_interleaver_free(&bit_interleavers_parity_bits[i]); + } +} /** * Rate matching for LTE Turbo Coder @@ -274,11 +287,13 @@ int srslte_rm_turbo_tx_lut(uint8_t *w_buff, uint8_t *systematic, uint8_t *parity if (rv_idx == 0) { // Systematic bits - srslte_bit_interleave(systematic, w_buff, interleaver_systematic_bits[cb_idx], in_len/3); + //srslte_bit_interleave(systematic, w_buff, interleaver_systematic_bits[cb_idx], in_len/3); + srslte_bit_interleaver_run(&bit_interleavers_systematic_bits[cb_idx], systematic, w_buff, 0); // Parity bits - srslte_bit_interleave_w_offset(parity, &w_buff[in_len/24], interleaver_parity_bits[cb_idx], 2*in_len/3, 4); + //srslte_bit_interleave_w_offset(parity, &w_buff[in_len/24], interleaver_parity_bits[cb_idx], 2*in_len/3, 4); + srslte_bit_interleaver_run(&bit_interleavers_parity_bits[cb_idx], parity, &w_buff[in_len/24], 4); } /* Bit selection and transmission 5.1.4.1.2 */ diff --git a/lib/src/phy/fec/test/rm_turbo_test.c b/lib/src/phy/fec/test/rm_turbo_test.c index 6943c72d1..1c5b2abf5 100644 --- a/lib/src/phy/fec/test/rm_turbo_test.c +++ b/lib/src/phy/fec/test/rm_turbo_test.c @@ -197,6 +197,7 @@ int main(int argc, char **argv) { } } + srslte_rm_turbo_free_tables(); free(rm_bits); free(rm_bits2); free(rm_bits2_bytes); diff --git a/lib/src/phy/fec/turbocoder.c b/lib/src/phy/fec/turbocoder.c index b7785980c..64f05b5e8 100644 --- a/lib/src/phy/fec/turbocoder.c +++ b/lib/src/phy/fec/turbocoder.c @@ -43,6 +43,7 @@ uint8_t tcod_lut_next_state[188][8][256]; uint8_t tcod_lut_output[188][8][256]; uint16_t tcod_per_fw[188][6144]; +static srslte_bit_interleaver_t tcod_interleavers[188]; static bool table_initiated = false; @@ -63,6 +64,9 @@ void srslte_tcod_free(srslte_tcod_t *h) { if (h->temp) { free(h->temp); } + for (int i = 0; i < 188; i++) { + srslte_bit_interleaver_free(&tcod_interleavers[i]); + } } /* Expects bits (1 byte = 1 bit) and produces bits. The systematic and parity bits are interlaced in the output */ @@ -198,8 +202,9 @@ int srslte_tcod_encode_lut(srslte_tcod_t *h, uint8_t *input, uint8_t *parity, ui } parity[long_cb/8] = 0; // will put tail here later - /* Interleave input */ - srslte_bit_interleave(input, h->temp, tcod_per_fw[cblen_idx], long_cb); + /* Interleave input */ + srslte_bit_interleaver_run(&tcod_interleavers[cblen_idx], input, h->temp, 0); + //srslte_bit_interleave(input, h->temp, tcod_per_fw[cblen_idx], long_cb); /* Parity bits for the 2nd constituent encoders */ uint8_t state1 = 0; @@ -297,6 +302,7 @@ void srslte_tcod_gentable() { for (uint32_t i=0;icb_in) { free(q->cb_in); } diff --git a/lib/src/phy/utils/bit.c b/lib/src/phy/utils/bit.c index b1ae383a6..809d4c392 100644 --- a/lib/src/phy/utils/bit.c +++ b/lib/src/phy/utils/bit.c @@ -30,6 +30,7 @@ #include #include #include +#include #ifdef LV_HAVE_SSE @@ -38,6 +39,172 @@ #endif /* LV_HAVE_SSE */ #include "srslte/phy/utils/bit.h" +#include "srslte/phy/utils/vector.h" + +void srslte_bit_interleaver_init(srslte_bit_interleaver_t *q, + uint16_t *interleaver, + uint32_t nof_bits) { + static const uint8_t mask[] = { 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 }; + + bzero(q, sizeof(srslte_bit_interleaver_t)); + + q->interleaver = srslte_vec_malloc(sizeof(uint16_t)*nof_bits); + q->byte_idx = srslte_vec_malloc(sizeof(uint16_t)*nof_bits); + q->bit_mask = srslte_vec_malloc(sizeof(uint8_t)*nof_bits); + q->nof_bits = nof_bits; + + for (int i = 0; i < nof_bits; i++) { + uint16_t i_px = interleaver[i]; + q->interleaver[i] = i_px; + q->byte_idx[i] = (uint16_t) (interleaver[i] / 8); + q->bit_mask[i] = (uint8_t) (mask[i_px%8]); + } +} + +void srslte_bit_interleaver_free(srslte_bit_interleaver_t *q) { + if (q->interleaver) { + free(q->interleaver); + } + + if (q->byte_idx) { + free(q->byte_idx); + } + + if (q->bit_mask) { + free(q->bit_mask); + } + + bzero(q, sizeof(srslte_bit_interleaver_t)); +} + +void srslte_bit_interleaver_run(srslte_bit_interleaver_t *q, uint8_t *input, uint8_t *output, uint16_t w_offset) { + static const uint8_t mask[] = { 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 }; + uint16_t *byte_idx = q->byte_idx; + uint8_t *bit_mask = q->bit_mask; + uint8_t *output_ptr = output; + + uint32_t st=0, w_offset_p=0; + + if (w_offset < 8 && w_offset > 0) { + st=1; + for (uint32_t j=0;j<8-w_offset;j++) { + uint16_t i_p = q->interleaver[j]; + if (input[i_p/8] & mask[i_p%8]) { + output[0] |= mask[j+w_offset]; + } else { + output[0] &= ~(mask[j+w_offset]); + } + } + w_offset_p=8-w_offset; + } + + uint32_t i = st * 8; + + byte_idx += i - w_offset_p; + bit_mask += i - w_offset_p; + output_ptr += st; + +#ifdef LV_HAVE_SSE + for(; i < q->nof_bits - 15; i += 16) { + __m128i in128; + in128 = _mm_insert_epi8(in128, input[*(byte_idx++)], 0x7); + in128 = _mm_insert_epi8(in128, input[*(byte_idx++)], 0x6); + in128 = _mm_insert_epi8(in128, input[*(byte_idx++)], 0x5); + in128 = _mm_insert_epi8(in128, input[*(byte_idx++)], 0x4); + in128 = _mm_insert_epi8(in128, input[*(byte_idx++)], 0x3); + in128 = _mm_insert_epi8(in128, input[*(byte_idx++)], 0x2); + in128 = _mm_insert_epi8(in128, input[*(byte_idx++)], 0x1); + in128 = _mm_insert_epi8(in128, input[*(byte_idx++)], 0x0); + in128 = _mm_insert_epi8(in128, input[*(byte_idx++)], 0xF); + in128 = _mm_insert_epi8(in128, input[*(byte_idx++)], 0xE); + in128 = _mm_insert_epi8(in128, input[*(byte_idx++)], 0xD); + in128 = _mm_insert_epi8(in128, input[*(byte_idx++)], 0xC); + in128 = _mm_insert_epi8(in128, input[*(byte_idx++)], 0xB); + in128 = _mm_insert_epi8(in128, input[*(byte_idx++)], 0xA); + in128 = _mm_insert_epi8(in128, input[*(byte_idx++)], 0x9); + in128 = _mm_insert_epi8(in128, input[*(byte_idx++)], 0x8); + + __m128i mask128 = _mm_loadu_si128((__m128i *) bit_mask); + mask128 = _mm_shuffle_epi8(mask128, _mm_set_epi8(0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7)); + + __m128i cmp128 = _mm_cmpeq_epi8(_mm_and_si128(in128, mask128), mask128); + *((uint16_t *) (output_ptr)) = (uint16_t) _mm_movemask_epi8(cmp128); + + bit_mask += 16; + output_ptr += 2; + } + +#endif /* LV_HAVE_SSE */ + + for(; i < q->nof_bits; i += 8) { + uint8_t out0 = (input[*(byte_idx++)] & *(bit_mask++))?mask[0]:(uint8_t)0; + uint8_t out1 = (input[*(byte_idx++)] & *(bit_mask++))?mask[1]:(uint8_t)0; + uint8_t out2 = (input[*(byte_idx++)] & *(bit_mask++))?mask[2]:(uint8_t)0; + uint8_t out3 = (input[*(byte_idx++)] & *(bit_mask++))?mask[3]:(uint8_t)0; + uint8_t out4 = (input[*(byte_idx++)] & *(bit_mask++))?mask[4]:(uint8_t)0; + uint8_t out5 = (input[*(byte_idx++)] & *(bit_mask++))?mask[5]:(uint8_t)0; + uint8_t out6 = (input[*(byte_idx++)] & *(bit_mask++))?mask[6]:(uint8_t)0; + uint8_t out7 = (input[*(byte_idx++)] & *(bit_mask++))?mask[7]:(uint8_t)0; + + *output_ptr = out0 | out1 | out2 | out3 | out4 | out5 | out6 | out7; + output_ptr++; + } + + for (uint32_t j=0;jnof_bits%8;j++) { + uint16_t i_p = q->interleaver[(q->nof_bits/8)*8+j-w_offset]; + if (input[i_p/8] & mask[i_p%8]) { + output[q->nof_bits/8] |= mask[j]; + } else { + output[q->nof_bits/8] &= ~(mask[j]); + } + } + for (uint32_t j=0;jinterleaver[(q->nof_bits/8)*8+j-w_offset]; + if (input[i_p/8] & (1<<(7-i_p%8))) { + output[q->nof_bits/8] |= mask[j]; + } else { + output[q->nof_bits/8] &= ~(mask[j]); + } + } + +#if 0 + /* THIS PIECE OF CODE IS FOR CHECKING SIMD BEHAVIOUR. DO NOT ENABLE. */ + uint8_t *output2 = malloc(q->nof_bits/8); + for (i=st;inof_bits/8;i++) { + + uint16_t i_p0 = q->interleaver[i*8+0-w_offset_p]; + uint16_t i_p1 = q->interleaver[i*8+1-w_offset_p]; + uint16_t i_p2 = q->interleaver[i*8+2-w_offset_p]; + uint16_t i_p3 = q->interleaver[i*8+3-w_offset_p]; + uint16_t i_p4 = q->interleaver[i*8+4-w_offset_p]; + uint16_t i_p5 = q->interleaver[i*8+5-w_offset_p]; + uint16_t i_p6 = q->interleaver[i*8+6-w_offset_p]; + uint16_t i_p7 = q->interleaver[i*8+7-w_offset_p]; + + uint8_t out0 = (input[i_p0/8] & mask[i_p0%8])?mask[0]:(uint8_t)0; + uint8_t out1 = (input[i_p1/8] & mask[i_p1%8])?mask[1]:(uint8_t)0; + uint8_t out2 = (input[i_p2/8] & mask[i_p2%8])?mask[2]:(uint8_t)0; + uint8_t out3 = (input[i_p3/8] & mask[i_p3%8])?mask[3]:(uint8_t)0; + uint8_t out4 = (input[i_p4/8] & mask[i_p4%8])?mask[4]:(uint8_t)0; + uint8_t out5 = (input[i_p5/8] & mask[i_p5%8])?mask[5]:(uint8_t)0; + uint8_t out6 = (input[i_p6/8] & mask[i_p6%8])?mask[6]:(uint8_t)0; + uint8_t out7 = (input[i_p7/8] & mask[i_p7%8])?mask[7]:(uint8_t)0; + + output2[i] = out0 | out1 | out2 | out3 | out4 | out5 | out6 | out7; + } + + for(i = st; i < q->nof_bits/8; i++) { + if (true || output[i] != output2[i]) { + printf("%05d/%05d %02X %02X\n", i, q->nof_bits/8, output[i], output2[i]); + } + //output[i] = output2[i]; + } + free(output2); +#endif +} + + void srslte_bit_interleave(uint8_t *input, uint8_t *output, uint16_t *interleaver, uint32_t nof_bits) { srslte_bit_interleave_w_offset(input, output, interleaver, nof_bits, 0); @@ -90,7 +257,11 @@ void srslte_bit_interleave_w_offset(uint8_t *input, uint8_t *output, uint16_t *i 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; + epx.m128 = _mm_blendv_epi8(epx.m128, epx2.m128, _mm_setr_epi8(0, 0, 0, 0, 0, 0, 0, 0, + (uint8_t) 0xFF, (uint8_t) 0xFF, + (uint8_t) 0xFF, (uint8_t) 0xFF, + (uint8_t) 0xFF, (uint8_t) 0xFF, + (uint8_t) 0xFF, (uint8_t) 0xFF)); b128.m128 = _mm_and_si128(epx.m128, _mm_set1_epi8(0x7)); b128.m128 = _mm_shuffle_epi8(m128mask, b128.m128); From af669a6cbba7ccb92704604bd5b3dde31dde5625 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 24 Oct 2017 10:07:54 +0200 Subject: [PATCH 089/242] Added RI reporting in enb and optimised RI computing calling time --- .../srslte/interfaces/enb_interfaces.h | 1 + .../srslte/interfaces/sched_interface.h | 1 + lib/include/srslte/phy/phch/pucch.h | 3 +- lib/src/phy/enb/enb_ul.c | 33 +++++-- lib/src/phy/phch/pucch.c | 6 +- lib/src/phy/phch/test/CMakeLists.txt | 1 + lib/src/phy/ue/ue_ul.c | 24 +++-- srsenb/hdr/mac/mac.h | 1 + srsenb/hdr/mac/mac_metrics.h | 1 + srsenb/hdr/mac/scheduler.h | 1 + srsenb/hdr/mac/scheduler_ue.h | 3 + srsenb/hdr/mac/ue.h | 2 + srsenb/src/mac/mac.cc | 16 +++- srsenb/src/mac/scheduler.cc | 18 +++- srsenb/src/mac/scheduler_ue.cc | 6 ++ srsenb/src/mac/ue.cc | 5 + srsenb/src/phy/phch_worker.cc | 27 ++++-- srsenb/src/upper/rrc.cc | 24 +++-- srsue/hdr/phy/phch_worker.h | 3 +- srsue/src/phy/phch_worker.cc | 91 ++++++++++--------- 20 files changed, 188 insertions(+), 79 deletions(-) diff --git a/lib/include/srslte/interfaces/enb_interfaces.h b/lib/include/srslte/interfaces/enb_interfaces.h index 0cb3d18d6..6050babeb 100644 --- a/lib/include/srslte/interfaces/enb_interfaces.h +++ b/lib/include/srslte/interfaces/enb_interfaces.h @@ -64,6 +64,7 @@ public: virtual int sr_detected(uint32_t tti, uint16_t rnti) = 0; virtual int rach_detected(uint32_t tti, uint32_t preamble_idx, uint32_t time_adv) = 0; + virtual int ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value) = 0; virtual int cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) = 0; virtual int snr_info(uint32_t tti, uint16_t rnti, float snr_db) = 0; virtual int ack_info(uint32_t tti, uint16_t rnti, bool ack) = 0; diff --git a/lib/include/srslte/interfaces/sched_interface.h b/lib/include/srslte/interfaces/sched_interface.h index a717b4293..7a375e16e 100644 --- a/lib/include/srslte/interfaces/sched_interface.h +++ b/lib/include/srslte/interfaces/sched_interface.h @@ -227,6 +227,7 @@ public: /* DL information */ virtual int dl_ack_info(uint32_t tti, uint16_t rnti, bool ack) = 0; virtual int dl_rach_info(uint32_t tti, uint32_t ra_id, uint16_t rnti, uint32_t estimated_size) = 0; + virtual int dl_ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value) = 0; virtual int dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) = 0; /* UL information */ diff --git a/lib/include/srslte/phy/phch/pucch.h b/lib/include/srslte/phy/phch/pucch.h index 8aa1495c8..29785c09a 100644 --- a/lib/include/srslte/phy/phch/pucch.h +++ b/lib/include/srslte/phy/phch/pucch.h @@ -157,7 +157,8 @@ SRSLTE_API int srslte_pucch_decode(srslte_pucch_t *q, cf_t *sf_symbols, cf_t *ce, float noise_estimate, - uint8_t bits[SRSLTE_PUCCH_MAX_BITS]); + uint8_t bits[SRSLTE_PUCCH_MAX_BITS], + uint32_t nof_bits); SRSLTE_API float srslte_pucch_alpha_format1(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB], srslte_pucch_cfg_t *cfg, diff --git a/lib/src/phy/enb/enb_ul.c b/lib/src/phy/enb/enb_ul.c index db05d44ea..b669b31e1 100644 --- a/lib/src/phy/enb/enb_ul.c +++ b/lib/src/phy/enb/enb_ul.c @@ -259,11 +259,15 @@ void srslte_enb_ul_fft(srslte_enb_ul_t *q, cf_t *signal_buffer) int get_pucch(srslte_enb_ul_t *q, uint16_t rnti, uint32_t pdcch_n_cce, uint32_t sf_rx, - srslte_uci_data_t *uci_data, uint8_t bits[SRSLTE_PUCCH_MAX_BITS]) + srslte_uci_data_t *uci_data, uint8_t bits[SRSLTE_PUCCH_MAX_BITS], uint32_t nof_bits) { float noise_power = srslte_chest_ul_get_noise_estimate(&q->chest); srslte_pucch_format_t format = srslte_pucch_get_format(uci_data, q->cell.cp); + if (format == SRSLTE_PUCCH_FORMAT_ERROR) { + fprintf(stderr,"Error getting format\n"); + return SRSLTE_ERROR; + } uint32_t n_pucch = srslte_pucch_get_npucch(pdcch_n_cce, format, uci_data->scheduling_request, &q->users[rnti]->pucch_sched); @@ -272,7 +276,7 @@ int get_pucch(srslte_enb_ul_t *q, uint16_t rnti, return SRSLTE_ERROR; } - int ret_val = srslte_pucch_decode(&q->pucch, format, n_pucch, sf_rx, rnti, q->sf_symbols, q->ce, noise_power, bits); + int ret_val = srslte_pucch_decode(&q->pucch, format, n_pucch, sf_rx, rnti, q->sf_symbols, q->ce, noise_power, bits, nof_bits); if (ret_val < 0) { fprintf(stderr,"Error decoding PUCCH\n"); return SRSLTE_ERROR; @@ -285,16 +289,19 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti, srslte_uci_data_t *uci_data) { uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS]; - - if (q->users[rnti]) { + uint8_t *pucch_bits_ptr = pucch_bits; - int ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, pucch_bits); + if (q->users[rnti]) { + uint32_t nof_uci_bits = (uci_data->uci_ri_len > 0) ? uci_data->uci_ri_len : (uci_data->uci_cqi_len + + uci_data->uci_dif_cqi_len + + uci_data->uci_pmi_len); + int ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, pucch_bits, nof_uci_bits); // If we are looking for SR and ACK at the same time and ret=0, means there is no SR. // try again to decode ACK only if (uci_data->scheduling_request && uci_data->uci_ack_len && ret_val != 1) { uci_data->scheduling_request = false; - ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, pucch_bits); + ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, pucch_bits, nof_uci_bits); } // update schedulign request @@ -304,12 +311,24 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti, // Save ACK bits if (uci_data->uci_ack_len > 0) { - uci_data->uci_ack = pucch_bits[0]; + uci_data->uci_ack = *(pucch_bits_ptr++); + } + + if (uci_data->uci_ack_len > 1) { + uci_data->uci_ack_2 = *(pucch_bits_ptr++); } // PUCCH2 CQI bits are decoded inside srslte_pucch_decode() if (uci_data->uci_cqi_len) { memcpy(uci_data->uci_cqi, pucch_bits, uci_data->uci_cqi_len*sizeof(uint8_t)); + } + + if (uci_data->uci_ri_len) { + uint8_t *ptr = pucch_bits; + uci_data->uci_ri = (uint8_t) srslte_bit_pack(&ptr, uci_data->uci_ri_len); + } + + if (uci_data->uci_cqi_len || uci_data->uci_ri_len) { if (uci_data->uci_ack_len >= 1) { uci_data->uci_ack = pucch_bits[20]; } diff --git a/lib/src/phy/phch/pucch.c b/lib/src/phy/phch/pucch.c index 498d34f3a..10c785177 100644 --- a/lib/src/phy/phch/pucch.c +++ b/lib/src/phy/phch/pucch.c @@ -173,7 +173,7 @@ srslte_pucch_format_t srslte_pucch_get_format(srslte_uci_data_t *uci_data, srslt { srslte_pucch_format_t format = SRSLTE_PUCCH_FORMAT_ERROR; // No CQI data - if (uci_data->uci_cqi_len == 0) { + if (uci_data->uci_cqi_len == 0 && uci_data->uci_ri_len == 0) { // 1-bit ACK + optional SR if (uci_data->uci_ack_len == 1) { format = SRSLTE_PUCCH_FORMAT_1A; @@ -750,7 +750,7 @@ float srslte_pucch_get_last_corr(srslte_pucch_t* q) /* Equalize, demodulate and decode PUCCH bits according to Section 5.4.1 of 36.211 */ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format, uint32_t n_pucch, uint32_t sf_idx, uint16_t rnti, cf_t *sf_symbols, cf_t *ce, float noise_estimate, - uint8_t bits[SRSLTE_PUCCH_MAX_BITS]) + uint8_t bits[SRSLTE_PUCCH_MAX_BITS], uint32_t nof_bits) { int ret = SRSLTE_ERROR_INVALID_INPUTS; if (q != NULL && @@ -838,7 +838,7 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format, } srslte_demod_soft_demodulate_s(SRSLTE_MOD_QPSK, q->z, llr_pucch2, SRSLTE_PUCCH2_NOF_BITS/2); srslte_scrambling_s(&q->users[rnti]->seq_f2[sf_idx], llr_pucch2); - q->last_corr = (float) srslte_uci_decode_cqi_pucch(&q->cqi, llr_pucch2, bits, 4)/2000; + q->last_corr = (float) srslte_uci_decode_cqi_pucch(&q->cqi, llr_pucch2, bits, nof_bits)/2000; ret = 1; } else { fprintf(stderr, "Decoding PUCCH2: rnti not set\n"); diff --git a/lib/src/phy/phch/test/CMakeLists.txt b/lib/src/phy/phch/test/CMakeLists.txt index 6e6b8c024..e63243d18 100644 --- a/lib/src/phy/phch/test/CMakeLists.txt +++ b/lib/src/phy/phch/test/CMakeLists.txt @@ -218,6 +218,7 @@ add_executable(pucch_test pucch_test.c) target_link_libraries(pucch_test srslte_phy) add_test(pucch_test pucch_test) +add_test(pucch_test_uci_cqi_decoder pucch_test -q) ######################################################################## # PRACH TEST diff --git a/lib/src/phy/ue/ue_ul.c b/lib/src/phy/ue/ue_ul.c index 37dfecd93..479299bd7 100644 --- a/lib/src/phy/ue/ue_ul.c +++ b/lib/src/phy/ue/ue_ul.c @@ -271,21 +271,33 @@ int srslte_ue_ul_cfg_grant(srslte_ue_ul_t *q, srslte_ra_ul_grant_t *grant, void pucch_encode_bits(srslte_uci_data_t *uci_data, srslte_pucch_format_t format, uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS], uint8_t pucch2_bits[SRSLTE_PUCCH_MAX_BITS]) -{ +{ + uint8_t uci_buffer[SRSLTE_CQI_MAX_BITS]; + uint8_t uci_buffer_len = 0; + if (format == SRSLTE_PUCCH_FORMAT_1A || format == SRSLTE_PUCCH_FORMAT_1B) { pucch_bits[0] = uci_data->uci_ack; pucch_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 1a } if (format >= SRSLTE_PUCCH_FORMAT_2) { + /* Append RI */ + uint8_t *ptr = uci_buffer; + srslte_bit_unpack(uci_data->uci_ri, &ptr, uci_data->uci_ri_len); + uci_buffer_len += uci_data->uci_ri_len; + + /* Append CQI */ + memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_cqi, uci_data->uci_cqi_len); + uci_buffer_len += uci_data->uci_cqi_len; + /* Append Differential CQI */ - memcpy(&uci_data->uci_cqi[uci_data->uci_cqi_len], uci_data->uci_dif_cqi, uci_data->uci_dif_cqi_len); - uci_data->uci_cqi_len += uci_data->uci_dif_cqi_len; + memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_dif_cqi, uci_data->uci_dif_cqi_len); + uci_buffer_len += uci_data->uci_dif_cqi_len; /* Append PMI */ - memcpy(&uci_data->uci_cqi[uci_data->uci_cqi_len], uci_data->uci_pmi, uci_data->uci_pmi_len); - uci_data->uci_cqi_len += uci_data->uci_pmi_len; + memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_pmi, uci_data->uci_pmi_len); + uci_buffer_len += uci_data->uci_pmi_len; - srslte_uci_encode_cqi_pucch(uci_data->uci_cqi, uci_data->uci_cqi_len, pucch_bits); + srslte_uci_encode_cqi_pucch(uci_buffer, uci_buffer_len, pucch_bits); if (format > SRSLTE_PUCCH_FORMAT_2) { pucch2_bits[0] = uci_data->uci_ack; pucch2_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 2a diff --git a/srsenb/hdr/mac/mac.h b/srsenb/hdr/mac/mac.h index d71245e89..c3df1c9be 100644 --- a/srsenb/hdr/mac/mac.h +++ b/srsenb/hdr/mac/mac.h @@ -72,6 +72,7 @@ public: int sr_detected(uint32_t tti, uint16_t rnti); int rach_detected(uint32_t tti, uint32_t preamble_idx, uint32_t time_adv); + int ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value); int cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value); int snr_info(uint32_t tti, uint16_t rnti, float snr); int ack_info(uint32_t tti, uint16_t rnti, bool ack); diff --git a/srsenb/hdr/mac/mac_metrics.h b/srsenb/hdr/mac/mac_metrics.h index 35a65f8ae..ba5821ea9 100644 --- a/srsenb/hdr/mac/mac_metrics.h +++ b/srsenb/hdr/mac/mac_metrics.h @@ -44,6 +44,7 @@ struct mac_metrics_t int ul_buffer; int dl_buffer; float dl_cqi; + float dl_ri; float phr; }; diff --git a/srsenb/hdr/mac/scheduler.h b/srsenb/hdr/mac/scheduler.h index 231239285..f9316b139 100644 --- a/srsenb/hdr/mac/scheduler.h +++ b/srsenb/hdr/mac/scheduler.h @@ -105,6 +105,7 @@ public: int dl_ack_info(uint32_t tti, uint16_t rnti, bool ack); int dl_rach_info(uint32_t tti, uint32_t ra_id, uint16_t rnti, uint32_t estimated_size); + int dl_ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value); int dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value); int ul_crc_info(uint32_t tti, uint16_t rnti, bool crc); diff --git a/srsenb/hdr/mac/scheduler_ue.h b/srsenb/hdr/mac/scheduler_ue.h index 3653ff65c..4e4b28698 100644 --- a/srsenb/hdr/mac/scheduler_ue.h +++ b/srsenb/hdr/mac/scheduler_ue.h @@ -69,6 +69,7 @@ public: void mac_buffer_state(uint32_t ce_code); void ul_recv_len(uint32_t lcid, uint32_t len); void set_ul_cqi(uint32_t tti, uint32_t cqi, uint32_t ul_ch_code); + void set_dl_ri(uint32_t tti, uint32_t ri); void set_dl_cqi(uint32_t tti, uint32_t cqi); int set_ack_info(uint32_t tti, bool ack); void set_ul_crc(uint32_t tti, bool crc_res); @@ -155,6 +156,8 @@ private: ue_bearer_t lch[sched_interface::MAX_LC]; int power_headroom; + uint32_t dl_ri; + uint32_t dl_ri_tti; uint32_t dl_cqi; uint32_t dl_cqi_tti; uint32_t cqi_request_tti; diff --git a/srsenb/hdr/mac/ue.h b/srsenb/hdr/mac/ue.h index b879d040b..4b65063d5 100644 --- a/srsenb/hdr/mac/ue.h +++ b/srsenb/hdr/mac/ue.h @@ -93,6 +93,7 @@ public: void metrics_rx(bool crc, uint32_t tbs); void metrics_tx(bool crc, uint32_t tbs); void metrics_phr(float phr); + void metrics_dl_ri(uint32_t dl_cqi); void metrics_dl_cqi(uint32_t dl_cqi); @@ -108,6 +109,7 @@ private: uint32_t phr_counter; uint32_t dl_cqi_counter; + uint32_t dl_ri_counter; mac_metrics_t metrics; srslte::mac_pcap* pcap; diff --git a/srsenb/src/mac/mac.cc b/srsenb/src/mac/mac.cc index 796d08025..23c2557ba 100644 --- a/srsenb/src/mac/mac.cc +++ b/srsenb/src/mac/mac.cc @@ -305,11 +305,25 @@ int mac::crc_info(uint32_t tti, uint16_t rnti, uint32_t nof_bytes, bool crc) } } -int mac::cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) +int mac::ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value) { log_h->step(tti); if (ue_db.count(rnti)) { + scheduler.dl_ri_info(tti, rnti, ri_value); + ue_db[rnti]->metrics_dl_ri(ri_value); + } else { + Error("User rnti=0x%x not found\n", rnti); + return -1; + } + return 0; +} + +int mac::cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) +{ + log_h->step(tti); + + if (ue_db.count(rnti)) { scheduler.dl_cqi_info(tti, rnti, cqi_value); ue_db[rnti]->metrics_dl_cqi(cqi_value); } else { diff --git a/srsenb/src/mac/scheduler.cc b/srsenb/src/mac/scheduler.cc index 801b68d38..298ce9625 100644 --- a/srsenb/src/mac/scheduler.cc +++ b/srsenb/src/mac/scheduler.cc @@ -266,12 +266,12 @@ int sched::ul_crc_info(uint32_t tti, uint16_t rnti, bool crc) return ret; } -int sched::dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) +int sched::dl_ri_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) { pthread_mutex_lock(&mutex); int ret = 0; if (ue_db.count(rnti)) { - ue_db[rnti].set_dl_cqi(tti, cqi_value); + ue_db[rnti].set_dl_ri(tti, cqi_value); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; @@ -280,6 +280,20 @@ int sched::dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) return ret; } +int sched::dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) +{ + pthread_mutex_lock(&mutex); + int ret = 0; + if (ue_db.count(rnti)) { + ue_db[rnti].set_dl_cqi(tti, cqi_value); + } else { + Error("User rnti=0x%x not found\n", rnti); + ret = -1; + } + pthread_mutex_unlock(&mutex); + return ret; +} + int sched::dl_rach_info(uint32_t tti, uint32_t ra_id, uint16_t rnti, uint32_t estimated_size) { for (int i=0;iset_ack(crc_res); } +void sched_ue::set_dl_ri(uint32_t tti, uint32_t ri) +{ + dl_ri = ri; + dl_ri_tti = tti; +} + void sched_ue::set_dl_cqi(uint32_t tti, uint32_t cqi) { dl_cqi = cqi; diff --git a/srsenb/src/mac/ue.cc b/srsenb/src/mac/ue.cc index 14944b6d4..a46b11cf6 100644 --- a/srsenb/src/mac/ue.cc +++ b/srsenb/src/mac/ue.cc @@ -407,6 +407,11 @@ void ue::metrics_phr(float phr) { phr_counter++; } +void ue::metrics_dl_ri(uint32_t dl_ri) { + metrics.dl_ri = SRSLTE_VEC_CMA((float) dl_ri, metrics.dl_ri, dl_ri_counter); + dl_ri_counter++; +} + void ue::metrics_dl_cqi(uint32_t dl_cqi) { metrics.dl_cqi = SRSLTE_VEC_CMA((float) dl_cqi, metrics.dl_cqi, dl_cqi_counter); dl_cqi_counter++; diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index d38242782..fd04ce438 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -533,7 +533,7 @@ int phch_worker::decode_pucch(uint32_t tti_rx) if (rnti >= SRSLTE_CRNTI_START && rnti <= SRSLTE_CRNTI_END && ue_db[rnti].has_grant_tti != (int) tti_rx) { // Check if user needs to receive PUCCH - bool needs_pucch = false, needs_ack=false, needs_sr=false, needs_cqi=false; + bool needs_pucch = false, needs_ack=false, needs_sr=false, needs_cqi=false, needs_ri=false; uint32_t last_n_pdcch = 0; bzero(&uci_data, sizeof(srslte_uci_data_t)); @@ -550,8 +550,18 @@ int phch_worker::decode_pucch(uint32_t tti_rx) uci_data.uci_ack_len = 1; } srslte_cqi_value_t cqi_value; + LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *dedicated = &ue_db[rnti].dedicated; + LIBLTE_RRC_TRANSMISSION_MODE_ENUM tx_mode = dedicated->antenna_info_explicit_value.tx_mode; + bool ri_report_present = dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx_present; + uint32_t pmi_idx = dedicated->cqi_report_cnfg.report_periodic.pmi_cnfg_idx; + uint32_t ri_idx = dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx; + if (ue_db[rnti].cqi_en && (ue_db[rnti].pucch_cqi_ack || !needs_ack)) { - if (srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) { + if (ri_report_present && srslte_ri_send(pmi_idx, ri_idx, tti_rx)) { + needs_pucch = true; + needs_ri = true; + uci_data.uci_ri_len = 1; + } else if (srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) { needs_pucch = true; needs_cqi = true; cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND; @@ -571,11 +581,14 @@ int phch_worker::decode_pucch(uint32_t tti_rx) phy->mac->sr_detected(tti_rx, rnti); } - char cqi_str[64]; - if (uci_data.uci_cqi_len) { + char cqi_ri_str[64]; + if (uci_data.uci_ri_len && needs_ri) { + phy->mac->ri_info(tti_rx, rnti, uci_data.uci_ri); + sprintf(cqi_ri_str, ", ri=%d", uci_data.uci_ri); + } else if (uci_data.uci_cqi_len && needs_cqi) { srslte_cqi_value_unpack(uci_data.uci_cqi, &cqi_value); phy->mac->cqi_info(tti_rx, rnti, cqi_value.wideband.wideband_cqi); - sprintf(cqi_str, ", cqi=%d", cqi_value.wideband.wideband_cqi); + sprintf(cqi_ri_str, ", cqi=%d", cqi_value.wideband.wideband_cqi); } log_h->info("PUCCH: rnti=0x%x, corr=%.2f, n_pucch=%d, n_prb=%d%s%s%s\n", rnti, @@ -583,7 +596,7 @@ int phch_worker::decode_pucch(uint32_t tti_rx) enb_ul.pucch.last_n_pucch, enb_ul.pucch.last_n_prb, needs_ack?(uci_data.uci_ack?", ack=1":", ack=0"):"", needs_sr?(uci_data.scheduling_request?", sr=yes":", sr=no"):"", - needs_cqi?cqi_str:""); + (needs_cqi || needs_ri)?cqi_ri_str:""); // Notify MAC of RL status @@ -709,7 +722,7 @@ int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants break; } - if (LOG_THIS(rnti)) { + if (LOG_THIS(rnti)) { uint8_t x = 0; uint8_t *ptr = grants[i].data[0]; uint32_t len = phy_grant.mcs[0].tbs / (uint32_t) 8; diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index 7b20209a5..90e175095 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -1109,17 +1109,21 @@ void rrc::ue::send_connection_setup(bool is_setup) mac_cfg->time_alignment_timer = parent->cfg.mac_cnfg.time_alignment_timer; // physicalConfigDedicated - rr_cfg->phy_cnfg_ded_present = true; + rr_cfg->phy_cnfg_ded_present = true; LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *phy_cfg = &rr_cfg->phy_cnfg_ded; bzero(phy_cfg, sizeof(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT)); phy_cfg->pusch_cnfg_ded_present = true; memcpy(&phy_cfg->pusch_cnfg_ded, &parent->cfg.pusch_cfg, sizeof(LIBLTE_RRC_PUSCH_CONFIG_DEDICATED_STRUCT)); phy_cfg->sched_request_cnfg_present = true; phy_cfg->sched_request_cnfg.setup_present = true; - phy_cfg->sched_request_cnfg.dsr_trans_max = parent->cfg.sr_cfg.dsr_max; - memcpy(&phy_cfg->antenna_info_explicit_value, &parent->cfg.antenna_info, sizeof(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT)); - phy_cfg->antenna_info_present = true; - phy_cfg->antenna_info_default_value = false; + phy_cfg->sched_request_cnfg.dsr_trans_max = parent->cfg.sr_cfg.dsr_max; + + if (parent->cfg.antenna_info.tx_mode > LIBLTE_RRC_TRANSMISSION_MODE_1) { + memcpy(&phy_cfg->antenna_info_explicit_value, &parent->cfg.antenna_info, + sizeof(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT)); + phy_cfg->antenna_info_present = true; + phy_cfg->antenna_info_default_value = false; + } if (is_setup) { if (sr_allocate(parent->cfg.sr_cfg.period, &phy_cfg->sched_request_cnfg.sr_cnfg_idx, &phy_cfg->sched_request_cnfg.sr_pucch_resource_idx)) { @@ -1149,8 +1153,14 @@ void rrc::ue::send_connection_setup(bool is_setup) phy_cfg->cqi_report_cnfg.report_periodic_present = true; phy_cfg->cqi_report_cnfg.report_periodic_setup_present = true; phy_cfg->cqi_report_cnfg.report_periodic.format_ind_periodic = LIBLTE_RRC_CQI_FORMAT_INDICATOR_PERIODIC_WIDEBAND_CQI; - phy_cfg->cqi_report_cnfg.report_periodic.simult_ack_nack_and_cqi = parent->cfg.cqi_cfg.simultaneousAckCQI; - phy_cfg->cqi_report_cnfg.report_periodic.ri_cnfg_idx_present = false; + phy_cfg->cqi_report_cnfg.report_periodic.simult_ack_nack_and_cqi = parent->cfg.cqi_cfg.simultaneousAckCQI; + if (phy_cfg->antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3 || + phy_cfg->antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { + phy_cfg->cqi_report_cnfg.report_periodic.ri_cnfg_idx_present = true; + phy_cfg->cqi_report_cnfg.report_periodic.ri_cnfg_idx = 483; + } else { + phy_cfg->cqi_report_cnfg.report_periodic.ri_cnfg_idx_present = false; + } if (is_setup) { if (cqi_allocate(parent->cfg.cqi_cfg.period, &phy_cfg->cqi_report_cnfg.report_periodic.pmi_cnfg_idx, diff --git a/srsue/hdr/phy/phch_worker.h b/srsue/hdr/phy/phch_worker.h index 0811723e0..74af27752 100644 --- a/srsue/hdr/phy/phch_worker.h +++ b/srsue/hdr/phy/phch_worker.h @@ -74,7 +74,8 @@ private: /* Internal methods */ bool extract_fft_and_pdcch_llr(); - + void compute_ri(); + /* ... for DL */ bool decode_pdcch_ul(mac_interface_phy::mac_grant_t *grant); bool decode_pdcch_dl(mac_interface_phy::mac_grant_t *grant); diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index c0fec2ba2..312ec57b1 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -258,41 +258,10 @@ void phch_worker::work_imp() set_uci_ack(dl_ack, dl_mac_grant.tb_en); } - /* Select Rank Indicator by computing Condition Number */ - if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) { - if (ue_dl.nof_rx_antennas > 1) { - /* If 2 ort more receiving antennas, select RI */ - float cn = 0.0f; - srslte_ue_dl_ri_select(&ue_dl, &uci_data.uci_ri, &cn); - uci_data.uci_ri_len = 1; - } else { - /* If only one receiving antenna, force RI for 1 layer */ - uci_data.uci_ri = 0; - uci_data.uci_ri_len = 1; - Warning("Only one receiving antenna with TM3. Forcing RI=1 layer.\n"); - } - } else if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4){ - float sinr = 0.0f; - uint8 packed_pmi = 0; - srslte_ue_dl_ri_pmi_select(&ue_dl, &uci_data.uci_ri, &packed_pmi, &sinr); - srslte_bit_unpack_vector(&packed_pmi, uci_data.uci_pmi, 2); - uci_data.uci_ri_len = 1; - if (uci_data.uci_ri == 0) { - uci_data.uci_pmi_len = 2; - uci_data.uci_dif_cqi_len = 0; - } else { - uci_data.uci_pmi_len = 1; - uci_data.uci_dif_cqi_len = 3; - } - - /* If only one antenna in TM4 print limitation warning */ - if (ue_dl.nof_rx_antennas < 2) { - Warning("Only one receiving antenna with TM4. Forcing RI=1 layer (PMI=%d).\n", packed_pmi); - } - } + compute_ri(); } } - + // Decode PHICH bool ul_ack = false; bool ul_ack_available = decode_phich(&ul_ack); @@ -338,7 +307,7 @@ void phch_worker::work_imp() phy->set_pending_ack(tti + 8, ue_ul.pusch_cfg.grant.n_prb_tilde[0], ul_action.phy_grant.ul.ncs_dmrs); } - } else if (dl_action.generate_ack || uci_data.scheduling_request || uci_data.uci_cqi_len > 0) { + } else if (dl_action.generate_ack || uci_data.scheduling_request || uci_data.uci_cqi_len > 0 || uci_data.uci_ri_len > 0) { encode_pucch(); signal_ready = true; } else if (srs_is_ready_to_send()) { @@ -387,6 +356,40 @@ void phch_worker::work_imp() #endif } +void phch_worker::compute_ri() { + /* Select Rank Indicator by computing Condition Number */ + if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) { + if (ue_dl.nof_rx_antennas > 1) { + /* If 2 ort more receiving antennas, select RI */ + float cn = 0.0f; + srslte_ue_dl_ri_select(&ue_dl, &uci_data.uci_ri, &cn); + Info("RI select %d layers, κ=%fdB\n", uci_data.uci_ri + 1, cn); + } else { + /* If only one receiving antenna, force RI for 1 layer */ + uci_data.uci_ri = 0; + Warning("Only one receiving antenna with TM3. Forcing RI=1 layer.\n"); + } + uci_data.uci_ri_len = 1; + } else if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { + float sinr = 0.0f; + uint8 packed_pmi = 0; + srslte_ue_dl_ri_pmi_select(&ue_dl, &uci_data.uci_ri, &packed_pmi, &sinr); + srslte_bit_unpack_vector(&packed_pmi, uci_data.uci_pmi, 2); + if (uci_data.uci_ri == 0) { + uci_data.uci_pmi_len = 2; + uci_data.uci_dif_cqi_len = 0; + } else { + uci_data.uci_pmi_len = 1; + uci_data.uci_dif_cqi_len = 3; + } + + /* If only one antenna in TM4 print limitation warning */ + if (ue_dl.nof_rx_antennas < 2) { + Warning("Only one receiving antenna with TM4. Forcing RI=1 layer (PMI=%d).\n", packed_pmi); + } + uci_data.uci_ri_len = 1; + } +} bool phch_worker::extract_fft_and_pdcch_llr() { bool decode_pdcch = false; @@ -612,8 +615,8 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL snprintf(timestr, 64, ", dec_time=%4d us", (int) t[0].tv_usec); #endif - snprintf(commonstr, 128, "PDSCH: l_crb=%2d, harq=%d, snr=%.1f dB", grant->nof_prb, harq_pid, - 10 * log10(srslte_chest_dl_get_snr(&ue_dl.chest))); + snprintf(commonstr, 128, "PDSCH: l_crb=%2d, harq=%d, snr=%.1f dB, tx_scheme=%s", grant->nof_prb, harq_pid, + 10 * log10(srslte_chest_dl_get_snr(&ue_dl.chest)), srslte_mimotype2str(mimo_type)); for (int i=0;itb_en[i]) { @@ -794,14 +797,14 @@ void phch_worker::set_uci_periodic_cqi() if (period_cqi.configured && rnti_is_set) { if (period_cqi.ri_idx_present && srslte_ri_send(period_cqi.pmi_idx, period_cqi.ri_idx, (tti+4)%10240)) { - if (uci_data.uci_ri_len) { - uci_data.uci_cqi[0] = uci_data.uci_ri; - uci_data.uci_cqi_len = uci_data.uci_ri_len; - uci_data.uci_ri_len = 0; - uci_data.uci_dif_cqi_len = 0; - uci_data.uci_pmi_len = 0; - Info("PUCCH: Periodic RI=%d\n", uci_data.uci_cqi[0]); + /* If the RI is not computed, compute it */ + if (uci_data.uci_ri_len < 1) { + compute_ri(); } + uci_data.uci_cqi_len = 0; + uci_data.uci_dif_cqi_len = 0; + uci_data.uci_pmi_len = 0; + Info("PUCCH: Periodic RI=%d\n", uci_data.uci_ri); } else if (srslte_cqi_send(period_cqi.pmi_idx, (tti+4)%10240)) { srslte_cqi_value_t cqi_report; if (period_cqi.format_is_subband) { @@ -937,7 +940,7 @@ void phch_worker::encode_pucch() char timestr[64]; timestr[0]='\0'; - if (uci_data.scheduling_request || uci_data.uci_ack_len > 0 || uci_data.uci_cqi_len > 0) + if (uci_data.scheduling_request || uci_data.uci_ack_len > 0 || uci_data.uci_cqi_len > 0 || uci_data.uci_ri_len > 0) { // Drop CQI if there is collision with ACK From ac8cbcaaea91116eb5a5f531e69a1eb8dd007f97 Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Wed, 25 Oct 2017 11:18:49 +0100 Subject: [PATCH 090/242] 1-byte PDU fix for RLC AM --- lib/src/upper/rlc_am.cc | 4 ++-- lib/test/upper/rlc_am_test.cc | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index b62a7e88e..96b231a09 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -613,7 +613,7 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) uint32_t pdu_space = nof_bytes; uint8_t *pdu_ptr = pdu->msg; - 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 +652,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/test/upper/rlc_am_test.cc b/lib/test/upper/rlc_am_test.cc index 7a37d0d5d..9ada2ba42 100644 --- a/lib/test/upper/rlc_am_test.cc +++ b/lib/test/upper/rlc_am_test.cc @@ -123,7 +123,7 @@ void basic_test() byte_buffer_t pdu_bufs[NBUFS]; for(int i=0;i Date: Thu, 26 Oct 2017 09:02:30 +0200 Subject: [PATCH 091/242] fix bug in RLC AM where poll bit was never set if poll_byte and poll_pdu are zero - In case both poll_pdu and poll_byte are zero a status PDU is requested from the other AM entity every N data PDUs --- lib/include/srslte/upper/rlc_am.h | 2 ++ lib/src/upper/rlc_am.cc | 12 ++++++++++++ 2 files changed, 14 insertions(+) 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/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index 96b231a09..05f35ad76 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -381,6 +381,18 @@ bool rlc_am::poll_required() return true; if(poll_retx()) return true; + + if(tx_sdu_queue.size() == 0 && retx_queue.size() == 0) + return true; + + /* According to 5.2.2.1 in 36.322 v13.3.0 a poll should be requested if + * the entire AM window is unacknowledged, i.e. no new PDU can be transmitted. + * However, it seems more appropiate to request more often if polling + * is disabled otherwise, e.g. every N PDUs. + */ + if (cfg.poll_pdu == 0 && cfg.poll_byte == 0 && vt_s % poll_periodicity == 0) + return true; + return false; } From 6985682ef0876285b93f4524cee26f8973d2d996 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 26 Oct 2017 17:09:28 +0200 Subject: [PATCH 092/242] Added 2nd Codeword interface in scheduler, plus pmi close loop reporting --- .../srslte/interfaces/enb_interfaces.h | 2 + .../srslte/interfaces/sched_interface.h | 4 +- lib/include/srslte/phy/enb/enb_dl.h | 4 +- lib/src/phy/enb/enb_dl.c | 24 +- lib/src/phy/enb/enb_ul.c | 12 +- lib/src/phy/ue/ue_dl.c | 4 +- lib/src/phy/ue/ue_ul.c | 5 +- srsenb/hdr/mac/mac.h | 3 + srsenb/hdr/mac/mac_metrics.h | 1 + srsenb/hdr/mac/scheduler.h | 2 + srsenb/hdr/mac/scheduler_harq.h | 40 +-- srsenb/hdr/mac/scheduler_ue.h | 16 +- srsenb/hdr/mac/ue.h | 2 + srsenb/src/mac/mac.cc | 39 ++- srsenb/src/mac/scheduler.cc | 62 ++++- srsenb/src/mac/scheduler_harq.cc | 98 ++++---- srsenb/src/mac/scheduler_metric.cc | 8 +- srsenb/src/mac/scheduler_ue.cc | 233 ++++++++++++++++-- srsenb/src/mac/ue.cc | 5 + srsenb/src/phy/phch_worker.cc | 99 +++++--- srsenb/src/upper/rrc.cc | 4 +- srsue/src/phy/phch_worker.cc | 21 +- 22 files changed, 523 insertions(+), 165 deletions(-) diff --git a/lib/include/srslte/interfaces/enb_interfaces.h b/lib/include/srslte/interfaces/enb_interfaces.h index 6050babeb..6f9db923a 100644 --- a/lib/include/srslte/interfaces/enb_interfaces.h +++ b/lib/include/srslte/interfaces/enb_interfaces.h @@ -65,6 +65,7 @@ public: virtual int rach_detected(uint32_t tti, uint32_t preamble_idx, uint32_t time_adv) = 0; virtual int ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value) = 0; + virtual int pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value) = 0; virtual int cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) = 0; virtual int snr_info(uint32_t tti, uint16_t rnti, float snr_db) = 0; virtual int ack_info(uint32_t tti, uint16_t rnti, bool ack) = 0; @@ -113,6 +114,7 @@ public: /* Manages UE bearers and associated configuration */ virtual int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t *cfg) = 0; virtual int bearer_ue_rem(uint16_t rnti, uint32_t lc_id) = 0; + virtual int set_dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dl_ant_info) = 0; virtual void phy_config_enabled(uint16_t rnti, bool enabled) = 0; }; diff --git a/lib/include/srslte/interfaces/sched_interface.h b/lib/include/srslte/interfaces/sched_interface.h index 7a375e16e..5e4b68acf 100644 --- a/lib/include/srslte/interfaces/sched_interface.h +++ b/lib/include/srslte/interfaces/sched_interface.h @@ -131,9 +131,10 @@ public: typedef struct { uint32_t rnti; + srslte_dci_format_t dci_format; srslte_ra_dl_dci_t dci; srslte_dci_location_t dci_location; - uint32_t tbs; + uint32_t tbs[SRSLTE_MAX_TB]; bool mac_ce_ta; bool mac_ce_rnti; uint32_t nof_pdu_elems; @@ -228,6 +229,7 @@ public: virtual int dl_ack_info(uint32_t tti, uint16_t rnti, bool ack) = 0; virtual int dl_rach_info(uint32_t tti, uint32_t ra_id, uint16_t rnti, uint32_t estimated_size) = 0; virtual int dl_ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value) = 0; + virtual int dl_pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value) = 0; virtual int dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) = 0; /* UL information */ diff --git a/lib/include/srslte/phy/enb/enb_dl.h b/lib/include/srslte/phy/enb/enb_dl.h index b63cb6416..581b98e23 100644 --- a/lib/include/srslte/phy/enb/enb_dl.h +++ b/lib/include/srslte/phy/enb/enb_dl.h @@ -95,6 +95,7 @@ typedef struct SRSLTE_API { typedef struct { uint16_t rnti; + srslte_dci_format_t dci_format; srslte_ra_dl_dci_t grant; srslte_dci_location_t location; srslte_softbuffer_tx_t *softbuffers[SRSLTE_MAX_TB]; @@ -162,8 +163,7 @@ SRSLTE_API int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q, int rv_idx[SRSLTE_MAX_CODEWORDS], uint32_t sf_idx, uint8_t *data[SRSLTE_MAX_CODEWORDS], - srslte_mimo_type_t mimo_type, - uint32_t pmi); + srslte_mimo_type_t mimo_type); SRSLTE_API int srslte_enb_dl_put_pdcch_dl(srslte_enb_dl_t *q, srslte_ra_dl_dci_t *grant, diff --git a/lib/src/phy/enb/enb_dl.c b/lib/src/phy/enb/enb_dl.c index d0db1f553..b845b4c8a 100644 --- a/lib/src/phy/enb/enb_dl.c +++ b/lib/src/phy/enb/enb_dl.c @@ -326,8 +326,30 @@ int srslte_enb_dl_put_pdcch_ul(srslte_enb_dl_t *q, srslte_ra_ul_dci_t *grant, int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q, srslte_ra_dl_grant_t *grant, srslte_softbuffer_tx_t *softbuffer[SRSLTE_MAX_CODEWORDS], uint16_t rnti, int rv_idx[SRSLTE_MAX_CODEWORDS], uint32_t sf_idx, - uint8_t *data[SRSLTE_MAX_CODEWORDS], srslte_mimo_type_t mimo_type, uint32_t pmi) + uint8_t *data[SRSLTE_MAX_CODEWORDS], srslte_mimo_type_t mimo_type) { + uint32_t pmi = 0; + uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(grant); + + /* Translates Precoding Information (pinfo) to Precoding matrix Index (pmi) as 3GPP 36.212 Table 5.3.3.1.5-4 */ + if (mimo_type == SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX) { + if (nof_tb == 1) { + if (grant->pinfo > 0 && grant->pinfo < 5) { + pmi = grant->pinfo - 1; + } else { + ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo); + return SRSLTE_ERROR; + } + } else { + if (grant->pinfo < 2) { + pmi = grant->pinfo; + } else { + ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo); + return SRSLTE_ERROR; + } + } + } + /* Configure pdsch_cfg parameters */ if (srslte_pdsch_cfg_mimo(&q->pdsch_cfg, q->cell, grant, q->cfi, sf_idx, rv_idx, mimo_type, pmi)) { fprintf(stderr, "Error configuring PDSCH\n"); diff --git a/lib/src/phy/enb/enb_ul.c b/lib/src/phy/enb/enb_ul.c index b669b31e1..c9c557a02 100644 --- a/lib/src/phy/enb/enb_ul.c +++ b/lib/src/phy/enb/enb_ul.c @@ -323,9 +323,17 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti, memcpy(uci_data->uci_cqi, pucch_bits, uci_data->uci_cqi_len*sizeof(uint8_t)); } + if (uci_data->uci_dif_cqi_len) { + memcpy(uci_data->uci_dif_cqi, pucch_bits + uci_data->uci_cqi_len, uci_data->uci_dif_cqi_len*sizeof(uint8_t)); + } + + if (uci_data->uci_pmi_len) { + memcpy(uci_data->uci_pmi, pucch_bits + uci_data->uci_cqi_len + uci_data->uci_dif_cqi_len, + uci_data->uci_pmi_len*sizeof(uint8_t)); + } + if (uci_data->uci_ri_len) { - uint8_t *ptr = pucch_bits; - uci_data->uci_ri = (uint8_t) srslte_bit_pack(&ptr, uci_data->uci_ri_len); + uci_data->uci_ri = pucch_bits[0]; /* Assume only one bit of RI */ } if (uci_data->uci_cqi_len || uci_data->uci_ri_len) { diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index c4e2d3f6c..1bef04981 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -677,6 +677,7 @@ int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, uint8_t *ri, uint8_t *pmi, flo } /* Set RI */ + q->ri = best_ri; if (ri != NULL) { *ri = best_ri; } @@ -712,9 +713,10 @@ int srslte_ue_dl_ri_select(srslte_ue_dl_t *q, uint8_t *ri, float *cn) { *cn = _cn; } + q->ri = (uint8_t)((_cn < 17.0f)? 1:0); /* Set rank indicator */ if (!ret && ri) { - *ri = (uint8_t)((_cn < 17.0f)? 1:0); + *ri = (uint8_t) q->ri; } return ret; diff --git a/lib/src/phy/ue/ue_ul.c b/lib/src/phy/ue/ue_ul.c index 479299bd7..03b53c40a 100644 --- a/lib/src/phy/ue/ue_ul.c +++ b/lib/src/phy/ue/ue_ul.c @@ -281,8 +281,9 @@ void pucch_encode_bits(srslte_uci_data_t *uci_data, srslte_pucch_format_t format } if (format >= SRSLTE_PUCCH_FORMAT_2) { /* Append RI */ - uint8_t *ptr = uci_buffer; - srslte_bit_unpack(uci_data->uci_ri, &ptr, uci_data->uci_ri_len); + if (uci_data->uci_ri_len) { + uci_data->uci_ri = uci_buffer[0]; // It assumes only 1 bit of RI + } uci_buffer_len += uci_data->uci_ri_len; /* Append CQI */ diff --git a/srsenb/hdr/mac/mac.h b/srsenb/hdr/mac/mac.h index c3df1c9be..14269b0eb 100644 --- a/srsenb/hdr/mac/mac.h +++ b/srsenb/hdr/mac/mac.h @@ -72,7 +72,10 @@ public: int sr_detected(uint32_t tti, uint16_t rnti); int rach_detected(uint32_t tti, uint32_t preamble_idx, uint32_t time_adv); + int set_dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dl_ant_info); + int ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value); + int pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value); int cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value); int snr_info(uint32_t tti, uint16_t rnti, float snr); int ack_info(uint32_t tti, uint16_t rnti, bool ack); diff --git a/srsenb/hdr/mac/mac_metrics.h b/srsenb/hdr/mac/mac_metrics.h index ba5821ea9..e11eda350 100644 --- a/srsenb/hdr/mac/mac_metrics.h +++ b/srsenb/hdr/mac/mac_metrics.h @@ -45,6 +45,7 @@ struct mac_metrics_t int dl_buffer; float dl_cqi; float dl_ri; + float dl_pmi; float phr; }; diff --git a/srsenb/hdr/mac/scheduler.h b/srsenb/hdr/mac/scheduler.h index f9316b139..898997449 100644 --- a/srsenb/hdr/mac/scheduler.h +++ b/srsenb/hdr/mac/scheduler.h @@ -103,9 +103,11 @@ public: int dl_rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue); int dl_mac_buffer_state(uint16_t rnti, uint32_t ce_code); + int dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dedicated); int dl_ack_info(uint32_t tti, uint16_t rnti, bool ack); int dl_rach_info(uint32_t tti, uint32_t ra_id, uint16_t rnti, uint32_t estimated_size); int dl_ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value); + int dl_pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value); int dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value); int ul_crc_info(uint32_t tti, uint16_t rnti, bool crc); diff --git a/srsenb/hdr/mac/scheduler_harq.h b/srsenb/hdr/mac/scheduler_harq.h index 2e09136f9..9e1c65c78 100644 --- a/srsenb/hdr/mac/scheduler_harq.h +++ b/srsenb/hdr/mac/scheduler_harq.h @@ -38,50 +38,50 @@ class harq_proc public: void config(uint32_t id, uint32_t max_retx, srslte::log* log_h); void set_max_retx(uint32_t max_retx); - void reset(); + void reset(uint32_t tb_idx); uint32_t get_id(); - bool is_empty(); + bool is_empty(uint32_t tb_idx); - void new_retx(uint32_t tti, int *mcs, int *tbs); + void new_retx(uint32_t tb_idx, uint32_t tti, int *mcs, int *tbs); - bool get_ack(); - void set_ack(bool ack); + bool get_ack(uint32_t tb_idx); + void set_ack(uint32_t tb_idx, bool ack); - uint32_t nof_tx(); - uint32_t nof_retx(); + uint32_t nof_tx(uint32_t tb_idx); + uint32_t nof_retx(uint32_t tb_idx); uint32_t get_tti(); - bool get_ndi(); + bool get_ndi(uint32_t tb_idx); protected: - void new_tx_common(uint32_t tti, int mcs, int tbs); - bool has_pending_retx_common(); + void new_tx_common(uint32_t tb_idx, uint32_t tti, int mcs, int tbs); + bool has_pending_retx_common(uint32_t tb_idx); - bool ack; + bool ack[SRSLTE_MAX_TB]; bool active; - bool ndi; + bool ndi[SRSLTE_MAX_TB]; uint32_t id; uint32_t max_retx; - uint32_t n_rtx; - uint32_t tx_cnt; + uint32_t n_rtx[SRSLTE_MAX_TB]; + uint32_t tx_cnt[SRSLTE_MAX_TB]; int tti; - int last_mcs; - int last_tbs; + int last_mcs[SRSLTE_MAX_TB]; + int last_tbs[SRSLTE_MAX_TB]; srslte::log* log_h; private: - bool ack_received; + bool ack_received[SRSLTE_MAX_TB]; }; class dl_harq_proc : public harq_proc { public: - void new_tx(uint32_t tti, int mcs, int tbs, uint32_t n_cce); + void new_tx(uint32_t tb_idx, uint32_t tti, int mcs, int tbs, uint32_t n_cce); uint32_t get_rbgmask(); void set_rbgmask(uint32_t new_mask); - bool has_pending_retx(uint32_t tti); - int get_tbs(); + bool has_pending_retx(uint32_t tb_idx, uint32_t tti); + int get_tbs(uint32_t tb_idx); uint32_t get_n_cce(); private: uint32_t rbgmask; diff --git a/srsenb/hdr/mac/scheduler_ue.h b/srsenb/hdr/mac/scheduler_ue.h index 4e4b28698..8b0304b09 100644 --- a/srsenb/hdr/mac/scheduler_ue.h +++ b/srsenb/hdr/mac/scheduler_ue.h @@ -68,8 +68,10 @@ public: void ul_phr(int phr); void mac_buffer_state(uint32_t ce_code); void ul_recv_len(uint32_t lcid, uint32_t len); + void set_dl_ant_info(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dedicated); void set_ul_cqi(uint32_t tti, uint32_t cqi, uint32_t ul_ch_code); void set_dl_ri(uint32_t tti, uint32_t ri); + void set_dl_pmi(uint32_t tti, uint32_t ri); void set_dl_cqi(uint32_t tti, uint32_t cqi); int set_ack_info(uint32_t tti, bool ack); void set_ul_crc(uint32_t tti, bool crc_res); @@ -107,9 +109,12 @@ public: void set_sr(); void unset_sr(); - int generate_format1(dl_harq_proc *h, sched_interface::dl_sched_data_t *data, uint32_t tti, uint32_t cfi); - int generate_format0(ul_harq_proc *h, sched_interface::ul_sched_data_t *data, uint32_t tti, bool cqi_request); - + int generate_format1(dl_harq_proc *h, sched_interface::dl_sched_data_t *data, uint32_t tti, uint32_t cfi); + int generate_format2a(dl_harq_proc *h, sched_interface::dl_sched_data_t *data, uint32_t tti, uint32_t cfi); + int generate_format2(dl_harq_proc *h, sched_interface::dl_sched_data_t *data, uint32_t tti, uint32_t cfi); + int generate_format0(ul_harq_proc *h, sched_interface::ul_sched_data_t *data, uint32_t tti, bool cqi_request); + + srslte_dci_format_t get_dci_format(); uint32_t get_aggr_level(uint32_t nof_bits); sched_dci_cce_t *get_locations(uint32_t current_cfi, uint32_t sf_idx); @@ -158,6 +163,8 @@ private: int power_headroom; uint32_t dl_ri; uint32_t dl_ri_tti; + uint32_t dl_pmi; + uint32_t dl_pmi_tti; uint32_t dl_cqi; uint32_t dl_cqi_tti; uint32_t cqi_request_tti; @@ -180,7 +187,8 @@ private: ul_harq_proc ul_harq[SCHED_MAX_HARQ_PROC]; bool phy_config_dedicated_enabled; - + LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT dl_ant_info; + }; } diff --git a/srsenb/hdr/mac/ue.h b/srsenb/hdr/mac/ue.h index 4b65063d5..3974ca52b 100644 --- a/srsenb/hdr/mac/ue.h +++ b/srsenb/hdr/mac/ue.h @@ -94,6 +94,7 @@ public: void metrics_tx(bool crc, uint32_t tbs); void metrics_phr(float phr); void metrics_dl_ri(uint32_t dl_cqi); + void metrics_dl_pmi(uint32_t dl_cqi); void metrics_dl_cqi(uint32_t dl_cqi); @@ -110,6 +111,7 @@ private: uint32_t phr_counter; uint32_t dl_cqi_counter; uint32_t dl_ri_counter; + uint32_t dl_pmi_counter; mac_metrics_t metrics; srslte::mac_pcap* pcap; diff --git a/srsenb/src/mac/mac.cc b/srsenb/src/mac/mac.cc index 23c2557ba..d1e6e01b4 100644 --- a/srsenb/src/mac/mac.cc +++ b/srsenb/src/mac/mac.cc @@ -305,6 +305,18 @@ int mac::crc_info(uint32_t tti, uint16_t rnti, uint32_t nof_bytes, bool crc) } } +int mac::set_dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dl_ant_info) { + log_h->step(tti); + + if (ue_db.count(rnti)) { + scheduler.dl_ant_info(rnti, dl_ant_info); + } else { + Error("User rnti=0x%x not found\n", rnti); + return -1; + } + return 0; +} + int mac::ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value) { log_h->step(tti); @@ -319,6 +331,20 @@ int mac::ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value) return 0; } +int mac::pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value) +{ + log_h->step(tti); + + if (ue_db.count(rnti)) { + scheduler.dl_pmi_info(tti, rnti, pmi_value); + ue_db[rnti]->metrics_dl_pmi(pmi_value); + } else { + Error("User rnti=0x%x not found\n", rnti); + return -1; + } + return 0; +} + int mac::cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) { log_h->step(tti); @@ -445,6 +471,7 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) // Copy grant info dl_sched_res->sched_grants[n].rnti = rnti; + dl_sched_res->sched_grants[n].dci_format = sched_result.data[i].dci_format; memcpy(&dl_sched_res->sched_grants[n].grant, &sched_result.data[i].dci, sizeof(srslte_ra_dl_dci_t)); memcpy(&dl_sched_res->sched_grants[n].location, &sched_result.data[i].dci_location, sizeof(srslte_dci_location_t)); @@ -454,10 +481,10 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) if (sched_result.data[i].nof_pdu_elems > 0) { dl_sched_res->sched_grants[n].data[0] = ue_db[rnti]->generate_pdu(sched_result.data[i].pdu, sched_result.data[i].nof_pdu_elems, - sched_result.data[i].tbs); + sched_result.data[i].tbs[0]); if (pcap) { - pcap->write_dl_crnti(dl_sched_res->sched_grants[n].data[0], sched_result.data[i].tbs, rnti, true, tti); + pcap->write_dl_crnti(dl_sched_res->sched_grants[n].data[0], sched_result.data[i].tbs[0], rnti, true, tti); } } else { @@ -469,7 +496,8 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) // Copy RAR grants for (uint32_t i=0;isched_grants[n].rnti = sched_result.rar[i].rarnti; + dl_sched_res->sched_grants[n].rnti = sched_result.rar[i].rarnti; + dl_sched_res->sched_grants[n].dci_format = SRSLTE_DCI_FORMAT1A; // Force Format 1A memcpy(&dl_sched_res->sched_grants[n].grant, &sched_result.rar[i].dci, sizeof(srslte_ra_dl_dci_t)); memcpy(&dl_sched_res->sched_grants[n].location, &sched_result.rar[i].dci_location, sizeof(srslte_dci_location_t)); @@ -481,7 +509,7 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) if (pcap) { - pcap->write_dl_ranti(dl_sched_res->sched_grants[n].data[0], sched_result.data[i].tbs, dl_sched_res->sched_grants[n].rnti, true, tti); + pcap->write_dl_ranti(dl_sched_res->sched_grants[n].data[0], sched_result.data[i].tbs[0], dl_sched_res->sched_grants[n].rnti, true, tti); } n++; @@ -490,7 +518,8 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) // Copy SI and Paging grants for (uint32_t i=0;isched_grants[n].rnti = (sched_result.bc[i].type == sched_interface::dl_sched_bc_t::BCCH ) ? SRSLTE_SIRNTI : SRSLTE_PRNTI; + dl_sched_res->sched_grants[n].rnti = (sched_result.bc[i].type == sched_interface::dl_sched_bc_t::BCCH ) ? SRSLTE_SIRNTI : SRSLTE_PRNTI; + dl_sched_res->sched_grants[n].dci_format = SRSLTE_DCI_FORMAT1A; // Force Format 1A memcpy(&dl_sched_res->sched_grants[n].grant, &sched_result.bc[i].dci, sizeof(srslte_ra_dl_dci_t)); memcpy(&dl_sched_res->sched_grants[n].location, &sched_result.bc[i].dci_location, sizeof(srslte_dci_location_t)); diff --git a/srsenb/src/mac/scheduler.cc b/srsenb/src/mac/scheduler.cc index 298ce9625..dd787a28d 100644 --- a/srsenb/src/mac/scheduler.cc +++ b/srsenb/src/mac/scheduler.cc @@ -238,6 +238,19 @@ int sched::dl_mac_buffer_state(uint16_t rnti, uint32_t ce_code) return ret; } +int sched::dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dl_ant_info) { + pthread_mutex_lock(&mutex); + int ret = 0; + if (ue_db.count(rnti)) { + ue_db[rnti].set_dl_ant_info(dl_ant_info); + } else { + Error("User rnti=0x%x not found\n", rnti); + ret = -1; + } + pthread_mutex_unlock(&mutex); + return ret; +} + int sched::dl_ack_info(uint32_t tti, uint16_t rnti, bool ack) { pthread_mutex_lock(&mutex); @@ -280,6 +293,20 @@ int sched::dl_ri_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) return ret; } +int sched::dl_pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value) +{ + pthread_mutex_lock(&mutex); + int ret = 0; + if (ue_db.count(rnti)) { + ue_db[rnti].set_dl_pmi(tti, pmi_value); + } else { + Error("User rnti=0x%x not found\n", rnti); + ret = -1; + } + pthread_mutex_unlock(&mutex); + return ret; +} + int sched::dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) { pthread_mutex_lock(&mutex); @@ -611,19 +638,34 @@ 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); - + srslte_dci_format_t dci_format = user->get_dci_format(); + data[nof_data_elems].dci_format = dci_format; + 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_aggr_level(srslte_dci_format_sizeof(dci_format, cfg.cell.nof_prb, cfg.cell.nof_ports)), user)) { - bool is_newtx = h->is_empty(); - int tbs = user->generate_format1(h, &data[nof_data_elems], current_tti, current_cfi); + bool is_newtx = h->is_empty(0); + int tbs = 0; + switch(dci_format) { + case SRSLTE_DCI_FORMAT1: + tbs = user->generate_format1(h, &data[nof_data_elems], current_tti, current_cfi); + break; + case SRSLTE_DCI_FORMAT2: + tbs = user->generate_format2(h, &data[nof_data_elems], current_tti, current_cfi); + break; + case SRSLTE_DCI_FORMAT2A: + tbs = user->generate_format2a(h, &data[nof_data_elems], current_tti, current_cfi); + break; + default: + Error("DCI format (%d) not implemented\n", dci_format); + } if (tbs >= 0) { log_h->info("SCHED: DL %s rnti=0x%x, pid=%d, mask=0x%x, dci=%d,%d, n_rtx=%d, tbs=%d, buffer=%d\n", !is_newtx?"retx":"tx", rnti, h->get_id(), h->get_rbgmask(), - data[nof_data_elems].dci_location.L, data[nof_data_elems].dci_location.ncce, h->nof_retx(), + data[nof_data_elems].dci_location.L, data[nof_data_elems].dci_location.ncce, h->nof_retx(0), tbs, user->get_pending_dl_new_data(current_tti)); nof_data_elems++; } else { @@ -633,7 +675,7 @@ int sched::dl_sched_data(dl_sched_data_t data[MAX_DATA_LIST]) tbs, user->get_pending_dl_new_data(current_tti)); } } else { - h->reset(); + h->reset(0); Warning("SCHED: Could not schedule DL DCI for rnti=0x%x, pid=%d\n", rnti, h->get_id()); } } @@ -721,7 +763,7 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched /* Indicate PHICH acknowledgment if needed */ if (h->has_pending_ack()) { - sched_result->phich[nof_phich_elems].phich = h->get_ack()?ul_sched_phich_t::ACK:ul_sched_phich_t::NACK; + sched_result->phich[nof_phich_elems].phich = h->get_ack(0)?ul_sched_phich_t::ACK:ul_sched_phich_t::NACK; sched_result->phich[nof_phich_elems].rnti = rnti; nof_phich_elems++; } @@ -778,7 +820,7 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched if (h) { ul_harq_proc::ul_alloc_t alloc = h->get_alloc(); - bool is_newtx = h->is_empty(); + bool is_newtx = h->is_empty(0); bool needs_pdcch = !h->is_adaptive_retx() && !is_rar; // Set number of retx @@ -797,7 +839,7 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched user->get_locations(current_cfi, sf_idx), aggr_level)) { - h->reset(); + h->reset(0); log_h->warning("SCHED: Could not schedule UL DCI rnti=0x%x, pid=%d, L=%d\n", rnti, h->get_id(), aggr_level); sched_result->pusch[nof_dci_elems].needs_pdcch = false; @@ -824,7 +866,7 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched is_newtx?"tx":"retx", rnti, h->get_id(), sched_result->pusch[nof_dci_elems].dci_location.L, sched_result->pusch[nof_dci_elems].dci_location.ncce, - alloc.RB_start, alloc.RB_start+alloc.L, h->nof_retx(), sched_result->pusch[nof_dci_elems].tbs, + alloc.RB_start, alloc.RB_start+alloc.L, h->nof_retx(0), sched_result->pusch[nof_dci_elems].tbs, user->get_pending_ul_new_data(current_tti),pending_data_before, user->get_pending_ul_old_data()); nof_dci_elems++; diff --git a/srsenb/src/mac/scheduler_harq.cc b/srsenb/src/mac/scheduler_harq.cc index a6ae70d19..cbb66c669 100644 --- a/srsenb/src/mac/scheduler_harq.cc +++ b/srsenb/src/mac/scheduler_harq.cc @@ -50,7 +50,9 @@ void harq_proc::config(uint32_t id_, uint32_t max_retx_, srslte::log* log_h_) log_h = log_h_; id = id_; max_retx = max_retx_; - ndi = false; + for (int i = 0; i < SRSLTE_MAX_TB; i++) { + ndi[i] = false; + } } void harq_proc::set_max_retx(uint32_t max_retx_) { @@ -63,57 +65,57 @@ uint32_t harq_proc::get_id() return id; } -void harq_proc::reset() +void harq_proc::reset(uint32_t tb_idx) { active = false; - ack = true; - ack_received = false; - n_rtx = 0; + ack[tb_idx] = true; + ack_received[tb_idx] = false; + n_rtx[tb_idx] = 0; tti = 0; - last_mcs = -1; - last_tbs = -1; - tx_cnt = 0; + last_mcs[tb_idx] = -1; + last_tbs[tb_idx] = -1; + tx_cnt[tb_idx] = 0; } -bool harq_proc::is_empty() +bool harq_proc::is_empty(uint32_t tb_idx) { - return !active || (active && ack && ack_received); + return !active || (active && ack[tb_idx] && ack_received[tb_idx]); } -bool harq_proc::has_pending_retx_common() +bool harq_proc::has_pending_retx_common(uint32_t tb_idx) { - return !ack && n_rtx < max_retx; + return !ack[tb_idx] && n_rtx[tb_idx] < max_retx; } uint32_t harq_proc::get_tti() { - return tti; + return (uint32_t) tti; } -bool harq_proc::get_ack() +bool harq_proc::get_ack(uint32_t tb_idx) { - return ack; + return ack[tb_idx]; } -void harq_proc::set_ack(bool ack_) +void harq_proc::set_ack(uint32_t tb_idx, bool ack_) { - ack = ack_; - ack_received = true; - log_h->debug("ACK=%d received pid=%d, n_rtx=%d, max_retx=%d\n", ack_, id, n_rtx, max_retx); - if (n_rtx + 1 >= max_retx) { - Warning("SCHED: discarting TB pid=%d, tti=%d, maximum number of retx exceeded (%d)\n", id, tti, max_retx); + ack[tb_idx] = ack_; + ack_received[tb_idx] = true; + log_h->debug("ACK=%d received pid=%d, tb_idx=%d, n_rtx=%d, max_retx=%d\n", ack_, id, tb_idx, n_rtx[tb_idx], max_retx); + if (n_rtx[tb_idx] + 1 >= max_retx) { + Warning("SCHED: discarting TB %d pid=%d, tti=%d, maximum number of retx exceeded (%d)\n", tb_idx, id, tti, max_retx); active = false; } } -void harq_proc::new_tx_common(uint32_t tti_, int mcs, int tbs) +void harq_proc::new_tx_common(uint32_t tb_idx, uint32_t tti_, int mcs, int tbs) { - reset(); - ndi = !ndi; + reset(tb_idx); + ndi[tb_idx] = !ndi[tb_idx]; tti = tti_; - tx_cnt++; - last_mcs = mcs; - last_tbs = tbs; + tx_cnt[tb_idx]++; + last_mcs[tb_idx] = mcs; + last_tbs[tb_idx] = tbs; if (max_retx) { active = true; @@ -122,42 +124,42 @@ void harq_proc::new_tx_common(uint32_t tti_, int mcs, int tbs) } } -void harq_proc::new_retx(uint32_t tti_, int *mcs, int *tbs) +void harq_proc::new_retx(uint32_t tb_idx, uint32_t tti_, int *mcs, int *tbs) { - ack_received = false; + ack_received[tb_idx] = false; tti = tti_; - n_rtx++; + n_rtx[tb_idx]++; if (mcs) { - *mcs = last_mcs; + *mcs = last_mcs[tb_idx]; } if (tbs) { - *tbs = last_tbs; + *tbs = last_tbs[tb_idx]; } } -uint32_t harq_proc::nof_tx() +uint32_t harq_proc::nof_tx(uint32_t tb_idx) { - return tx_cnt; + return tx_cnt[tb_idx]; } -uint32_t harq_proc::nof_retx() +uint32_t harq_proc::nof_retx(uint32_t tb_idx) { - return n_rtx; + return n_rtx[tb_idx]; } -bool harq_proc::get_ndi() +bool harq_proc::get_ndi(uint32_t tb_idx) { - return ndi; + return ndi[tb_idx]; } /****************************************************** * UE::DL HARQ class * ******************************************************/ -void dl_harq_proc::new_tx(uint32_t tti, int mcs, int tbs, uint32_t n_cce_) +void dl_harq_proc::new_tx(uint32_t tb_idx, uint32_t tti, int mcs, int tbs, uint32_t n_cce_) { n_cce = n_cce_; - new_tx_common(tti, mcs, tbs); + new_tx_common(tb_idx, tti, mcs, tbs); } uint32_t dl_harq_proc::get_n_cce() @@ -175,14 +177,14 @@ void dl_harq_proc::set_rbgmask(uint32_t new_mask) rbgmask = new_mask; } -bool dl_harq_proc::has_pending_retx(uint32_t current_tti) +bool dl_harq_proc::has_pending_retx(uint32_t tb_idx, uint32_t current_tti) { - return srslte_tti_interval(current_tti, tti) >= 8 && has_pending_retx_common(); + return srslte_tti_interval(current_tti, tti) >= 8 && has_pending_retx_common(tb_idx); } -int dl_harq_proc::get_tbs() +int dl_harq_proc::get_tbs(uint32_t tb_idx) { - return last_tbs; + return last_tbs[tb_idx]; } @@ -215,7 +217,7 @@ bool ul_harq_proc::is_adaptive_retx() void ul_harq_proc::new_tx(uint32_t tti_, int mcs, int tbs) { need_ack = true; - new_tx_common(tti_, mcs, tbs); + new_tx_common(0, tti_, mcs, tbs); pending_data = tbs; } @@ -225,7 +227,7 @@ bool ul_harq_proc::has_pending_ack() bool ret = need_ack; // Reset if already received a positive ACK - if (active && ack) { + if (active && ack[0]) { active = false; } if (!active) { @@ -244,9 +246,9 @@ void ul_harq_proc::reset_pending_data() } - uint32_t ul_harq_proc::get_pending_data() +uint32_t ul_harq_proc::get_pending_data() { - return pending_data; + return (uint32_t) pending_data; } void ul_harq_proc::set_rar_mcs(uint32_t mcs) diff --git a/srsenb/src/mac/scheduler_metric.cc b/srsenb/src/mac/scheduler_metric.cc index 708ab2dd8..ee3f44e6f 100644 --- a/srsenb/src/mac/scheduler_metric.cc +++ b/srsenb/src/mac/scheduler_metric.cc @@ -212,7 +212,7 @@ void ul_metric_rr::new_tti(std::map &ue_db, uint32_t nof_rb_, nof_users_with_data = 0; for(std::map::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) { sched_ue *user = (sched_ue*) &iter->second; - if (user->get_pending_ul_new_data(current_tti) || !user->get_ul_harq(current_tti)->is_empty()) { + if (user->get_pending_ul_new_data(current_tti) || !user->get_ul_harq(current_tti)->is_empty(0)) { user->ue_idx = nof_users_with_data; nof_users_with_data++; } @@ -284,7 +284,7 @@ ul_harq_proc* ul_metric_rr::get_user_allocation(sched_ue *user) uint32_t pending_data = user->get_pending_ul_new_data(current_tti); ul_harq_proc *h = user->get_ul_harq(current_tti); - if (pending_data || !h->is_empty()) { + if (pending_data || !h->is_empty(0)) { if (nof_users_with_data) { if ((current_tti%nof_users_with_data) != user->ue_idx) { return NULL; @@ -294,7 +294,7 @@ ul_harq_proc* ul_metric_rr::get_user_allocation(sched_ue *user) // Schedule retx if we have space - if (!h->is_empty()) { + if (!h->is_empty(0)) { ul_harq_proc::ul_alloc_t alloc = h->get_alloc(); @@ -313,7 +313,7 @@ ul_harq_proc* ul_metric_rr::get_user_allocation(sched_ue *user) } } // If could not schedule the reTx, or there wasn't any pending retx, find an empty PID - if (h->is_empty()) { + if (h->is_empty(0)) { // Allocate resources based on pending data if (pending_data) { uint32_t pending_rb = user->get_required_prb_ul(pending_data); diff --git a/srsenb/src/mac/scheduler_ue.cc b/srsenb/src/mac/scheduler_ue.cc index 8abb86d88..974791957 100644 --- a/srsenb/src/mac/scheduler_ue.cc +++ b/srsenb/src/mac/scheduler_ue.cc @@ -109,8 +109,8 @@ void sched_ue::reset() ul_cqi_tti = 0; cqi_request_tti = 0; for (int i=0;iset_ack(crc_res); + get_ul_harq(tti)->set_ack(0, crc_res); } void sched_ue::set_dl_ri(uint32_t tti, uint32_t ri) @@ -329,10 +329,21 @@ void sched_ue::set_dl_ri(uint32_t tti, uint32_t ri) dl_ri_tti = tti; } +void sched_ue::set_dl_pmi(uint32_t tti, uint32_t pmi) +{ + dl_pmi = pmi; + dl_pmi_tti = tti; +} + void sched_ue::set_dl_cqi(uint32_t tti, uint32_t cqi) { - dl_cqi = cqi; - dl_cqi_tti = tti; + dl_cqi = cqi; + dl_cqi_tti = tti; +} + +void sched_ue::set_dl_ant_info(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *d) +{ + memcpy(&dl_ant_info, d, sizeof(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT)); } void sched_ue::set_ul_cqi(uint32_t tti, uint32_t cqi, uint32_t ul_ch_code) @@ -363,10 +374,10 @@ void sched_ue::tpc_dec() { // Generates a Format1 grant -int sched_ue::generate_format1(dl_harq_proc *h, - sched_interface::dl_sched_data_t *data, - uint32_t tti, - uint32_t cfi) +int sched_ue::generate_format1(dl_harq_proc *h, + sched_interface::dl_sched_data_t *data, + uint32_t tti, + uint32_t cfi) { srslte_ra_dl_dci_t *dci = &data->dci; bzero(dci, sizeof(srslte_ra_dl_dci_t)); @@ -385,7 +396,7 @@ int sched_ue::generate_format1(dl_harq_proc *h, if (is_first_dl_tx()) { need_conres_ce = true; } - if (h->is_empty()) { + if (h->is_empty(0)) { uint32_t req_bytes = get_pending_dl_new_data(tti); @@ -401,11 +412,11 @@ int sched_ue::generate_format1(dl_harq_proc *h, mcs = fixed_mcs_dl; } - h->new_tx(tti, mcs, tbs, data->dci_location.ncce); + h->new_tx(0, tti, mcs, tbs, data->dci_location.ncce); Debug("SCHED: Alloc format1 new mcs=%d, tbs=%d, nof_prb=%d, req_bytes=%d\n", mcs, tbs, nof_prb, req_bytes); } else { - h->new_retx(tti, &mcs, &tbs); + h->new_retx(0, tti, &mcs, &tbs); Debug("SCHED: Alloc format1 previous mcs=%d, tbs=%d\n", mcs, tbs); } @@ -431,19 +442,159 @@ int sched_ue::generate_format1(dl_harq_proc *h, if (tbs > 0) { dci->harq_process = h->get_id(); dci->mcs_idx = mcs; - dci->rv_idx = sched::get_rvidx(h->nof_retx()); - dci->ndi = h->get_ndi(); - dci->tpc_pucch = next_tpc_pucch; + dci->rv_idx = sched::get_rvidx(h->nof_retx(0)); + dci->ndi = h->get_ndi(0); + dci->tpc_pucch = next_tpc_pucch; next_tpc_pucch = 1; - data->tbs = tbs; + data->tbs[0] = tbs; dci->tb_en[0] = true; dci->tb_en[1] = false; } return tbs; } +// Generates a Format2a grant +int sched_ue::generate_format2a(dl_harq_proc *h, + sched_interface::dl_sched_data_t *data, + uint32_t tti, + uint32_t cfi) +{ + srslte_ra_dl_dci_t *dci = &data->dci; + bzero(dci, sizeof(srslte_ra_dl_dci_t)); + + uint32_t sf_idx = tti%10; + + int mcs = 0; + int tbs = 0; + + dci->alloc_type = SRSLTE_RA_ALLOC_TYPE0; + dci->type0_alloc.rbg_bitmask = h->get_rbgmask(); + + if (h->is_empty(0)) { + + uint32_t req_bytes = get_pending_dl_new_data(tti); + + uint32_t nof_prb = format1_count_prb(h->get_rbgmask(), cell.nof_prb); + srslte_ra_dl_grant_t grant; + srslte_ra_dl_dci_to_grant_prb_allocation(dci, &grant, cell.nof_prb); + uint32_t nof_ctrl_symbols = cfi+(cell.nof_prb<10?1:0); + uint32_t nof_re = srslte_ra_dl_grant_nof_re(&grant, cell, sf_idx, nof_ctrl_symbols); + if (fixed_mcs_dl < 0) { + tbs = alloc_tbs_dl(nof_prb, nof_re, req_bytes, &mcs); + } else { + tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_dl), nof_prb)/8; + mcs = fixed_mcs_dl; + } + + h->new_tx(0, tti, mcs, tbs, data->dci_location.ncce); + + Debug("SCHED: Alloc format1 new mcs=%d, tbs=%d, nof_prb=%d, req_bytes=%d\n", mcs, tbs, nof_prb, req_bytes); + } else { + h->new_retx(0, tti, &mcs, &tbs); + Debug("SCHED: Alloc format1 previous mcs=%d, tbs=%d\n", mcs, tbs); + } + + int rem_tbs = tbs; + int x = 0; + do { + x = alloc_pdu(rem_tbs, &data->pdu[data->nof_pdu_elems]); + rem_tbs -= x; + if (x) { + data->nof_pdu_elems++; + } + } while(rem_tbs > 0 && x > 0); + + data->rnti = rnti; + + if (tbs > 0) { + dci->harq_process = h->get_id(); + dci->mcs_idx = mcs; + dci->rv_idx = sched::get_rvidx(h->nof_retx(0)); + dci->ndi = h->get_ndi(0); + dci->tpc_pucch = next_tpc_pucch; + next_tpc_pucch = 1; + data->tbs[0] = tbs; + dci->tb_en[0] = true; + dci->tb_en[1] = false; + } + return tbs; +} -int sched_ue::generate_format0(ul_harq_proc *h, +// Generates a Format2 grant +int sched_ue::generate_format2(dl_harq_proc *h, + sched_interface::dl_sched_data_t *data, + uint32_t tti, + uint32_t cfi) +{ + srslte_ra_dl_dci_t *dci = &data->dci; + bzero(dci, sizeof(srslte_ra_dl_dci_t)); + + uint32_t sf_idx = tti%10; + + int mcs = 0; + int tbs = 0; + + dci->alloc_type = SRSLTE_RA_ALLOC_TYPE0; + dci->type0_alloc.rbg_bitmask = h->get_rbgmask(); + + if (h->is_empty(0)) { + + uint32_t req_bytes = get_pending_dl_new_data(tti); + + uint32_t nof_prb = format1_count_prb(h->get_rbgmask(), cell.nof_prb); + srslte_ra_dl_grant_t grant; + srslte_ra_dl_dci_to_grant_prb_allocation(dci, &grant, cell.nof_prb); + uint32_t nof_ctrl_symbols = cfi+(cell.nof_prb<10?1:0); + uint32_t nof_re = srslte_ra_dl_grant_nof_re(&grant, cell, sf_idx, nof_ctrl_symbols); + if (fixed_mcs_dl < 0) { + tbs = alloc_tbs_dl(nof_prb, nof_re, req_bytes, &mcs); + } else { + tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_dl), nof_prb)/8; + mcs = fixed_mcs_dl; + } + + h->new_tx(0, tti, mcs, tbs, data->dci_location.ncce); + + Debug("SCHED: Alloc format2 new mcs=%d, tbs=%d, nof_prb=%d, req_bytes=%d\n", mcs, tbs, nof_prb, req_bytes); + } else { + h->new_retx(0, tti, &mcs, &tbs); + Debug("SCHED: Alloc format2 previous mcs=%d, tbs=%d\n", mcs, tbs); + } + + int rem_tbs = tbs; + int x = 0; + do { + x = alloc_pdu(rem_tbs, &data->pdu[data->nof_pdu_elems]); + rem_tbs -= x; + if (x) { + data->nof_pdu_elems++; + } + } while(rem_tbs > 0 && x > 0); + + data->rnti = rnti; + + if (tbs > 0) { + dci->pinfo = (uint8_t) (dl_pmi + 1); +/* if (SRSLTE_RA_DL_GRANT_NOF_TB(dci) == 1) { + dci->pinfo = (uint8_t) (dl_pmi + 1); + } else { + dci->pinfo = (uint8_t) (dl_pmi & 1); + }*/ + dci->harq_process = h->get_id(); + dci->mcs_idx = mcs; + dci->rv_idx = sched::get_rvidx(h->nof_retx(0)); + dci->ndi = h->get_ndi(0); + dci->tpc_pucch = next_tpc_pucch; + next_tpc_pucch = 1; + data->tbs[0] = tbs; + dci->tb_en[0] = true; + dci->tb_en[1] = false; + } + return tbs; +} + + +int sched_ue::generate_format0(ul_harq_proc *h, sched_interface::ul_sched_data_t *data, uint32_t tti, bool cqi_request) @@ -459,7 +610,7 @@ int sched_ue::generate_format0(ul_harq_proc *h, if (h->get_rar_mcs(&mcs)) { tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs), allocation.L)/8; h->new_tx(tti, mcs, tbs); - } else if (h->is_empty()) { + } else if (h->is_empty(0)) { uint32_t req_bytes = get_pending_ul_new_data(tti); @@ -475,7 +626,7 @@ int sched_ue::generate_format0(ul_harq_proc *h, h->new_tx(tti, mcs, tbs); } else { - h->new_retx(tti, &mcs, NULL); + h->new_retx(0, tti, &mcs, NULL); tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs), allocation.L)/8; } @@ -486,8 +637,8 @@ int sched_ue::generate_format0(ul_harq_proc *h, dci->type2_alloc.L_crb = allocation.L; dci->type2_alloc.RB_start = allocation.RB_start; dci->mcs_idx = mcs; - dci->rv_idx = sched::get_rvidx(h->nof_retx()); - dci->ndi = h->get_ndi(); + dci->rv_idx = sched::get_rvidx(h->nof_retx(0)); + dci->ndi = h->get_ndi(0); dci->cqi_request = cqi_request; dci->freq_hop_fl = srslte_ra_ul_dci_t::SRSLTE_RA_PUSCH_HOP_DISABLED; dci->tpc_pusch = next_tpc_pusch; @@ -518,7 +669,7 @@ uint32_t sched_ue::get_max_retx() { bool sched_ue::is_first_dl_tx() { for (int i=0;i 0) { + if (dl_harq[i].nof_tx(0) > 0) { return false; } } @@ -666,7 +817,7 @@ dl_harq_proc* sched_ue::get_pending_dl_harq(uint32_t tti) int oldest_idx=-1; uint32_t oldest_tti = 0; for (int i=0;i oldest_tti) { oldest_idx = i; @@ -684,7 +835,7 @@ dl_harq_proc* sched_ue::get_pending_dl_harq(uint32_t tti) dl_harq_proc* sched_ue::get_empty_dl_harq() { for (int i=0;icell.nof_prb) * sizeof(cf_t)); } if (srslte_enb_dl_init(&enb_dl, phy->cell.nof_prb)) { fprintf(stderr, "Error initiating ENB DL\n"); @@ -566,6 +567,10 @@ int phch_worker::decode_pucch(uint32_t tti_rx) needs_cqi = true; cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND; uci_data.uci_cqi_len = srslte_cqi_size(&cqi_value); + if (tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { + //uci_data.uci_dif_cqi_len = 3; + uci_data.uci_pmi_len = 2; + } } } @@ -589,6 +594,17 @@ int phch_worker::decode_pucch(uint32_t tti_rx) srslte_cqi_value_unpack(uci_data.uci_cqi, &cqi_value); phy->mac->cqi_info(tti_rx, rnti, cqi_value.wideband.wideband_cqi); sprintf(cqi_ri_str, ", cqi=%d", cqi_value.wideband.wideband_cqi); + + if (uci_data.uci_pmi_len) { + uint8_t *ptr = uci_data.uci_pmi; + uint32_t packed_pmi = uci_data.uci_pmi[0]; + if (uci_data.uci_pmi_len > 1) { + packed_pmi = (packed_pmi << 1) + uci_data.uci_pmi[1]; + } + phy->mac->pmi_info(tti_rx, rnti, packed_pmi); + sprintf(cqi_ri_str, "%s, pmi=%c", cqi_ri_str, packed_pmi + 0x30); + } + } log_h->info("PUCCH: rnti=0x%x, corr=%.2f, n_pucch=%d, n_prb=%d%s%s%s\n", rnti, @@ -656,35 +672,16 @@ int phch_worker::encode_pdcch_dl(srslte_enb_dl_pdsch_t *grants, uint32_t nof_gra { /* For each grant... */ for (uint32_t i=0;irnti; if (rnti) { - bool dedicated_acknowledged = ue_db[grants[i].rnti].dedicated_ack; - bool antenna_info_present = ue_db[grants[i].rnti].dedicated.antenna_info_present; - LIBLTE_RRC_TRANSMISSION_MODE_ENUM tx_mode = ue_db[grants[i].rnti].dedicated.antenna_info_explicit_value.tx_mode; - - srslte_dci_format_t format = SRSLTE_DCI_FORMAT1; - switch(grants[i].grant.alloc_type) { - case SRSLTE_RA_ALLOC_TYPE0: - case SRSLTE_RA_ALLOC_TYPE1: - if (dedicated_acknowledged && antenna_info_present && tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) { - format = SRSLTE_DCI_FORMAT2A; - } else if (dedicated_acknowledged && antenna_info_present && tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { - format = SRSLTE_DCI_FORMAT2; - } else { - format = SRSLTE_DCI_FORMAT1; - } - break; - case SRSLTE_RA_ALLOC_TYPE2: - format = SRSLTE_DCI_FORMAT1A; - break; - } - if (srslte_enb_dl_put_pdcch_dl(&enb_dl, &grants[i].grant, format, grants[i].location, rnti, sf_idx)) { + if (srslte_enb_dl_put_pdcch_dl(&enb_dl, &grants[i].grant, grant->dci_format, grants[i].location, rnti, sf_idx)) { fprintf(stderr, "Error putting PDCCH %d\n",i); return SRSLTE_ERROR; - } + } if (LOG_THIS(rnti)) { - Info("PDCCH: DL DCI %s rnti=0x%x, cce_index=%d, L=%d, tti_tx=%d\n", srslte_dci_format_string(format), + Info("PDCCH: DL DCI %s rnti=0x%x, cce_index=%d, L=%d, tti_tx=%d\n", srslte_dci_format_string(grant->dci_format), rnti, grants[i].location.ncce, (1<info_hex(ptr, len, - "PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tbs=%d, mcs=%d, rv=%d, tti_tx=%d\n", + "PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tbs=%d, mcs=%d, rv=%d, tti_tx=%d, tx_scheme=%s%s\n", rnti, phy_grant.nof_prb, grant_str, grants[i].grant.harq_process, - phy_grant.mcs[0].tbs/8, phy_grant.mcs[0].idx, grants[i].grant.rv_idx, tti_tx); + phy_grant.mcs[0].tbs/8, phy_grant.mcs[0].idx, grants[i].grant.rv_idx, tti_tx, srslte_mimotype2str(mimo_type), pinfo_str); } int rv[SRSLTE_MAX_CODEWORDS] = {grants[i].grant.rv_idx, grants[i].grant.rv_idx_1}; - if (srslte_enb_dl_put_pdsch(&enb_dl, &phy_grant, grants[i].softbuffers, rnti, rv, sf_idx, grants[i].data, mimo_type, 0)) { + if (srslte_enb_dl_put_pdsch(&enb_dl, &phy_grant, grants[i].softbuffers, rnti, rv, sf_idx, grants[i].data, mimo_type)) { fprintf(stderr, "Error putting PDSCH %d\n",i); return SRSLTE_ERROR; } diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index 90e175095..54a8b2663 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -864,6 +864,7 @@ void rrc::ue::handle_rrc_con_setup_complete(LIBLTE_RRC_CONNECTION_SETUP_COMPLETE // Acknowledge Dedicated Configuration parent->phy->set_conf_dedicated_ack(rnti, true); + parent->mac->phy_config_enabled(rnti, true); if(has_tmsi) { parent->s1ap->initial_ue(rnti, pdu, m_tmsi, mmec); @@ -1211,7 +1212,8 @@ void rrc::ue::send_connection_setup(bool is_setup) // Configure PHY layer parent->phy->set_config_dedicated(rnti, phy_cfg); parent->phy->set_conf_dedicated_ack(rnti, false); - parent->mac->phy_config_enabled(rnti, true); + parent->mac->set_dl_ant_info(rnti, &phy_cfg->antenna_info_explicit_value); + parent->mac->phy_config_enabled(rnti, false); rr_cfg->drb_to_add_mod_list_size = 0; rr_cfg->drb_to_release_list_size = 0; diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 312ec57b1..4ccbbae69 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -374,7 +374,6 @@ void phch_worker::compute_ri() { float sinr = 0.0f; uint8 packed_pmi = 0; srslte_ue_dl_ri_pmi_select(&ue_dl, &uci_data.uci_ri, &packed_pmi, &sinr); - srslte_bit_unpack_vector(&packed_pmi, uci_data.uci_pmi, 2); if (uci_data.uci_ri == 0) { uci_data.uci_pmi_len = 2; uci_data.uci_dif_cqi_len = 0; @@ -382,6 +381,8 @@ void phch_worker::compute_ri() { uci_data.uci_pmi_len = 1; uci_data.uci_dif_cqi_len = 3; } + srslte_bit_unpack_vector(&packed_pmi, uci_data.uci_pmi, uci_data.uci_pmi_len); + Info("pmi=%d\n", packed_pmi); /* If only one antenna in TM4 print limitation warning */ if (ue_dl.nof_rx_antennas < 2) { @@ -615,9 +616,13 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL snprintf(timestr, 64, ", dec_time=%4d us", (int) t[0].tv_usec); #endif - snprintf(commonstr, 128, "PDSCH: l_crb=%2d, harq=%d, snr=%.1f dB, tx_scheme=%s", grant->nof_prb, harq_pid, - 10 * log10(srslte_chest_dl_get_snr(&ue_dl.chest)), srslte_mimotype2str(mimo_type)); + char pinfo_str[16] = {0}; + if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { + snprintf(pinfo_str, 15, ", pinfo=%x", grant->pinfo); + } + snprintf(commonstr, 128, "PDSCH: l_crb=%2d, harq=%d, snr=%.1f dB, tx_scheme=%s%s", grant->nof_prb, harq_pid, + 10 * log10(srslte_chest_dl_get_snr(&ue_dl.chest)), srslte_mimotype2str(mimo_type), pinfo_str); for (int i=0;itb_en[i]) { snprintf(tbstr[i], 128, ", TB%d: tbs=%d, mcs=%d, rv=%d, crc=%s, it=%d", @@ -826,6 +831,16 @@ void phch_worker::set_uci_periodic_cqi() } Info("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.wideband.wideband_cqi, phy->avg_snr_db); } + if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { + if (ue_dl.ri == 0) { + uci_data.uci_pmi_len = 2; + } else { + uci_data.uci_pmi_len = 1; + uci_data.uci_dif_cqi_len = 3; + } + uint8_t *ptr = uci_data.uci_pmi; + srslte_bit_unpack(ue_dl.pmi[ue_dl.ri], &ptr, uci_data.uci_pmi_len); + } uci_data.uci_cqi_len = srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi); rar_cqi_request = false; } From 50b196a04e019d8516fdca1efe79fb30e60ba803 Mon Sep 17 00:00:00 2001 From: Merlin Chlosta Date: Fri, 27 Oct 2017 16:18:55 +0200 Subject: [PATCH 093/242] Write SFN to MAC-LTE PCAP file --- lib/include/srslte/common/pcap.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) 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 */ From abbd2e0f85e932246ec382f4afa6f454031e06be Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 28 Oct 2017 14:33:01 -0700 Subject: [PATCH 094/242] return error on precoding error --- lib/src/phy/mimo/precoding.c | 2 +- lib/src/phy/phch/pdsch.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) 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/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index b438a2957..ddfcf3f86 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -677,8 +677,10 @@ 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) { From 9c04bf2848beb52b5b64ef2a6bba35570e89a5b5 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 28 Oct 2017 16:13:17 -0700 Subject: [PATCH 095/242] Removed metrics period from listener --- lib/include/srslte/common/metrics_hub.h | 6 +++--- srsue/hdr/metrics_csv.h | 4 +++- srsue/hdr/metrics_stdout.h | 4 +++- srsue/src/main.cc | 2 ++ srsue/src/metrics_csv.cc | 9 +++++++-- srsue/src/metrics_stdout.cc | 6 +++++- 6 files changed, 23 insertions(+), 8 deletions(-) diff --git a/lib/include/srslte/common/metrics_hub.h b/lib/include/srslte/common/metrics_hub.h index 66cc4acbd..a9b77d5f6 100644 --- a/lib/include/srslte/common/metrics_hub.h +++ b/lib/include/srslte/common/metrics_hub.h @@ -24,8 +24,8 @@ template 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 @@ -57,7 +57,7 @@ private: bzero(&metric, sizeof(metrics_t)); m->get_metrics(metric); for (uint32_t i=0;iset_metrics(metric, report_period_secs); + listeners[i]->set_metrics(metric); } } } 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/src/main.cc b/srsue/src/main.cc index b933b66f3..01f77f2fa 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -386,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; From c7f74099549f8da2b4a8ab388b8c2756be650d34 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 28 Oct 2017 21:07:19 -0700 Subject: [PATCH 096/242] Edit warning log --- srsenb/src/mac/scheduler.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) 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] ); } } } From 1d095b006adc7db940f9b7d7ebc6672f352db64a Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 28 Oct 2017 23:30:29 -0700 Subject: [PATCH 097/242] Removed unused nof_tb variable --- lib/examples/pdsch_enodeb.c | 3 ++- lib/include/srslte/phy/phch/ra.h | 1 - lib/src/phy/phch/ra.c | 2 -- lib/src/phy/phch/test/pmch_test.c | 1 - lib/src/phy/ue/ue_dl.c | 1 - 5 files changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/examples/pdsch_enodeb.c b/lib/examples/pdsch_enodeb.c index f7f17bc2b..1d807973c 100644 --- a/lib/examples/pdsch_enodeb.c +++ b/lib/examples/pdsch_enodeb.c @@ -942,7 +942,8 @@ int main(int argc, char **argv) { } /* Configure pmch_cfg parameters */ srslte_ra_dl_grant_t grant; - grant.nof_tb = 1; + grant.tb_en[0] = true; + grant.tb_en[1] = false; grant.mcs[0].idx = 2; grant.mcs[0].mod = SRSLTE_MOD_QPSK; grant.nof_prb = cell.nof_prb; diff --git a/lib/include/srslte/phy/phch/ra.h b/lib/include/srslte/phy/phch/ra.h index aef8f4751..e9c402236 100644 --- a/lib/include/srslte/phy/phch/ra.h +++ b/lib/include/srslte/phy/phch/ra.h @@ -104,7 +104,6 @@ typedef struct SRSLTE_API { uint32_t nof_prb; uint32_t Qm[SRSLTE_MAX_CODEWORDS]; srslte_ra_mcs_t mcs[SRSLTE_MAX_CODEWORDS]; - uint32_t nof_tb; srslte_sf_t sf_type; bool tb_en[SRSLTE_MAX_CODEWORDS]; uint32_t pinfo; diff --git a/lib/src/phy/phch/ra.c b/lib/src/phy/phch/ra.c index 913bd9548..8fe0ef934 100644 --- a/lib/src/phy/phch/ra.c +++ b/lib/src/phy/phch/ra.c @@ -526,11 +526,9 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr 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; grant->mcs[0].tbs = srslte_dl_fill_ra_mcs(&grant->mcs[0], n_prb); - grant->nof_tb++; } else { grant->mcs[0].tbs = 0; } diff --git a/lib/src/phy/phch/test/pmch_test.c b/lib/src/phy/phch/test/pmch_test.c index a9c29ef64..bf415e692 100644 --- a/lib/src/phy/phch/test/pmch_test.c +++ b/lib/src/phy/phch/test/pmch_test.c @@ -167,7 +167,6 @@ 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; diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index 930fe2623..1c3b79440 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -608,7 +608,6 @@ 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; From be0b832927241544e84b3d1643d558354019ed20 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sun, 29 Oct 2017 10:29:53 -0700 Subject: [PATCH 098/242] Implement CW swap and TB to CW mapping for TM4 --- lib/src/phy/phch/dci.c | 28 +++++++++++++++++++++++++++- srsue/src/phy/phch_worker.cc | 7 +------ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/lib/src/phy/phch/dci.c b/lib/src/phy/phch/dci.c index 471429145..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" @@ -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/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 33795a69f..cf0eab94c 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -504,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]; @@ -633,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)); } From de937faa205fbcc04140c5143d51a5374b06bc69 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sun, 29 Oct 2017 11:02:18 -0700 Subject: [PATCH 099/242] Set invalid inputs error to dlsch_decode --- lib/src/phy/phch/pdsch.c | 3 +++ lib/src/phy/phch/sch.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index ddfcf3f86..99f4fbfa5 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -610,6 +610,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); diff --git a/lib/src/phy/phch/sch.c b/lib/src/phy/phch/sch.c index e76fa6aef..b9860ffa4 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; From f9e428ef68eee9a3feb9ffecf202c0af8a9e26c8 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 30 Oct 2017 14:25:03 +0100 Subject: [PATCH 100/242] Optimised RI/PMI calculation call --- lib/include/srslte/phy/phch/uci.h | 1 + lib/src/phy/ue/ue_ul.c | 31 +++++++++++++++---------------- srsue/src/phy/phch_worker.cc | 18 +++++++----------- 3 files changed, 23 insertions(+), 27 deletions(-) diff --git a/lib/include/srslte/phy/phch/uci.h b/lib/include/srslte/phy/phch/uci.h index dc2030517..c20fca239 100644 --- a/lib/include/srslte/phy/phch/uci.h +++ b/lib/include/srslte/phy/phch/uci.h @@ -73,6 +73,7 @@ typedef struct SRSLTE_API { uint8_t uci_ack; // 1st codeword bit for HARQ-ACK uint8_t uci_ack_2; // 2st codeword bit for HARQ-ACK uint32_t uci_ack_len; + bool ri_periodic_report; bool scheduling_request; bool channel_selection; bool cqi_ack; diff --git a/lib/src/phy/ue/ue_ul.c b/lib/src/phy/ue/ue_ul.c index cb2a6277a..1351cfca6 100644 --- a/lib/src/phy/ue/ue_ul.c +++ b/lib/src/phy/ue/ue_ul.c @@ -282,24 +282,23 @@ void pucch_encode_bits(srslte_uci_data_t *uci_data, srslte_pucch_format_t format pucch_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 1a } if (format >= SRSLTE_PUCCH_FORMAT_2) { - /* Append RI */ - if (uci_data->uci_ri_len) { - uci_data->uci_ri = uci_buffer[0]; // It assumes only 1 bit of RI - } - uci_buffer_len += uci_data->uci_ri_len; - - /* Append CQI */ - memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_cqi, uci_data->uci_cqi_len); - uci_buffer_len += uci_data->uci_cqi_len; - - /* Append Differential CQI */ - memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_dif_cqi, uci_data->uci_dif_cqi_len); - uci_buffer_len += uci_data->uci_dif_cqi_len; + /* Put RI (goes alone) */ + if (uci_data->ri_periodic_report) { + uci_buffer[0] = uci_data->uci_ri; // It assumes only 1 bit of RI + uci_buffer_len += uci_data->uci_ri_len; + } else { + /* Append CQI */ + memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_cqi, uci_data->uci_cqi_len); + uci_buffer_len += uci_data->uci_cqi_len; - /* Append PMI */ - memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_pmi, uci_data->uci_pmi_len); - uci_buffer_len += uci_data->uci_pmi_len; + /* Append Differential CQI */ + memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_dif_cqi, uci_data->uci_dif_cqi_len); + uci_buffer_len += uci_data->uci_dif_cqi_len; + /* Append PMI */ + memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_pmi, uci_data->uci_pmi_len); + uci_buffer_len += uci_data->uci_pmi_len; + } srslte_uci_encode_cqi_pucch(uci_buffer, uci_buffer_len, pucch_bits); if (format > SRSLTE_PUCCH_FORMAT_2) { pucch2_bits[0] = uci_data->uci_ack; diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 1a6c67ef2..45b89ca82 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -256,8 +256,6 @@ void phch_worker::work_imp() if (dl_action.generate_ack) { set_uci_ack(dl_ack, dl_mac_grant.tb_en); } - - compute_ri(); } } @@ -306,6 +304,8 @@ void phch_worker::work_imp() /* Transmit PUSCH, PUCCH or SRS */ bool signal_ready = false; if (ul_action.tx_enabled) { + compute_ri(); + encode_pusch(&ul_action.phy_grant.ul, ul_action.payload_ptr[0], ul_action.current_tx_nb, &ul_action.softbuffers[0], ul_action.rv[0], ul_action.rnti, ul_mac_grant.is_from_rar); signal_ready = true; @@ -363,8 +363,9 @@ void phch_worker::work_imp() } void phch_worker::compute_ri() { - /* Select Rank Indicator by computing Condition Number */ - if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) { + if (uci_data.uci_ri_len > 0) { + /* Do nothing */ + } else if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) { if (ue_dl.nof_rx_antennas > 1) { /* If 2 ort more receiving antennas, select RI */ float cn = 0.0f; @@ -834,13 +835,8 @@ void phch_worker::set_uci_periodic_cqi() if (period_cqi.configured && rnti_is_set) { if (period_cqi.ri_idx_present && srslte_ri_send(period_cqi.pmi_idx, period_cqi.ri_idx, TTI_TX(tti))) { - /* If the RI is not computed, compute it */ - if (uci_data.uci_ri_len < 1) { - compute_ri(); - } - uci_data.uci_cqi_len = 0; - uci_data.uci_dif_cqi_len = 0; - uci_data.uci_pmi_len = 0; + compute_ri(); + uci_data.ri_periodic_report = true; Info("PUCCH: Periodic RI=%d\n", uci_data.uci_ri); } else if (srslte_cqi_send(period_cqi.pmi_idx, TTI_TX(tti))) { srslte_cqi_value_t cqi_report; From 45d78d33fb785ae7f7b01447ad13b0f9bc535980 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Mon, 30 Oct 2017 16:44:52 -0700 Subject: [PATCH 101/242] Consider negative elapsed time values in activity monitor due to multiple PHY threads. Fixes issue #111 --- srsenb/src/upper/rrc.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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, From 81b34afff9221d04b1c57581f9ac75f4313e1da7 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Mon, 30 Oct 2017 21:49:02 -0700 Subject: [PATCH 102/242] Normalize srsENB OFDM tx signal (srsENB not working PDSCH before this commit until ofdm changes commit) --- lib/src/phy/enb/enb_dl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/phy/enb/enb_dl.c b/lib/src/phy/enb/enb_dl.c index 54a63bc2a..2dee5b7f7 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) @@ -275,7 +276,7 @@ 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) { // TODO: PAPR control - float norm_factor = (float) sqrt(q->cell.nof_prb)/15; + 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]); From 98969b2011fc7fdbc6aa995645b0f5585fb7f27e Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 31 Oct 2017 12:19:35 +0100 Subject: [PATCH 103/242] Implemented 3GPP 36.212 Tables 5.3.3.1.5-1 and 5.3.3.1.5-2 --- lib/include/srslte/phy/phch/pdsch_cfg.h | 1 + lib/include/srslte/phy/phch/ra.h | 1 + lib/src/phy/phch/pdsch.c | 64 ++++++++++++++----------- lib/src/phy/phch/ra.c | 5 +- lib/src/phy/phch/sch.c | 12 ++--- lib/src/phy/phch/test/CMakeLists.txt | 16 +++++++ lib/src/phy/phch/test/pdsch_test.c | 17 ++++++- 7 files changed, 79 insertions(+), 37 deletions(-) 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 e9c402236..f4274e416 100644 --- a/lib/include/srslte/phy/phch/ra.h +++ b/lib/include/srslte/phy/phch/ra.h @@ -107,6 +107,7 @@ typedef struct SRSLTE_API { 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)) diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index 99f4fbfa5..7c744f552 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) { @@ -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); @@ -690,16 +691,22 @@ int srslte_pdsch_decode(srslte_pdsch_t *q, 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 ++) { + + /* 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] && !acks[tb]) { - int ret = srslte_pdsch_codeword_decode(q, cfg, softbuffers[tb], rnti, data[tb], tb, &acks[tb]); + 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; + /* Check if there has been any execution error */ + if (ret) { + return ret; + } } + + cw_idx = (cw_idx + 1) % SRSLTE_MAX_CODEWORDS; } } @@ -772,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 8fe0ef934..735794e35 100644 --- a/lib/src/phy/phch/ra.c +++ b/lib/src/phy/phch/ra.c @@ -546,6 +546,7 @@ 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 (grant->mcs[0].tbs < 0 || grant->mcs[1].tbs < 0) { return SRSLTE_ERROR; @@ -559,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) { diff --git a/lib/src/phy/phch/sch.c b/lib/src/phy/phch/sch.c index b9860ffa4..930364725 100644 --- a/lib/src/phy/phch/sch.c +++ b/lib/src/phy/phch/sch.c @@ -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/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; } } From 3a054a22b922dbfc28a0fc33c50e099ad0eda221 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 31 Oct 2017 07:26:49 -0700 Subject: [PATCH 104/242] Remove OFDM normalization from enb_dl_init and do it before transmission --- lib/src/phy/enb/enb_dl.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/src/phy/enb/enb_dl.c b/lib/src/phy/enb/enb_dl.c index 2dee5b7f7..98224d740 100644 --- a/lib/src/phy/enb/enb_dl.c +++ b/lib/src/phy/enb/enb_dl.c @@ -71,10 +71,6 @@ int srslte_enb_dl_init(srslte_enb_dl_t *q, cf_t *out_buffer[SRSLTE_MAX_PORTS], u } } - for (int i = 0; i < q->cell.nof_ports; i++) { - srslte_ofdm_set_normalize(&q->ifft[i], true); - } - if (srslte_pbch_init(&q->pbch)) { fprintf(stderr, "Error creating PBCH object\n"); goto clean_exit; From 0d95159a2a45a0cdf3de81cea12c414ff384558a Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 31 Oct 2017 08:01:02 -0700 Subject: [PATCH 105/242] Fix issue #114 --- lib/src/common/pdu.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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); From bb2bc952470b2d69eb3592839aa3ee4f8a43ca92 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 31 Oct 2017 22:46:57 -0700 Subject: [PATCH 106/242] Fix diversity tx not working for 4 ports --- lib/src/phy/phch/pdsch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index 7c744f552..b984adee3 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -493,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) { From d615dc9ec9194dc565a6417baec7e53d8c79b8dd Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 1 Nov 2017 16:30:14 -0700 Subject: [PATCH 107/242] Added missing deallocation in RLC UM in case of too small pdu --- lib/src/upper/rlc_um.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/upper/rlc_um.cc b/lib/src/upper/rlc_um.cc index d95e186e7..4756e2f7c 100644 --- a/lib/src/upper/rlc_um.cc +++ b/lib/src/upper/rlc_um.cc @@ -279,6 +279,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) 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; @@ -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(); From 935afe6ef35886956aeb722c4d64f5bde708bd6d Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Thu, 2 Nov 2017 17:44:56 +0000 Subject: [PATCH 108/242] Minor soapy fix --- lib/src/phy/rf/rf_soapy_imp.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/lib/src/phy/rf/rf_soapy_imp.c b/lib/src/phy/rf/rf_soapy_imp.c index fef533ffc..18c5b01cd 100644 --- a/lib/src/phy/rf/rf_soapy_imp.c +++ b/lib/src/phy/rf/rf_soapy_imp.c @@ -286,11 +286,6 @@ double rf_soapy_set_rx_srate(void *h, double rate) return SRSLTE_ERROR; } - if (SoapySDRDevice_setBandwidth(handler->device, 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); } From cd6ca95cd18cb429185b04b35f6f3417c9662db5 Mon Sep 17 00:00:00 2001 From: yagoda Date: Wed, 8 Nov 2017 15:43:38 +0000 Subject: [PATCH 109/242] lime additions and resampler optimizations (#94) * adding optimizations to fractional resampler * adding txrx delay for N210 and Lime * minor corrections to Lime api * optimization of the fractional resampler --- .../srslte/phy/resampling/resample_arb.h | 7 +- lib/src/phy/resampling/resample_arb.c | 169 ++++++++++++------ .../phy/resampling/test/resample_arb_bench.c | 11 +- .../phy/resampling/test/resample_arb_test.c | 9 +- lib/src/phy/rf/rf_soapy_imp.c | 25 ++- lib/src/phy/rf/rf_soapy_imp.h | 2 +- lib/src/radio/radio.cc | 47 ++++- 7 files changed, 200 insertions(+), 70 deletions(-) diff --git a/lib/include/srslte/phy/resampling/resample_arb.h b/lib/include/srslte/phy/resampling/resample_arb.h index 98d004b0b..4ebb8dc08 100644 --- a/lib/include/srslte/phy/resampling/resample_arb.h +++ b/lib/include/srslte/phy/resampling/resample_arb.h @@ -38,10 +38,13 @@ #define RESAMPLE_ARB_ #include +#include #include #include "srslte/config.h" + +#define SRSLTE_RESAMPLE_ARB_N_35 35 #define SRSLTE_RESAMPLE_ARB_N 32 // Polyphase filter rows #define SRSLTE_RESAMPLE_ARB_M 8 // Polyphase filter columns @@ -49,11 +52,13 @@ typedef struct SRSLTE_API { float rate; // Resample rate float step; // Step increment through filter float acc; // Index into filter + bool interpolate; cf_t reg[SRSLTE_RESAMPLE_ARB_M]; // Our window of samples + } srslte_resample_arb_t; SRSLTE_API void srslte_resample_arb_init(srslte_resample_arb_t *q, - float rate); + float rate, bool interpolate); SRSLTE_API int srslte_resample_arb_compute(srslte_resample_arb_t *q, cf_t *input, diff --git a/lib/src/phy/resampling/resample_arb.c b/lib/src/phy/resampling/resample_arb.c index 7bdb4deec..2b04f587c 100644 --- a/lib/src/phy/resampling/resample_arb.c +++ b/lib/src/phy/resampling/resample_arb.c @@ -28,64 +28,104 @@ #include #include "srslte/phy/resampling/resample_arb.h" #include "srslte/phy/utils/debug.h" +#include "srslte/phy/utils/vector.h" -float srslte_resample_arb_polyfilt[SRSLTE_RESAMPLE_ARB_N][SRSLTE_RESAMPLE_ARB_M] = -{{0,0.002400347599485495,-0.006922416132556366,0.0179104136912176,0.99453086623794,-0.008521087756729117,0.0008598969867484128,0.0004992625165376107}, -{-0.001903604727400391,0.004479591950094871,-0.01525319260830623,0.04647449496926549,0.9910477342662829,-0.03275243420114668,0.008048813755373533,-0.001216900416836847}, -{-0.001750442300940216,0.006728826416921727,-0.02407540632178267,0.07708575473589654,0.9841056525667189,-0.05473739187922162,0.01460652754040275,-0.002745266140572769}, -{-0.001807302702047332,0.009130494591071001,-0.03332524241797466,0.1096377743266821,0.9737536341125557,-0.07444712408657775,0.0205085154280773,-0.004077596041064956}, -{-0.002005048395707184,0.01166717081713966,-0.04292591596219218,0.1440068251440274,0.9600641782991848,-0.09187282739868929,0.02573649090563353,-0.005218582609802016}, -{-0.002303606593778858,0.01431549924598744,-0.05279365431190471,0.1800496557331084,0.9431333663677619,-0.107022659158021,0.03028295984887362,-0.006178495199082676}, -{-0.002673824939871474,0.01705308556587308,-0.06283262272105428,0.2176066284621515,0.9230793648715676,-0.1199244901666642,0.03414559686566755,-0.006951034565279722}, -{-0.003099294850834212,0.01985022208215894,-0.07294100481214681,0.2564996326404178,0.9000412628278351,-0.1306207218667012,0.03733448898243594,-0.007554128492547957}, -{-0.003564415127592977,0.02267702927238637,-0.08300660359189582,0.2965368855416621,0.874178327911914,-0.1391710078036285,0.03986356581130199,-0.007992692892036229}, -{-0.004060222849803048,0.02549633298710617,-0.09291211362877161,0.3375102453232687,0.8456688916962831,-0.1456479420005528,0.04175429631970297,-0.00827816851803391}, -{-0.004574770330592958,0.02827133859849648,-0.1025308044303699,0.379200979038518,0.8147072909915275,-0.1501397816831265,0.04303284689167361,-0.008423951215857236}, -{-0.005100453570725489,0.0309593063669097,-0.1117325201826136,0.4213772298764557,0.7815036335229155,-0.1527444636485677,0.0437349357738538,-0.008441129184587313}, -{-0.005625340687997995,0.03351877124912608,-0.1203802123857154,0.463798444519773,0.7462810500374923,-0.1535722712206338,0.04389261707032224,-0.008345136869130621}, -{-0.006140888413286479,0.03590276234084221,-0.1283350405000867,0.5062161107254219,0.7092744343987509,-0.152741400055636,0.04355110899623683,-0.008147838953503964}, -{-0.006634012711933725,0.03806645580467819,-0.1354549138065051,0.5483763739419955,0.6707272107491931,-0.1503798528838644,0.0427502160096194,-0.007865132034489236}, -{-0.007094909626785393,0.03996043743797257,-0.1415969539549883,0.5900207719663111,0.6308907308946271,-0.1466186670140106,0.04153829696698895,-0.007508971112586246}, -{-0.007508971112586246,0.04153829696698895,-0.1466186670140106,0.6308907308946271,0.5900207719663111,-0.1415969539549883,0.03996043743797257,-0.007094909626785393}, -{-0.007865132034489236,0.0427502160096194,-0.1503798528838644,0.6707272107491931,0.5483763739419955,-0.1354549138065051,0.03806645580467819,-0.006634012711933725}, -{-0.008147838953503964,0.04355110899623683,-0.152741400055636,0.7092744343987509,0.5062161107254219,-0.1283350405000867,0.03590276234084221,-0.006140888413286479}, -{-0.008345136869130621,0.04389261707032224,-0.1535722712206338,0.7462810500374923,0.463798444519773,-0.1203802123857154,0.03351877124912608,-0.005625340687997995}, -{-0.008441129184587313,0.0437349357738538,-0.1527444636485677,0.7815036335229155,0.4213772298764557,-0.1117325201826136,0.0309593063669097,-0.005100453570725489}, -{-0.008423951215857236,0.04303284689167361,-0.1501397816831265,0.8147072909915275,0.379200979038518,-0.1025308044303699,0.02827133859849648,-0.004574770330592958}, -{-0.00827816851803391,0.04175429631970297,-0.1456479420005528,0.8456688916962831,0.3375102453232687,-0.09291211362877161,0.02549633298710617,-0.004060222849803048}, -{-0.007992692892036229,0.03986356581130199,-0.1391710078036285,0.874178327911914,0.2965368855416621,-0.08300660359189582,0.02267702927238637,-0.003564415127592977}, -{-0.007554128492547957,0.03733448898243594,-0.1306207218667012,0.9000412628278351,0.2564996326404178,-0.07294100481214681,0.01985022208215894,-0.003099294850834212}, -{-0.006951034565279722,0.03414559686566755,-0.1199244901666642,0.9230793648715676,0.2176066284621515,-0.06283262272105428,0.01705308556587308,-0.002673824939871474}, -{-0.006178495199082676,0.03028295984887362,-0.107022659158021,0.9431333663677619,0.1800496557331084,-0.05279365431190471,0.01431549924598744,-0.002303606593778858}, -{-0.005218582609802016,0.02573649090563353,-0.09187282739868929,0.9600641782991848,0.1440068251440274,-0.04292591596219218,0.01166717081713966,-0.002005048395707184}, -{-0.004077596041064956,0.0205085154280773,-0.07444712408657775,0.9737536341125557,0.1096377743266821,-0.03332524241797466,0.009130494591071001,-0.001807302702047332}, -{-0.002745266140572769,0.01460652754040275,-0.05473739187922162,0.9841056525667189,0.07708575473589654,-0.02407540632178267,0.006728826416921727,-0.001750442300940216}, -{-0.001216900416836847,0.008048813755373533,-0.03275243420114668,0.9910477342662829,0.04647449496926549,-0.01525319260830623,0.004479591950094871,-0.001903604727400391}, -{0.0004992625165376107,0.0008598969867484128,-0.008521087756729117,0.99453086623794,0.0179104136912176,-0.006922416132556366,0.002400347599485495,0}}; -// TODO: use lte/utils/vector.h and Volk -cf_t srslte_resample_arb_dot_prod(cf_t* x, float *y, int len) -{ - cf_t res = 0+0*I; - for(int i=0;ireg[1], &q->reg[0], (SRSLTE_RESAMPLE_ARB_M-1)*sizeof(cf_t)); q->reg[0] = x; } // Initialize our struct -void srslte_resample_arb_init(srslte_resample_arb_t *q, float rate){ +void srslte_resample_arb_init(srslte_resample_arb_t *q, float rate, bool interpolate){ + memset(q->reg, 0, SRSLTE_RESAMPLE_ARB_M*sizeof(cf_t)); q->acc = 0.0; q->rate = rate; + q->interpolate = interpolate; q->step = (1/rate)*SRSLTE_RESAMPLE_ARB_N; } @@ -94,19 +134,48 @@ int srslte_resample_arb_compute(srslte_resample_arb_t *q, cf_t *input, cf_t *out int cnt = 0; int n_out = 0; int idx = 0; + cf_t res1,res2; + cf_t *filter_input; + float frac = 0; + memset(q->reg, 0, SRSLTE_RESAMPLE_ARB_M*sizeof(cf_t)); + + while (cnt < n_in) { + + if(cntreg[SRSLTE_RESAMPLE_ARB_M - cnt], input, (cnt)*sizeof(cf_t)); + filter_input = q->reg; + } else{ + filter_input = &input[cnt-SRSLTE_RESAMPLE_ARB_M]; + } + + res1 = srslte_resample_arb_dot_prod(filter_input, srslte_resample_arb_polyfilt[idx], SRSLTE_RESAMPLE_ARB_M); + if(q->interpolate){ + res2 = srslte_resample_arb_dot_prod(filter_input, srslte_resample_arb_polyfilt[(idx%SRSLTE_RESAMPLE_ARB_N)+1], SRSLTE_RESAMPLE_ARB_M); + } - while(cnt < n_in) - { - *output = srslte_resample_arb_dot_prod(q->reg, srslte_resample_arb_polyfilt[idx], SRSLTE_RESAMPLE_ARB_M); + if(idx == SRSLTE_RESAMPLE_ARB_N){ + *output = res1; + }else { + *output = (q->interpolate)?(res1 + (res2-res1)*frac):res1; + } + output++; n_out++; q->acc += q->step; - idx = (int)roundf(q->acc); + idx = (int)(q->acc); + while(idx >= SRSLTE_RESAMPLE_ARB_N){ q->acc -= SRSLTE_RESAMPLE_ARB_N; idx -= SRSLTE_RESAMPLE_ARB_N; - if(cnt < n_in) - srslte_resample_arb_push(q, input[cnt++]); + if(cnt < n_in){ + cnt++; + } + } + + if(q->interpolate){ + frac = q->acc - idx; + if(frac < 0) + frac = frac*(-1); } } return n_out; diff --git a/lib/src/phy/resampling/test/resample_arb_bench.c b/lib/src/phy/resampling/test/resample_arb_bench.c index 48879d036..773291913 100644 --- a/lib/src/phy/resampling/test/resample_arb_bench.c +++ b/lib/src/phy/resampling/test/resample_arb_bench.c @@ -35,9 +35,9 @@ #include "srslte/phy/resampling/resample_arb.h" - +#define ITERATIONS 10000 int main(int argc, char **argv) { - int N=10000000; + int N=9000; float rate = 24.0/25.0; cf_t *in = malloc(N*sizeof(cf_t)); cf_t *out = malloc(N*sizeof(cf_t)); @@ -46,12 +46,15 @@ int main(int argc, char **argv) { in[i] = sin(i*2*M_PI/100); srslte_resample_arb_t r; - srslte_resample_arb_init(&r, rate); + srslte_resample_arb_init(&r, rate, 0); clock_t start = clock(), diff; - //int n_out = srslte_resample_arb_compute(&r, in, out, N); + for(int xx = 0; xx diff && pre != post){ - printf("Interpolation failed at index %f", idx); + printf("Interpolation failed at index %f\n", idx); exit(-1); } } - free(in); free(out); } diff --git a/lib/src/phy/rf/rf_soapy_imp.c b/lib/src/phy/rf/rf_soapy_imp.c index 18c5b01cd..90ede26e9 100644 --- a/lib/src/phy/rf/rf_soapy_imp.c +++ b/lib/src/phy/rf/rf_soapy_imp.c @@ -38,6 +38,7 @@ #include typedef struct { + char *devname; SoapySDRKwargs args; SoapySDRDevice *device; SoapySDRRange *ranges; @@ -51,7 +52,6 @@ typedef struct { cf_t zero_mem[64*1024]; - int soapy_error(void *h) { return 0; @@ -90,7 +90,8 @@ void rf_soapy_register_error_handler(void *notused, srslte_rf_error_handler_t ne char* rf_soapy_devname(void* h) { - return "soapy"; + rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; + return handler->devname; } @@ -196,11 +197,15 @@ int rf_soapy_open_multi(char *args, void **h, uint32_t nof_rx_antennas) printf("No Soapy devices found.\n"); return SRSLTE_ERROR; } - + char* devname; for (size_t i = 0; i < length; i++) { printf("Soapy has Found device #%d: ", (int)i); for (size_t j = 0; j < soapy_args[i].size; j++) { printf("%s=%s, ", soapy_args[i].keys[j], soapy_args[i].vals[j]); + if(!strcmp(soapy_args[i].keys[j],"name") && !strcmp(soapy_args[i].vals[j], "LimeSDR-USB")){ + devname = DEVNAME_LIME; + + } } printf("\n"); } @@ -218,7 +223,7 @@ int rf_soapy_open_multi(char *args, void **h, uint32_t nof_rx_antennas) handler->device = sdr; handler->tx_stream_active = false; handler->rx_stream_active = false; - + handler->devname = devname; if(SoapySDRDevice_getNumChannels(handler->device,SOAPY_SDR_RX) > 0){ printf("setting up RX stream\n"); if(SoapySDRDevice_setupStream(handler->device, &(handler->rxStream), SOAPY_SDR_RX, SOAPY_SDR_CF32, NULL, 0, NULL) != 0) { @@ -234,6 +239,14 @@ int rf_soapy_open_multi(char *args, void **h, uint32_t nof_rx_antennas) return SRSLTE_ERROR; } } + size_t sensor_length; + char** sensors; + sensors = SoapySDRDevice_listSensors(handler->device, &sensor_length); + for(int i = 0; i < sensor_length;i++) + { + printf("available sensors are : \n"); + puts(sensors[i]); + } return SRSLTE_SUCCESS; } @@ -267,7 +280,7 @@ int rf_soapy_close(void *h) void rf_soapy_set_master_clock_rate(void *h, double rate) { // Allow the soapy to automatically set the appropriate clock rate - // TODO: implement this function + } @@ -285,7 +298,6 @@ double rf_soapy_set_rx_srate(void *h, double rate) printf("setSampleRate Rx fail: %s\n", SoapySDRDevice_lastError()); return SRSLTE_ERROR; } - return SoapySDRDevice_getSampleRate(handler->device, SOAPY_SDR_RX,0); } @@ -296,7 +308,6 @@ double rf_soapy_set_tx_srate(void *h, double rate) printf("setSampleRate Tx fail: %s\n", SoapySDRDevice_lastError()); return SRSLTE_ERROR; } - return SoapySDRDevice_getSampleRate(handler->device, SOAPY_SDR_TX,0); } diff --git a/lib/src/phy/rf/rf_soapy_imp.h b/lib/src/phy/rf/rf_soapy_imp.h index 19de4536c..5dd1c6c44 100644 --- a/lib/src/phy/rf/rf_soapy_imp.h +++ b/lib/src/phy/rf/rf_soapy_imp.h @@ -28,7 +28,7 @@ #include #include "srslte/config.h" #include "srslte/phy/rf/rf.h" - +#define DEVNAME_LIME "lime" SRSLTE_API int rf_soapy_open(char *args, void **handler); diff --git a/lib/src/radio/radio.cc b/lib/src/radio/radio.cc index 42d4143f9..dc84ad921 100644 --- a/lib/src/radio/radio.cc +++ b/lib/src/radio/radio.cc @@ -59,6 +59,7 @@ bool radio::init(char *args, char *devname) } else if (strstr(srslte_rf_name(&rf_device), "bladerf")) { burst_preamble_sec = blade_default_burst_preamble_sec; } else { + burst_preamble_sec = 0; printf("\nWarning burst preamble is not calibrated for device %s. Set a value manually\n\n", srslte_rf_name(&rf_device)); } @@ -329,11 +330,10 @@ void radio::set_tx_srate(double srate) } burst_preamble_time_rounded = (double) burst_preamble_samples/cur_tx_srate; - int nsamples=0; /* Set time advance for each known device if in auto mode */ if (tx_adv_auto) { - + /* This values have been calibrated using the prach_test_usrp tool in srsLTE */ if (!strcmp(srslte_rf_name(&rf_device), "uhd_b200")) { @@ -355,7 +355,48 @@ void radio::set_tx_srate(double srate) /* Interpolate from known values */ printf("\nWarning TX/RX time offset for sampling rate %.0f KHz not calibrated. Using interpolated value\n\n", cur_tx_srate); nsamples = cur_tx_srate*(uhd_default_tx_adv_samples * (1/cur_tx_srate) + uhd_default_tx_adv_offset_sec); - } + } + + }else if(!strcmp(srslte_rf_name(&rf_device), "uhd_usrp2")) { + double srate_khz = round(cur_tx_srate/1e3); + if (srate_khz == 1.92e3) { + nsamples = 14;// estimated + } else if (srate_khz == 3.84e3) { + nsamples = 32; + } else if (srate_khz == 5.76e3) { + nsamples = 43; + } else if (srate_khz == 11.52e3) { + nsamples = 54; + } else if (srate_khz == 15.36e3) { + nsamples = 65;// to calc + } else if (srate_khz == 23.04e3) { + nsamples = 80; // to calc + } else { + /* Interpolate from known values */ + printf("\nWarning TX/RX time offset for sampling rate %.0f KHz not calibrated. Using interpolated value\n\n", cur_tx_srate); + nsamples = cur_tx_srate*(uhd_default_tx_adv_samples * (1/cur_tx_srate) + uhd_default_tx_adv_offset_sec); + } + + } else if(!strcmp(srslte_rf_name(&rf_device), "lime")) { + double srate_khz = round(cur_tx_srate/1e3); + if (srate_khz == 1.92e3) { + nsamples = 70;// estimated + } else if (srate_khz == 3.84e3) { + nsamples = 76;//estimated + } else if (srate_khz == 5.76e3) { + nsamples = 76; + } else if (srate_khz == 11.52e3) { + nsamples = 76; + } else if (srate_khz == 15.36e3) { + nsamples = 73; + } else if (srate_khz == 23.04e3) { + nsamples = 87; + } else { + /* Interpolate from known values */ + printf("\nWarning TX/RX time offset for sampling rate %.0f KHz not calibrated. Using interpolated value\n\n", cur_tx_srate); + nsamples = cur_tx_srate*(uhd_default_tx_adv_samples * (1/cur_tx_srate) + uhd_default_tx_adv_offset_sec); + } + } else if (!strcmp(srslte_rf_name(&rf_device), "uhd_x300")) { // In X300 TX/RX offset is independent of sampling rate From 75957d41d712bf3b34526e0e43bae78496b6299e Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 8 Nov 2017 17:10:16 +0100 Subject: [PATCH 110/242] Added DCI formats 2 and 2a inScheduler. Improved UE PHCH, corrected some MIMO bugs on both sides. --- lib/examples/pdsch_enodeb.c | 2 +- .../srslte/interfaces/enb_interfaces.h | 2 +- .../srslte/interfaces/sched_interface.h | 6 +- lib/include/srslte/phy/phch/pdsch_cfg.h | 1 + lib/include/srslte/phy/phch/ra.h | 2 +- lib/include/srslte/phy/utils/debug.h | 2 +- lib/src/phy/enb/enb_dl.c | 34 +-- lib/src/phy/phch/pdsch.c | 94 +++++--- lib/src/phy/phch/pucch.c | 28 ++- lib/src/phy/phch/ra.c | 20 +- lib/src/phy/phch/test/pmch_test.c | 1 - lib/src/phy/phch/uci.c | 4 +- lib/src/phy/ue/ue_dl.c | 1 - srsenb/hdr/mac/mac.h | 2 +- srsenb/hdr/mac/scheduler.h | 2 +- srsenb/hdr/mac/scheduler_harq.h | 2 +- srsenb/hdr/mac/scheduler_ue.h | 2 +- srsenb/hdr/mac/ue.h | 8 +- srsenb/hdr/phy/phch_common.h | 6 +- srsenb/hdr/phy/phch_worker.h | 2 + srsenb/src/mac/mac.cc | 46 ++-- srsenb/src/mac/scheduler.cc | 15 +- srsenb/src/mac/scheduler_harq.cc | 18 +- srsenb/src/mac/scheduler_ue.cc | 221 ++++++++---------- srsenb/src/mac/ue.cc | 4 +- srsenb/src/phy/phch_common.cc | 22 +- srsenb/src/phy/phch_worker.cc | 137 +++++++---- srsue/src/phy/phch_worker.cc | 27 +-- 28 files changed, 406 insertions(+), 305 deletions(-) diff --git a/lib/examples/pdsch_enodeb.c b/lib/examples/pdsch_enodeb.c index f7f17bc2b..afa47c9d4 100644 --- a/lib/examples/pdsch_enodeb.c +++ b/lib/examples/pdsch_enodeb.c @@ -942,7 +942,7 @@ int main(int argc, char **argv) { } /* Configure pmch_cfg parameters */ srslte_ra_dl_grant_t grant; - grant.nof_tb = 1; + grant.tb_en[0] = true; grant.mcs[0].idx = 2; grant.mcs[0].mod = SRSLTE_MOD_QPSK; grant.nof_prb = cell.nof_prb; diff --git a/lib/include/srslte/interfaces/enb_interfaces.h b/lib/include/srslte/interfaces/enb_interfaces.h index 6f9db923a..175f99f59 100644 --- a/lib/include/srslte/interfaces/enb_interfaces.h +++ b/lib/include/srslte/interfaces/enb_interfaces.h @@ -68,7 +68,7 @@ public: virtual int pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value) = 0; virtual int cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) = 0; virtual int snr_info(uint32_t tti, uint16_t rnti, float snr_db) = 0; - virtual int ack_info(uint32_t tti, uint16_t rnti, bool ack) = 0; + virtual int ack_info(uint32_t tti, uint16_t rnti, uint32_t tb_idx, bool ack) = 0; virtual int crc_info(uint32_t tti, uint16_t rnti, uint32_t nof_bytes, bool crc_res) = 0; virtual int get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) = 0; diff --git a/lib/include/srslte/interfaces/sched_interface.h b/lib/include/srslte/interfaces/sched_interface.h index 5e4b68acf..562499dfb 100644 --- a/lib/include/srslte/interfaces/sched_interface.h +++ b/lib/include/srslte/interfaces/sched_interface.h @@ -137,8 +137,8 @@ public: uint32_t tbs[SRSLTE_MAX_TB]; bool mac_ce_ta; bool mac_ce_rnti; - uint32_t nof_pdu_elems; - dl_sched_pdu_t pdu[MAX_RLC_PDU_LIST]; + uint32_t nof_pdu_elems[SRSLTE_MAX_TB]; + dl_sched_pdu_t pdu[SRSLTE_MAX_TB][MAX_RLC_PDU_LIST]; } dl_sched_data_t; typedef struct { @@ -226,7 +226,7 @@ public: virtual int dl_mac_buffer_state(uint16_t rnti, uint32_t ce_code) = 0; /* DL information */ - virtual int dl_ack_info(uint32_t tti, uint16_t rnti, bool ack) = 0; + virtual int dl_ack_info(uint32_t tti, uint16_t rnti, uint32_t tb_idx, bool ack) = 0; virtual int dl_rach_info(uint32_t tti, uint32_t ra_id, uint16_t rnti, uint32_t estimated_size) = 0; virtual int dl_ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value) = 0; virtual int dl_pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value) = 0; 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 aef8f4751..f4274e416 100644 --- a/lib/include/srslte/phy/phch/ra.h +++ b/lib/include/srslte/phy/phch/ra.h @@ -104,10 +104,10 @@ typedef struct SRSLTE_API { uint32_t nof_prb; uint32_t Qm[SRSLTE_MAX_CODEWORDS]; srslte_ra_mcs_t mcs[SRSLTE_MAX_CODEWORDS]; - uint32_t nof_tb; 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)) diff --git a/lib/include/srslte/phy/utils/debug.h b/lib/include/srslte/phy/utils/debug.h index c88e1a3ce..00588ca84 100644 --- a/lib/include/srslte/phy/utils/debug.h +++ b/lib/include/srslte/phy/utils/debug.h @@ -65,7 +65,7 @@ SRSLTE_API extern int srslte_verbose; #if CMAKE_BUILD_TYPE==Debug /* In debug mode, it prints out the */ -#define ERROR(_fmt, ...) fprintf(stderr, "%s.%d: " _fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) +#define ERROR(_fmt, ...) fprintf(stderr, "\e[31m%s.%d: " _fmt "\e[0m\n", __FILE__, __LINE__, ##__VA_ARGS__) #else #define ERROR(_fmt, ...) fprintf(stderr, "[ERROR in %s]:" _fmt "\n", __FUNCTION__, ##__VA_ARGS__) #endif /* CMAKE_BUILD_TYPE==Debug */ diff --git a/lib/src/phy/enb/enb_dl.c b/lib/src/phy/enb/enb_dl.c index fbc22212d..5bb8c476d 100644 --- a/lib/src/phy/enb/enb_dl.c +++ b/lib/src/phy/enb/enb_dl.c @@ -341,26 +341,34 @@ int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q, srslte_ra_dl_grant_t *grant, srs /* Translates Precoding Information (pinfo) to Precoding matrix Index (pmi) as 3GPP 36.212 Table 5.3.3.1.5-4 */ if (mimo_type == SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX) { - if (nof_tb == 1) { - if (grant->pinfo > 0 && grant->pinfo < 5) { - pmi = grant->pinfo - 1; - } else { - ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo); - return SRSLTE_ERROR; - } - } else { - if (grant->pinfo < 2) { - pmi = grant->pinfo; - } else { + switch(nof_tb) { + case 1: + if (grant->pinfo == 0) { + mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY; + } else if (grant->pinfo > 0 && grant->pinfo < 5) { + pmi = grant->pinfo - 1; + } else { + ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo); + return SRSLTE_ERROR; + } + break; + case 2: + if (grant->pinfo < 2) { + pmi = grant->pinfo; + } else { + ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo); + return SRSLTE_ERROR; + } + break; + default: ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo); return SRSLTE_ERROR; - } } } /* Configure pdsch_cfg parameters */ if (srslte_pdsch_cfg_mimo(&q->pdsch_cfg, q->cell, grant, q->cfi, sf_idx, rv_idx, mimo_type, pmi)) { - fprintf(stderr, "Error configuring PDSCH\n"); + ERROR("Error configuring PDSCH (rnti=0x%04x)", rnti); return SRSLTE_ERROR; } diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index b438a2957..6479b5abd 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -467,7 +467,7 @@ int srslte_pdsch_cfg_mimo(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra for (int cw = 0; cw < SRSLTE_MAX_CODEWORDS; cw++) { if (grant->tb_en[cw]) { if (srslte_cbsegm(&cfg->cb_segm[cw], (uint32_t) cfg->grant.mcs[cw].tbs)) { - fprintf(stderr, "Error computing Codeblock (1) segmentation for TBS=%d\n", cfg->grant.mcs[cw].tbs); + fprintf(stderr, "Error computing Codeword (%d) segmentation for TBS=%d\n", cw, cfg->grant.mcs[cw].tbs); return SRSLTE_ERROR; } } @@ -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,30 @@ 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]; - - 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, + 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]; + bool valid_inputs = true; + + if (!softbuffer) { + ERROR("Error encoding (TB%d -> CW%d), softbuffer=NULL", tb_idx, codeword_idx); + valid_inputs = false; + } + + if (!data) { + ERROR("Error encoding (TB%d -> CW%d), data=NULL", tb_idx, codeword_idx); + valid_inputs = false; + } + + if (nbits->nof_bits && valid_inputs) { + 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; } @@ -570,6 +582,8 @@ static int srslte_pdsch_codeword_encode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *c (uint8_t *) q->e[codeword_idx], q->d[codeword_idx], nbits->nof_bits); + } else { + return SRSLTE_ERROR_INVALID_INPUTS; } return SRSLTE_SUCCESS; @@ -577,15 +591,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 +615,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 +624,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 +694,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 ++) { + + /* 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] && !acks[tb]) { - int ret = srslte_pdsch_codeword_decode(q, cfg, softbuffers[tb], rnti, data[tb], tb, &acks[tb]); + 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; + /* Check if there has been any execution error */ + if (ret) { + return ret; + } } + + cw_idx = (cw_idx + 1) % SRSLTE_MAX_CODEWORDS; } } @@ -767,20 +792,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/pucch.c b/lib/src/phy/phch/pucch.c index 10c785177..91445f99a 100644 --- a/lib/src/phy/phch/pucch.c +++ b/lib/src/phy/phch/pucch.c @@ -791,7 +791,7 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format, // Perform ML-decoding float corr=0, corr_max=-1e9; - int b_max = 0; // default bit value, eg. HI is NACK + uint8_t b_max = 0, b2_max = 0; // default bit value, eg. HI is NACK switch(format) { case SRSLTE_PUCCH_FORMAT_1: bzero(bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t)); @@ -808,7 +808,7 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format, case SRSLTE_PUCCH_FORMAT_1A: bzero(bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t)); ret = 0; - for (int b=0;b<2;b++) { + for (uint8_t b=0;b<2;b++) { bits[0] = b; pucch_encode(q, format, n_pucch, sf_idx, rnti, bits, q->z_tmp); corr = srslte_vec_corr_ccc(q->z, q->z_tmp, nof_re); @@ -824,6 +824,30 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format, q->last_corr = corr_max; bits[0] = b_max; break; + case SRSLTE_PUCCH_FORMAT_1B: + bzero(bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t)); + ret = 0; + for (uint8_t b=0;b<2;b++) { + for (uint8_t b2 = 0; b2 < 2; b2++) { + bits[0] = b; + bits[1] = b2; + pucch_encode(q, format, n_pucch, sf_idx, rnti, bits, q->z_tmp); + corr = srslte_vec_corr_ccc(q->z, q->z_tmp, nof_re); + if (corr > corr_max) { + corr_max = corr; + b_max = b; + b2_max = b2; + } + if (corr_max > q->threshold_format1) { // check with format1 in case ack+sr because ack only is binary + ret = 1; + } + DEBUG("format1b b=%d, corr=%f, nof_re=%d\n", b, corr, nof_re); + } + } + q->last_corr = corr_max; + bits[0] = b_max; + bits[1] = b2_max; + break; case SRSLTE_PUCCH_FORMAT_2: case SRSLTE_PUCCH_FORMAT_2A: case SRSLTE_PUCCH_FORMAT_2B: diff --git a/lib/src/phy/phch/ra.c b/lib/src/phy/phch/ra.c index 913bd9548..e37266858 100644 --- a/lib/src/phy/phch/ra.c +++ b/lib/src/phy/phch/ra.c @@ -526,11 +526,9 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr 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; grant->mcs[0].tbs = srslte_dl_fill_ra_mcs(&grant->mcs[0], n_prb); - grant->nof_tb++; } else { grant->mcs[0].tbs = 0; } @@ -560,16 +558,16 @@ void srslte_ra_dl_grant_to_nbits(srslte_ra_dl_grant_t *grant, uint32_t cfi, srsl srslte_ra_nbits_t nbits [SRSLTE_MAX_CODEWORDS]) { // Compute number of RE - for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { + for (int i = 0; i < SRSLTE_MAX_TB; i++) { + /* Compute number of RE for first transport block */ + nbits[i].nof_re = srslte_ra_dl_grant_nof_re(grant, cell, sf_idx, cell.nof_prb < 10 ? (cfi + 1) : cfi); + nbits[i].lstart = cell.nof_prb < 10 ? (cfi + 1) : cfi; + 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) { + nbits[i].nof_symb = 2 * SRSLTE_CP_EXT_NSYMB - nbits[0].lstart; + } 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) { - nbits[i].nof_symb = 2 * SRSLTE_CP_EXT_NSYMB - nbits[0].lstart; - } nbits[i].nof_bits = nbits[i].nof_re * grant->Qm[i]; } } diff --git a/lib/src/phy/phch/test/pmch_test.c b/lib/src/phy/phch/test/pmch_test.c index a9c29ef64..bf415e692 100644 --- a/lib/src/phy/phch/test/pmch_test.c +++ b/lib/src/phy/phch/test/pmch_test.c @@ -167,7 +167,6 @@ 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; diff --git a/lib/src/phy/phch/uci.c b/lib/src/phy/phch/uci.c index 4345824a7..0b9a54058 100644 --- a/lib/src/phy/phch/uci.c +++ b/lib/src/phy/phch/uci.c @@ -686,7 +686,9 @@ int srslte_uci_decode_ack(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_s } } - if (acks) { + if (nof_acks == 1 && acks) { + acks[0] = (uint8_t)(acks_sum[0] + acks_sum[1] + acks_sum[2] > 0); + } else if (acks) { acks[0] = (uint8_t)(acks_sum[0] > 0); acks[1] = (uint8_t)(acks_sum[1] > 0); // TODO: Do something with acks_sum[2] diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index 0f0307b0d..a677aa70d 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -608,7 +608,6 @@ 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; diff --git a/srsenb/hdr/mac/mac.h b/srsenb/hdr/mac/mac.h index 14269b0eb..4e37d439f 100644 --- a/srsenb/hdr/mac/mac.h +++ b/srsenb/hdr/mac/mac.h @@ -78,7 +78,7 @@ public: int pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value); int cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value); int snr_info(uint32_t tti, uint16_t rnti, float snr); - int ack_info(uint32_t tti, uint16_t rnti, bool ack); + int ack_info(uint32_t tti, uint16_t rnti, uint32_t tb_idx, bool ack); int crc_info(uint32_t tti, uint16_t rnti, uint32_t nof_bytes, bool crc_res); int get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res); diff --git a/srsenb/hdr/mac/scheduler.h b/srsenb/hdr/mac/scheduler.h index 898997449..c3ca7d624 100644 --- a/srsenb/hdr/mac/scheduler.h +++ b/srsenb/hdr/mac/scheduler.h @@ -104,7 +104,7 @@ public: int dl_mac_buffer_state(uint16_t rnti, uint32_t ce_code); int dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dedicated); - int dl_ack_info(uint32_t tti, uint16_t rnti, bool ack); + int dl_ack_info(uint32_t tti, uint16_t rnti, uint32_t tb_idx, bool ack); int dl_rach_info(uint32_t tti, uint32_t ra_id, uint16_t rnti, uint32_t estimated_size); int dl_ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value); int dl_pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value); diff --git a/srsenb/hdr/mac/scheduler_harq.h b/srsenb/hdr/mac/scheduler_harq.h index 9e1c65c78..211ec7d8d 100644 --- a/srsenb/hdr/mac/scheduler_harq.h +++ b/srsenb/hdr/mac/scheduler_harq.h @@ -58,7 +58,7 @@ protected: bool has_pending_retx_common(uint32_t tb_idx); bool ack[SRSLTE_MAX_TB]; - bool active; + bool active[SRSLTE_MAX_TB]; bool ndi[SRSLTE_MAX_TB]; uint32_t id; uint32_t max_retx; diff --git a/srsenb/hdr/mac/scheduler_ue.h b/srsenb/hdr/mac/scheduler_ue.h index 24ac06659..448e01954 100644 --- a/srsenb/hdr/mac/scheduler_ue.h +++ b/srsenb/hdr/mac/scheduler_ue.h @@ -73,7 +73,7 @@ public: void set_dl_ri(uint32_t tti, uint32_t ri); void set_dl_pmi(uint32_t tti, uint32_t ri); void set_dl_cqi(uint32_t tti, uint32_t cqi); - int set_ack_info(uint32_t tti, bool ack); + int set_ack_info(uint32_t tti, uint32_t tb_idx, bool ack); void set_ul_crc(uint32_t tti, bool crc_res); /******************************************************* diff --git a/srsenb/hdr/mac/ue.h b/srsenb/hdr/mac/ue.h index 33ec7150a..3550519e8 100644 --- a/srsenb/hdr/mac/ue.h +++ b/srsenb/hdr/mac/ue.h @@ -75,7 +75,7 @@ public: uint8_t* generate_pdu(sched_interface::dl_sched_pdu_t pdu[sched_interface::MAX_RLC_PDU_LIST], uint32_t nof_pdu_elems, uint32_t grant_size); - srslte_softbuffer_tx_t* get_tx_softbuffer(uint32_t harq_process); + srslte_softbuffer_tx_t* get_tx_softbuffer(uint32_t harq_process, uint32_t tb_idx); srslte_softbuffer_rx_t* get_rx_softbuffer(uint32_t tti); bool process_pdus(); @@ -122,9 +122,9 @@ private: uint32_t last_tti; - uint32_t nof_failures; - - const static int NOF_HARQ_PROCESSES = 2*HARQ_DELAY_MS; + uint32_t nof_failures; + + const static int NOF_HARQ_PROCESSES = 2 * HARQ_DELAY_MS * SRSLTE_MAX_TB; srslte_softbuffer_tx_t softbuffer_tx[NOF_HARQ_PROCESSES]; srslte_softbuffer_rx_t softbuffer_rx[NOF_HARQ_PROCESSES]; diff --git a/srsenb/hdr/phy/phch_common.h b/srsenb/hdr/phy/phch_common.h index c11a47938..950fd8fa1 100644 --- a/srsenb/hdr/phy/phch_common.h +++ b/srsenb/hdr/phy/phch_common.h @@ -83,7 +83,7 @@ public: // Map of pending ACKs for each user typedef struct { - bool is_pending[TTIMOD_SZ]; + bool is_pending[TTIMOD_SZ][SRSLTE_MAX_TB]; uint16_t n_pdcch[TTIMOD_SZ]; } pending_ack_t; std::map pending_ack; @@ -91,8 +91,8 @@ public: void ack_add_rnti(uint16_t rnti); void ack_rem_rnti(uint16_t rnti); void ack_clear(uint32_t sf_idx); - void ack_set_pending(uint32_t sf_idx, uint16_t rnti, uint32_t n_pdcch); - bool ack_is_pending(uint32_t sf_idx, uint16_t rnti, uint32_t *last_n_pdcch = NULL); + void ack_set_pending(uint32_t sf_idx, uint16_t rnti, uint32_t tb_idx, uint32_t n_pdcch); + bool ack_is_pending(uint32_t sf_idx, uint16_t rnti, uint32_t tb_idx, uint32_t *last_n_pdcch = NULL); private: std::vector tx_mutex; diff --git a/srsenb/hdr/phy/phch_worker.h b/srsenb/hdr/phy/phch_worker.h index 29483d961..2ffc090b6 100644 --- a/srsenb/hdr/phy/phch_worker.h +++ b/srsenb/hdr/phy/phch_worker.h @@ -106,8 +106,10 @@ private: dedicated_ack(false) {bzero(&metrics, sizeof(phy_metrics_t));} uint32_t I_sr; uint32_t pmi_idx; + uint32_t ri_idx; bool I_sr_en; bool cqi_en; + bool ri_en; bool pucch_cqi_ack; int has_grant_tti; LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT dedicated; diff --git a/srsenb/src/mac/mac.cc b/srsenb/src/mac/mac.cc index 0b6f65983..69ed37728 100644 --- a/srsenb/src/mac/mac.cc +++ b/srsenb/src/mac/mac.cc @@ -262,10 +262,10 @@ void mac::rl_ok(uint16_t rnti) } } -int mac::ack_info(uint32_t tti, uint16_t rnti, bool ack) +int mac::ack_info(uint32_t tti, uint16_t rnti, uint32_t tb_idx, bool ack) { log_h->step(tti); - uint32_t nof_bytes = scheduler.dl_ack_info(tti, rnti, ack); + uint32_t nof_bytes = scheduler.dl_ack_info(tti, rnti, tb_idx, ack); ue_db[rnti]->metrics_tx(ack, nof_bytes); if (ack) { @@ -474,25 +474,39 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) dl_sched_res->sched_grants[n].dci_format = sched_result.data[i].dci_format; memcpy(&dl_sched_res->sched_grants[n].grant, &sched_result.data[i].dci, sizeof(srslte_ra_dl_dci_t)); memcpy(&dl_sched_res->sched_grants[n].location, &sched_result.data[i].dci_location, sizeof(srslte_dci_location_t)); - - dl_sched_res->sched_grants[n].softbuffers[0] = ue_db[rnti]->get_tx_softbuffer(sched_result.data[i].dci.harq_process); - - // Get PDU if it's a new transmission - if (sched_result.data[i].nof_pdu_elems > 0) { - dl_sched_res->sched_grants[n].data[0] = ue_db[rnti]->generate_pdu(sched_result.data[i].pdu, - sched_result.data[i].nof_pdu_elems, - sched_result.data[i].tbs[0]); - if (pcap) { - pcap->write_dl_crnti(dl_sched_res->sched_grants[n].data[0], sched_result.data[i].tbs[0], rnti, true, tti); + for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { + if (sched_result.data[i].dci.tb_en[tb] && sched_result.data[i].nof_pdu_elems[tb] > 0) { + dl_sched_res->sched_grants[n].softbuffers[tb] = + ue_db[rnti]->get_tx_softbuffer(sched_result.data[i].dci.harq_process, tb); + + /* Get PDU if it's a new transmission */ + dl_sched_res->sched_grants[n].data[tb] = ue_db[rnti]->generate_pdu(sched_result.data[i].pdu[tb], + sched_result.data[i].nof_pdu_elems[tb], + sched_result.data[i].tbs[tb]); + + if (!dl_sched_res->sched_grants[n].data[tb]) { + Error("Error! PDU was not generated (rnti=0x%04x, tb=%d)\n", rnti, tb); + sched_result.data[i].dci.tb_en[tb] = false; + } + + if (pcap) { + pcap->write_dl_crnti(dl_sched_res->sched_grants[n].data[tb], sched_result.data[i].tbs[tb], rnti, true, tti); + } + + } else { + /* TB not enabled OR no data to send: set pointers to NULL */ + dl_sched_res->sched_grants[n].softbuffers[tb] = NULL; + dl_sched_res->sched_grants[n].data[tb] = NULL; + if (sched_result.data[i].dci.tb_en[tb]) { + Warning("Transport block without PDU elements (rnti: %04x)\n", rnti); + sched_result.data[i].dci.tb_en[tb] = false; + } } - - } else { - dl_sched_res->sched_grants[n].data[0] = NULL; } n++; } - + // Copy RAR grants for (uint32_t i=0;i= 0) { - log_h->info("SCHED: DL %s rnti=0x%x, pid=%d, mask=0x%x, dci=%d,%d, n_rtx=%d, tbs=%d, buffer=%d\n", + log_h->info("SCHED: DL %s rnti=0x%x, pid=%d, mask=0x%x, dci=%d,%d, n_rtx=%d, tbs=%d, buffer=%d, tb_en={%s,%s}\n", !is_newtx?"retx":"tx", rnti, h->get_id(), h->get_rbgmask(), - data[nof_data_elems].dci_location.L, data[nof_data_elems].dci_location.ncce, h->nof_retx(0), - tbs, user->get_pending_dl_new_data(current_tti)); + data[nof_data_elems].dci_location.L, data[nof_data_elems].dci_location.ncce, h->nof_retx(0) + h->nof_retx(1), + tbs, user->get_pending_dl_new_data(current_tti), data[nof_data_elems].dci.tb_en[0]?"y":"n", + data[nof_data_elems].dci.tb_en[1]?"y":"n"); nof_data_elems++; } else { log_h->warning("SCHED: Error DL %s rnti=0x%x, pid=%d, mask=0x%x, dci=%d,%d, tbs=%d, buffer=%d\n", @@ -675,7 +676,9 @@ int sched::dl_sched_data(dl_sched_data_t data[MAX_DATA_LIST]) tbs, user->get_pending_dl_new_data(current_tti)); } } else { - h->reset(0); + for(uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { + h->reset(tb); + } Warning("SCHED: Could not schedule DL DCI for rnti=0x%x, pid=%d\n", rnti, h->get_id()); } } diff --git a/srsenb/src/mac/scheduler_harq.cc b/srsenb/src/mac/scheduler_harq.cc index 85be81406..6e1596850 100644 --- a/srsenb/src/mac/scheduler_harq.cc +++ b/srsenb/src/mac/scheduler_harq.cc @@ -67,7 +67,7 @@ uint32_t harq_proc::get_id() void harq_proc::reset(uint32_t tb_idx) { - active = false; + active[tb_idx] = false; ack[tb_idx] = true; ack_received[tb_idx] = false; n_rtx[tb_idx] = 0; @@ -79,7 +79,7 @@ void harq_proc::reset(uint32_t tb_idx) bool harq_proc::is_empty(uint32_t tb_idx) { - return !active || (active && ack[tb_idx] && ack_received[tb_idx]); + return !active[tb_idx] || (active[tb_idx] && ack[tb_idx] && ack_received[tb_idx]); } bool harq_proc::has_pending_retx_common(uint32_t tb_idx) @@ -104,7 +104,7 @@ void harq_proc::set_ack(uint32_t tb_idx, bool ack_) log_h->debug("ACK=%d received pid=%d, tb_idx=%d, n_rtx=%d, max_retx=%d\n", ack_, id, tb_idx, n_rtx[tb_idx], max_retx); if (n_rtx[tb_idx] + 1 >= max_retx) { Warning("SCHED: discarting TB %d pid=%d, tti=%d, maximum number of retx exceeded (%d)\n", tb_idx, id, tti, max_retx); - active = false; + active[tb_idx] = false; } } @@ -118,9 +118,9 @@ void harq_proc::new_tx_common(uint32_t tb_idx, uint32_t tti_, int mcs, int tbs) last_tbs[tb_idx] = tbs; if (max_retx) { - active = true; + active[tb_idx] = true; } else { - active = false; // Can reuse this process if no retx are allowed + active[tb_idx] = false; // Can reuse this process if no retx are allowed } } @@ -227,10 +227,10 @@ bool ul_harq_proc::has_pending_ack() bool ret = need_ack; // Reset if already received a positive ACK - if (active && ack[0]) { - active = false; + if (active[0] && ack[0]) { + active[0] = false; } - if (!active) { + if (!active[0]) { need_ack = false; } return ret; @@ -240,7 +240,7 @@ bool ul_harq_proc::has_pending_ack() void ul_harq_proc::reset_pending_data() { - if (!active) { + if (!active[0]) { pending_data = 0; } } diff --git a/srsenb/src/mac/scheduler_ue.cc b/srsenb/src/mac/scheduler_ue.cc index 53d4c30cd..f7a1cc407 100644 --- a/srsenb/src/mac/scheduler_ue.cc +++ b/srsenb/src/mac/scheduler_ue.cc @@ -27,11 +27,7 @@ #include #include #include -#include -#include -#include -#include "srslte/srslte.h" #include "srslte/common/pdu.h" #include "mac/scheduler_ue.h" #include "mac/scheduler.h" @@ -109,8 +105,10 @@ void sched_ue::reset() ul_cqi_tti = 0; cqi_request_tti = 0; for (int i=0;ipdu[0].lcid = srslte::sch_subh::CON_RES_ID; - data->nof_pdu_elems++; + data->pdu[0][0].lcid = srslte::sch_subh::CON_RES_ID; + data->nof_pdu_elems[0]++; Info("SCHED: Added MAC Contention Resolution CE for rnti=0x%x\n", rnti); } int rem_tbs = tbs; int x = 0; do { - x = alloc_pdu(rem_tbs, &data->pdu[data->nof_pdu_elems]); + x = alloc_pdu(rem_tbs, &data->pdu[0][data->nof_pdu_elems[0]]); rem_tbs -= x; if (x) { - data->nof_pdu_elems++; + data->nof_pdu_elems[0]++; } } while(rem_tbs > 0 && x > 0); @@ -441,13 +439,14 @@ int sched_ue::generate_format1(dl_harq_proc *h, if (tbs > 0) { dci->harq_process = h->get_id(); - dci->mcs_idx = mcs; + dci->mcs_idx = (uint32_t) mcs; dci->rv_idx = sched::get_rvidx(h->nof_retx(0)); dci->ndi = h->get_ndi(0); - dci->tpc_pucch = next_tpc_pucch; + dci->tpc_pucch = (uint8_t) next_tpc_pucch; next_tpc_pucch = 1; - data->tbs[0] = tbs; - dci->tb_en[0] = true; + data->tbs[0] = (uint32_t) tbs; + data->tbs[1] = 0; + dci->tb_en[0] = true; dci->tb_en[1] = false; } return tbs; @@ -464,60 +463,90 @@ int sched_ue::generate_format2a(dl_harq_proc *h, uint32_t sf_idx = tti%10; - int mcs = 0; - int tbs = 0; - dci->alloc_type = SRSLTE_RA_ALLOC_TYPE0; dci->type0_alloc.rbg_bitmask = h->get_rbgmask(); - if (h->is_empty(0)) { + uint32_t nof_prb = format1_count_prb(h->get_rbgmask(), cell.nof_prb); + uint32_t nof_ctrl_symbols = cfi + (cell.nof_prb < 10 ? 1 : 0); + srslte_ra_dl_grant_t grant; + srslte_ra_dl_dci_to_grant_prb_allocation(dci, &grant, cell.nof_prb); + uint32_t nof_re = srslte_ra_dl_grant_nof_re(&grant, cell, sf_idx, nof_ctrl_symbols); + uint32_t req_bytes = get_pending_dl_new_data(tti); + + for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { + int mcs = 0; + int tbs = 0; + + /* + * If one layer (RI = 0) Then + * If TB1 has pending harq + * Send TB1 only + * Else + * Send TB0 Only + * End If + * Else (RI != 0) + * Send TB0 and TB1 + * End If + */ + if (dl_ri == 1 || (dl_ri == 0 && ((tb == 0 && h->is_empty(1)) || (tb == 1 && !h->is_empty(1))))) { + if (h->is_empty(tb)) { + if (fixed_mcs_dl < 0) { + tbs = alloc_tbs_dl(nof_prb, nof_re, req_bytes, &mcs); + } else { + tbs = srslte_ra_tbs_from_idx((uint32_t) srslte_ra_tbs_idx_from_mcs((uint32_t) fixed_mcs_dl), nof_prb) / 8; + mcs = fixed_mcs_dl; + } - uint32_t req_bytes = get_pending_dl_new_data(tti); + h->new_tx(tb, tti, mcs, tbs, data->dci_location.ncce); - uint32_t nof_prb = format1_count_prb(h->get_rbgmask(), cell.nof_prb); - srslte_ra_dl_grant_t grant; - srslte_ra_dl_dci_to_grant_prb_allocation(dci, &grant, cell.nof_prb); - uint32_t nof_ctrl_symbols = cfi+(cell.nof_prb<10?1:0); - uint32_t nof_re = srslte_ra_dl_grant_nof_re(&grant, cell, sf_idx, nof_ctrl_symbols); - if (fixed_mcs_dl < 0) { - tbs = alloc_tbs_dl(nof_prb, nof_re, req_bytes, &mcs); - } else { - tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_dl), nof_prb)/8; - mcs = fixed_mcs_dl; + Debug("SCHED: Alloc format2/2a new mcs=%d, tbs=%d, nof_prb=%d, req_bytes=%d\n", mcs, tbs, nof_prb, req_bytes); + } else { + h->new_retx(tb, tti, &mcs, &tbs); + Debug("SCHED: Alloc format2/2a previous mcs=%d, tbs=%d\n", mcs, tbs); + } } - h->new_tx(0, tti, mcs, tbs, data->dci_location.ncce); + int rem_tbs = tbs; + int x = 0; + do { + x = alloc_pdu(rem_tbs, &data->pdu[tb][data->nof_pdu_elems[tb]]); + rem_tbs -= x; + if (x) { + data->nof_pdu_elems[tb]++; + } + } while (rem_tbs > 0 && x > 0); - Debug("SCHED: Alloc format1 new mcs=%d, tbs=%d, nof_prb=%d, req_bytes=%d\n", mcs, tbs, nof_prb, req_bytes); - } else { - h->new_retx(0, tti, &mcs, &tbs); - Debug("SCHED: Alloc format1 previous mcs=%d, tbs=%d\n", mcs, tbs); - } + data->rnti = rnti; - int rem_tbs = tbs; - int x = 0; - do { - x = alloc_pdu(rem_tbs, &data->pdu[data->nof_pdu_elems]); - rem_tbs -= x; - if (x) { - data->nof_pdu_elems++; + if (tbs > 0 && data->nof_pdu_elems[tb]) { + if (tb == 0) { + dci->mcs_idx = (uint32_t) mcs; + dci->rv_idx = sched::get_rvidx(h->nof_retx(tb)); + dci->ndi = h->get_ndi(tb); + } else { + dci->mcs_idx_1 = (uint32_t) mcs; + dci->rv_idx_1 = sched::get_rvidx(h->nof_retx(tb)); + dci->ndi_1 = h->get_ndi(tb); + } + data->tbs[tb] = (uint32_t) tbs; + dci->tb_en[tb] = true; + } else { + data->tbs[tb] = 0; + dci->tb_en[tb] = false; } - } while(rem_tbs > 0 && x > 0); - data->rnti = rnti; - - if (tbs > 0) { - dci->harq_process = h->get_id(); - dci->mcs_idx = mcs; - dci->rv_idx = sched::get_rvidx(h->nof_retx(0)); - dci->ndi = h->get_ndi(0); - dci->tpc_pucch = next_tpc_pucch; - next_tpc_pucch = 1; - data->tbs[0] = tbs; - dci->tb_en[0] = true; - dci->tb_en[1] = false; + if ( req_bytes > (uint32_t) tbs) { + req_bytes -= tbs; + } else { + req_bytes = 0; + } } - return tbs; + + dci->harq_process = h->get_id(); + dci->tpc_pucch = (uint8_t) next_tpc_pucch; + next_tpc_pucch = 1; + + return data->tbs[0] + data->tbs[1]; } // Generates a Format2 grant @@ -526,71 +555,17 @@ int sched_ue::generate_format2(dl_harq_proc *h, uint32_t tti, uint32_t cfi) { - srslte_ra_dl_dci_t *dci = &data->dci; - bzero(dci, sizeof(srslte_ra_dl_dci_t)); - - uint32_t sf_idx = tti%10; - - int mcs = 0; - int tbs = 0; - - dci->alloc_type = SRSLTE_RA_ALLOC_TYPE0; - dci->type0_alloc.rbg_bitmask = h->get_rbgmask(); - - if (h->is_empty(0)) { - - uint32_t req_bytes = get_pending_dl_new_data(tti); - - uint32_t nof_prb = format1_count_prb(h->get_rbgmask(), cell.nof_prb); - srslte_ra_dl_grant_t grant; - srslte_ra_dl_dci_to_grant_prb_allocation(dci, &grant, cell.nof_prb); - uint32_t nof_ctrl_symbols = cfi+(cell.nof_prb<10?1:0); - uint32_t nof_re = srslte_ra_dl_grant_nof_re(&grant, cell, sf_idx, nof_ctrl_symbols); - if (fixed_mcs_dl < 0) { - tbs = alloc_tbs_dl(nof_prb, nof_re, req_bytes, &mcs); - } else { - tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_dl), nof_prb)/8; - mcs = fixed_mcs_dl; - } + /* Call Format 2a (common) */ + int ret = generate_format2a(h, data, tti, cfi); - h->new_tx(0, tti, mcs, tbs, data->dci_location.ncce); - - Debug("SCHED: Alloc format2 new mcs=%d, tbs=%d, nof_prb=%d, req_bytes=%d\n", mcs, tbs, nof_prb, req_bytes); + /* Compute precoding information */ + if (SRSLTE_RA_DL_GRANT_NOF_TB(&data->dci) == 1) { + data->dci.pinfo = (uint8_t) (dl_pmi + 1) % (uint8_t) 5; } else { - h->new_retx(0, tti, &mcs, &tbs); - Debug("SCHED: Alloc format2 previous mcs=%d, tbs=%d\n", mcs, tbs); + data->dci.pinfo = (uint8_t) (dl_pmi & 1); } - int rem_tbs = tbs; - int x = 0; - do { - x = alloc_pdu(rem_tbs, &data->pdu[data->nof_pdu_elems]); - rem_tbs -= x; - if (x) { - data->nof_pdu_elems++; - } - } while(rem_tbs > 0 && x > 0); - - data->rnti = rnti; - - if (tbs > 0) { - dci->pinfo = (uint8_t) (dl_pmi + 1); -/* if (SRSLTE_RA_DL_GRANT_NOF_TB(dci) == 1) { - dci->pinfo = (uint8_t) (dl_pmi + 1); - } else { - dci->pinfo = (uint8_t) (dl_pmi & 1); - }*/ - dci->harq_process = h->get_id(); - dci->mcs_idx = mcs; - dci->rv_idx = sched::get_rvidx(h->nof_retx(0)); - dci->ndi = h->get_ndi(0); - dci->tpc_pucch = next_tpc_pucch; - next_tpc_pucch = 1; - data->tbs[0] = tbs; - dci->tb_en[0] = true; - dci->tb_en[1] = false; - } - return tbs; + return ret; } @@ -818,7 +793,7 @@ dl_harq_proc* sched_ue::get_pending_dl_harq(uint32_t tti) int oldest_idx=-1; uint32_t oldest_tti = 0; for (int i=0;i oldest_tti) { oldest_idx = i; @@ -839,7 +814,7 @@ dl_harq_proc* sched_ue::get_pending_dl_harq(uint32_t tti) dl_harq_proc* sched_ue::get_empty_dl_harq() { for (int i=0;i -#include #define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) #define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) @@ -98,14 +97,18 @@ void phch_common::ack_clear(uint32_t sf_idx) { for(std::map::iterator iter=pending_ack.begin(); iter!=pending_ack.end(); ++iter) { pending_ack_t *p = (pending_ack_t*) &iter->second; - p->is_pending[sf_idx] = false; + for (uint32_t tb_idx = 0; tb_idx < SRSLTE_MAX_TB; tb_idx++) { + p->is_pending[sf_idx][tb_idx] = false; + } } } void phch_common::ack_add_rnti(uint16_t rnti) { for (int sf_idx=0;sf_idxcqi_report_cnfg.report_periodic_setup_present; uint32_t pmi_idx = dedicated->cqi_report_cnfg.report_periodic.pmi_cnfg_idx; bool pucch_cqi_ack = dedicated->cqi_report_cnfg.report_periodic.simult_ack_nack_and_cqi; + bool pucch_ri = dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx_present; + uint32_t ri_idx = dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx; pthread_mutex_lock(&mutex); if (ue_db.count(rnti)) { @@ -255,6 +257,14 @@ void phch_worker::set_config_dedicated(uint16_t rnti, ue_db[rnti].cqi_en = false; } + if (pucch_ri) { + ue_db[rnti].ri_idx = ri_idx; + ue_db[rnti].ri_en = true; + } else { + ue_db[rnti].ri_idx = 0; + ue_db[rnti].ri_en = false; + } + /* Copy all dedicated RRC configuration to UE */ memcpy(&ue_db[rnti].dedicated, dedicated, sizeof(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT)); } else { @@ -355,8 +365,15 @@ void phch_worker::work_imp() phy->ack_clear(TTIMOD(TTI_TX(t_tx_dl))); for (uint32_t i=0;i= SRSLTE_CRNTI_START && dl_grants[t_tx_dl].sched_grants[i].rnti <= SRSLTE_CRNTI_END) { - phy->ack_set_pending(TTIMOD(TTI_TX(t_tx_dl)), dl_grants[t_tx_dl].sched_grants[i].rnti, dl_grants[t_tx_dl].sched_grants[i].location.ncce); + uint16_t rnti = dl_grants[t_tx_dl].sched_grants[i].rnti; + if (rnti >= SRSLTE_CRNTI_START && rnti <= SRSLTE_CRNTI_END) { + /* For each TB */ + for (uint32_t tb_idx = 0; tb_idx < SRSLTE_MAX_TB; tb_idx++) { + /* If TB enabled, set pending ACK */ + if (dl_grants[t_tx_dl].sched_grants[i].grant.tb_en[tb_idx]) { + phy->ack_set_pending(TTIMOD(TTI_TX(t_tx_dl)), rnti, tb_idx, dl_grants[t_tx_dl].sched_grants[i].location.ncce); + } + } } } @@ -407,17 +424,33 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) gettimeofday(&t[1], NULL); #endif + bool acks_pending[SRSLTE_MAX_TB] = {false}; + // Get pending ACKs with an associated PUSCH transmission - if (phy->ack_is_pending(t_rx, rnti)) { - uci_data.uci_ack_len = 1; + for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { + acks_pending[tb] = phy->ack_is_pending(t_rx, rnti, tb); + if (acks_pending[tb]) { + uci_data.uci_ack_len++; + } } + // Configure PUSCH CQI channel srslte_cqi_value_t cqi_value; - bool cqi_enabled = false; - if (ue_db[rnti].cqi_en && srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) { + bool cqi_enabled = false, ri_enabled = false; +#if 0 + if (ue_db[rnti].cqi_en && ue_db[rnti].ri_en && srslte_ri_send(ue_db[rnti].pmi_idx, ue_db[rnti].ri_idx, tti_rx) ) { + uci_data.uci_ri_len = 1; /* Asumes only 1 bit for RI */ + ri_enabled = true; + } else if (ue_db[rnti].cqi_en && srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) { cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND; cqi_enabled = true; - } else if (grants[i].grant.cqi_request) { + if (ue_db[rnti].dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { + //uci_data.uci_dif_cqi_len = 3; + uci_data.uci_pmi_len = 2; + } + } else +#endif + if (grants[i].grant.cqi_request) { cqi_value.type = SRSLTE_CQI_TYPE_SUBBAND_HL; cqi_value.subband_hl.N = (phy->cell.nof_prb > 7) ? srslte_cqi_hl_get_no_subbands(phy->cell.nof_prb) : 0; cqi_enabled = true; @@ -485,14 +518,16 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) } */ log_h->info_hex(grants[i].data, phy_grant.mcs.tbs/8, - "PUSCH: rnti=0x%x, prb=(%d,%d), tbs=%d, mcs=%d, rv=%d, snr=%.1f dB, n_iter=%d, crc=%s%s%s%s\n", + "PUSCH: rnti=0x%x, prb=(%d,%d), tbs=%d, mcs=%d, rv=%d, snr=%.1f dB, n_iter=%d, crc=%s%s%s%s%s\n", rnti, phy_grant.n_prb[0], phy_grant.n_prb[0]+phy_grant.L_prb, phy_grant.mcs.tbs/8, phy_grant.mcs.idx, grants[i].grant.rv_idx, snr_db, srslte_pusch_last_noi(&enb_ul.pusch), crc_res?"OK":"KO", - uci_data.uci_ack_len>0?(uci_data.uci_ack?", ack=1":", ack=0"):"", + (uci_data.uci_ack_len)?(uci_data.uci_ack?"1":"0"):"", + (uci_data.uci_ack_len > 1)?(uci_data.uci_ack_2?"1":"0"):"", uci_data.uci_cqi_len>0?cqi_str:"", + uci_data.uci_ri_len>0?(uci_data.uci_ri?", ri=0":", ri=1"):"", timestr); // Notify MAC of RL status @@ -507,8 +542,13 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) // Notify MAC new received data and HARQ Indication value phy->mac->crc_info(tti_rx, rnti, phy_grant.mcs.tbs/8, crc_res); - if (uci_data.uci_ack_len) { - phy->mac->ack_info(tti_rx, rnti, uci_data.uci_ack && (crc_res || snr_db > PUSCH_RL_SNR_DB_TH)); + uint32_t ack_idx = 0; + for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { + if (acks_pending[tb]) { + bool ack = ((ack_idx++ == 0) ? uci_data.uci_ack : uci_data.uci_ack_2); + bool valid = (crc_res || snr_db > PUSCH_RL_SNR_DB_TH); + phy->mac->ack_info(tti_rx, rnti, tb, ack && valid); + } } // Notify MAC of UL SNR and DL CQI @@ -536,7 +576,8 @@ int phch_worker::decode_pucch() if (rnti >= SRSLTE_CRNTI_START && rnti <= SRSLTE_CRNTI_END && ue_db[rnti].has_grant_tti != (int) tti_rx) { // Check if user needs to receive PUCCH - bool needs_pucch = false, needs_ack=false, needs_sr=false, needs_cqi=false, needs_ri=false; + bool needs_pucch = false, needs_ack[SRSLTE_MAX_TB] = {false}, needs_sr = false, needs_cqi = false, + needs_ri = false; uint32_t last_n_pdcch = 0; bzero(&uci_data, sizeof(srslte_uci_data_t)); @@ -548,23 +589,23 @@ int phch_worker::decode_pucch() } } - if (phy->ack_is_pending(t_rx, rnti, &last_n_pdcch)) { - needs_pucch = true; - needs_ack = true; - uci_data.uci_ack_len = 1; + for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { + needs_ack[tb] = phy->ack_is_pending(t_rx, rnti, tb, &last_n_pdcch); + if (needs_ack[tb]) { + needs_pucch = true; + uci_data.uci_ack_len++; + } } srslte_cqi_value_t cqi_value; LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *dedicated = &ue_db[rnti].dedicated; LIBLTE_RRC_TRANSMISSION_MODE_ENUM tx_mode = dedicated->antenna_info_explicit_value.tx_mode; - bool ri_report_present = dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx_present; - uint32_t pmi_idx = dedicated->cqi_report_cnfg.report_periodic.pmi_cnfg_idx; - uint32_t ri_idx = dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx; - if (ue_db[rnti].cqi_en && (ue_db[rnti].pucch_cqi_ack || !needs_ack)) { - if (ri_report_present && srslte_ri_send(pmi_idx, ri_idx, tti_rx)) { + if (ue_db[rnti].cqi_en && (ue_db[rnti].pucch_cqi_ack || !needs_ack[0] || !needs_ack[1])) { + if (ue_db[rnti].ri_en && srslte_ri_send(ue_db[rnti].pmi_idx, ue_db[rnti].ri_idx, tti_rx)) { needs_pucch = true; needs_ri = true; uci_data.uci_ri_len = 1; + uci_data.ri_periodic_report = true; } else if (srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) { needs_pucch = true; needs_cqi = true; @@ -582,8 +623,14 @@ int phch_worker::decode_pucch() fprintf(stderr, "Error getting PUCCH\n"); return SRSLTE_ERROR; } - if (uci_data.uci_ack_len > 0) { - phy->mac->ack_info(tti_rx, rnti, uci_data.uci_ack && (srslte_pucch_get_last_corr(&enb_ul.pucch) >= PUCCH_RL_CORR_TH)); + /* If only one ACK is required, it can be for TB0 or TB1 */ + uint32_t ack_idx = 0; + for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { + if (needs_ack[tb]) { + bool ack = ((ack_idx++ == 0) ? uci_data.uci_ack : uci_data.uci_ack_2); + bool valid = srslte_pucch_get_last_corr(&enb_ul.pucch) >= PUCCH_RL_CORR_TH; + phy->mac->ack_info(tti_rx, rnti, tb, ack && valid); + } } if (uci_data.scheduling_request) { phy->mac->sr_detected(tti_rx, rnti); @@ -609,12 +656,13 @@ int phch_worker::decode_pucch() } } - log_h->info("PUCCH: rnti=0x%x, corr=%.2f, n_pucch=%d, n_prb=%d%s%s%s\n", + log_h->info("PUCCH: rnti=0x%x, corr=%.2f, n_pucch=%d, n_prb=%d%s%s%s%s\n", rnti, srslte_pucch_get_last_corr(&enb_ul.pucch), enb_ul.pucch.last_n_pucch, enb_ul.pucch.last_n_prb, - needs_ack?(uci_data.uci_ack?", ack=1":", ack=0"):"", - needs_sr?(uci_data.scheduling_request?", sr=yes":", sr=no"):"", + (uci_data.uci_ack_len)?(uci_data.uci_ack?", ack=1":", ack=0"):"", + (uci_data.uci_ack_len > 1)?(uci_data.uci_ack_2?"1":"0"):"", + needs_sr?(uci_data.scheduling_request?", sr=yes":", sr=no"):"", (needs_cqi || needs_ri)?cqi_ri_str:""); @@ -728,7 +776,7 @@ int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants break; case SRSLTE_DCI_FORMAT2A: if (SRSLTE_RA_DL_GRANT_NOF_TB(&phy_grant) == 1) { - mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY; + mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY; } else if (SRSLTE_RA_DL_GRANT_NOF_TB(&phy_grant) == 2) { mimo_type = SRSLTE_MIMO_TYPE_CDD; } @@ -765,26 +813,29 @@ int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants if (dci_format == SRSLTE_DCI_FORMAT2) { snprintf(pinfo_str, 15, ", pinfo=%x", phy_grant.pinfo); } + char tbstr[SRSLTE_MAX_TB][128]; + for (int tb = 0; tb < SRSLTE_MAX_TB; tb++) { + if (phy_grant.tb_en[tb]) { + snprintf(tbstr[tb], 128, ", TB%d: tbs=%d, mcs=%d, rv=%d%s%s", + tb, + phy_grant.mcs[tb].tbs / 8, + phy_grant.mcs[tb].idx, + (tb == 0) ? grants[i].grant.rv_idx : grants[i].grant.rv_idx_1, + grants[i].softbuffers[tb]==NULL?", \e[31msoftbuffer=NULL\e[0m":"", + grants[i].data[tb]==NULL?", \e[31mdata=NULL\e[0m":""); + } else { + tbstr[tb][0] = '\0'; + } + } log_h->info_hex(ptr, len, - "PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tbs=%d, mcs=%d, rv=%d, tti_tx_dl=%d, tx_scheme=%s%s\n", - rnti, phy_grant.nof_prb, grant_str, grants[i].grant.harq_process, - phy_grant.mcs[0].tbs / 8, phy_grant.mcs[0].idx, grants[i].grant.rv_idx, tti_tx_dl, - srslte_mimotype2str(mimo_type), pinfo_str); - } - - srslte_softbuffer_tx_t *sb[SRSLTE_MAX_CODEWORDS]; - uint8_t *d[SRSLTE_MAX_CODEWORDS]; - int rv[SRSLTE_MAX_CODEWORDS]; - - for (int tb = 0; tb < 2; tb++) { - sb[tb] = grants[tb].softbuffers[tb]; - d[tb] = grants[tb].data[tb]; + "PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tti_tx_dl=%d, tx_scheme=%s%s%s%s\n", + rnti, phy_grant.nof_prb, grant_str, grants[i].grant.harq_process, tti_tx_dl, + srslte_mimotype2str(mimo_type), pinfo_str, tbstr[0], tbstr[1]); } - rv[0] = grants[i].grant.rv_idx; - rv[1] = grants[i].grant.rv_idx_1; + int rv[SRSLTE_MAX_CODEWORDS] = {grants[i].grant.rv_idx, grants[i].grant.rv_idx_1}; - if (srslte_enb_dl_put_pdsch(&enb_dl, &phy_grant, sb, rnti, rv, sf_tx, d, mimo_type)) { + if (srslte_enb_dl_put_pdsch(&enb_dl, &phy_grant, grants[i].softbuffers, rnti, rv, sf_tx, grants[i].data, mimo_type)) { fprintf(stderr, "Error putting PDSCH %d\n", i); return SRSLTE_ERROR; } diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 45b89ca82..0f9dd6602 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -389,7 +389,7 @@ void phch_worker::compute_ri() { uci_data.uci_dif_cqi_len = 3; } srslte_bit_unpack_vector(&packed_pmi, uci_data.uci_pmi, uci_data.uci_pmi_len); - Info("pmi=%d\n", packed_pmi); + Info("ri=%d; pmi=%d; SINR=%.1fdB\n", ue_dl.ri, ue_dl.pmi[ue_dl.ri], 10*log10f(ue_dl.sinr[ue_dl.ri][ue_dl.pmi[ue_dl.ri]])); /* If only one antenna in TM4 print limitation warning */ if (ue_dl.nof_rx_antennas < 2) { @@ -604,7 +604,8 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL /* Setup PDSCH configuration for this CFI, SFIDX and RVIDX */ if (valid_config) { if (!srslte_ue_dl_cfg_grant(&ue_dl, grant, cfi, tti%10, rv, mimo_type)) { - if (ue_dl.pdsch_cfg.grant.mcs[0].mod > 0 && ue_dl.pdsch_cfg.grant.mcs[0].tbs >= 0) { + if ((ue_dl.pdsch_cfg.grant.mcs[0].mod > 0 && ue_dl.pdsch_cfg.grant.mcs[0].tbs >= 0) || + (ue_dl.pdsch_cfg.grant.mcs[1].mod > 0 && ue_dl.pdsch_cfg.grant.mcs[1].tbs >= 0)) { float noise_estimate = srslte_chest_dl_get_noise_estimate(&ue_dl.chest); @@ -796,21 +797,15 @@ void phch_worker::reset_uci() void phch_worker::set_uci_ack(bool ack[SRSLTE_MAX_CODEWORDS], bool tb_en[SRSLTE_MAX_CODEWORDS]) { - uint32_t nof_tb = 0; - if (tb_en[0]) { - uci_data.uci_ack = (uint8_t) ((ack[0]) ? 1 : 0); - nof_tb = 1; - } else { - uci_data.uci_ack = 1; - } - - if (tb_en[1]) { - uci_data.uci_ack_2 = (uint8_t) ((ack[1]) ? 1 : 0); - nof_tb = 2; + /* Map ACK according to 3GPP 36.212 clause 5.2.3.1 */ + uint32_t nof_ack = 0; + for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { + if (tb_en[tb]) { + ((nof_ack == 0)?uci_data.uci_ack:uci_data.uci_ack_2) = (uint8_t)(ack[tb]?1:0); + nof_ack++; + } } - - uci_data.uci_ack_len = nof_tb; - + uci_data.uci_ack_len = nof_ack; } void phch_worker::set_uci_sr() From 646f949d7706ddefcb425a99cdbf812029b29b87 Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Wed, 8 Nov 2017 16:19:32 +0000 Subject: [PATCH 111/242] Fix for debug inline issue --- lib/src/phy/resampling/resample_arb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/phy/resampling/resample_arb.c b/lib/src/phy/resampling/resample_arb.c index 2b04f587c..441e8c0dc 100644 --- a/lib/src/phy/resampling/resample_arb.c +++ b/lib/src/phy/resampling/resample_arb.c @@ -106,7 +106,7 @@ float srslte_resample_arb_polyfilt[SRSLTE_RESAMPLE_ARB_N][SRSLTE_RESAMPLE_ARB_M] {0.000764085430796, -0.030612377229395, 0.154765509342932, 0.702921418438421, 0.206204344739138, -0.034615802155152, 0.000568080243211, 0.000003596427925}, {0.000722236729272, -0.032053439082436, 0.171322660416961, 0.704261032406613, 0.188481383863832, -0.033395686652146, 0.000657994314549 , 0.000002955485215}}; -inline cf_t srslte_resample_arb_dot_prod(cf_t* x, float *y, int len){ +static inline cf_t srslte_resample_arb_dot_prod(cf_t* x, float *y, int len){ cf_t res1 = srslte_vec_dot_prod_cfc(x,y,len); return res1; From 0c9db8013d8aa13916856eb96c68e0401f798046 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 9 Nov 2017 07:45:41 +0100 Subject: [PATCH 112/242] Log TA commands --- srsue/src/phy/phy.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 9760ab374..fe5528d79 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -201,7 +201,7 @@ 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); + Info("PHY: 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() From d59bd77d4058c4ebc5dd8773a13ff3872dfab159 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 9 Nov 2017 07:45:41 +0100 Subject: [PATCH 113/242] Log TA commands --- srsue/src/phy/phy.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 9760ab374..fe5528d79 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -201,7 +201,7 @@ 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); + Info("PHY: 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() From 69682d488b1abd2919b81ad736cc81ce9f19c20d Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 9 Nov 2017 15:08:46 +0100 Subject: [PATCH 114/242] eNB: Do not consider CQI/RI if PUCCH has low correlation --- srsenb/src/phy/phch_worker.cc | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index 4d70853b5..abd7961ce 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -637,24 +637,25 @@ int phch_worker::decode_pucch() } char cqi_ri_str[64]; - if (uci_data.uci_ri_len && needs_ri) { - phy->mac->ri_info(tti_rx, rnti, uci_data.uci_ri); - sprintf(cqi_ri_str, ", ri=%d", uci_data.uci_ri); - } else if (uci_data.uci_cqi_len && needs_cqi) { - srslte_cqi_value_unpack(uci_data.uci_cqi, &cqi_value); - phy->mac->cqi_info(tti_rx, rnti, cqi_value.wideband.wideband_cqi); - sprintf(cqi_ri_str, ", cqi=%d", cqi_value.wideband.wideband_cqi); - - if (uci_data.uci_pmi_len) { - uint8_t *ptr = uci_data.uci_pmi; - uint32_t packed_pmi = uci_data.uci_pmi[0]; - if (uci_data.uci_pmi_len > 1) { - packed_pmi = (packed_pmi << 1) + uci_data.uci_pmi[1]; + if (srslte_pucch_get_last_corr(&enb_ul.pucch) > PUCCH_RL_CORR_TH) { + if (uci_data.uci_ri_len && needs_ri) { + phy->mac->ri_info(tti_rx, rnti, uci_data.uci_ri); + sprintf(cqi_ri_str, ", ri=%d", uci_data.uci_ri); + } else if (uci_data.uci_cqi_len && needs_cqi) { + srslte_cqi_value_unpack(uci_data.uci_cqi, &cqi_value); + phy->mac->cqi_info(tti_rx, rnti, cqi_value.wideband.wideband_cqi); + sprintf(cqi_ri_str, ", cqi=%d", cqi_value.wideband.wideband_cqi); + + if (uci_data.uci_pmi_len) { + uint32_t packed_pmi = uci_data.uci_pmi[0]; + if (uci_data.uci_pmi_len > 1) { + packed_pmi = (packed_pmi << 1) + uci_data.uci_pmi[1]; + } + phy->mac->pmi_info(tti_rx, rnti, packed_pmi); + sprintf(cqi_ri_str, "%s, pmi=%c", cqi_ri_str, packed_pmi + 0x30); } - phy->mac->pmi_info(tti_rx, rnti, packed_pmi); - sprintf(cqi_ri_str, "%s, pmi=%c", cqi_ri_str, packed_pmi + 0x30); - } + } } log_h->info("PUCCH: rnti=0x%x, corr=%.2f, n_pucch=%d, n_prb=%d%s%s%s%s\n", rnti, From 42626a112032eadf32ed29c4d4cb682a749dba6d Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 9 Nov 2017 15:10:03 +0100 Subject: [PATCH 115/242] eNB: retransmissions in Diversity mode --- srsenb/src/mac/scheduler_ue.cc | 38 +++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/srsenb/src/mac/scheduler_ue.cc b/srsenb/src/mac/scheduler_ue.cc index f7a1cc407..1d84031a1 100644 --- a/srsenb/src/mac/scheduler_ue.cc +++ b/srsenb/src/mac/scheduler_ue.cc @@ -458,6 +458,7 @@ int sched_ue::generate_format2a(dl_harq_proc *h, uint32_t tti, uint32_t cfi) { + bool tb_en[SRSLTE_MAX_TB] = {false}; srslte_ra_dl_dci_t *dci = &data->dci; bzero(dci, sizeof(srslte_ra_dl_dci_t)); @@ -473,22 +474,35 @@ int sched_ue::generate_format2a(dl_harq_proc *h, uint32_t nof_re = srslte_ra_dl_grant_nof_re(&grant, cell, sf_idx, nof_ctrl_symbols); uint32_t req_bytes = get_pending_dl_new_data(tti); + if (dl_ri == 0) { + if (h->is_empty(1)) { + /* One layer, tb1 buffer is empty, send tb0 only */ + tb_en[0] = true; + } else { + /* One layer, tb1 buffer is not empty, send tb1 only */ + tb_en[1] = true; + } + } else { + /* Two layers, retransmit what TBs that have not been Acknowledged */ + bool no_retx = true; + for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { + if (!h->is_empty(tb)) { + tb_en[tb] = true; + no_retx = false; + } + } + /* Two layers, no retransmissions... */ + if (no_retx) { + tb_en[0] = true; + tb_en[1] = true; + } + } + for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { int mcs = 0; int tbs = 0; - /* - * If one layer (RI = 0) Then - * If TB1 has pending harq - * Send TB1 only - * Else - * Send TB0 Only - * End If - * Else (RI != 0) - * Send TB0 and TB1 - * End If - */ - if (dl_ri == 1 || (dl_ri == 0 && ((tb == 0 && h->is_empty(1)) || (tb == 1 && !h->is_empty(1))))) { + if (tb_en[tb]) { if (h->is_empty(tb)) { if (fixed_mcs_dl < 0) { tbs = alloc_tbs_dl(nof_prb, nof_re, req_bytes, &mcs); From 650cc0788cace56760bab0d7d38234c020543245 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 9 Nov 2017 15:10:49 +0100 Subject: [PATCH 116/242] eNB: Added RI metrics trace --- srsenb/src/mac/ue.cc | 2 +- srsenb/src/metrics_stdout.cc | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/srsenb/src/mac/ue.cc b/srsenb/src/mac/ue.cc index a389e7aeb..d41afaf73 100644 --- a/srsenb/src/mac/ue.cc +++ b/srsenb/src/mac/ue.cc @@ -408,7 +408,7 @@ void ue::metrics_phr(float phr) { } void ue::metrics_dl_ri(uint32_t dl_ri) { - metrics.dl_ri = SRSLTE_VEC_CMA((float) dl_ri, metrics.dl_ri, dl_ri_counter); + metrics.dl_ri = SRSLTE_VEC_EMA((float) dl_ri, metrics.dl_ri, 0.5f); dl_ri_counter++; } diff --git a/srsenb/src/metrics_stdout.cc b/srsenb/src/metrics_stdout.cc index ec55b0dcf..efea243f1 100644 --- a/srsenb/src/metrics_stdout.cc +++ b/srsenb/src/metrics_stdout.cc @@ -108,8 +108,8 @@ void metrics_stdout::print_metrics() { n_reports = 0; cout << endl; - cout << "------DL-------------------------UL-------------------------------" << endl; - cout << "rnti cqi mcs brate bler snr phr mcs brate bler bsr" << endl; + cout << "------DL-------------------------------UL--------------------------------" << endl; + cout << "rnti cqi ri mcs brate bler snr phr mcs brate bler bsr" << endl; } if (metrics.rrc.n_ues > 0) { @@ -123,6 +123,7 @@ void metrics_stdout::print_metrics() cout << std::hex << metrics.mac[i].rnti << " "; cout << float_to_string(metrics.mac[i].dl_cqi, 2); + cout << float_to_string(metrics.mac[i].dl_ri + 1, 3); cout << float_to_string(metrics.phy[i].dl.mcs, 2); if (metrics.mac[i].tx_brate > 0 && metrics_report_period) { cout << float_to_eng_string((float) metrics.mac[i].tx_brate/metrics_report_period, 2); From 2b0a4fa2d05c19f05d7f1017db1393e7befd5536 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 9 Nov 2017 15:42:02 +0100 Subject: [PATCH 117/242] eNB: solved sched-pdsch bug --- lib/src/phy/phch/pdsch.c | 5 ----- srsenb/src/mac/mac.cc | 11 +++-------- srsenb/src/mac/scheduler_ue.cc | 27 ++++++++++++++------------- 3 files changed, 17 insertions(+), 26 deletions(-) diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index 6479b5abd..1b3a3859d 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -555,11 +555,6 @@ static int srslte_pdsch_codeword_encode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *c valid_inputs = false; } - if (!data) { - ERROR("Error encoding (TB%d -> CW%d), data=NULL", tb_idx, codeword_idx); - valid_inputs = false; - } - if (nbits->nof_bits && valid_inputs) { 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, diff --git a/srsenb/src/mac/mac.cc b/srsenb/src/mac/mac.cc index 69ed37728..80c5e1ddf 100644 --- a/srsenb/src/mac/mac.cc +++ b/srsenb/src/mac/mac.cc @@ -476,10 +476,10 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) memcpy(&dl_sched_res->sched_grants[n].location, &sched_result.data[i].dci_location, sizeof(srslte_dci_location_t)); for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { - if (sched_result.data[i].dci.tb_en[tb] && sched_result.data[i].nof_pdu_elems[tb] > 0) { - dl_sched_res->sched_grants[n].softbuffers[tb] = - ue_db[rnti]->get_tx_softbuffer(sched_result.data[i].dci.harq_process, tb); + dl_sched_res->sched_grants[n].softbuffers[tb] = + ue_db[rnti]->get_tx_softbuffer(sched_result.data[i].dci.harq_process, tb); + if (sched_result.data[i].nof_pdu_elems[tb] > 0) { /* Get PDU if it's a new transmission */ dl_sched_res->sched_grants[n].data[tb] = ue_db[rnti]->generate_pdu(sched_result.data[i].pdu[tb], sched_result.data[i].nof_pdu_elems[tb], @@ -496,12 +496,7 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) } else { /* TB not enabled OR no data to send: set pointers to NULL */ - dl_sched_res->sched_grants[n].softbuffers[tb] = NULL; dl_sched_res->sched_grants[n].data[tb] = NULL; - if (sched_result.data[i].dci.tb_en[tb]) { - Warning("Transport block without PDU elements (rnti: %04x)\n", rnti); - sched_result.data[i].dci.tb_en[tb] = false; - } } } n++; diff --git a/srsenb/src/mac/scheduler_ue.cc b/srsenb/src/mac/scheduler_ue.cc index 1d84031a1..44c3d3185 100644 --- a/srsenb/src/mac/scheduler_ue.cc +++ b/srsenb/src/mac/scheduler_ue.cc @@ -513,6 +513,16 @@ int sched_ue::generate_format2a(dl_harq_proc *h, h->new_tx(tb, tti, mcs, tbs, data->dci_location.ncce); + int rem_tbs = tbs; + int x = 0; + do { + x = alloc_pdu(rem_tbs, &data->pdu[tb][data->nof_pdu_elems[tb]]); + rem_tbs -= x; + if (x) { + data->nof_pdu_elems[tb]++; + } + } while (rem_tbs > 0 && x > 0); + Debug("SCHED: Alloc format2/2a new mcs=%d, tbs=%d, nof_prb=%d, req_bytes=%d\n", mcs, tbs, nof_prb, req_bytes); } else { h->new_retx(tb, tti, &mcs, &tbs); @@ -520,19 +530,8 @@ int sched_ue::generate_format2a(dl_harq_proc *h, } } - int rem_tbs = tbs; - int x = 0; - do { - x = alloc_pdu(rem_tbs, &data->pdu[tb][data->nof_pdu_elems[tb]]); - rem_tbs -= x; - if (x) { - data->nof_pdu_elems[tb]++; - } - } while (rem_tbs > 0 && x > 0); - - data->rnti = rnti; - - if (tbs > 0 && data->nof_pdu_elems[tb]) { + /* Fill DCI TB dedicated fields */ + if (tbs > 0) { if (tb == 0) { dci->mcs_idx = (uint32_t) mcs; dci->rv_idx = sched::get_rvidx(h->nof_retx(tb)); @@ -556,6 +555,8 @@ int sched_ue::generate_format2a(dl_harq_proc *h, } } + /* Fill common fields */ + data->rnti = rnti; dci->harq_process = h->get_id(); dci->tpc_pucch = (uint8_t) next_tpc_pucch; next_tpc_pucch = 1; From f00a75262859be8c2ab659ed9174663573c9323c Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 9 Nov 2017 16:08:18 +0100 Subject: [PATCH 118/242] Fixed bug in PDSCH retx in srsENB --- srsenb/src/mac/scheduler_ue.cc | 47 +++++++++++++++------------------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/srsenb/src/mac/scheduler_ue.cc b/srsenb/src/mac/scheduler_ue.cc index 94056b990..7a810e2cc 100644 --- a/srsenb/src/mac/scheduler_ue.cc +++ b/srsenb/src/mac/scheduler_ue.cc @@ -25,11 +25,6 @@ */ #include -#include -#include -#include -#include -#include #include "srslte/srslte.h" #include "srslte/common/pdu.h" @@ -395,32 +390,32 @@ int sched_ue::generate_format1(dl_harq_proc *h, mcs = fixed_mcs_dl; } - h->new_tx(tti, mcs, tbs, data->dci_location.ncce); - + h->new_tx(tti, mcs, tbs, data->dci_location.ncce); + + // Allocate MAC ConRes CE + if (need_conres_ce) { + data->pdu[0].lcid = srslte::sch_subh::CON_RES_ID; + data->nof_pdu_elems++; + Info("SCHED: Added MAC Contention Resolution CE for rnti=0x%x\n", rnti); + } + + int rem_tbs = tbs; + int x = 0; + do { + x = alloc_pdu(rem_tbs, &data->pdu[data->nof_pdu_elems]); + rem_tbs -= x; + if (x) { + data->nof_pdu_elems++; + } + } while(rem_tbs > 0 && x > 0); + Debug("SCHED: Alloc format1 new mcs=%d, tbs=%d, nof_prb=%d, req_bytes=%d\n", mcs, tbs, nof_prb, req_bytes); } else { h->new_retx(tti, &mcs, &tbs); Debug("SCHED: Alloc format1 previous mcs=%d, tbs=%d\n", mcs, tbs); } - - // Allocate MAC ConRes CE - if (need_conres_ce) { - data->pdu[0].lcid = srslte::sch_subh::CON_RES_ID; - data->nof_pdu_elems++; - Info("SCHED: Added MAC Contention Resolution CE for rnti=0x%x\n", rnti); - } - - int rem_tbs = tbs; - int x = 0; - do { - x = alloc_pdu(rem_tbs, &data->pdu[data->nof_pdu_elems]); - rem_tbs -= x; - if (x) { - data->nof_pdu_elems++; - } - } while(rem_tbs > 0 && x > 0); - - data->rnti = rnti; + + data->rnti = rnti; if (tbs > 0) { dci->harq_process = h->get_id(); From 84db67860829397137c1a3af3b448d823a2b3bb1 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 9 Nov 2017 16:18:59 +0100 Subject: [PATCH 119/242] Fixed Format1C RV with P-RNTI --- lib/src/phy/phch/ra.c | 11 ++++++----- srsue/src/phy/phch_worker.cc | 5 ++++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/src/phy/phch/ra.c b/lib/src/phy/phch/ra.c index 735794e35..17866f5d3 100644 --- a/lib/src/phy/phch/ra.c +++ b/lib/src/phy/phch/ra.c @@ -590,11 +590,12 @@ int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t *dci, 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) - { - dci->rv_idx = 0; - } + if (dci->dci_is_1c) { + if ((msg_rnti >= SRSLTE_RARNTI_START && msg_rnti <= SRSLTE_RARNTI_END) || msg_rnti == SRSLTE_PRNTI) + { + dci->rv_idx = 0; + } + } } else { return SRSLTE_ERROR; } diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index cf0eab94c..3629424ac 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -535,7 +535,7 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { if (grant->tb_en[tb] && (rv[tb] < 0 || rv[tb] > 3)) { valid_config = false; - Error("Wrong RV (%d) for TB index %d", rv[tb], tb); + Error("Wrong RV (%d) for TB index %d\n", rv[tb], tb); } } @@ -645,6 +645,9 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL Error("Error configuring DL grant\n"); ret = SRSLTE_ERROR; } + } else { + Error("Error invalid DL config\n"); + ret = SRSLTE_ERROR; } return ret; } From aedec8638da9a2a4ef1e95e7b7e0a605d63443b6 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 9 Nov 2017 17:43:13 +0100 Subject: [PATCH 120/242] Fixed TA command when negative offset --- srsue/src/phy/phy.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index fe5528d79..6dfb2c6d7 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -199,9 +199,10 @@ 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); - Info("PHY: Set TA: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, ((float) n_ta)*SRSLTE_LTE_TS*1e6); + uint32_t new_nta = srslte_N_ta_new(n_ta, ta_cmd); + sf_recv.set_time_adv_sec(((float) (new_nta - n_ta))*SRSLTE_LTE_TS); + Info("PHY: Set TA: ta_cmd: %d, n_ta: %d, old_n_ta: %d, ta_usec: %.1f\n", ta_cmd, new_nta, n_ta, ((float) new_nta)*SRSLTE_LTE_TS*1e6); + n_ta = new_nta; } void phy::configure_prach_params() From aeb16a5b7a24f4af9554c56df0ad7c80db0a003f Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 9 Nov 2017 17:43:13 +0100 Subject: [PATCH 121/242] Fixed TA command when negative offset --- srsue/src/phy/phy.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index fe5528d79..6dfb2c6d7 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -199,9 +199,10 @@ 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); - Info("PHY: Set TA: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, ((float) n_ta)*SRSLTE_LTE_TS*1e6); + uint32_t new_nta = srslte_N_ta_new(n_ta, ta_cmd); + sf_recv.set_time_adv_sec(((float) (new_nta - n_ta))*SRSLTE_LTE_TS); + Info("PHY: Set TA: ta_cmd: %d, n_ta: %d, old_n_ta: %d, ta_usec: %.1f\n", ta_cmd, new_nta, n_ta, ((float) new_nta)*SRSLTE_LTE_TS*1e6); + n_ta = new_nta; } void phy::configure_prach_params() From a992fcf6079ce6f3391be2f1f0aab9dc389246e7 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 10 Nov 2017 07:42:45 +0100 Subject: [PATCH 122/242] Fix concurrent access segfault in RLC AM --- lib/src/upper/rlc_am.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index 05f35ad76..96405e22a 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -296,8 +296,9 @@ int rlc_am::read_pdu(uint8_t *payload, uint32_t nof_bytes) } // RETX if required if(retx_queue.size() > 0) { + int ret = build_retx_pdu(payload, nof_bytes); pthread_mutex_unlock(&mutex); - return build_retx_pdu(payload, nof_bytes); + return ret; } // Build a PDU from SDUs From bf32d45b6fbfc0ba7b1ba88994cbf06d5f38d8b3 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 10 Nov 2017 07:54:30 +0100 Subject: [PATCH 123/242] Check valid nof_tb before call to pdsch and log instead of print --- srsue/src/phy/phch_worker.cc | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 3629424ac..a8ffeabcb 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -539,10 +539,15 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL } } + uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(grant); switch(phy->config->dedicated.antenna_info_explicit_value.tx_mode) { /* Implemented Tx Modes */ case LIBLTE_RRC_TRANSMISSION_MODE_1: mimo_type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA; + if (nof_tb != 1) { + Error("Wrong number of transport blocks (%d) for single antenna.", nof_tb); + valid_config = false; + } break; case LIBLTE_RRC_TRANSMISSION_MODE_2: if (cell.nof_ports > 1) { @@ -550,26 +555,30 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL } else { mimo_type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA; } + if (nof_tb != 1) { + Error("Wrong number of transport blocks (%d) for transmit diversity.", nof_tb); + valid_config = false; + } break; case LIBLTE_RRC_TRANSMISSION_MODE_3: - if (SRSLTE_RA_DL_GRANT_NOF_TB(grant) == 1) { + if (nof_tb == 1) { mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY; - } else if (ue_dl.nof_rx_antennas > 1 && SRSLTE_RA_DL_GRANT_NOF_TB(grant) == 2) { + } else if (ue_dl.nof_rx_antennas > 1 && nof_tb == 2) { mimo_type = SRSLTE_MIMO_TYPE_CDD; } else { Error("Wrong combination of antennas (%d) or transport blocks (%d) for TM3\n", ue_dl.nof_rx_antennas, - SRSLTE_RA_DL_GRANT_NOF_TB(grant)); + nof_tb); valid_config = false; } break; case LIBLTE_RRC_TRANSMISSION_MODE_4: - if (SRSLTE_RA_DL_GRANT_NOF_TB(grant) == 1) { + if (nof_tb == 1) { mimo_type = (grant->pinfo == 0) ? SRSLTE_MIMO_TYPE_TX_DIVERSITY : SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX; - } else if (ue_dl.nof_rx_antennas > 1 && SRSLTE_RA_DL_GRANT_NOF_TB(grant) == 2) { + } else if (ue_dl.nof_rx_antennas > 1 && nof_tb == 2) { mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX; } else { Error("Wrong combination of antennas (%d) or transport blocks (%d) for TM3\n", ue_dl.nof_rx_antennas, - SRSLTE_RA_DL_GRANT_NOF_TB(grant)); + nof_tb); valid_config = false; } break; From e983987563128be7ff70da3cbc1d9fddb03bfe3a Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 10 Nov 2017 09:09:46 +0100 Subject: [PATCH 124/242] Check retx.sn exists in tx_window in required buffer size --- lib/src/upper/rlc_am.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index 96405e22a..0d3d8e426 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -1148,7 +1148,13 @@ bool rlc_am::add_segment_and_check(rlc_amd_rx_pdu_segments_t *pdu, rlc_amd_rx_pd int rlc_am::required_buffer_size(rlc_amd_retx_t retx) { if(!retx.is_segment){ - return rlc_am_packed_length(&tx_window[retx.sn].header) + tx_window[retx.sn].buf->N_bytes; + if (tx_window.count(retx.sn)) { + return rlc_am_packed_length(&tx_window[retx.sn].header) + tx_window[retx.sn].buf->N_bytes; + } else { + log->console("retx.sn=%d does not exist\n"); + log->warning("retx.sn=%d does not exist in required_buffer_size()\n"); + return -1; + } } // Construct new header From 05973790ba8d800b811a86a6821523b4d1de5bfe Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 10 Nov 2017 12:39:28 +0100 Subject: [PATCH 125/242] Add checks for existence of retx buffer and remove from queue if not --- lib/src/upper/rlc_am.cc | 53 +++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index 0d3d8e426..b6599f24a 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -201,8 +201,14 @@ uint32_t rlc_am::get_total_buffer_state() rlc_amd_retx_t retx = retx_queue.front(); log->debug("Buffer state - retx - SN: %d, Segment: %s, %d:%d\n", retx.sn, retx.is_segment ? "true" : "false", retx.so_start, retx.so_end); if(tx_window.end() != tx_window.find(retx.sn)) { - n_bytes += required_buffer_size(retx); + int req_bytes = required_buffer_size(retx); + if (req_bytes < 0) { + log->error("In get_total_buffer_state(): Removing retx.sn=%d from queue\n", retx.sn); + retx_queue.pop_front(); + } else { + n_bytes += req_bytes; log->debug("Buffer state - retx: %d bytes\n", n_bytes); + } } } @@ -250,7 +256,13 @@ uint32_t rlc_am::get_buffer_state() rlc_amd_retx_t retx = retx_queue.front(); log->debug("Buffer state - retx - SN: %d, Segment: %s, %d:%d\n", retx.sn, retx.is_segment ? "true" : "false", retx.so_start, retx.so_end); if(tx_window.end() != tx_window.find(retx.sn)) { - n_bytes = required_buffer_size(retx); + int req_bytes = required_buffer_size(retx); + if (req_bytes < 0) { + log->error("In get_buffer_state(): Removing retx.sn=%d from queue\n", retx.sn); + retx_queue.pop_front(); + goto unlock_and_return; + } + n_bytes = (uint32_t) req_bytes; log->debug("Buffer state - retx: %d bytes\n", n_bytes); goto unlock_and_return; } @@ -439,16 +451,33 @@ int rlc_am::build_status_pdu(uint8_t *payload, uint32_t nof_bytes) int rlc_am::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes) { + // Check there is at least 1 element before calling front() + if (retx_queue.empty()) { + log->error("In build_retx_pdu(): retx_queue is empty\n"); + return -1; + } + rlc_amd_retx_t retx = retx_queue.front(); // Sanity check - drop any retx SNs not present in tx_window while(tx_window.end() == tx_window.find(retx.sn)) { retx_queue.pop_front(); - retx = retx_queue.front(); + if (!retx_queue.empty()) { + retx = retx_queue.front(); + } else { + log->error("In build_retx_pdu(): retx_queue is empty during sanity check\n"); + return -1; + } } // Is resegmentation needed? - if(retx.is_segment || required_buffer_size(retx) > (int)nof_bytes) { + int req_size = required_buffer_size(retx); + if (req_size < 0) { + log->error("In build_retx_pdu(): Removing retx.sn=%d from queue\n", retx.sn); + retx_queue.pop_front(); + return -1; + } + if(retx.is_segment || req_size > (int)nof_bytes) { log->debug("%s build_retx_pdu - resegmentation required\n", rrc->get_rb_name(lcid).c_str()); return build_segment(payload, nof_bytes, retx); } @@ -482,6 +511,10 @@ int rlc_am::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes) int rlc_am::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_amd_retx_t retx) { + if (!tx_window[retx.sn].buf) { + log->error("In build_segment: retx.sn=%d has null buffer\n", retx.sn); + return 0; + } if(!retx.is_segment){ retx.so_start = 0; retx.so_end = tx_window[retx.sn].buf->N_bytes; @@ -1149,10 +1182,16 @@ int rlc_am::required_buffer_size(rlc_amd_retx_t retx) { if(!retx.is_segment){ if (tx_window.count(retx.sn)) { - return rlc_am_packed_length(&tx_window[retx.sn].header) + tx_window[retx.sn].buf->N_bytes; + if (tx_window[retx.sn].buf) { + return rlc_am_packed_length(&tx_window[retx.sn].header) + tx_window[retx.sn].buf->N_bytes; + } else { + log->console("retx.sn=%d has null ptr\n", retx.sn); + log->warning("retx.sn=%d has null ptr in required_buffer_size()\n", retx.sn); + return -1; + } } else { - log->console("retx.sn=%d does not exist\n"); - log->warning("retx.sn=%d does not exist in required_buffer_size()\n"); + log->console("retx.sn=%d does not exist\n", retx.sn); + log->warning("retx.sn=%d does not exist in required_buffer_size()\n", retx.sn); return -1; } } From 42d08046d372ce2446547a95cbf41663ddd37a64 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 10 Nov 2017 17:59:35 +0100 Subject: [PATCH 126/242] Fixed bug with UL adaptive retx --- lib/include/srslte/common/common.h | 1 + srsue/hdr/mac/ul_harq.h | 6 ++++-- srsue/src/phy/phch_worker.cc | 26 +++++++++++++++----------- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/lib/include/srslte/common/common.h b/lib/include/srslte/common/common.h index 6372af73e..c450fc1d0 100644 --- a/lib/include/srslte/common/common.h +++ b/lib/include/srslte/common/common.h @@ -46,6 +46,7 @@ #define HARQ_DELAY_MS 4 #define MSG3_DELAY_MS 2 // Delay added to HARQ_DELAY_MS +#define TTI_RX(tti) (tti>HARQ_DELAY_MS?((tti-HARQ_DELAY_MS)%10240):(10240+tti-HARQ_DELAY_MS)) #define TTI_TX(tti) ((tti+HARQ_DELAY_MS)%10240) #define TTI_RX_ACK(tti) ((tti+(2*HARQ_DELAY_MS))%10240) diff --git a/srsue/hdr/mac/ul_harq.h b/srsue/hdr/mac/ul_harq.h index 4749971b6..50143a571 100644 --- a/srsue/hdr/mac/ul_harq.h +++ b/srsue/hdr/mac/ul_harq.h @@ -219,7 +219,7 @@ private: // Receive and route HARQ feedbacks if (grant) { - if ((!(grant->rnti_type == SRSLTE_RNTI_TEMP) && grant->ndi[0] != get_ndi()) || + if ((!(grant->rnti_type == SRSLTE_RNTI_TEMP) && grant->ndi[0] != get_ndi() && grant->phy_grant.ul.mcs.idx < 29) || (grant->rnti_type == SRSLTE_RNTI_USER && !has_grant()) || grant->is_from_rar) { @@ -245,7 +245,7 @@ private: Warning("Uplink grant but no MAC PDU in Multiplex Unit buffer\n"); } } - } else { + } else if (has_grant()) { // Adaptive Re-TX if (current_tx_nb >= max_retx) { Info("UL %d: Maximum number of ReTX reached (%d). Discarting TB.\n", pid, max_retx); @@ -254,6 +254,8 @@ private: } else { generate_retx(tti_tx, grant, action); } + } else { + Warning("UL %d: Received mcs=%d but no previous grant available for this PID.\n", pid, grant->phy_grant.ul.mcs.idx); } } else if (has_grant()) { // Non-Adaptive Re-Tx diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index a8ffeabcb..ff7412d77 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -27,6 +27,7 @@ #include #include #include "phy/phch_worker.h" +#include "srslte/srslte.h" #include "srslte/interfaces/ue_interfaces.h" #include "srslte/asn1/liblte_rrc.h" @@ -40,8 +41,6 @@ #ifdef ENABLE_GUI #include "srsgui/srsgui.h" #include -#include "srslte/srslte.h" -#include "srslte/interfaces/ue_interfaces.h" void init_plots(srsue::phch_worker *worker); pthread_t plot_thread; @@ -323,9 +322,9 @@ void phch_worker::work_imp() ul_action.tti_offset = HARQ_DELAY_MS; /* Send UL grant or HARQ information (from PHICH) to MAC */ - if (ul_grant_available && ul_ack_available) { + if (ul_grant_available && ul_ack_available && ul_mac_grant.phy_grant.ul.mcs.idx < 29) { phy->mac->new_grant_ul_ack(ul_mac_grant, ul_ack, &ul_action); - } else if (ul_grant_available && !ul_ack_available) { + } else if (ul_grant_available && (!ul_ack_available || ul_mac_grant.phy_grant.ul.mcs.idx < 29)) { phy->mac->new_grant_ul(ul_mac_grant, &ul_action); } else if (!ul_grant_available && ul_ack_available) { phy->mac->harq_recv(tti, ul_ack, &ul_action); @@ -480,11 +479,15 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant) 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) + // Set last TBS for this TB (pid) in case of mcs>28 (7.1.7.2 of 36.213) for (int i=0;iphy_grant.dl.mcs[i].tbs < 0) { + if (grant->phy_grant.dl.mcs[i].idx > 28) { grant->phy_grant.dl.mcs[i].tbs = last_dl_tbs[grant->pid%(2*HARQ_DELAY_MS)][i]; } + if(grant->phy_grant.dl.mcs[i].tbs < 0) { + Info("Invalid TBS size for PDSCH grant\n"); + grant->phy_grant.dl.mcs[i].tbs = 0; + } // save it last_dl_tbs[grant->pid%(2*HARQ_DELAY_MS)][i] = grant->phy_grant.dl.mcs[i].tbs; } @@ -743,16 +746,17 @@ bool phch_worker::decode_pdcch_ul(mac_interface_phy::mac_grant_t* grant) 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)]; + if (grant->phy_grant.ul.mcs.idx > 28) { + grant->phy_grant.ul.mcs.tbs = last_ul_tbs[TTI_RX(tti)%(2*HARQ_DELAY_MS)]; + Info("RETX: mcs=%d, old_tbs=%d pid=%d\n", grant->phy_grant.ul.mcs.idx, grant->phy_grant.ul.mcs.tbs, TTI_TX(tti)%(2*HARQ_DELAY_MS)); } - last_ul_tbs[tti%(2*HARQ_DELAY_MS)] = grant->phy_grant.ul.mcs.tbs; + last_ul_tbs[TTI_RX(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.mcs.mod = last_ul_mod[TTI_RX(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; + last_ul_mod[TTI_RX(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 */ From 9389cc1957116784b2ff0670bd3793d36087784e Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 10 Nov 2017 17:59:43 +0100 Subject: [PATCH 127/242] Removed deallocating unkown buffer error --- lib/include/srslte/common/buffer_pool.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/include/srslte/common/buffer_pool.h b/lib/include/srslte/common/buffer_pool.h index 1c6dfc53a..567203c75 100644 --- a/lib/include/srslte/common/buffer_pool.h +++ b/lib/include/srslte/common/buffer_pool.h @@ -123,8 +123,6 @@ public: used.erase(elem); available.push(b); ret = true; - } else { - printf("Error deallocating from buffer pool: buffer not created in this pool.\n"); } pthread_mutex_unlock(&mutex); return ret; From 9cf95f5c32c90044eb33cb659430145aff68cbab Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 10 Nov 2017 18:00:05 +0100 Subject: [PATCH 128/242] Attempt to reset timer regardless of N310 --- srsue/hdr/upper/rrc.h | 2 ++ srsue/src/upper/rrc.cc | 13 ++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index 3e2fb70dd..0e123e988 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -127,6 +127,8 @@ private: // RRC constants and timers srslte::mac_interface_timers *mac_timers; + uint32_t sync_reset_cnt; + const static uint32_t SYNC_RESET_TIMEOUT = 10; uint32_t n310_cnt, N310; uint32_t n311_cnt, N311; uint32_t t301, t310, t311; diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 10373dcf2..7b4bef710 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -48,6 +48,9 @@ rrc::rrc() :state(RRC_STATE_IDLE) ,drb_up(false) { + sync_reset_cnt = 0; + n310_cnt = 0; + n311_cnt = 0; } static void liblte_rrc_handler(void *ctx, char *str) { @@ -489,13 +492,17 @@ void rrc::earfcn_end() { // Detection of physical layer problems (5.3.11.1) void rrc::out_of_sync() { + // attempt resync + sync_reset_cnt++; + if (sync_reset_cnt >= SYNC_RESET_TIMEOUT) { + rrc_log->info("Detected %d out-of-sync from PHY. Resynchronizing PHY.\n", sync_reset_cnt); + phy->sync_reset(); + sync_reset_cnt = 0; + } 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(); - mac_timers->timer_get(t310)->reset(); mac_timers->timer_get(t310)->run(); n310_cnt = 0; From 4eb5ee5c582e5fa83bfc9e4ce8f754495d9b94ad Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 10 Nov 2017 18:01:32 +0100 Subject: [PATCH 129/242] Removed console debugging messages --- lib/src/upper/rlc_am.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index b6599f24a..f8abc0aef 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -1185,12 +1185,10 @@ int rlc_am::required_buffer_size(rlc_amd_retx_t retx) if (tx_window[retx.sn].buf) { return rlc_am_packed_length(&tx_window[retx.sn].header) + tx_window[retx.sn].buf->N_bytes; } else { - log->console("retx.sn=%d has null ptr\n", retx.sn); log->warning("retx.sn=%d has null ptr in required_buffer_size()\n", retx.sn); return -1; } } else { - log->console("retx.sn=%d does not exist\n", retx.sn); log->warning("retx.sn=%d does not exist in required_buffer_size()\n", retx.sn); return -1; } From 710cb583b0fe696a3b403c8ed0f838ba2a83b7a9 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 10 Nov 2017 18:02:34 +0100 Subject: [PATCH 130/242] Make last pdu in grant to use all available space. Fixes when 1 byte is in RLC AM but grant is 3 bytes (header is 2) --- srsue/src/mac/mux.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/srsue/src/mac/mux.cc b/srsue/src/mac/mux.cc index e38300b87..957c257a1 100644 --- a/srsue/src/mac/mux.cc +++ b/srsue/src/mac/mux.cc @@ -286,7 +286,7 @@ bool mux::sched_sdu(lchid_t *ch, int *sdu_space, int max_sdu_sz) } log_h->info("SDU: scheduled lcid=%d, rlc_buffer=%d, allocated=%d/%d\n", - ch->id, ch->buffer_len, sched_len, *sdu_space); + ch->id, ch->buffer_len, sched_len, sdu_space?*sdu_space:0); *sdu_space -= sched_len; ch->buffer_len -= sched_len; @@ -309,12 +309,11 @@ bool mux::allocate_sdu(uint32_t lcid, srslte::sch_pdu* pdu_msg, int max_sdu_sz) sdu_len = max_sdu_sz; } int sdu_space = pdu_msg->get_sdu_space(); - if (sdu_len > sdu_space) { + if (sdu_len > sdu_space || max_sdu_sz < 0) { sdu_len = sdu_space; - } + } if (sdu_len > MIN_RLC_SDU_LEN) { if (pdu_msg->new_subh()) { // there is space for a new subheader - int sdu_len2 = sdu_len; sdu_len = pdu_msg->get()->set_sdu(lcid, sdu_len, rlc); if (sdu_len > 0) { // new SDU could be added From e5f78b16204bbe9f5a0b7bc14590827a73fe352c Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 10 Nov 2017 19:11:15 +0100 Subject: [PATCH 131/242] Print error to console if security/integrity not supported --- srsue/src/upper/nas.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index 110c8c78e..d8bd40c6e 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -480,6 +480,7 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu) { sec_mode_cmd.nas_ksi.tsc_flag != LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE) { sec_mode_rej.emm_cause = LIBLTE_MME_EMM_CAUSE_UE_SECURITY_CAPABILITIES_MISMATCH; nas_log->warning("Sending Security Mode Reject due to security capabilities mismatch\n"); + nas_log->console("Unsupported Security Mode Command settings: use ciphering algorithm EEA0 and integrity check EIA1 or EIA2.\n"); success = false; } else { // Generate NAS encryption key and integrity protection key From 344ace8f52289c50caf61459cb5ff6ddec891fe4 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sun, 12 Nov 2017 11:43:56 +0100 Subject: [PATCH 132/242] Fix issue #120 --- lib/src/phy/phch/ra.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/phy/phch/ra.c b/lib/src/phy/phch/ra.c index be10c304c..19b78c60a 100644 --- a/lib/src/phy/phch/ra.c +++ b/lib/src/phy/phch/ra.c @@ -663,7 +663,7 @@ uint32_t srslte_ra_type1_N_rb(uint32_t nof_prb) { /* Convert Type2 scheduling L_crb and RB_start to RIV value */ uint32_t srslte_ra_type2_to_riv(uint32_t L_crb, uint32_t RB_start, uint32_t nof_prb) { uint32_t riv; - if (L_crb <= nof_prb / 2) { + if ((L_crb - 1) <= nof_prb / 2) { riv = nof_prb * (L_crb - 1) + RB_start; } else { riv = nof_prb * (nof_prb - L_crb + 1) + nof_prb - 1 - RB_start; @@ -907,4 +907,4 @@ void srslte_ra_prb_fprint(FILE *f, srslte_ra_dl_grant_t *grant) { } } -} \ No newline at end of file +} From b23be658cc2efdd84f290164360871037fb38d70 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 13 Nov 2017 10:14:11 +0100 Subject: [PATCH 133/242] Added PDSCH decoder maximum bitrate (from DSP execution time) --- lib/examples/pdsch_ue.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/lib/examples/pdsch_ue.c b/lib/examples/pdsch_ue.c index bf4414f08..681b75566 100644 --- a/lib/examples/pdsch_ue.c +++ b/lib/examples/pdsch_ue.c @@ -326,7 +326,8 @@ srslte_netsink_t net_sink, net_sink_signal; #define PRINT_LINE_ADVANCE_CURSOR() printf("\033[%dB", prev_nof_lines + 1) int main(int argc, char **argv) { - int ret; + struct timeval t[3]; + int ret; int decimate = 1; srslte_cell_t cell; int64_t sf_cnt; @@ -559,7 +560,7 @@ int main(int argc, char **argv) { // Variables for measurements uint32_t nframes=0; uint8_t ri = 0, pmi = 0; - float rsrp0=0.0, rsrp1=0.0, rsrq=0.0, noise=0.0, enodebrate = 0.0, uerate = 0.0, + float rsrp0=0.0, rsrp1=0.0, rsrq=0.0, noise=0.0, enodebrate = 0.0, uerate = 0.0, procrate = 0.0, sinr[SRSLTE_MAX_LAYERS][SRSLTE_MAX_CODEBOOKS], cn = 0.0; bool decode_pdsch = false; @@ -655,6 +656,7 @@ int main(int argc, char **argv) { decode_pdsch = false; } } + gettimeofday(&t[1], NULL); if (decode_pdsch) { if(sfidx != 1 || prog_args.mbsfn_area_id < 0){ // Not an MBSFN subframe if (cell.nof_ports == 1) { @@ -690,6 +692,8 @@ int main(int argc, char **argv) { INFO("mbsfn PDU size is %d\n", n); } } + gettimeofday(&t[2], NULL); + get_time_interval(t); if (n < 0) { // fprintf(stderr, "Error decoding UE DL\n");fflush(stdout); } else if (n > 0) { @@ -723,16 +727,19 @@ int main(int argc, char **argv) { } - nof_trials++; - - + nof_trials++; + + uint32_t nof_bits = ((acks[0]?ue_dl.pdsch_cfg.grant.mcs[0].tbs:0) + (acks[1]?ue_dl.pdsch_cfg.grant.mcs[1].tbs:0)); rsrq = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrq(&ue_dl.chest), rsrq, 0.1f); rsrp0 = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp_port(&ue_dl.chest, 0), rsrp0, 0.05f); rsrp1 = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp_port(&ue_dl.chest, 1), rsrp1, 0.05f); noise = SRSLTE_VEC_EMA(srslte_chest_dl_get_noise_estimate(&ue_dl.chest), noise, 0.05f); - enodebrate = SRSLTE_VEC_EMA((ue_dl.pdsch_cfg.grant.mcs[0].tbs + ue_dl.pdsch_cfg.grant.mcs[1].tbs)/1000.0f, enodebrate, 0.05f); - uerate = SRSLTE_VEC_EMA(((acks[0]?ue_dl.pdsch_cfg.grant.mcs[0].tbs:0) + (acks[1]?ue_dl.pdsch_cfg.grant.mcs[1].tbs:0))/1000.0f, uerate, 0.01f); - + enodebrate = SRSLTE_VEC_EMA(nof_bits/1000.0f, enodebrate, 0.05f); + uerate = SRSLTE_VEC_EMA(nof_bits/1000.0f, uerate, 0.001f); + float elapsed = (float) t[0].tv_usec + t[0].tv_sec*1.0e+6f; + if (elapsed != 0.0f) { + procrate = SRSLTE_VEC_EMA(nof_bits/elapsed, procrate, 0.01f); + } nframes++; if (isnan(rsrq)) { @@ -769,7 +776,7 @@ int main(int argc, char **argv) { PRINT_LINE("nof codewords: %d", SRSLTE_RA_DL_GRANT_NOF_TB(&ue_dl.pdsch_cfg.grant)); PRINT_LINE(" CFO: %+5.2f kHz", srslte_ue_sync_get_cfo(&ue_sync) / 1000); PRINT_LINE(" SNR: %+5.1f dB | %+5.1f dB", 10 * log10(rsrp0 / noise), 10 * log10(rsrp1 / noise)); - PRINT_LINE(" Rb: %6.2f / %6.2f Mbps (net/maximum)", uerate, enodebrate); + PRINT_LINE(" Rb: %6.2f / %6.2f / %6.2f Mbps (net/maximum/processing)", uerate, enodebrate, procrate); PRINT_LINE(" PDCCH-Miss: %5.2f%%", 100 * (1 - (float) ue_dl.nof_detected / nof_trials)); PRINT_LINE(" PDSCH-BLER: %5.2f%%", (float) 100 * ue_dl.pdsch_pkt_errors / ue_dl.pdsch_pkts_total); if(prog_args.mbsfn_area_id > -1){ From ca07f0064dcf3d7cde67a8bfb1be722a9aeeac03 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 13 Nov 2017 10:47:02 +0100 Subject: [PATCH 134/242] Remove otw_format=sc12/sc16 from device args, also commas. --- lib/src/phy/rf/rf_uhd_imp.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/src/phy/rf/rf_uhd_imp.c b/lib/src/phy/rf/rf_uhd_imp.c index 29aec5b44..cfe8418b8 100644 --- a/lib/src/phy/rf/rf_uhd_imp.c +++ b/lib/src/phy/rf/rf_uhd_imp.c @@ -291,6 +291,13 @@ int rf_uhd_open(char *args, void **h) return rf_uhd_open_multi(args, h, 1); } +#define REMOVE_SUBSTRING_WITHCOMAS(S, TOREMOVE) \ + remove_substring(args, TOREMOVE ",");\ + remove_substring(args, TOREMOVE ", ");\ + remove_substring(args, "," TOREMOVE);\ + remove_substring(args, ", " TOREMOVE);\ + remove_substring(args, TOREMOVE); + static void remove_substring(char *s,const char *toremove) { while((s=strstr(s,toremove))) { @@ -336,11 +343,11 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels) // Check external clock argument enum {DEFAULT, EXTERNAL, GPSDO} clock_src; if (strstr(args, "clock=external")) { - remove_substring(args, "clock=external"); + REMOVE_SUBSTRING_WITHCOMAS(args, "clock=external"); clock_src = EXTERNAL; } else if (strstr(args, "clock=gpsdo")) { printf("Using GPSDO clock\n"); - remove_substring(args, "clock=gpsdo"); + REMOVE_SUBSTRING_WITHCOMAS(args, "clock=gpsdo"); clock_src = GPSDO; } else { clock_src = DEFAULT; @@ -349,8 +356,10 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels) // Set over the wire format char *otw_format = "sc16"; if (strstr(args, "otw_format=sc12")) { + REMOVE_SUBSTRING_WITHCOMAS(args, "otw_format=sc12"); otw_format = "sc12"; } else if (strstr(args, "otw_format=sc16")) { + REMOVE_SUBSTRING_WITHCOMAS(args, "otw_format=sc16"); /* Do nothing */ } else if (strstr(args, "otw_format=")) { fprintf(stderr, "Wrong over the wire format. Valid formats: sc12, sc16\n"); From 861d65b070454c532a95310f636937d335710035 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 13 Nov 2017 16:01:01 +0100 Subject: [PATCH 135/242] Added subdev RF arguments. It fixes #95 --- lib/src/phy/rf/rf_uhd_imp.c | 65 +++++++++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/lib/src/phy/rf/rf_uhd_imp.c b/lib/src/phy/rf/rf_uhd_imp.c index cfe8418b8..729d96e11 100644 --- a/lib/src/phy/rf/rf_uhd_imp.c +++ b/lib/src/phy/rf/rf_uhd_imp.c @@ -292,11 +292,11 @@ int rf_uhd_open(char *args, void **h) } #define REMOVE_SUBSTRING_WITHCOMAS(S, TOREMOVE) \ - remove_substring(args, TOREMOVE ",");\ - remove_substring(args, TOREMOVE ", ");\ - remove_substring(args, "," TOREMOVE);\ - remove_substring(args, ", " TOREMOVE);\ - remove_substring(args, TOREMOVE); + remove_substring(S, TOREMOVE ",");\ + remove_substring(S, TOREMOVE ", ");\ + remove_substring(S, "," TOREMOVE);\ + remove_substring(S, ", " TOREMOVE);\ + remove_substring(S, TOREMOVE) static void remove_substring(char *s,const char *toremove) { @@ -305,6 +305,17 @@ static void remove_substring(char *s,const char *toremove) } } +static void copy_subdev_string(char *dst, char *src) { + int n = 0; + size_t len = strlen(src); + /* Copy until end of string or comma */ + while (n < len && src != '\0' && src[n] != ',') { + dst[n] = src[n]; + n++; + } + dst[n] = '\0'; +} + int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels) { if (h) { @@ -366,6 +377,26 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels) return -1; } + // Set transmitter subdevice spec string + const char tx_subdev_arg[] = "tx_subdev_spec="; + char tx_subdev_str[64] = {0}; + char *tx_subdev_ptr = strstr(args, tx_subdev_arg); + if (tx_subdev_ptr) { + copy_subdev_string(tx_subdev_str, tx_subdev_ptr + strlen(tx_subdev_arg)); + remove_substring(args, tx_subdev_arg); + remove_substring(args, tx_subdev_str); + } + + // Set receiver subdevice spec string + const char rx_subdev_arg[] = "rx_subdev_spec="; + char rx_subdev_str[64] = {0}; + char *rx_subdev_ptr = strstr(args, rx_subdev_arg); + if (rx_subdev_ptr) { + copy_subdev_string(rx_subdev_str, rx_subdev_ptr + strlen(rx_subdev_arg)); + remove_substring(args, rx_subdev_arg); + remove_substring(args, rx_subdev_str); + } + /* If device type or name not given in args, choose a B200 */ if (args[0]=='\0') { if (find_string(devices_str, "type=b200") && !strstr(args, "recv_frame_size")) { @@ -405,7 +436,29 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels) fprintf(stderr, "Error opening UHD: code %d\n", error); return -1; } - + + /* Set transmitter subdev spec if specified */ + if (strlen(tx_subdev_str)) { + uhd_subdev_spec_handle subdev_spec_handle = {0}; + + printf("Setting tx_subdev_spec to '%s'\n", tx_subdev_str); + + uhd_subdev_spec_make(&subdev_spec_handle, tx_subdev_str); + uhd_usrp_set_tx_subdev_spec(handler->usrp, subdev_spec_handle, 0); + uhd_subdev_spec_free(&subdev_spec_handle); + } + + /* Set receiver subdev spec if specified */ + if (strlen(rx_subdev_str)) { + uhd_subdev_spec_handle subdev_spec_handle = {0}; + + printf("Setting rx_subdev_spec to '%s'\n", rx_subdev_str); + + uhd_subdev_spec_make(&subdev_spec_handle, rx_subdev_str); + uhd_usrp_set_rx_subdev_spec(handler->usrp, subdev_spec_handle, 0); + uhd_subdev_spec_free(&subdev_spec_handle); + } + if (!handler->devname) { char dev_str[1024]; uhd_usrp_get_mboard_name(handler->usrp, 0, dev_str, 1024); From 72d83be8bcd24cd9f363a109f26cafcbb58e55bc Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 14 Nov 2017 11:48:09 +0100 Subject: [PATCH 136/242] Fix minor issues with adaptive retx ENB --- srsenb/hdr/phy/phch_worker.h | 7 ++++++- srsenb/src/mac/scheduler.cc | 4 ++-- srsenb/src/mac/scheduler_harq.cc | 7 +++---- srsenb/src/mac/scheduler_ue.cc | 16 +++++++++++----- srsenb/src/phy/phch_worker.cc | 16 ++++++++++++++++ 5 files changed, 38 insertions(+), 12 deletions(-) diff --git a/srsenb/hdr/phy/phch_worker.h b/srsenb/hdr/phy/phch_worker.h index dd95aaa93..523fefeec 100644 --- a/srsenb/hdr/phy/phch_worker.h +++ b/srsenb/hdr/phy/phch_worker.h @@ -95,7 +95,7 @@ private: srslte_enb_dl_t enb_dl; srslte_enb_ul_t enb_ul; - srslte_timestamp_t tx_time; + srslte_timestamp_t tx_time; // Class to store user information class ue { @@ -112,6 +112,11 @@ private: void metrics_read(phy_metrics_t *metrics); void metrics_dl(uint32_t mcs); void metrics_ul(uint32_t mcs, float rssi, float sinr, uint32_t turbo_iters); + + 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]; + private: phy_metrics_t metrics; }; diff --git a/srsenb/src/mac/scheduler.cc b/srsenb/src/mac/scheduler.cc index 81ed0882e..f477895b5 100644 --- a/srsenb/src/mac/scheduler.cc +++ b/srsenb/src/mac/scheduler.cc @@ -709,7 +709,7 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched /* Indicate PHICH acknowledgment if needed */ if (h->has_pending_ack()) { - sched_result->phich[nof_phich_elems].phich = h->get_ack()?ul_sched_phich_t::ACK:ul_sched_phich_t::NACK; + sched_result->phich[nof_phich_elems].phich = h->get_ack()?ul_sched_phich_t::ACK:ul_sched_phich_t::NACK; sched_result->phich[nof_phich_elems].rnti = rnti; nof_phich_elems++; } @@ -767,7 +767,7 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched { ul_harq_proc::ul_alloc_t alloc = h->get_alloc(); bool is_newtx = h->is_empty(); - bool needs_pdcch = !h->is_adaptive_retx() && !is_rar; + bool needs_pdcch = h->is_adaptive_retx() && !is_rar; // Set number of retx if (is_newtx) { diff --git a/srsenb/src/mac/scheduler_harq.cc b/srsenb/src/mac/scheduler_harq.cc index f5209b374..88ae6b74d 100644 --- a/srsenb/src/mac/scheduler_harq.cc +++ b/srsenb/src/mac/scheduler_harq.cc @@ -198,13 +198,13 @@ ul_harq_proc::ul_alloc_t ul_harq_proc::get_alloc() void ul_harq_proc::set_alloc(ul_harq_proc::ul_alloc_t alloc) { - is_adaptive = false; + is_adaptive = true; memcpy(&allocation, &alloc, sizeof(ul_alloc_t)); } void ul_harq_proc::same_alloc() { - is_adaptive = true; + is_adaptive = false; } bool ul_harq_proc::is_adaptive_retx() @@ -243,8 +243,7 @@ void ul_harq_proc::reset_pending_data() } } - - uint32_t ul_harq_proc::get_pending_data() +uint32_t ul_harq_proc::get_pending_data() { return pending_data; } diff --git a/srsenb/src/mac/scheduler_ue.cc b/srsenb/src/mac/scheduler_ue.cc index 7a810e2cc..87949179e 100644 --- a/srsenb/src/mac/scheduler_ue.cc +++ b/srsenb/src/mac/scheduler_ue.cc @@ -444,7 +444,8 @@ int sched_ue::generate_format0(ul_harq_proc *h, int tbs = 0; ul_harq_proc::ul_alloc_t allocation = h->get_alloc(); - + + bool is_newtx = true; if (h->get_rar_mcs(&mcs)) { tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs), allocation.L)/8; h->new_tx(tti, mcs, tbs); @@ -463,7 +464,8 @@ int sched_ue::generate_format0(ul_harq_proc *h, h->new_tx(tti, mcs, tbs); - } else { + } else { + is_newtx = false; h->new_retx(tti, &mcs, NULL); tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs), allocation.L)/8; } @@ -474,9 +476,13 @@ int sched_ue::generate_format0(ul_harq_proc *h, if (tbs > 0) { dci->type2_alloc.L_crb = allocation.L; dci->type2_alloc.RB_start = allocation.RB_start; - dci->mcs_idx = mcs; - dci->rv_idx = sched::get_rvidx(h->nof_retx()); - dci->ndi = h->get_ndi(); + dci->rv_idx = sched::get_rvidx(h->nof_retx()); + if (!is_newtx && h->is_adaptive_retx()) { + dci->mcs_idx = 28+dci->rv_idx; + } else { + dci->mcs_idx = mcs; + } + dci->ndi = h->get_ndi(); dci->cqi_request = cqi_request; dci->freq_hop_fl = srslte_ra_ul_dci_t::SRSLTE_RA_PUSCH_HOP_DISABLED; dci->tpc_pusch = next_tpc_pusch; diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index 103017fcc..c023c13e0 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -412,6 +412,22 @@ 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)) { + + // Handle Format0 adaptive retx + // Use last TBS for this TB in case of mcs>28 + if (phy_grant.mcs.idx > 28) { + phy_grant.mcs.tbs = ue_db[rnti].last_ul_tbs[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)]; + Info("RETX: mcs=%d, old_tbs=%d pid=%d\n", phy_grant.mcs.idx, phy_grant.mcs.tbs, TTI_TX(tti_rx)%(2*HARQ_DELAY_MS)); + } + ue_db[rnti].last_ul_tbs[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)] = phy_grant.mcs.tbs; + + if (phy_grant.mcs.mod == SRSLTE_MOD_LAST) { + phy_grant.mcs.mod = ue_db[rnti].last_ul_mod[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)]; + phy_grant.Qm = srslte_mod_bits_x_symbol(phy_grant.mcs.mod); + } + ue_db[rnti].last_ul_mod[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)] = phy_grant.mcs.mod; + + if (phy_grant.mcs.mod == SRSLTE_MOD_64QAM) { phy_grant.mcs.mod = SRSLTE_MOD_16QAM; } From 058fbd71127a3fb1c38bd575c455beef2b42721f Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 14 Nov 2017 11:48:19 +0100 Subject: [PATCH 137/242] Fix adaptive retx in UE --- lib/src/phy/ue/ue_ul.c | 2 +- srsue/hdr/mac/ul_harq.h | 119 +++++++++++++++-------------------- srsue/hdr/phy/phch_worker.h | 1 + srsue/src/mac/mac.cc | 2 +- srsue/src/mac/mux.cc | 7 +-- srsue/src/phy/phch_worker.cc | 48 +++++++------- 6 files changed, 84 insertions(+), 95 deletions(-) diff --git a/lib/src/phy/ue/ue_ul.c b/lib/src/phy/ue/ue_ul.c index 853937f7c..ec2809dfe 100644 --- a/lib/src/phy/ue/ue_ul.c +++ b/lib/src/phy/ue/ue_ul.c @@ -453,7 +453,7 @@ int srslte_ue_ul_pusch_encode_rnti_softbuffer(srslte_ue_ul_t *q, if (srslte_pusch_encode(&q->pusch, &q->pusch_cfg, softbuffer, data, uci_data, rnti, q->sf_symbols)) { fprintf(stderr, "Error encoding TB\n"); - return ret; + return SRSLTE_ERROR; } if (q->signals_pregenerated) { diff --git a/srsue/hdr/mac/ul_harq.h b/srsue/hdr/mac/ul_harq.h index 50143a571..5b7426b35 100644 --- a/srsue/hdr/mac/ul_harq.h +++ b/srsue/hdr/mac/ul_harq.h @@ -44,39 +44,35 @@ namespace srsue { template -class ul_harq_entity -{ +class ul_harq_entity { public: - static uint32_t pidof(uint32_t tti) - { - return (uint32_t) tti%N; + static uint32_t pidof(uint32_t tti) { + return (uint32_t) tti % N; } - - ul_harq_entity() : proc(N) - { + + ul_harq_entity() : proc(N) { contention_timer = NULL; - pcap = NULL; - mux_unit = NULL; - log_h = NULL; - params = NULL; - rntis = NULL; - average_retx = 0; - nof_pkts = 0; + pcap = NULL; + mux_unit = NULL; + log_h = NULL; + params = NULL; + rntis = NULL; + average_retx = 0; + nof_pkts = 0; } - bool init(srslte::log *log_h_, + bool init(srslte::log *log_h_, mac_interface_rrc_common::ue_rnti_t *rntis_, mac_interface_rrc_common::ul_harq_params_t *params_, - srslte::timers::timer* contention_timer_, - mux *mux_unit_) - { - log_h = log_h_; - mux_unit = mux_unit_; - params = params_; - rntis = rntis_; + srslte::timers::timer *contention_timer_, + mux *mux_unit_) { + log_h = log_h_; + mux_unit = mux_unit_; + params = params_; + rntis = rntis_; contention_timer = contention_timer_; - for (uint32_t i=0;iMAC interface for UL processes **************************/ - void new_grant_ul(Tgrant grant, Taction *action) + void new_grant_ul(Tgrant grant, Taction *action) { + new_grant_ul_ack(grant, NULL, action); + } + void new_grant_ul_ack(Tgrant grant, bool *ack, Taction *action) { if (grant.rnti_type == SRSLTE_RNTI_USER || grant.rnti_type == SRSLTE_RNTI_TEMP || @@ -115,27 +111,20 @@ public: if (grant.rnti_type == SRSLTE_RNTI_USER && proc[pidof(grant.tti)].is_sps()) { grant.ndi[0] = true; } - run_tti(grant.tti, &grant, action); + run_tti(grant.tti, &grant, ack, action); } else if (grant.rnti_type == SRSLTE_RNTI_SPS) { if (grant.ndi[0]) { grant.ndi[0] = proc[pidof(grant.tti)].get_ndi(); - run_tti(grant.tti, &grant, action); + run_tti(grant.tti, &grant, ack, action); } else { Info("Not implemented\n"); } } } - void new_grant_ul_ack(Tgrant grant, bool ack, Taction *action) - { - set_ack(grant.tti, ack, action); - new_grant_ul(grant, action); - } - void harq_recv(uint32_t tti, bool ack, Taction *action) { - set_ack(tti, ack, action); - run_tti(tti, NULL, action); + run_tti(tti, NULL, &ack, action); } int get_current_tbs(uint32_t tti) @@ -206,10 +195,19 @@ private: bzero(&cur_grant, sizeof(Tgrant)); } - void reset_ndi() { ndi = false; } - - void run_tti(uint32_t tti_tx, Tgrant *grant, Taction* action) + void reset_ndi() { cur_grant.ndi[0] = false; } + + void run_tti(uint32_t tti_tx, Tgrant *grant, bool *ack, Taction* action) { + if (ack) { + if (grant) { + if (grant->ndi[0] == get_ndi()) { + *ack = false; + } + } + set_harq_feedback(*ack); + } + uint32_t max_retx; if (is_msg3) { max_retx = harq_entity->params->max_harq_msg3_tx; @@ -219,9 +217,9 @@ private: // Receive and route HARQ feedbacks if (grant) { - if ((!(grant->rnti_type == SRSLTE_RNTI_TEMP) && grant->ndi[0] != get_ndi() && grant->phy_grant.ul.mcs.idx < 29) || - (grant->rnti_type == SRSLTE_RNTI_USER && !has_grant()) || - grant->is_from_rar) + if ((!(grant->rnti_type == SRSLTE_RNTI_TEMP) && grant->ndi[0] != get_ndi()) || + (grant->rnti_type == SRSLTE_RNTI_USER && !has_grant()) || + grant->is_from_rar) { // New transmission @@ -255,7 +253,7 @@ private: generate_retx(tti_tx, grant, action); } } else { - Warning("UL %d: Received mcs=%d but no previous grant available for this PID.\n", pid, grant->phy_grant.ul.mcs.idx); + Warning("UL %d: Received retransmission but no previous grant available for this PID.\n", pid); } } else if (has_grant()) { // Non-Adaptive Re-Tx @@ -294,7 +292,7 @@ private: } bool has_grant() { return is_grant_configured; } - bool get_ndi() { return ndi; } + bool get_ndi() { return cur_grant.ndi[0]; } bool is_sps() { return false; } uint32_t last_tx_tti() { return tti_last_tx; } uint32_t get_nof_retx() { return current_tx_nb; } @@ -307,7 +305,6 @@ private: uint32_t current_tx_nb; uint32_t current_irv; bool harq_feedback; - bool ndi; srslte::log *log_h; ul_harq_entity *harq_entity; bool is_grant_configured; @@ -398,24 +395,12 @@ private: // Implements Section 5.4.2.1 // Called with UL grant - void run_tti(uint32_t tti, Tgrant *grant, Taction* action) + void run_tti(uint32_t tti, Tgrant *grant, bool *ack, Taction* action) { uint32_t tti_tx = (tti+action->tti_offset)%10240; - proc[pidof(tti_tx)].run_tti(tti_tx, grant, action); + proc[pidof(tti_tx)].run_tti(tti_tx, grant, ack, action); } - void set_ack(uint32_t tti, bool ack, Taction *action) - { - int tti_harq = (int) tti - action->tti_offset; - if (tti_harq < 0) { - tti_harq += 10240; - } - uint32_t pid_harq = pidof(tti_harq); - if (proc[pid_harq].has_grant() && (proc[pid_harq].last_tx_tti() <= (uint32_t)tti_harq)) { - proc[pid_harq].set_harq_feedback(ack); - } - } - ul_sps ul_sps_assig; srslte::timers::timer *contention_timer; diff --git a/srsue/hdr/phy/phch_worker.h b/srsue/hdr/phy/phch_worker.h index c26966c17..61a3b7f23 100644 --- a/srsue/hdr/phy/phch_worker.h +++ b/srsue/hdr/phy/phch_worker.h @@ -153,6 +153,7 @@ private: // 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]; + uint32_t last_ul_tti[2*HARQ_DELAY_MS]; srslte_mod_t last_ul_mod[2*HARQ_DELAY_MS]; // Metrics diff --git a/srsue/src/mac/mac.cc b/srsue/src/mac/mac.cc index f8d10bb34..3d1f60f56 100644 --- a/srsue/src/mac/mac.cc +++ b/srsue/src/mac/mac.cc @@ -308,7 +308,7 @@ void mac::new_grant_ul(mac_interface_phy::mac_grant_t grant, mac_interface_phy:: void mac::new_grant_ul_ack(mac_interface_phy::mac_grant_t grant, bool ack, mac_interface_phy::tb_action_ul_t* action) { int tbs = ul_harq.get_current_tbs(tti); - ul_harq.new_grant_ul_ack(grant, ack, action); + ul_harq.new_grant_ul_ack(grant, &ack, action); if (!ack) { metrics.tx_errors++; } else { diff --git a/srsue/src/mac/mux.cc b/srsue/src/mac/mux.cc index 957c257a1..4e1a3b870 100644 --- a/srsue/src/mac/mux.cc +++ b/srsue/src/mac/mux.cc @@ -236,8 +236,7 @@ uint8_t* mux::pdu_get(uint8_t *payload, uint32_t pdu_sz, uint32_t tx_tti, uint32 // Now allocate the SDUs from the RLC for (uint32_t i=0;iinfo("Allocating scheduled lch=%d len=%d\n", lch[i].id, lch[i].sched_len); - allocate_sdu(lch[i].id, &pdu_msg, lch[i].sched_len); + allocate_sdu(lch[i].id, &pdu_msg, lch[i].sched_len); } } @@ -285,7 +284,7 @@ bool mux::sched_sdu(lchid_t *ch, int *sdu_space, int max_sdu_sz) sched_len = *sdu_space; } - log_h->info("SDU: scheduled lcid=%d, rlc_buffer=%d, allocated=%d/%d\n", + log_h->debug("SDU: scheduled lcid=%d, rlc_buffer=%d, allocated=%d/%d\n", ch->id, ch->buffer_len, sched_len, sdu_space?*sdu_space:0); *sdu_space -= sched_len; @@ -317,7 +316,7 @@ bool mux::allocate_sdu(uint32_t lcid, srslte::sch_pdu* pdu_msg, int max_sdu_sz) sdu_len = pdu_msg->get()->set_sdu(lcid, sdu_len, rlc); if (sdu_len > 0) { // new SDU could be added - Info("SDU: allocated lcid=%d, rlc_buffer=%d, allocated=%d/%d, max_sdu_sz=%d, remaining=%d\n", + Debug("SDU: allocated lcid=%d, rlc_buffer=%d, allocated=%d/%d, max_sdu_sz=%d, remaining=%d\n", lcid, buffer_state, sdu_len, sdu_space, max_sdu_sz, pdu_msg->rem_size()); return true; } else { diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index ff7412d77..ce35680d0 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -322,9 +322,9 @@ void phch_worker::work_imp() ul_action.tti_offset = HARQ_DELAY_MS; /* Send UL grant or HARQ information (from PHICH) to MAC */ - if (ul_grant_available && ul_ack_available && ul_mac_grant.phy_grant.ul.mcs.idx < 29) { + if (ul_grant_available && ul_ack_available) { phy->mac->new_grant_ul_ack(ul_mac_grant, ul_ack, &ul_action); - } else if (ul_grant_available && (!ul_ack_available || ul_mac_grant.phy_grant.ul.mcs.idx < 29)) { + } else if (ul_grant_available && !ul_ack_available) { phy->mac->new_grant_ul(ul_mac_grant, &ul_action); } else if (!ul_grant_available && ul_ack_available) { phy->mac->harq_recv(tti, ul_ack, &ul_action); @@ -743,30 +743,36 @@ bool phch_worker::decode_pdcch_ul(mac_interface_phy::mac_grant_t* grant) } } - if (ret) { + // Handle Format0 adaptive retx + if (ret) { // Use last TBS for this TB in case of mcs>28 if (grant->phy_grant.ul.mcs.idx > 28) { - grant->phy_grant.ul.mcs.tbs = last_ul_tbs[TTI_RX(tti)%(2*HARQ_DELAY_MS)]; - Info("RETX: mcs=%d, old_tbs=%d pid=%d\n", grant->phy_grant.ul.mcs.idx, grant->phy_grant.ul.mcs.tbs, TTI_TX(tti)%(2*HARQ_DELAY_MS)); + // Make sure we received a grant in the previous TTI for this PID + if (last_ul_tti[TTI_RX(tti)%(2*HARQ_DELAY_MS)] == TTI_RX(tti)) { + grant->phy_grant.ul.mcs.tbs = last_ul_tbs[TTI_RX(tti)%(2*HARQ_DELAY_MS)]; + grant->phy_grant.ul.mcs.mod = last_ul_mod[TTI_RX(tti)%(2*HARQ_DELAY_MS)]; + grant->phy_grant.ul.Qm = srslte_mod_bits_x_symbol(grant->phy_grant.ul.mcs.mod); + } else { + Warning("Missed original grant in adaptive retx\n"); + ret = false; + } } + } + if (ret) { last_ul_tbs[TTI_RX(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_RX(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_RX(tti)%(2*HARQ_DELAY_MS)] = grant->phy_grant.ul.mcs.mod; - } + last_ul_tti[TTI_RX(tti)%(2*HARQ_DELAY_MS)] = TTI_TX(tti); - /* 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) { - grant->phy_grant.ul.mcs.mod = SRSLTE_MOD_16QAM; - grant->phy_grant.ul.Qm = 4; + /* 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) { + grant->phy_grant.ul.mcs.mod = SRSLTE_MOD_16QAM; + grant->phy_grant.ul.Qm = 4; + } } } - + /* Make sure the grant is valid */ if (ret && !srslte_dft_precoding_valid_prb(grant->phy_grant.ul.L_prb) && grant->phy_grant.ul.L_prb <= cell.nof_prb) { Warning("Received invalid UL grant. L=%d\n", grant->phy_grant.ul.L_prb); @@ -783,11 +789,9 @@ bool phch_worker::decode_pdcch_ul(mac_interface_phy::mac_grant_t* grant) if (SRSLTE_VERBOSE_ISINFO()) { srslte_ra_pusch_fprint(stdout, &dci_unpacked, cell.nof_prb); } - - return true; - } else { - return false; - } + } + + return ret; } void phch_worker::reset_uci() From 49a621e1937d9f435d83e226c55b3bb11631a2eb Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 14 Nov 2017 13:44:47 +0100 Subject: [PATCH 138/242] removed last tti in adaptive retx. moved to phch_common --- lib/include/srslte/common/common.h | 2 ++ srsue/hdr/mac/ul_harq.h | 3 +-- srsue/hdr/phy/phch_common.h | 14 +++++++++++--- srsue/hdr/phy/phch_worker.h | 6 ------ srsue/src/phy/phch_worker.cc | 24 +++++++++--------------- 5 files changed, 23 insertions(+), 26 deletions(-) diff --git a/lib/include/srslte/common/common.h b/lib/include/srslte/common/common.h index c450fc1d0..41a89fb36 100644 --- a/lib/include/srslte/common/common.h +++ b/lib/include/srslte/common/common.h @@ -50,6 +50,8 @@ #define TTI_TX(tti) ((tti+HARQ_DELAY_MS)%10240) #define TTI_RX_ACK(tti) ((tti+(2*HARQ_DELAY_MS))%10240) +#define UL_PIDOF(tti) (tti%(2*HARQ_DELAY_MS)) + #define TTIMOD_SZ (((2*HARQ_DELAY_MS) < 10)?10:20) #define TTIMOD(tti) (tti%TTIMOD_SZ) diff --git a/srsue/hdr/mac/ul_harq.h b/srsue/hdr/mac/ul_harq.h index 5b7426b35..72b691c00 100644 --- a/srsue/hdr/mac/ul_harq.h +++ b/srsue/hdr/mac/ul_harq.h @@ -217,7 +217,7 @@ private: // Receive and route HARQ feedbacks if (grant) { - if ((!(grant->rnti_type == SRSLTE_RNTI_TEMP) && grant->ndi[0] != get_ndi()) || + if ((!(grant->rnti_type == SRSLTE_RNTI_TEMP) && grant->ndi[0] != get_ndi() && ack) || (grant->rnti_type == SRSLTE_RNTI_USER && !has_grant()) || grant->is_from_rar) { @@ -294,7 +294,6 @@ private: bool has_grant() { return is_grant_configured; } bool get_ndi() { return cur_grant.ndi[0]; } bool is_sps() { return false; } - uint32_t last_tx_tti() { return tti_last_tx; } uint32_t get_nof_retx() { return current_tx_nb; } int get_current_tbs() { return cur_grant.n_bytes[0]*8; } diff --git a/srsue/hdr/phy/phch_common.h b/srsue/hdr/phy/phch_common.h index 39e9e9685..0fe8529da 100644 --- a/srsue/hdr/phy/phch_common.h +++ b/srsue/hdr/phy/phch_common.h @@ -64,8 +64,16 @@ namespace srsue { float rx_gain_offset; float avg_snr_db; float avg_noise; - float avg_rsrp; - + float avg_rsrp; + + // Save last TBS for mcs>28 cases + int last_dl_tbs[2*HARQ_DELAY_MS][SRSLTE_MAX_CODEWORDS]; + uint32_t last_dl_tti[2*HARQ_DELAY_MS]; + + int last_ul_tbs[2*HARQ_DELAY_MS]; + uint32_t last_ul_tti[2*HARQ_DELAY_MS]; + srslte_mod_t last_ul_mod[2*HARQ_DELAY_MS]; + phch_common(uint32_t max_mutex = 3); void init(phy_interface_rrc::phy_cfg_t *config, phy_args_t *args, @@ -139,7 +147,7 @@ namespace srsue { uint32_t n_dmrs; } pending_ack_t; pending_ack_t pending_ack[TTIMOD_SZ]; - + bool is_first_tx; uint32_t nof_workers; diff --git a/srsue/hdr/phy/phch_worker.h b/srsue/hdr/phy/phch_worker.h index 61a3b7f23..e7030d777 100644 --- a/srsue/hdr/phy/phch_worker.h +++ b/srsue/hdr/phy/phch_worker.h @@ -150,12 +150,6 @@ private: 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]; - uint32_t last_ul_tti[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/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index ce35680d0..97fad0720 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -477,19 +477,19 @@ 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)); + grant->pid = ASYNC_DL_SCHED?dci_unpacked.harq_process:(UL_PIDOF(TTI_TX(tti))); // Set last TBS for this TB (pid) in case of mcs>28 (7.1.7.2 of 36.213) for (int i=0;iphy_grant.dl.mcs[i].idx > 28) { - grant->phy_grant.dl.mcs[i].tbs = last_dl_tbs[grant->pid%(2*HARQ_DELAY_MS)][i]; + grant->phy_grant.dl.mcs[i].tbs = phy->last_dl_tbs[grant->pid][i]; } if(grant->phy_grant.dl.mcs[i].tbs < 0) { Info("Invalid TBS size for PDSCH grant\n"); grant->phy_grant.dl.mcs[i].tbs = 0; } // save it - last_dl_tbs[grant->pid%(2*HARQ_DELAY_MS)][i] = grant->phy_grant.dl.mcs[i].tbs; + phy->last_dl_tbs[grant->pid][i] = grant->phy_grant.dl.mcs[i].tbs; } /* Fill MAC grant structure */ @@ -749,21 +749,15 @@ bool phch_worker::decode_pdcch_ul(mac_interface_phy::mac_grant_t* grant) // Use last TBS for this TB in case of mcs>28 if (grant->phy_grant.ul.mcs.idx > 28) { // Make sure we received a grant in the previous TTI for this PID - if (last_ul_tti[TTI_RX(tti)%(2*HARQ_DELAY_MS)] == TTI_RX(tti)) { - grant->phy_grant.ul.mcs.tbs = last_ul_tbs[TTI_RX(tti)%(2*HARQ_DELAY_MS)]; - grant->phy_grant.ul.mcs.mod = last_ul_mod[TTI_RX(tti)%(2*HARQ_DELAY_MS)]; - grant->phy_grant.ul.Qm = srslte_mod_bits_x_symbol(grant->phy_grant.ul.mcs.mod); - } else { - Warning("Missed original grant in adaptive retx\n"); - ret = false; - } + grant->phy_grant.ul.mcs.tbs = phy->last_ul_tbs[UL_PIDOF(TTI_TX(tti))]; + grant->phy_grant.ul.mcs.mod = phy->last_ul_mod[UL_PIDOF(TTI_TX(tti))]; + grant->phy_grant.ul.Qm = srslte_mod_bits_x_symbol(grant->phy_grant.ul.mcs.mod); } } if (ret) { - last_ul_tbs[TTI_RX(tti)%(2*HARQ_DELAY_MS)] = grant->phy_grant.ul.mcs.tbs; - last_ul_mod[TTI_RX(tti)%(2*HARQ_DELAY_MS)] = grant->phy_grant.ul.mcs.mod; - last_ul_tti[TTI_RX(tti)%(2*HARQ_DELAY_MS)] = TTI_TX(tti); - + phy->last_ul_tbs[UL_PIDOF(TTI_TX(tti))] = grant->phy_grant.ul.mcs.tbs; + phy->last_ul_mod[UL_PIDOF(TTI_TX(tti))] = grant->phy_grant.ul.mcs.mod; + phy->last_ul_tti[UL_PIDOF(TTI_TX(tti))] = TTI_RX_ACK(tti); /* 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) { From b084b153cf151e96c9144fdfa90a3f0edae32a7f Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 14 Nov 2017 17:11:48 +0100 Subject: [PATCH 139/242] Added UE Mode 3-1 aperiodic reporting --- lib/include/srslte/phy/phch/cqi.h | 21 +++- lib/include/srslte/phy/phch/uci.h | 1 + lib/src/phy/phch/cqi.c | 73 +++++++++++-- lib/src/phy/phch/pucch.c | 2 +- lib/src/phy/ue/ue_dl.c | 4 +- lib/src/phy/ue/ue_ul.c | 28 +++-- srsenb/src/phy/phch_worker.cc | 2 +- srsue/hdr/phy/phch_worker.h | 3 +- srsue/src/phy/phch_worker.cc | 175 ++++++++++++++++++++---------- 9 files changed, 221 insertions(+), 88 deletions(-) diff --git a/lib/include/srslte/phy/phch/cqi.h b/lib/include/srslte/phy/phch/cqi.h index cfc9e92e7..0d0c17fec 100644 --- a/lib/include/srslte/phy/phch/cqi.h +++ b/lib/include/srslte/phy/phch/cqi.h @@ -55,13 +55,22 @@ typedef struct { } srslte_cqi_periodic_cfg_t; /* Table 5.2.2.6.2-1: Fields for channel quality information feedback for higher layer configured subband -CQI reports -(transmission mode 1, transmission mode 2, transmission mode 3, transmission mode 7 and -transmission mode 8 configured without PMI/RI reporting). */ + CQI reports (transmission mode 1, transmission mode 2, transmission mode 3, transmission mode 7 and + transmission mode 8 configured without PMI/RI reporting). */ + +/* Table 5.2.2.6.2-2: Fields for channel quality information (CQI) feedback for higher layer configured subband CQI + reports (transmission mode 4, transmission mode 5 and transmission mode 6). */ + typedef struct SRSLTE_API { - uint8_t wideband_cqi; // 4-bit width - uint32_t subband_diff_cqi; // 2N-bit width - uint32_t N; + uint8_t wideband_cqi_cw0; // 4-bit width + uint32_t subband_diff_cqi_cw0; // 2N-bit width + uint8_t wideband_cqi_cw1; // if RI > 1 then 4-bit width otherwise 0-bit width + uint32_t subband_diff_cqi_cw1; // if RI > 1 then 2N-bit width otherwise 0-bit width + uint32_t pmi; // if RI > 1 then 2-bit width otherwise 1-bit width + uint32_t N; + bool pmi_present; + bool four_antenna_ports; // If cell has 4 antenna ports then true otherwise false + bool rank_is_not_one; // If rank > 1 then true otherwise false } srslte_cqi_hl_subband_t; /* Table 5.2.2.6.3-1: Fields for channel quality information feedback for UE selected subband CQI diff --git a/lib/include/srslte/phy/phch/uci.h b/lib/include/srslte/phy/phch/uci.h index ff315384e..91592501f 100644 --- a/lib/include/srslte/phy/phch/uci.h +++ b/lib/include/srslte/phy/phch/uci.h @@ -73,6 +73,7 @@ typedef struct SRSLTE_API { uint8_t uci_ack; // 1st codeword bit for HARQ-ACK uint8_t uci_ack_2; // 2st codeword bit for HARQ-ACK uint32_t uci_ack_len; + bool ri_periodic_report; bool scheduling_request; bool channel_selection; bool cqi_ack; diff --git a/lib/src/phy/phch/cqi.c b/lib/src/phy/phch/cqi.c index 0041c3fcb..2c0940af5 100644 --- a/lib/src/phy/phch/cqi.c +++ b/lib/src/phy/phch/cqi.c @@ -44,11 +44,38 @@ *******************************************************/ int srslte_cqi_hl_subband_pack(srslte_cqi_hl_subband_t *msg, uint8_t buff[SRSLTE_CQI_MAX_BITS]) { - uint8_t *body_ptr = buff; - srslte_bit_unpack(msg->wideband_cqi, &body_ptr, 4); - srslte_bit_unpack(msg->subband_diff_cqi, &body_ptr, 2*msg->N); - - return 4+2*msg->N; + uint8_t *body_ptr = buff; + uint32_t bit_count = 0; + + /* Unpack codeword 0, common for 3GPP 36.212 Tables 5.2.2.6.2-1 and 5.2.2.6.2-2 */ + srslte_bit_unpack(msg->wideband_cqi_cw0, &body_ptr, 4); + srslte_bit_unpack(msg->subband_diff_cqi_cw0, &body_ptr, 2*msg->N); + bit_count += 4+2*msg->N; + + /* Unpack codeword 1, 3GPP 36.212 Table 5.2.2.6.2-2 */ + if (msg->rank_is_not_one) { + srslte_bit_unpack(msg->wideband_cqi_cw1, &body_ptr, 4); + srslte_bit_unpack(msg->subband_diff_cqi_cw1, &body_ptr, 2*msg->N); + bit_count += 4+2*msg->N; + } + + /* If PMI is present, unpack it */ + if (msg->pmi_present) { + if (msg->four_antenna_ports) { + srslte_bit_unpack(msg->pmi, &body_ptr, 4); + bit_count += 4; + } else { + if (msg->rank_is_not_one) { + srslte_bit_unpack(msg->pmi, &body_ptr, 1); + bit_count += 1; + } else { + srslte_bit_unpack(msg->pmi, &body_ptr, 2); + bit_count += 2; + } + } + } + + return bit_count; } int srslte_cqi_ue_subband_pack(srslte_cqi_ue_subband_t *msg, uint8_t buff[SRSLTE_CQI_MAX_BITS]) @@ -98,11 +125,37 @@ int srslte_cqi_value_pack(srslte_cqi_value_t *value, uint8_t buff[SRSLTE_CQI_MAX int srslte_cqi_hl_subband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_hl_subband_t *msg) { - uint8_t *body_ptr = buff; - msg->wideband_cqi = srslte_bit_pack(&body_ptr, 4); - msg->subband_diff_cqi = srslte_bit_pack(&body_ptr, 2*msg->N); - - return 4+2*msg->N; + uint8_t *body_ptr = buff; + uint32_t bit_count = 0; + + msg->wideband_cqi_cw0 = (uint8_t) srslte_bit_pack(&body_ptr, 4); + msg->subband_diff_cqi_cw0 = srslte_bit_pack(&body_ptr, 2*msg->N); + bit_count += 4+2*msg->N; + + /* Unpack codeword 1, 3GPP 36.212 Table 5.2.2.6.2-2 */ + if (msg->rank_is_not_one) { + msg->wideband_cqi_cw1 = (uint8_t) srslte_bit_pack(&body_ptr, 4); + msg->subband_diff_cqi_cw1 = srslte_bit_pack(&body_ptr, 2*msg->N); + bit_count += 4+2*msg->N; + } + + /* If PMI is present, unpack it */ + if (msg->pmi_present) { + if (msg->four_antenna_ports) { + msg->pmi = (uint8_t) srslte_bit_pack(&body_ptr, 4); + bit_count += 4; + } else { + if (msg->rank_is_not_one) { + msg->pmi = (uint8_t) srslte_bit_pack(&body_ptr, 1); + bit_count += 1; + } else { + msg->pmi = (uint8_t) srslte_bit_pack(&body_ptr, 2); + bit_count += 2; + } + } + } + + return bit_count; } int srslte_cqi_ue_subband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_ue_subband_t *msg) diff --git a/lib/src/phy/phch/pucch.c b/lib/src/phy/phch/pucch.c index 498d34f3a..8e60f9f2c 100644 --- a/lib/src/phy/phch/pucch.c +++ b/lib/src/phy/phch/pucch.c @@ -173,7 +173,7 @@ srslte_pucch_format_t srslte_pucch_get_format(srslte_uci_data_t *uci_data, srslt { srslte_pucch_format_t format = SRSLTE_PUCCH_FORMAT_ERROR; // No CQI data - if (uci_data->uci_cqi_len == 0) { + if (uci_data->uci_cqi_len == 0 && uci_data->uci_ri_len == 0) { // 1-bit ACK + optional SR if (uci_data->uci_ack_len == 1) { format = SRSLTE_PUCCH_FORMAT_1A; diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index 1c3b79440..a677aa70d 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -684,6 +684,7 @@ int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, uint8_t *ri, uint8_t *pmi, flo } /* Set RI */ + q->ri = best_ri; if (ri != NULL) { *ri = best_ri; } @@ -719,9 +720,10 @@ int srslte_ue_dl_ri_select(srslte_ue_dl_t *q, uint8_t *ri, float *cn) { *cn = _cn; } + q->ri = (uint8_t)((_cn < 17.0f)? 1:0); /* Set rank indicator */ if (!ret && ri) { - *ri = (uint8_t)((_cn < 17.0f)? 1:0); + *ri = (uint8_t) q->ri; } return ret; diff --git a/lib/src/phy/ue/ue_ul.c b/lib/src/phy/ue/ue_ul.c index 853937f7c..1351cfca6 100644 --- a/lib/src/phy/ue/ue_ul.c +++ b/lib/src/phy/ue/ue_ul.c @@ -273,21 +273,33 @@ int srslte_ue_ul_cfg_grant(srslte_ue_ul_t *q, srslte_ra_ul_grant_t *grant, void pucch_encode_bits(srslte_uci_data_t *uci_data, srslte_pucch_format_t format, uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS], uint8_t pucch2_bits[SRSLTE_PUCCH_MAX_BITS]) -{ +{ + uint8_t uci_buffer[SRSLTE_CQI_MAX_BITS]; + uint8_t uci_buffer_len = 0; + if (format == SRSLTE_PUCCH_FORMAT_1A || format == SRSLTE_PUCCH_FORMAT_1B) { pucch_bits[0] = uci_data->uci_ack; pucch_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 1a } if (format >= SRSLTE_PUCCH_FORMAT_2) { - /* Append Differential CQI */ - memcpy(&uci_data->uci_cqi[uci_data->uci_cqi_len], uci_data->uci_dif_cqi, uci_data->uci_dif_cqi_len); - uci_data->uci_cqi_len += uci_data->uci_dif_cqi_len; + /* Put RI (goes alone) */ + if (uci_data->ri_periodic_report) { + uci_buffer[0] = uci_data->uci_ri; // It assumes only 1 bit of RI + uci_buffer_len += uci_data->uci_ri_len; + } else { + /* Append CQI */ + memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_cqi, uci_data->uci_cqi_len); + uci_buffer_len += uci_data->uci_cqi_len; - /* Append PMI */ - memcpy(&uci_data->uci_cqi[uci_data->uci_cqi_len], uci_data->uci_pmi, uci_data->uci_pmi_len); - uci_data->uci_cqi_len += uci_data->uci_pmi_len; + /* Append Differential CQI */ + memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_dif_cqi, uci_data->uci_dif_cqi_len); + uci_buffer_len += uci_data->uci_dif_cqi_len; - srslte_uci_encode_cqi_pucch(uci_data->uci_cqi, uci_data->uci_cqi_len, pucch_bits); + /* Append PMI */ + memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_pmi, uci_data->uci_pmi_len); + uci_buffer_len += uci_data->uci_pmi_len; + } + srslte_uci_encode_cqi_pucch(uci_buffer, uci_buffer_len, pucch_bits); if (format > SRSLTE_PUCCH_FORMAT_2) { pucch2_bits[0] = uci_data->uci_ack; pucch2_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 2a diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index 103017fcc..fd7501547 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -445,7 +445,7 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) if (ue_db[rnti].cqi_en) { wideband_cqi_value = cqi_value.wideband.wideband_cqi; } else if (grants[i].grant.cqi_request) { - wideband_cqi_value = cqi_value.subband_hl.wideband_cqi; + wideband_cqi_value = cqi_value.subband_hl.wideband_cqi_cw0; } snprintf(cqi_str, 64, ", cqi=%d", wideband_cqi_value); } diff --git a/srsue/hdr/phy/phch_worker.h b/srsue/hdr/phy/phch_worker.h index c26966c17..12d14756c 100644 --- a/srsue/hdr/phy/phch_worker.h +++ b/srsue/hdr/phy/phch_worker.h @@ -74,7 +74,8 @@ private: /* Internal methods */ bool extract_fft_and_pdcch_llr(); - + void compute_ri(); + /* ... for DL */ bool decode_pdcch_ul(mac_interface_phy::mac_grant_t *grant); bool decode_pdcch_dl(mac_interface_phy::mac_grant_t *grant); diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index ff7412d77..2a489e7c2 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -255,39 +255,6 @@ void phch_worker::work_imp() if (dl_action.generate_ack) { set_uci_ack(dl_ack, dl_mac_grant.tb_en); } - - /* Select Rank Indicator by computing Condition Number */ - if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) { - if (ue_dl.nof_rx_antennas > 1) { - /* If 2 ort more receiving antennas, select RI */ - float cn = 0.0f; - srslte_ue_dl_ri_select(&ue_dl, &uci_data.uci_ri, &cn); - uci_data.uci_ri_len = 1; - } else { - /* If only one receiving antenna, force RI for 1 layer */ - uci_data.uci_ri = 0; - uci_data.uci_ri_len = 1; - Warning("Only one receiving antenna with TM3. Forcing RI=1 layer.\n"); - } - } else if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4){ - float sinr = 0.0f; - uint8 packed_pmi = 0; - srslte_ue_dl_ri_pmi_select(&ue_dl, &uci_data.uci_ri, &packed_pmi, &sinr); - srslte_bit_unpack_vector(&packed_pmi, uci_data.uci_pmi, 2); - uci_data.uci_ri_len = 1; - if (uci_data.uci_ri == 0) { - uci_data.uci_pmi_len = 2; - uci_data.uci_dif_cqi_len = 0; - } else { - uci_data.uci_pmi_len = 1; - uci_data.uci_dif_cqi_len = 3; - } - - /* If only one antenna in TM4 print limitation warning */ - if (ue_dl.nof_rx_antennas < 2) { - Warning("Only one receiving antenna with TM4. Forcing RI=1 layer (PMI=%d).\n", packed_pmi); - } - } } } @@ -343,7 +310,7 @@ void phch_worker::work_imp() phy->set_pending_ack(TTI_RX_ACK(tti), ue_ul.pusch_cfg.grant.n_prb_tilde[0], ul_action.phy_grant.ul.ncs_dmrs); } - } else if (dl_action.generate_ack || uci_data.scheduling_request || uci_data.uci_cqi_len > 0) { + } else if (dl_action.generate_ack || uci_data.scheduling_request || uci_data.uci_cqi_len > 0 || uci_data.uci_ri_len > 0) { encode_pucch(); signal_ready = true; } else if (srs_is_ready_to_send()) { @@ -392,6 +359,42 @@ void phch_worker::work_imp() #endif } +void phch_worker::compute_ri() { + if (uci_data.uci_ri_len > 0) { + /* Do nothing */ + } else if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) { + if (ue_dl.nof_rx_antennas > 1) { + /* If 2 ort more receiving antennas, select RI */ + float cn = 0.0f; + srslte_ue_dl_ri_select(&ue_dl, &uci_data.uci_ri, &cn); + Info("RI select %d layers, κ=%fdB\n", uci_data.uci_ri + 1, cn); + } else { + /* If only one receiving antenna, force RI for 1 layer */ + uci_data.uci_ri = 0; + Warning("Only one receiving antenna with TM3. Forcing RI=1 layer.\n"); + } + uci_data.uci_ri_len = 1; + } else if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { + float sinr = 0.0f; + uint8 packed_pmi = 0; + srslte_ue_dl_ri_pmi_select(&ue_dl, &uci_data.uci_ri, &packed_pmi, &sinr); + if (uci_data.uci_ri == 0) { + uci_data.uci_pmi_len = 2; + uci_data.uci_dif_cqi_len = 0; + } else { + uci_data.uci_pmi_len = 1; + uci_data.uci_dif_cqi_len = 3; + } + srslte_bit_unpack_vector(&packed_pmi, uci_data.uci_pmi, uci_data.uci_pmi_len); + Info("ri=%d; pmi=%d; SINR=%.1fdB\n", ue_dl.ri, ue_dl.pmi[ue_dl.ri], 10*log10f(ue_dl.sinr[ue_dl.ri][ue_dl.pmi[ue_dl.ri]])); + + /* If only one antenna in TM4 print limitation warning */ + if (ue_dl.nof_rx_antennas < 2) { + Warning("Only one receiving antenna with TM4. Forcing RI=1 layer (PMI=%d).\n", packed_pmi); + } + uci_data.uci_ri_len = 1; + } +} bool phch_worker::extract_fft_and_pdcch_llr() { bool decode_pdcch = false; @@ -797,21 +800,15 @@ void phch_worker::reset_uci() void phch_worker::set_uci_ack(bool ack[SRSLTE_MAX_CODEWORDS], bool tb_en[SRSLTE_MAX_CODEWORDS]) { - uint32_t nof_tb = 0; - if (tb_en[0]) { - uci_data.uci_ack = (uint8_t) ((ack[0]) ? 1 : 0); - nof_tb = 1; - } else { - uci_data.uci_ack = 1; - } - - if (tb_en[1]) { - uci_data.uci_ack_2 = (uint8_t) ((ack[1]) ? 1 : 0); - nof_tb = 2; + /* Map ACK according to 3GPP 36.212 clause 5.2.3.1 */ + uint32_t nof_ack = 0; + for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { + if (tb_en[tb]) { + ((nof_ack == 0)?uci_data.uci_ack:uci_data.uci_ack_2) = (uint8_t)(ack[tb]?1:0); + nof_ack++; + } } - - uci_data.uci_ack_len = nof_tb; - + uci_data.uci_ack_len = nof_ack; } void phch_worker::set_uci_sr() @@ -836,14 +833,9 @@ void phch_worker::set_uci_periodic_cqi() if (period_cqi.configured && rnti_is_set) { if (period_cqi.ri_idx_present && srslte_ri_send(period_cqi.pmi_idx, period_cqi.ri_idx, TTI_TX(tti))) { - if (uci_data.uci_ri_len) { - uci_data.uci_cqi[0] = uci_data.uci_ri; - uci_data.uci_cqi_len = uci_data.uci_ri_len; - uci_data.uci_ri_len = 0; - uci_data.uci_dif_cqi_len = 0; - uci_data.uci_pmi_len = 0; - Info("PUCCH: Periodic RI=%d\n", uci_data.uci_cqi[0]); - } + compute_ri(); + uci_data.ri_periodic_report = true; + Info("PUCCH: Periodic RI=%d\n", uci_data.uci_ri); } else if (srslte_cqi_send(period_cqi.pmi_idx, TTI_TX(tti))) { srslte_cqi_value_t cqi_report; if (period_cqi.format_is_subband) { @@ -865,6 +857,16 @@ void phch_worker::set_uci_periodic_cqi() } Info("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.wideband.wideband_cqi, phy->avg_snr_db); } + if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { + if (ue_dl.ri == 0) { + uci_data.uci_pmi_len = 2; + } else { + uci_data.uci_pmi_len = 1; + uci_data.uci_dif_cqi_len = 3; + } + uint8_t *ptr = uci_data.uci_pmi; + srslte_bit_unpack(ue_dl.pmi[ue_dl.ri], &ptr, uci_data.uci_pmi_len); + } uci_data.uci_cqi_len = srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi); rar_cqi_request = false; } @@ -886,18 +888,71 @@ void phch_worker::set_uci_aperiodic_cqi() reported RI. For other transmission modes they are reported conditioned on rank 1. */ if (rnti_is_set) { - srslte_cqi_value_t cqi_report; + srslte_cqi_value_t cqi_report = {0}; cqi_report.type = SRSLTE_CQI_TYPE_SUBBAND_HL; - cqi_report.subband_hl.wideband_cqi = srslte_cqi_from_snr(phy->avg_snr_db); + cqi_report.subband_hl.wideband_cqi_cw0 = srslte_cqi_from_snr(phy->avg_snr_db); // TODO: implement subband CQI properly - cqi_report.subband_hl.subband_diff_cqi = 0; // Always report zero offset on all subbands + cqi_report.subband_hl.subband_diff_cqi_cw0 = 0; // Always report zero offset on all subbands cqi_report.subband_hl.N = (cell.nof_prb > 7) ? srslte_cqi_hl_get_no_subbands(cell.nof_prb) : 0; Info("PUSCH: Aperiodic CQI=%d, SNR=%.1f dB, for %d subbands\n", cqi_report.wideband.wideband_cqi, phy->avg_snr_db, cqi_report.subband_hl.N); uci_data.uci_cqi_len = srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi); } break; + case LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM31: + /* only Higher Layer-configured subband feedback support right now, according to TS36.213 section 7.2.1 + - A single precoding matrix is selected from the codebook subset assuming transmission on set S subbands + - A UE shall report one subband CQI value per codeword for each set S subband which are calculated assuming + the use of the single precoding matrix in all subbands and assuming transmission in the corresponding + subband. + - A UE shall report a wideband CQI value per codeword which is calculated assuming the use of the single + precoding matrix in all subbands and transmission on set S subbands + - The UE shall report the single selected precoding matrix indicator. + - For transmission mode 4 the reported PMI and CQI values are calculated conditioned on the reported RI. For + other transmission modes they are reported conditioned on rank 1. + */ + if (rnti_is_set) { + /* Compute RI, PMI and SINR */ + compute_ri(); + + /* Select RI, PMI and SINR */ + uint32_t ri = ue_dl.ri; // Select RI (0: 1 layer, 1: 2 layer, otherwise: not implemented) + uint32_t pmi = ue_dl.pmi[ri]; // Select PMI + float sinr_db = 10 * log10(ue_dl.sinr[ri][pmi]); + + /* Fill CQI Report */ + srslte_cqi_value_t cqi_report = {0}; + cqi_report.type = SRSLTE_CQI_TYPE_SUBBAND_HL; + + cqi_report.subband_hl.wideband_cqi_cw0 = srslte_cqi_from_snr(sinr_db); + cqi_report.subband_hl.subband_diff_cqi_cw0 = 0; // Always report zero offset on all subbands + + if (ri > 0) { + cqi_report.subband_hl.rank_is_not_one = true; + cqi_report.subband_hl.wideband_cqi_cw1 = srslte_cqi_from_snr(sinr_db); + cqi_report.subband_hl.subband_diff_cqi_cw1 = 0; // Always report zero offset on all subbands + } + + cqi_report.subband_hl.pmi = pmi; + cqi_report.subband_hl.pmi_present = true; + cqi_report.subband_hl.four_antenna_ports = (cell.nof_ports == 4); + + // TODO: implement subband CQI properly + cqi_report.subband_hl.N = (uint32_t) ((cell.nof_prb > 7) ? srslte_cqi_hl_get_no_subbands(cell.nof_prb) : 0); + + if (cqi_report.subband_hl.rank_is_not_one) { + Info("PUSCH: Aperiodic ri~1, CQI=%02d/%02d, SINR=%2.1f/%2.1fdB, pmi=%d for %d subbands\n", + cqi_report.subband_hl.wideband_cqi_cw0, cqi_report.subband_hl.wideband_cqi_cw1, + sinr_db, sinr_db, pmi, cqi_report.subband_hl.N); + } else { + Info("PUSCH: Aperiodic ri=1, CQI=%d/%d, SINR=%2.1f dB, for %d subbands\n", + cqi_report.wideband.wideband_cqi, + phy->avg_snr_db, cqi_report.subband_hl.N); + } + uci_data.uci_cqi_len = srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi); + } + break; default: Warning("Received CQI request but mode %s is not supported\n", liblte_rrc_cqi_report_mode_aperiodic_text[phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic]); @@ -979,7 +1034,7 @@ void phch_worker::encode_pucch() char timestr[64]; timestr[0]='\0'; - if (uci_data.scheduling_request || uci_data.uci_ack_len > 0 || uci_data.uci_cqi_len > 0) + if (uci_data.scheduling_request || uci_data.uci_ack_len > 0 || uci_data.uci_cqi_len > 0 || uci_data.uci_ri_len > 0) { // Drop CQI if there is collision with ACK From c6e947e7ca05872b8c7f5b57072d0da9ace16d20 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 15 Nov 2017 13:18:15 +0100 Subject: [PATCH 140/242] Enable S-TMSI attach --- srsue/hdr/ue_base.h | 14 ++-- srsue/hdr/upper/rrc.h | 21 +++++- srsue/src/main.cc | 19 +++-- srsue/src/ue.cc | 7 +- srsue/src/upper/rrc.cc | 162 ++++++++++++++++++++++++++++++----------- srsue/ue.conf.example | 26 +++++-- 6 files changed, 184 insertions(+), 65 deletions(-) diff --git a/srsue/hdr/ue_base.h b/srsue/hdr/ue_base.h index b547945a9..13e2e4660 100644 --- a/srsue/hdr/ue_base.h +++ b/srsue/hdr/ue_base.h @@ -38,6 +38,7 @@ #include "srslte/radio/radio_multi.h" #include "phy/phy.h" #include "upper/usim.h" +#include "upper/rrc.h" #include "srslte/interfaces/ue_interfaces.h" #include "srslte/common/logger.h" @@ -104,12 +105,11 @@ typedef struct { typedef struct { std::string ip_netmask; - phy_args_t phy; - float metrics_period_secs; - bool pregenerate_signals; - std::string ue_cateogry; - bool metrics_csv_enable; - std::string metrics_csv_filename; + phy_args_t phy; + float metrics_period_secs; + bool pregenerate_signals; + bool metrics_csv_enable; + std::string metrics_csv_filename; }expert_args_t; typedef struct { @@ -120,6 +120,8 @@ typedef struct { log_args_t log; gui_args_t gui; usim_args_t usim; + rrc_args_t rrc; + std::string ue_category_str; expert_args_t expert; }all_args_t; diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index 0e123e988..37ab941cd 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -39,6 +39,15 @@ #include +typedef struct { + bool stmsi_attach; + LIBLTE_RRC_S_TMSI_STRUCT stmsi_value; + uint32_t ue_category; + uint32_t feature_group; + uint8_t supported_bands[LIBLTE_RRC_BAND_N_ITEMS]; + uint32_t nof_supported_bands; +}rrc_args_t; + using srslte::byte_buffer_t; namespace srsue { @@ -73,7 +82,7 @@ public: rrc_state_t get_state(); - void set_ue_category(int category); + void set_args(rrc_args_t *args); // Timeout callback interface void timer_expired(uint32_t timeout_id); @@ -98,6 +107,9 @@ private: uint8_t transaction_id; bool drb_up; + rrc_args_t args; + bool first_stimsi_attempt; + bool reestablishment_in_progress; // timeouts in ms @@ -132,7 +144,6 @@ private: uint32_t n310_cnt, N310; uint32_t n311_cnt, N311; uint32_t t301, t310, t311; - int ue_category; typedef struct { uint32_t earfcn; @@ -269,7 +280,11 @@ private: void set_mac_default(); void set_rrc_default(); void set_bearers(); - + + // s-tmsi persistent file + bool read_stimsi_file(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi); + bool write_stimsi_file(LIBLTE_RRC_S_TMSI_STRUCT s_tmsi); + }; } // namespace srsue diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 01f77f2fa..cc0b07043 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -75,10 +75,19 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { ("rf.device_args", bpo::value(&args->rf.device_args)->default_value("auto"), "Front-end device arguments") ("rf.time_adv_nsamples", bpo::value(&args->rf.time_adv_nsamples)->default_value("auto"), "Transmission time advance") - ("rf.burst_preamble_us", bpo::value(&args->rf.burst_preamble)->default_value("auto"), - "Transmission time advance") + ("rf.burst_preamble_us", bpo::value(&args->rf.burst_preamble)->default_value("auto"), "Transmission time advance") + + ("rrc.stmsi_attach", bpo::value(&args->rrc.stmsi_attach)->default_value(false),"If enabled, always tries first an S-TMSI attach using the\n" + "S-TMSI value stored in .stimsi file generated in previous run") + ("rrc.mmec_value", bpo::value(&args->rrc.stmsi_value.mmec)->default_value(0), "If defined (non-zero), overwrites the value stored in .stimsi file") + ("rrc.mtmsi_value", bpo::value(&args->rrc.stmsi_value.m_tmsi)->default_value(0), "If defined (non-zero), overwrites the value stored in .stimsi file") + + ("rrc.feature_group", bpo::value(&args->rrc.feature_group)->default_value(0xe6041c00), "Hex value of the featureGroupIndicators field in the" + "UECapabilityInformation message. Default 0xe6041c00") + ("rrc.ue_category", bpo::value(&args->ue_category_str)->default_value("4"), "UE Category (1 to 5)") - ("pcap.enable", bpo::value(&args->pcap.enable)->default_value(false), + + ("pcap.enable", bpo::value(&args->pcap.enable)->default_value(false), "Enable MAC packet captures for wireshark") ("pcap.filename", bpo::value(&args->pcap.filename)->default_value("ue.pcap"), "MAC layer capture filename") @@ -134,10 +143,6 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { bpo::value(&args->expert.phy.sync_cpu_affinity)->default_value(-1), "index of the core used by the sync thread") - ("expert.ue_category", - bpo::value(&args->expert.ue_cateogry)->default_value("4"), - "UE Category (1 to 5)") - ("expert.metrics_period_secs", bpo::value(&args->expert.metrics_period_secs)->default_value(1.0), "Periodicity for metrics in seconds") diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index a99281e6f..ca56db556 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -188,7 +188,12 @@ bool ue::init(all_args_t *args_) gw.set_netmask(args->expert.ip_netmask); rrc.init(&phy, &mac, &rlc, &pdcp, &nas, &usim, &mac, &rrc_log); - rrc.set_ue_category(atoi(args->expert.ue_cateogry.c_str())); + + // Get current band from provided EARFCN + args->rrc.supported_bands[0] = srslte_band_get_band(args->rf.dl_earfcn); + args->rrc.nof_supported_bands = 1; + args->rrc.ue_category = atoi(args->ue_category_str.c_str()); + rrc.set_args(&args->rrc); // Currently EARFCN list is set to only one frequency as indicated in ue.conf std::vector earfcn_list; diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 7b4bef710..b0cd99741 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -26,12 +26,11 @@ #include +#include +#include #include -#include "srslte/asn1/liblte_rrc.h" #include "upper/rrc.h" -#include -#include -#include +#include "srslte/asn1/liblte_rrc.h" #include "srslte/common/security.h" #include "srslte/common/bcd_helpers.h" @@ -93,9 +92,15 @@ void rrc::init(phy_interface_rrc *phy_, pthread_mutex_init(&mutex, NULL); + first_stimsi_attempt = false; reestablishment_in_progress = false; - ue_category = SRSLTE_UE_CATEGORY; + args.ue_category = SRSLTE_UE_CATEGORY; + args.supported_bands[0] = 7; + args.nof_supported_bands = 1; + args.feature_group = 0xe6041c00; + args.stmsi_attach = false; + t301 = mac_timers->timer_get_unique_id(); t310 = mac_timers->timer_get_unique_id(); t311 = mac_timers->timer_get_unique_id(); @@ -131,12 +136,8 @@ bool rrc::have_drb() { return drb_up; } -void rrc::set_ue_category(int category) { - if (category >= 1 && category <= 5) { - ue_category = category; - } else { - rrc_log->error("Unsupported UE category %d\n", category); - } +void rrc::set_args(rrc_args_t *args) { + memcpy(&this->args, args, sizeof(rrc_args_t)); } /* @@ -591,6 +592,66 @@ void rrc::timer_expired(uint32_t timeout_id) { * *******************************************************************************/ +bool rrc::read_stimsi_file(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) { + std::ifstream file; + std::string line; + if (!s_tmsi) { + return false; + } + + const char *mmec_str = "mmec="; + size_t mmec_str_len = strlen(mmec_str); + const char *mtmsi_str = "mtmsi="; + size_t mtmsi_str_len = strlen(mtmsi_str); + + file.open(".stmsi", std::ios::in); + if (file.is_open()) { + bool read_ok = true; + if (std::getline(file, line)) { + if (!line.substr(0,mmec_str_len).compare(mmec_str)) { + s_tmsi->mmec = atoi(line.substr(5).c_str()); + } else { + read_ok = false; + } + } else { + read_ok = false; + } + if (std::getline(file, line)) { + if (!line.substr(0,mtmsi_str_len).compare(mtmsi_str)) { + s_tmsi->m_tmsi = atoi(line.substr(mtmsi_str_len).c_str()); + } else { + read_ok = false; + } + } else { + read_ok = false; + } + file.close(); + if (read_ok) { + rrc_log->info("Read S-TMSI value: %x:%x\n", s_tmsi->mmec, s_tmsi->m_tmsi); + return true; + } else { + rrc_log->error("Invalid s-tmsi persistent file format\n"); + return false; + } + } else { + return false; + } +} + +bool rrc::write_stimsi_file(LIBLTE_RRC_S_TMSI_STRUCT s_tmsi) { + std::ofstream file; + file.open(".stmsi", std::ios::out | std::ios::trunc); + if (file.is_open()) { + file << "mmec=" << (int) s_tmsi.mmec << std::endl; + file << "mtmsi=" << (int) s_tmsi.m_tmsi << std::endl; + rrc_log->info("Saved S-TMSI in persistent file: %x:%x\n", s_tmsi.mmec, s_tmsi.m_tmsi); + file.close(); + return true; + } else { + return false; + } +} + void rrc::send_con_request() { rrc_log->debug("Preparing RRC Connection Request\n"); LIBLTE_RRC_UL_CCCH_MSG_STRUCT ul_ccch_msg; @@ -598,13 +659,32 @@ void rrc::send_con_request() { // Prepare ConnectionRequest packet ul_ccch_msg.msg_type = LIBLTE_RRC_UL_CCCH_MSG_TYPE_RRC_CON_REQ; - if (nas->get_s_tmsi(&s_tmsi)) { + bool valid_stmsi = false; + + if (nas->get_s_tmsi(&s_tmsi) || (args.stmsi_attach && !first_stimsi_attempt)) { ul_ccch_msg.msg.rrc_con_req.ue_id_type = LIBLTE_RRC_CON_REQ_UE_ID_TYPE_S_TMSI; - ul_ccch_msg.msg.rrc_con_req.ue_id.s_tmsi = s_tmsi; - } else { + if (nas->get_s_tmsi(&s_tmsi)) { + ul_ccch_msg.msg.rrc_con_req.ue_id.s_tmsi = s_tmsi; + valid_stmsi = true; + } else { + first_stimsi_attempt = true; + if (args.stmsi_value.m_tmsi) { + ul_ccch_msg.msg.rrc_con_req.ue_id.s_tmsi = args.stmsi_value; + valid_stmsi = true; + } else { + if (!read_stimsi_file(&ul_ccch_msg.msg.rrc_con_req.ue_id.s_tmsi)) { + rrc_log->warning("Could not read S-TMSI from persistent file. Trying normal attach.\n"); + } else { + valid_stmsi = true; + } + } + } + } + if (!valid_stmsi) { ul_ccch_msg.msg.rrc_con_req.ue_id_type = LIBLTE_RRC_CON_REQ_UE_ID_TYPE_RANDOM_VALUE; ul_ccch_msg.msg.rrc_con_req.ue_id.random = 1000; } + ul_ccch_msg.msg.rrc_con_req.cause = LIBLTE_RRC_CON_REQ_EST_CAUSE_MO_SIGNALLING; liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf); @@ -876,6 +956,14 @@ void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGU nas_sdu->N_bytes = reconfig->ded_info_nas_list[i].N_bytes; nas->write_pdu(lcid, nas_sdu); } + + // Get S-TMSI from NAS and store it in persistent file + LIBLTE_RRC_S_TMSI_STRUCT s_tmsi; + if (nas->get_s_tmsi(&s_tmsi)) { + if (!write_stimsi_file(s_tmsi)) { + rrc_log->warning("Could not store S-TMSI in persistent file\n"); + } + } } /* Actions upon reception of RRCConnectionRelease 5.3.8.3 */ @@ -1022,10 +1110,12 @@ void rrc::write_pdu_pcch(byte_buffer_t *pdu) { LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi_paged; for (uint32_t i = 0; i < pcch_msg.paging_record_list_size; i++) { s_tmsi_paged = &pcch_msg.paging_record_list[i].ue_identity.s_tmsi; - rrc_log->info("Received paging (%d/%d) for UE 0x%x\n", i + 1, pcch_msg.paging_record_list_size, - pcch_msg.paging_record_list[i].ue_identity.s_tmsi); - rrc_log->console("Received paging (%d/%d) for UE 0x%x\n", i + 1, pcch_msg.paging_record_list_size, - pcch_msg.paging_record_list[i].ue_identity.s_tmsi); + rrc_log->info("Received paging (%d/%d) for UE %x:%x\n", i + 1, pcch_msg.paging_record_list_size, + pcch_msg.paging_record_list[i].ue_identity.s_tmsi.mmec, + pcch_msg.paging_record_list[i].ue_identity.s_tmsi.m_tmsi); + rrc_log->console("Received paging (%d/%d) for UE %x:%x\n", i + 1, pcch_msg.paging_record_list_size, + pcch_msg.paging_record_list[i].ue_identity.s_tmsi.mmec, + pcch_msg.paging_record_list[i].ue_identity.s_tmsi.m_tmsi); if (s_tmsi.mmec == s_tmsi_paged->mmec && s_tmsi.m_tmsi == s_tmsi_paged->m_tmsi) { rrc_log->info("S-TMSI match in paging message\n"); rrc_log->console("S-TMSI match in paging message\n"); @@ -1200,7 +1290,7 @@ void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu) { * *******************************************************************************/ void rrc::enable_capabilities() { - bool enable_ul_64 = ue_category >= 5 && current_cell->sib2.rr_config_common_sib.pusch_cnfg.enable_64_qam; + bool enable_ul_64 = args.ue_category >= 5 && current_cell->sib2.rr_config_common_sib.pusch_cnfg.enable_64_qam; rrc_log->info("%s 64QAM PUSCH\n", enable_ul_64 ? "Enabling" : "Disabling"); phy->set_config_64qam_en(enable_ul_64); } @@ -1218,7 +1308,7 @@ void rrc::send_rrc_ue_cap_info(uint32_t lcid, byte_buffer_t *pdu) { LIBLTE_RRC_UE_EUTRA_CAPABILITY_STRUCT *cap = &info->ue_capability_rat[0].eutra_capability; cap->access_stratum_release = LIBLTE_RRC_ACCESS_STRATUM_RELEASE_REL8; - cap->ue_category = ue_category; + cap->ue_category = args.ue_category; cap->pdcp_params.max_rohc_ctxts_present = false; cap->pdcp_params.supported_rohc_profiles[0] = false; @@ -1234,31 +1324,17 @@ void rrc::send_rrc_ue_cap_info(uint32_t lcid, byte_buffer_t *pdu) { cap->phy_params.specific_ref_sigs_supported = false; cap->phy_params.tx_antenna_selection_supported = false; - //TODO: Generate this from user input? - cap->rf_params.N_supported_band_eutras = 3; - cap->rf_params.supported_band_eutra[0].band_eutra = 3; - cap->rf_params.supported_band_eutra[0].half_duplex = false; - cap->rf_params.supported_band_eutra[1].band_eutra = 7; - cap->rf_params.supported_band_eutra[1].half_duplex = false; - cap->rf_params.supported_band_eutra[2].band_eutra = 20; - cap->rf_params.supported_band_eutra[2].half_duplex = false; - - cap->meas_params.N_band_list_eutra = 3; - cap->meas_params.band_list_eutra[0].N_inter_freq_need_for_gaps = 3; - cap->meas_params.band_list_eutra[0].inter_freq_need_for_gaps[0] = true; - cap->meas_params.band_list_eutra[0].inter_freq_need_for_gaps[1] = true; - cap->meas_params.band_list_eutra[0].inter_freq_need_for_gaps[2] = true; - cap->meas_params.band_list_eutra[1].N_inter_freq_need_for_gaps = 3; - cap->meas_params.band_list_eutra[1].inter_freq_need_for_gaps[0] = true; - cap->meas_params.band_list_eutra[1].inter_freq_need_for_gaps[1] = true; - cap->meas_params.band_list_eutra[1].inter_freq_need_for_gaps[2] = true; - cap->meas_params.band_list_eutra[2].N_inter_freq_need_for_gaps = 3; - cap->meas_params.band_list_eutra[2].inter_freq_need_for_gaps[0] = true; - cap->meas_params.band_list_eutra[2].inter_freq_need_for_gaps[1] = true; - cap->meas_params.band_list_eutra[2].inter_freq_need_for_gaps[2] = true; + cap->rf_params.N_supported_band_eutras = args.nof_supported_bands; + cap->meas_params.N_band_list_eutra = args.nof_supported_bands; + for (uint32_t i=0;irf_params.supported_band_eutra[i].band_eutra = args.supported_bands[i]; + cap->rf_params.supported_band_eutra[i].half_duplex = false; + cap->meas_params.band_list_eutra[i].N_inter_freq_need_for_gaps = 1; + cap->meas_params.band_list_eutra[i].inter_freq_need_for_gaps[0] = true; + } cap->feature_group_indicator_present = true; - cap->feature_group_indicator = 0x62001000; + cap->feature_group_indicator = args.feature_group; cap->inter_rat_params.utra_fdd_present = false; cap->inter_rat_params.utra_tdd128_present = false; cap->inter_rat_params.utra_tdd384_present = false; diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index 5b3559ae9..867221e87 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -92,19 +92,36 @@ k = 00112233445566778899aabbccddeeff imsi = 001010123456789 imei = 353490069873319 + +##################################################################### +# RRC configuration +# +# stimsi_attach: If enabled, always tries first an S-TMSI attach using the +# S-TMSI value stored in .stimsi file generated in previous run +# mmec_value: If defined (non-zero), overwrites the value stored in .stimsi file +# m_tmsi_value: If defined (non-zero), overwrites the value stored in .stimsi file +# +# ue_category: Sets UE category (range 1-5). Default: 4 +# feature_group: Hex value of the featureGroupIndicators field in the +# UECapabilityInformation message. Default 0xe6041c00 +##################################################################### +[rrc] +#stmsi_attach = false +#mmec_value = 0 +#mtmsi_value = 0 +#ue_category = 4 +#feature_group = 0xe6041c00 + [gui] enable = false ##################################################################### # Expert configuration options # -# 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., +# 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. # cqi_max: Upper bound on the maximum CQI to be reported. Default 15. # cqi_fixed: Fixes the reported CQI to a constant value. Default disabled. @@ -146,7 +163,6 @@ enable = false [expert] #ip_netmask = 255.255.255.0 #rssi_sensor_enabled = false -#ue_category = 4 #prach_gain = 30 #cqi_max = 15 #cqi_fixed = 10 From b7d678f05eddbf9c82409d421895c8fd57b14231 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 15 Nov 2017 13:45:26 +0100 Subject: [PATCH 141/242] Solved bug when parsing two times the same subdev_spec --- lib/src/phy/rf/rf_uhd_imp.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/src/phy/rf/rf_uhd_imp.c b/lib/src/phy/rf/rf_uhd_imp.c index 729d96e11..9ed9e5501 100644 --- a/lib/src/phy/rf/rf_uhd_imp.c +++ b/lib/src/phy/rf/rf_uhd_imp.c @@ -309,7 +309,7 @@ static void copy_subdev_string(char *dst, char *src) { int n = 0; size_t len = strlen(src); /* Copy until end of string or comma */ - while (n < len && src != '\0' && src[n] != ',') { + while (n < len && src[n] != '\0' && src[n] != ',') { dst[n] = src[n]; n++; } @@ -383,8 +383,6 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels) char *tx_subdev_ptr = strstr(args, tx_subdev_arg); if (tx_subdev_ptr) { copy_subdev_string(tx_subdev_str, tx_subdev_ptr + strlen(tx_subdev_arg)); - remove_substring(args, tx_subdev_arg); - remove_substring(args, tx_subdev_str); } // Set receiver subdevice spec string @@ -393,6 +391,14 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels) char *rx_subdev_ptr = strstr(args, rx_subdev_arg); if (rx_subdev_ptr) { copy_subdev_string(rx_subdev_str, rx_subdev_ptr + strlen(rx_subdev_arg)); + } + + if (tx_subdev_ptr) { + remove_substring(args, tx_subdev_arg); + remove_substring(args, tx_subdev_str); + } + + if (rx_subdev_ptr) { remove_substring(args, rx_subdev_arg); remove_substring(args, rx_subdev_str); } From e04a22191185ede06eb6b7d392c6f950f6715d07 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 16 Nov 2017 12:14:27 +0100 Subject: [PATCH 142/242] Removed volk occurrences. Fixes #103 --- CMakeLists.txt | 15 --------------- lib/src/phy/CMakeLists.txt | 4 ---- lib/src/phy/utils/vector_simd.c | 1 - 3 files changed, 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index efaa1973a..bead502f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -189,21 +189,6 @@ if(ENABLE_GUI) endif(SRSGUI_FOUND) endif(ENABLE_GUI) -# VOLK -include(CheckFunctionExistsMath) -if(ENABLE_VOLK) - find_package(Volk) - if(VOLK_FOUND) - include_directories(${VOLK_INCLUDE_DIRS}) - link_directories(${VOLK_LIBRARY_DIRS}) - message(STATUS "Compiling with VOLK SIMD library.") - else(VOLK_FOUND) - message(STATUS "VOLK SIMD library NOT found. Using generic implementation.") - endif(VOLK_FOUND) -else(ENABLE_VOLK) - message(STATUS "VOLK library disabled") -endif(ENABLE_VOLK) - ######################################################################## # Install Dirs ######################################################################## diff --git a/lib/src/phy/CMakeLists.txt b/lib/src/phy/CMakeLists.txt index 572ff19c3..b52af7b1d 100644 --- a/lib/src/phy/CMakeLists.txt +++ b/lib/src/phy/CMakeLists.txt @@ -57,9 +57,5 @@ set(srslte_srcs $ add_library(srslte_phy STATIC ${srslte_srcs}) target_link_libraries(srslte_phy ${FFT_LIBRARIES}) -if(VOLK_FOUND) - target_link_libraries(srslte_phy ${VOLK_LIBRARIES}) -endif(VOLK_FOUND) - target_link_libraries(srslte_phy pthread m) install(TARGETS srslte_phy DESTINATION ${LIBRARY_DIR}) diff --git a/lib/src/phy/utils/vector_simd.c b/lib/src/phy/utils/vector_simd.c index ab281a653..23c58cfce 100644 --- a/lib/src/phy/utils/vector_simd.c +++ b/lib/src/phy/utils/vector_simd.c @@ -199,7 +199,6 @@ void srslte_vec_lut_sss_simd(short *x, unsigned short *lut, short *y, int len) { } } -/* Modified from volk_32f_s32f_convert_16i_a_simd2. Removed clipping */ void srslte_vec_convert_fi_simd(float *x, int16_t *z, float scale, int len) { int i = 0; From e2a61af462a9d4a4c75c531c0aedc520ddeed105 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 16 Nov 2017 14:48:03 +0100 Subject: [PATCH 143/242] Added Aperiodic mode 3-1 in enb and some more optimizations --- lib/include/srslte/phy/enb/enb_ul.h | 1 + lib/include/srslte/phy/phch/pusch.h | 1 + lib/include/srslte/phy/phch/uci.h | 36 +++--- lib/src/phy/enb/enb_ul.c | 10 +- lib/src/phy/phch/cqi.c | 37 +++++- lib/src/phy/phch/pusch.c | 35 +++++- lib/src/phy/phch/sch.c | 19 +-- lib/src/phy/phch/test/pusch_test.c | 2 +- lib/src/phy/phch/uci.c | 180 ++++++++++------------------ lib/src/phy/ue/ue_dl.c | 3 +- srsenb/src/phy/phch_worker.cc | 35 ++++-- srsenb/src/upper/rrc.cc | 6 +- srsue/src/phy/phch_worker.cc | 16 +-- 13 files changed, 200 insertions(+), 181 deletions(-) diff --git a/lib/include/srslte/phy/enb/enb_ul.h b/lib/include/srslte/phy/enb/enb_ul.h index 6839cfc9e..8699a2a37 100644 --- a/lib/include/srslte/phy/enb/enb_ul.h +++ b/lib/include/srslte/phy/enb/enb_ul.h @@ -140,6 +140,7 @@ SRSLTE_API int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q, uint32_t rv_idx, uint32_t current_tx_nb, uint8_t *data, + srslte_cqi_value_t *cqi_value, srslte_uci_data_t *uci_data, uint32_t tti); diff --git a/lib/include/srslte/phy/phch/pusch.h b/lib/include/srslte/phy/phch/pusch.h index 2328c8ff3..01db068a5 100644 --- a/lib/include/srslte/phy/phch/pusch.h +++ b/lib/include/srslte/phy/phch/pusch.h @@ -142,6 +142,7 @@ SRSLTE_API int srslte_pusch_decode(srslte_pusch_t *q, float noise_estimate, uint16_t rnti, uint8_t *data, + srslte_cqi_value_t *cqi_value, srslte_uci_data_t *uci_data); SRSLTE_API float srslte_pusch_average_noi(srslte_pusch_t *q); diff --git a/lib/include/srslte/phy/phch/uci.h b/lib/include/srslte/phy/phch/uci.h index c20fca239..6ea00c5d1 100644 --- a/lib/include/srslte/phy/phch/uci.h +++ b/lib/include/srslte/phy/phch/uci.h @@ -136,31 +136,25 @@ SRSLTE_API int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, uint32_t H_prime_total, srslte_uci_bit_t *ri_bits); -SRSLTE_API int srslte_uci_decode_ack(srslte_pusch_cfg_t *cfg, - int16_t *q_bits, - uint8_t *c_seq, - float beta, - uint32_t H_prime_total, - uint32_t O_cqi, - srslte_uci_bit_t *ack_bits, - uint8_t acks[2], - uint32_t nof_acks); - -SRSLTE_API int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg, - uint8_t data, +SRSLTE_API int srslte_uci_encode_ack_ri(srslte_pusch_cfg_t *cfg, + uint8_t *data, + uint32_t data_len, uint32_t O_cqi, float beta, uint32_t H_prime_total, - srslte_uci_bit_t *ri_bits); - -SRSLTE_API int srslte_uci_decode_ri(srslte_pusch_cfg_t *cfg, - int16_t *q_bits, - uint8_t *c_seq, - float beta, - uint32_t H_prime_total, - uint32_t O_cqi, srslte_uci_bit_t *ri_bits, - uint8_t *data); + bool is_ri); + +SRSLTE_API int srslte_uci_decode_ack_ri(srslte_pusch_cfg_t *cfg, + int16_t *q_bits, + uint8_t *c_seq, + float beta, + uint32_t H_prime_total, + uint32_t O_cqi, + srslte_uci_bit_t *ack_ri_bits, + uint8_t data[2], + uint32_t nof_bits, + bool is_ri); #endif diff --git a/lib/src/phy/enb/enb_ul.c b/lib/src/phy/enb/enb_ul.c index c492369dc..8ea5dd3e4 100644 --- a/lib/src/phy/enb/enb_ul.c +++ b/lib/src/phy/enb/enb_ul.c @@ -290,10 +290,9 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti, srslte_uci_data_t *uci_data) { uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS]; - uint8_t *pucch_bits_ptr = pucch_bits; if (q->users[rnti]) { - uint32_t nof_uci_bits = (uci_data->uci_ri_len > 0) ? uci_data->uci_ri_len : (uci_data->uci_cqi_len + + uint32_t nof_uci_bits = uci_data->ri_periodic_report ? uci_data->uci_ri_len : (uci_data->uci_cqi_len + uci_data->uci_dif_cqi_len + uci_data->uci_pmi_len); int ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, pucch_bits, nof_uci_bits); @@ -312,11 +311,11 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti, // Save ACK bits if (uci_data->uci_ack_len > 0) { - uci_data->uci_ack = *(pucch_bits_ptr++); + uci_data->uci_ack = pucch_bits[0]; } if (uci_data->uci_ack_len > 1) { - uci_data->uci_ack_2 = *(pucch_bits_ptr++); + uci_data->uci_ack_2 = pucch_bits[1]; } // PUCCH2 CQI bits are decoded inside srslte_pucch_decode() @@ -355,7 +354,7 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti, int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q, srslte_ra_ul_grant_t *grant, srslte_softbuffer_rx_t *softbuffer, uint16_t rnti, uint32_t rv_idx, uint32_t current_tx_nb, - uint8_t *data, srslte_uci_data_t *uci_data, uint32_t tti) + uint8_t *data, srslte_cqi_value_t *cqi_value, srslte_uci_data_t *uci_data, uint32_t tti) { if (q->users[rnti]) { if (srslte_pusch_cfg(&q->pusch, @@ -391,6 +390,7 @@ int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q, srslte_ra_ul_grant_t *grant, srs softbuffer, q->sf_symbols, q->ce, noise_power, rnti, data, + cqi_value, uci_data); } diff --git a/lib/src/phy/phch/cqi.c b/lib/src/phy/phch/cqi.c index 2c0940af5..8589ee51a 100644 --- a/lib/src/phy/phch/cqi.c +++ b/lib/src/phy/phch/cqi.c @@ -199,17 +199,44 @@ int srslte_cqi_value_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_value_ } int srslte_cqi_size(srslte_cqi_value_t *value) { + int size = 0; + switch(value->type) { case SRSLTE_CQI_TYPE_WIDEBAND: - return 4; + size = 4; + break; case SRSLTE_CQI_TYPE_SUBBAND: - return 4+(value->subband.subband_label_2_bits)?2:1; + size = 4 + (value->subband.subband_label_2_bits) ? 2 : 1; + break; case SRSLTE_CQI_TYPE_SUBBAND_UE: - return 4+2+value->subband_ue.L; + size = 4 + 2 + value->subband_ue.L; + break; case SRSLTE_CQI_TYPE_SUBBAND_HL: - return 4+2*value->subband_hl.N; + /* First codeword */ + size += 4 + 2 * value->subband_hl.N; + + /* Add Second codeword if required */ + if (value->subband_hl.rank_is_not_one && value->subband_hl.pmi_present) { + size += 4 + 2 * value->subband_hl.N; + } + + /* Add PMI if required*/ + if (value->subband_hl.pmi_present) { + if (value->subband_hl.four_antenna_ports) { + size += 4; + } else { + if (value->subband_hl.rank_is_not_one) { + size += 1; + } else { + size += 2; + } + } + } + break; + default: + size = SRSLTE_ERROR; } - return -1; + return size; } static bool srslte_cqi_get_N(uint32_t I_cqi_pmi, uint32_t *N_p, uint32_t *N_offset) { diff --git a/lib/src/phy/phch/pusch.c b/lib/src/phy/phch/pusch.c index ba1195507..c3e4e45f8 100644 --- a/lib/src/phy/phch/pusch.c +++ b/lib/src/phy/phch/pusch.c @@ -566,9 +566,9 @@ int srslte_pusch_decode(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, cf_t *sf_symbols, cf_t *ce, float noise_estimate, uint16_t rnti, - uint8_t *data, srslte_uci_data_t *uci_data) + uint8_t *data, srslte_cqi_value_t *cqi_value, srslte_uci_data_t *uci_data) { - + int ret = SRSLTE_ERROR_INVALID_INPUTS; uint32_t n; if (q != NULL && @@ -607,19 +607,42 @@ int srslte_pusch_decode(srslte_pusch_t *q, // Generate scrambling sequence if not pre-generated srslte_sequence_t *seq = get_user_sequence(q, rnti, cfg->sf_idx, cfg->nbits.nof_bits); + // Set CQI len assuming RI = 1 (3GPP 36.212 Clause 5.2.4.1. Uplink control information on PUSCH without UL-SCH data) + if (cqi_value) { + if (cqi_value->type == SRSLTE_CQI_TYPE_SUBBAND_HL) { + cqi_value->subband_hl.rank_is_not_one = false; + } + uci_data->uci_cqi_len = (uint32_t) srslte_cqi_size(cqi_value); + uci_data->uci_ri_len = (q->cell.nof_ports == 4) ? 2 : 1; + } + // Decode RI/HARQ bits before descrambling if (srslte_ulsch_uci_decode_ri_ack(&q->ul_sch, cfg, softbuffer, q->q, seq->c, uci_data)) { fprintf(stderr, "Error decoding RI/HARQ bits\n"); return SRSLTE_ERROR; } + + // Set CQI len with corresponding RI + if (cqi_value) { + if (cqi_value->type == SRSLTE_CQI_TYPE_SUBBAND_HL) { + cqi_value->subband_hl.rank_is_not_one = (uci_data->uci_ri != 0); + } + uci_data->uci_cqi_len = (uint32_t) srslte_cqi_size(cqi_value); + } // Descrambling srslte_scrambling_s_offset(seq, q->q, 0, cfg->nbits.nof_bits); - - return srslte_ulsch_uci_decode(&q->ul_sch, cfg, softbuffer, q->q, q->g, data, uci_data); - } else { - return SRSLTE_ERROR_INVALID_INPUTS; + + // Decode + ret = srslte_ulsch_uci_decode(&q->ul_sch, cfg, softbuffer, q->q, q->g, data, uci_data); + + // Unpack CQI value if available + if (cqi_value) { + srslte_cqi_value_unpack(uci_data->uci_cqi, cqi_value); + } } + + return ret; } uint32_t srslte_pusch_last_noi(srslte_pusch_t *q) { diff --git a/lib/src/phy/phch/sch.c b/lib/src/phy/phch/sch.c index 930364725..1e972594d 100644 --- a/lib/src/phy/phch/sch.c +++ b/lib/src/phy/phch/sch.c @@ -658,7 +658,7 @@ int srslte_ulsch_uci_decode_ri_ack(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srs if (cfg->cb_segm.tbs == 0) { beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi]; } - ret = srslte_uci_decode_ack(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, acks, uci_data->uci_ack_len); + ret = srslte_uci_decode_ack_ri(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, acks, uci_data->uci_ack_len, false); if (ret < 0) { return ret; } @@ -678,7 +678,7 @@ int srslte_ulsch_uci_decode_ri_ack(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srs if (cfg->cb_segm.tbs == 0) { beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi]; } - ret = srslte_uci_decode_ri(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, &uci_data->uci_ri); + ret = srslte_uci_decode_ack_ri(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, &uci_data->uci_ri, uci_data->uci_ri_len, true); if (ret < 0) { return ret; } @@ -756,13 +756,18 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q, uint32_t nb_q = cfg->nbits.nof_bits; uint32_t Qm = cfg->grant.Qm; - // Encode RI - if (uci_data.uci_ri_len > 0) { + // Encode RI if CQI enabled + if (uci_data.uci_ri_len > 0 || uci_data.uci_cqi_len > 0) { + /* If no RI is reported set it to zero as specified in 3GPP 36.213 clause 7.2.1 */ + if (uci_data.uci_ri_len == 0) { + uci_data.uci_ri = 0; + } float beta = beta_ri_offset[cfg->uci_cfg.I_offset_ri]; if (cfg->cb_segm.tbs == 0) { beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi]; } - ret = srslte_uci_encode_ri(cfg, uci_data.uci_ri, uci_data.uci_cqi_len, beta, nb_q/Qm, q->ack_ri_bits); + uint8_t ri[2] = {uci_data.uci_ri, 0}; + ret = srslte_uci_encode_ack_ri(cfg, ri, uci_data.uci_ri_len, uci_data.uci_cqi_len, beta, nb_q/Qm, q->ack_ri_bits, true); if (ret < 0) { return ret; } @@ -809,8 +814,8 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q, if (cfg->cb_segm.tbs == 0) { beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi]; } - ret = srslte_uci_encode_ack(cfg, acks, uci_data.uci_ack_len, uci_data.uci_cqi_len, - beta, nb_q / Qm, &q->ack_ri_bits[Q_prime_ri * Qm]); + ret = srslte_uci_encode_ack_ri(cfg, acks, uci_data.uci_ack_len, uci_data.uci_cqi_len, + beta, nb_q / Qm, &q->ack_ri_bits[Q_prime_ri * Qm], false); if (ret < 0) { return ret; } diff --git a/lib/src/phy/phch/test/pusch_test.c b/lib/src/phy/phch/test/pusch_test.c index cf0be75c3..651803617 100644 --- a/lib/src/phy/phch/test/pusch_test.c +++ b/lib/src/phy/phch/test/pusch_test.c @@ -252,7 +252,7 @@ int main(int argc, char **argv) { } gettimeofday(&t[1], NULL); - int r = srslte_pusch_decode(&pusch_rx, &cfg, &softbuffer_rx, sf_symbols, ce, 0, rnti, data, &uci_data_rx); + int r = srslte_pusch_decode(&pusch_rx, &cfg, &softbuffer_rx, sf_symbols, ce, 0, rnti, data, NULL, &uci_data_rx); gettimeofday(&t[2], NULL); get_time_interval(t); if (r) { diff --git a/lib/src/phy/phch/uci.c b/lib/src/phy/phch/uci.c index 0b9a54058..8a1a36544 100644 --- a/lib/src/phy/phch/uci.c +++ b/lib/src/phy/phch/uci.c @@ -606,9 +606,7 @@ static uint32_t encode_ri_ack(uint8_t data[2], uint32_t data_len, srslte_uci_bit /* Decode UCI HARQ/ACK bits as described in 5.2.2.6 of 36.212 * Currently only supporting 1-bit HARQ */ -#ifndef MIMO_ENB - -static int32_t decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos) +static int32_t decode_ri_ack_1bit(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos) { uint32_t p0 = pos[0].position; uint32_t p1 = pos[1].position; @@ -618,33 +616,8 @@ static int32_t decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t * return -(q0+q1); } -int srslte_uci_decode_ack(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_seq, - float beta, uint32_t H_prime_total, - uint32_t O_cqi, srslte_uci_bit_t *ack_bits, uint8_t acks[2], uint32_t nof_acks) -{ - int32_t rx_ack = 0; - - if (beta < 0) { - fprintf(stderr, "Error beta is reserved\n"); - return -1; - } - - uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta); - - // Use the same interleaver function to get the HARQ bit position - for (uint32_t i=0;igrant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ack_bits[cfg->grant.Qm*i]); - rx_ack += (int32_t) decode_ri_ack(q_bits, c_seq, &ack_bits[cfg->grant.Qm*i]); - } - - if (acks) { - acks[0] = rx_ack>0; - } - return (int) Qprime; -} -#else -static void decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos, uint32_t Qm, int32_t data[3]) +static void decode_ri_ack_2bits(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos, uint32_t Qm, int32_t data[3]) { uint32_t p0 = pos[Qm * 0 + 0].position; uint32_t p1 = pos[Qm * 0 + 1].position; @@ -665,120 +638,91 @@ static void decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos data[2] -= q2 + q5; } -int srslte_uci_decode_ack(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_seq, - float beta, uint32_t H_prime_total, - uint32_t O_cqi, srslte_uci_bit_t *ack_bits, uint8_t acks[2], uint32_t nof_acks) -{ - int32_t acks_sum[3] = {0, 0, 0}; - +/* Encode UCI ACK/RI bits as described in 5.2.2.6 of 36.212 + * Currently only supporting 1-bit RI + */ +int srslte_uci_encode_ack_ri(srslte_pusch_cfg_t *cfg, + uint8_t *data, uint32_t data_len, + uint32_t O_cqi, float beta, uint32_t H_prime_total, + srslte_uci_bit_t *bits, bool ack_ri) { if (beta < 0) { fprintf(stderr, "Error beta is reserved\n"); - return -1; + return -1; } + uint32_t Qprime = Q_prime_ri_ack(cfg, data_len, O_cqi, beta); + srslte_uci_bit_type_t q_encoded_bits[18]; - uint32_t Qprime = Q_prime_ri_ack(cfg, nof_acks, O_cqi, beta); + uint32_t nof_encoded_bits = encode_ri_ack(data, data_len, q_encoded_bits, cfg->grant.Qm); - // Use the same interleaver function to get the HARQ bit position for (uint32_t i = 0; i < Qprime; i++) { - uci_ulsch_interleave_ack_gen(i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ack_bits[cfg->grant.Qm*i]); - if ((i % 3 == 0) && i > 0) { - decode_ri_ack(q_bits, &c_seq[0], &ack_bits[cfg->grant.Qm*(i-3)], cfg->grant.Qm, acks_sum); + if (ack_ri) { + uci_ulsch_interleave_ri_gen(i, + cfg->grant.Qm, + H_prime_total, + cfg->nbits.nof_symb, + cfg->cp, + &bits[cfg->grant.Qm * i]); + } else { + uci_ulsch_interleave_ack_gen(i, + cfg->grant.Qm, + H_prime_total, + cfg->nbits.nof_symb, + cfg->cp, + &bits[cfg->grant.Qm * i]); } + uci_ulsch_interleave_put(&q_encoded_bits[(i * cfg->grant.Qm) % nof_encoded_bits], + cfg->grant.Qm, + &bits[cfg->grant.Qm * i]); } - if (nof_acks == 1 && acks) { - acks[0] = (uint8_t)(acks_sum[0] + acks_sum[1] + acks_sum[2] > 0); - } else if (acks) { - acks[0] = (uint8_t)(acks_sum[0] > 0); - acks[1] = (uint8_t)(acks_sum[1] > 0); - // TODO: Do something with acks_sum[2] - } - return (int) Qprime; -} -#endif - -/* Encode UCI HARQ/ACK bits as described in 5.2.2.6 of 36.212 - * Currently only supporting 1-bit HARQ - */ -int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, uint8_t acks[2], uint32_t nof_acks, - uint32_t O_cqi, float beta, uint32_t H_prime_total, - srslte_uci_bit_t *ack_bits) -{ - if (beta < 0) { - fprintf(stderr, "Error beta is reserved\n"); - return -1; - } - - uint32_t Qprime = Q_prime_ri_ack(cfg, nof_acks, O_cqi, beta); - srslte_uci_bit_type_t q_encoded_bits[18]; - - uint32_t nof_encoded_bits = encode_ri_ack(acks, nof_acks, q_encoded_bits, cfg->grant.Qm); - - for (uint32_t i=0;igrant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ack_bits[cfg->grant.Qm*i]); - uci_ulsch_interleave_put(&q_encoded_bits[(i*cfg->grant.Qm)%nof_encoded_bits], cfg->grant.Qm, &ack_bits[cfg->grant.Qm*i]); - } - return (int) Qprime; } -/* Encode UCI RI bits as described in 5.2.2.6 of 36.212 +/* Decode UCI ACK/RI bits as described in 5.2.2.6 of 36.212 * Currently only supporting 1-bit RI */ -int srslte_uci_decode_ri(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_seq, - float beta, uint32_t H_prime_total, - uint32_t O_cqi, srslte_uci_bit_t *ri_bits, uint8_t *data) +int srslte_uci_decode_ack_ri(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_seq, + float beta, uint32_t H_prime_total, + uint32_t O_cqi, srslte_uci_bit_t *ack_ri_bits, uint8_t data[2], uint32_t nof_bits, bool is_ri) { - int32_t ri_sum[3] = {0, 0, 0}; - + int32_t sum[3] = {0, 0, 0}; + if (beta < 0) { fprintf(stderr, "Error beta is reserved\n"); - return -1; + return -1; } - uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta); + uint32_t Qprime = Q_prime_ri_ack(cfg, nof_bits, O_cqi, beta); - // Use the same interleaver function to get the HARQ bit position - for (uint32_t i=0;igrant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ri_bits[cfg->grant.Qm*i]); - if ((i % 3 == 0) && i > 0) { - //decode_ri_ack(q_bits, &c_seq[0], &ri_bits[cfg->grant.Qm*(i-3)], cfg->grant.Qm, ri_sum); - } - } + for (uint32_t i = 0; i < Qprime; i++) { + if (is_ri) { + uci_ulsch_interleave_ri_gen(i, + cfg->grant.Qm, + H_prime_total, + cfg->nbits.nof_symb, + cfg->cp, + &ack_ri_bits[cfg->grant.Qm * i]); + } else { + uci_ulsch_interleave_ack_gen(i, + cfg->grant.Qm, + H_prime_total, + cfg->nbits.nof_symb, + cfg->cp, + &ack_ri_bits[cfg->grant.Qm * i]); - if (data) { - *data = (uint8_t) ((ri_sum[0] + ri_sum[1] + ri_sum[2]) > 0); + } + if (nof_bits == 2 && (i % 3 == 0) && i > 0) { + decode_ri_ack_2bits(q_bits, &c_seq[0], &ack_ri_bits[cfg->grant.Qm * (i - 3)], cfg->grant.Qm, sum); + } else if (nof_bits == 1) { + sum[0] += (int32_t) decode_ri_ack_1bit(q_bits, c_seq, &ack_ri_bits[cfg->grant.Qm * i]); + } } - return (int) Qprime; -} - - -/* Encode UCI RI bits as described in 5.2.2.6 of 36.212 - * Currently only supporting 1-bit RI - */ -int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg, - uint8_t ri, - uint32_t O_cqi, float beta, uint32_t H_prime_total, - srslte_uci_bit_t *ri_bits) -{ - // FIXME: It supports RI of 1 bit only - uint8_t data[2] = {ri, 0}; - if (beta < 0) { - fprintf(stderr, "Error beta is reserved\n"); - return -1; + data[0] = (uint8_t) (sum[0] > 0); + if (nof_bits == 2) { + data[1] = (uint8_t) (sum[1] > 0); } - uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta); - srslte_uci_bit_type_t q_encoded_bits[18]; - uint32_t nof_encoded_bits = encode_ri_ack(data, 1, q_encoded_bits, cfg->grant.Qm); - - for (uint32_t i=0;igrant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ri_bits[cfg->grant.Qm*i]); - uci_ulsch_interleave_put(&q_encoded_bits[(i*cfg->grant.Qm)%nof_encoded_bits], cfg->grant.Qm, &ri_bits[cfg->grant.Qm*i]); - } - return (int) Qprime; } - diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index a677aa70d..3a3198dea 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -669,7 +669,8 @@ int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, uint8_t *ri, uint8_t *pmi, flo /* Select the best Rank indicator (RI) and Precoding Matrix Indicator (PMI) */ for (uint32_t nof_layers = 1; nof_layers <= SRSLTE_MAX_LAYERS; nof_layers++) { float _sinr = q->sinr[nof_layers - 1][q->pmi[nof_layers - 1]] * nof_layers * nof_layers; - if (_sinr > best_sinr + 0.1) { + /* Find best SINR, force maximum number of layers if SNR is higher than 30 dB */ + if (_sinr > best_sinr + 0.1 || _sinr > 1.0e+3) { best_sinr = _sinr; best_pmi = (uint8_t) q->pmi[nof_layers - 1]; best_ri = (uint8_t) (nof_layers - 1); diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index 8ed6428ef..990633aa7 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -435,8 +435,8 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) } // Configure PUSCH CQI channel - srslte_cqi_value_t cqi_value; - bool cqi_enabled = false, ri_enabled = false; + srslte_cqi_value_t cqi_value = {0}; + bool cqi_enabled = false; #if 0 if (ue_db[rnti].cqi_en && ue_db[rnti].ri_en && srslte_ri_send(ue_db[rnti].pmi_idx, ue_db[rnti].ri_idx, tti_rx) ) { uci_data.uci_ri_len = 1; /* Asumes only 1 bit for RI */ @@ -450,14 +450,13 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) } } else #endif - if (grants[i].grant.cqi_request) { + if (grants[i].grant.cqi_request) { cqi_value.type = SRSLTE_CQI_TYPE_SUBBAND_HL; cqi_value.subband_hl.N = (phy->cell.nof_prb > 7) ? srslte_cqi_hl_get_no_subbands(phy->cell.nof_prb) : 0; + cqi_value.subband_hl.four_antenna_ports = (phy->cell.nof_ports == 4); + cqi_value.subband_hl.pmi_present = (ue_db[rnti].dedicated.cqi_report_cnfg.report_mode_aperiodic == LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM31); cqi_enabled = true; } - if (cqi_enabled) { - uci_data.uci_cqi_len = srslte_cqi_size(&cqi_value); - } // mark this tti as having an ul grant to avoid pucch ue_db[rnti].has_grant_tti = tti_rx; @@ -473,6 +472,7 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) rnti, grants[i].rv_idx, grants[i].current_tx_nb, grants[i].data, + (cqi_enabled) ? &cqi_value : NULL, &uci_data, sf_rx); } else { @@ -494,11 +494,24 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) char cqi_str[64]; if (cqi_enabled) { - srslte_cqi_value_unpack(uci_data.uci_cqi, &cqi_value); if (ue_db[rnti].cqi_en) { wideband_cqi_value = cqi_value.wideband.wideband_cqi; } else if (grants[i].grant.cqi_request) { wideband_cqi_value = cqi_value.subband_hl.wideband_cqi_cw0; + if (cqi_value.subband_hl.pmi_present) { + if (cqi_value.subband_hl.rank_is_not_one) { + Info("PUSCH: Aperiodic ri~1, CQI=%02d/%02d, pmi=%d for %d subbands\n", + cqi_value.subband_hl.wideband_cqi_cw0, cqi_value.subband_hl.wideband_cqi_cw1, + cqi_value.subband_hl.pmi, cqi_value.subband_hl.N); + } else { + Info("PUSCH: Aperiodic ri=1, CQI=%02d, pmi=%d for %d subbands\n", + cqi_value.subband_hl.wideband_cqi_cw0, cqi_value.subband_hl.pmi, cqi_value.subband_hl.N); + } + } else { + Info("PUSCH: Aperiodic ri%s, CQI=%02d for %d subbands\n", + cqi_value.subband_hl.rank_is_not_one?"~1":"=1", + cqi_value.subband_hl.wideband_cqi_cw0, cqi_value.subband_hl.N); + } } snprintf(cqi_str, 64, ", cqi=%d", wideband_cqi_value); } @@ -551,13 +564,19 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) } } - // Notify MAC of UL SNR and DL CQI + // Notify MAC of UL SNR, DL CQI and DL RI if (snr_db >= PUSCH_RL_SNR_DB_TH) { phy->mac->snr_info(tti_rx, rnti, snr_db); } if (uci_data.uci_cqi_len>0 && crc_res) { phy->mac->cqi_info(tti_rx, rnti, wideband_cqi_value); } + if (uci_data.uci_ri_len > 0 && crc_res) { + phy->mac->ri_info(tti_rx, rnti, uci_data.uci_ri); + } + if (cqi_value.subband_hl.pmi_present && crc_res) { + phy->mac->pmi_info(tti_rx, rnti, cqi_value.subband_hl.pmi); + } // Save metrics stats ue_db[rnti].metrics_ul(phy_grant.mcs.idx, 0, snr_db, srslte_pusch_last_noi(&enb_ul.pusch)); diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index 4dde48be1..6bf5bc698 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -1153,7 +1153,11 @@ void rrc::ue::send_connection_setup(bool is_setup) phy_cfg->cqi_report_cnfg_present = true; if(parent->cfg.cqi_cfg.mode == RRC_CFG_CQI_MODE_APERIODIC) { phy_cfg->cqi_report_cnfg.report_mode_aperiodic_present = true; - phy_cfg->cqi_report_cnfg.report_mode_aperiodic = LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30; + if (phy_cfg->antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { + phy_cfg->cqi_report_cnfg.report_mode_aperiodic = LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM31; + } else { + phy_cfg->cqi_report_cnfg.report_mode_aperiodic = LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30; + } } else { phy_cfg->cqi_report_cnfg.report_periodic_present = true; phy_cfg->cqi_report_cnfg.report_periodic_setup_present = true; diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 088c4a22c..f4dd2a8b5 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -303,8 +303,6 @@ void phch_worker::work_imp() /* Transmit PUSCH, PUCCH or SRS */ bool signal_ready = false; if (ul_action.tx_enabled) { - compute_ri(); - encode_pusch(&ul_action.phy_grant.ul, ul_action.payload_ptr[0], ul_action.current_tx_nb, &ul_action.softbuffers[0], ul_action.rv[0], ul_action.rnti, ul_mac_grant.is_from_rar); signal_ready = true; @@ -841,7 +839,9 @@ void phch_worker::set_uci_periodic_cqi() if (period_cqi.configured && rnti_is_set) { if (period_cqi.ri_idx_present && srslte_ri_send(period_cqi.pmi_idx, period_cqi.ri_idx, TTI_TX(tti))) { + /* Compute RI, PMI and SINR */ compute_ri(); + uci_data.ri_periodic_report = true; Info("PUCCH: Periodic RI=%d\n", uci_data.uci_ri); } else if (srslte_cqi_send(period_cqi.pmi_idx, TTI_TX(tti))) { @@ -884,6 +884,9 @@ void phch_worker::set_uci_periodic_cqi() void phch_worker::set_uci_aperiodic_cqi() { if (phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic_present) { + /* Compute RI, PMI and SINR */ + compute_ri(); + switch(phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic) { case LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30: /* only Higher Layer-configured subband feedback support right now, according to TS36.213 section 7.2.1 @@ -921,9 +924,6 @@ void phch_worker::set_uci_aperiodic_cqi() other transmission modes they are reported conditioned on rank 1. */ if (rnti_is_set) { - /* Compute RI, PMI and SINR */ - compute_ri(); - /* Select RI, PMI and SINR */ uint32_t ri = ue_dl.ri; // Select RI (0: 1 layer, 1: 2 layer, otherwise: not implemented) uint32_t pmi = ue_dl.pmi[ri]; // Select PMI @@ -954,9 +954,9 @@ void phch_worker::set_uci_aperiodic_cqi() cqi_report.subband_hl.wideband_cqi_cw0, cqi_report.subband_hl.wideband_cqi_cw1, sinr_db, sinr_db, pmi, cqi_report.subband_hl.N); } else { - Info("PUSCH: Aperiodic ri=1, CQI=%d/%d, SINR=%2.1f dB, for %d subbands\n", - cqi_report.wideband.wideband_cqi, - phy->avg_snr_db, cqi_report.subband_hl.N); + Info("PUSCH: Aperiodic ri=1, CQI=%02d, SINR=%2.1f, pmi=%d for %d subbands\n", + cqi_report.subband_hl.wideband_cqi_cw0, + sinr_db, pmi, cqi_report.subband_hl.N); } uci_data.uci_cqi_len = srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi); } From 12d8b373c7e5f7a2c15e9ef3216c5d87c6e51e79 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Mon, 20 Nov 2017 10:02:39 +0100 Subject: [PATCH 144/242] srsUE takes and reports intra-frequency measurements correctly --- CMakeLists.txt | 16 - lib/include/srslte/asn1/liblte_rrc.h | 3 + lib/include/srslte/common/threads.h | 14 +- lib/include/srslte/interfaces/ue_interfaces.h | 9 +- lib/include/srslte/phy/common/phy_common.h | 3 +- lib/include/srslte/phy/utils/ringbuffer.h | 5 +- lib/src/phy/CMakeLists.txt | 4 - lib/src/phy/sync/sync.c | 1 - lib/src/phy/utils/ringbuffer.c | 20 +- srsue/hdr/phy/phch_common.h | 4 +- srsue/hdr/phy/phch_recv.h | 109 ++- srsue/hdr/phy/phy.h | 11 +- srsue/hdr/ue.h | 2 - srsue/hdr/upper/rrc.h | 172 ++++- srsue/src/mac/mac.cc | 2 + srsue/src/main.cc | 5 - srsue/src/phy/phch_common.cc | 3 + srsue/src/phy/phch_recv.cc | 470 +++++++----- srsue/src/phy/phch_worker.cc | 15 +- srsue/src/phy/phy.cc | 21 +- srsue/src/ue.cc | 5 - srsue/src/upper/rrc.cc | 714 ++++++++++++++++-- 22 files changed, 1198 insertions(+), 410 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index efaa1973a..73b38ceb1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,7 +61,6 @@ set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "") option(ENABLE_SRSUE "Build srsUE application" ON) option(ENABLE_SRSENB "Build srsENB application" ON) -option(ENABLE_VOLK "Enable use of VOLK SIMD library" OFF) option(ENABLE_GUI "Enable GUI (using srsGUI)" ON) option(ENABLE_BLADERF "Enable BladeRF" ON) @@ -189,21 +188,6 @@ if(ENABLE_GUI) endif(SRSGUI_FOUND) endif(ENABLE_GUI) -# VOLK -include(CheckFunctionExistsMath) -if(ENABLE_VOLK) - find_package(Volk) - if(VOLK_FOUND) - include_directories(${VOLK_INCLUDE_DIRS}) - link_directories(${VOLK_LIBRARY_DIRS}) - message(STATUS "Compiling with VOLK SIMD library.") - else(VOLK_FOUND) - message(STATUS "VOLK SIMD library NOT found. Using generic implementation.") - endif(VOLK_FOUND) -else(ENABLE_VOLK) - message(STATUS "VOLK library disabled") -endif(ENABLE_VOLK) - ######################################################################## # Install Dirs ######################################################################## diff --git a/lib/include/srslte/asn1/liblte_rrc.h b/lib/include/srslte/asn1/liblte_rrc.h index c5c3b60e2..46f725ec3 100644 --- a/lib/include/srslte/asn1/liblte_rrc.h +++ b/lib/include/srslte/asn1/liblte_rrc.h @@ -1218,6 +1218,9 @@ typedef enum{ }LIBLTE_RRC_REPORT_AMOUNT_ENUM; static const char liblte_rrc_report_amount_text[LIBLTE_RRC_REPORT_AMOUNT_N_ITEMS][20] = { "r1", "r2", "r4", "r8", "r16", "r32", "r64", "INFINITY"}; + +static const int8 liblte_rrc_report_amount_num[LIBLTE_RRC_REPORT_AMOUNT_N_ITEMS] = {1, 2, 4, 8, 16, 32, 64, -1}; + typedef enum{ LIBLTE_RRC_THRESHOLD_UTRA_TYPE_RSCP = 0, LIBLTE_RRC_THRESHOLD_UTRA_TYPE_ECNO, diff --git a/lib/include/srslte/common/threads.h b/lib/include/srslte/common/threads.h index a8807ba9b..077dda72b 100644 --- a/lib/include/srslte/common/threads.h +++ b/lib/include/srslte/common/threads.h @@ -78,22 +78,30 @@ class periodic_thread : public thread { public: void start_periodic(int period_us_, int priority = -1) { + run_enable = true; period_us = period_us_; start(priority); } + void stop() { + run_enable = false; + wait_thread_finish(); + } protected: virtual void run_period() = 0; private: int wakeups_missed; int timer_fd; - int period_us; + int period_us; + bool run_enable; void run_thread() { if (make_periodic()) { return; } - while(1) { + while(run_enable) { run_period(); - wait_period(); + if (run_enable) { + wait_period(); + } } } int make_periodic() { diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index 88dfd285c..a4ecf1345 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -134,6 +134,7 @@ class rrc_interface_mac : public rrc_interface_mac_common { public: virtual void release_pucch_srs() = 0; + virtual void run_tti(uint32_t tti) = 0; }; // RRC interface for PHY @@ -144,6 +145,7 @@ public: virtual void out_of_sync() = 0; virtual void earfcn_end() = 0; virtual void cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) = 0; + virtual void new_phy_meas(float rsrp, float rsrq, uint32_t tti, uint32_t earfcn = 0, uint32_t pci = 0) = 0; }; // RRC interface for NAS @@ -521,7 +523,7 @@ public: bool enable_64qam; } phy_cfg_t; - virtual void get_current_cell(srslte_cell_t *cell) = 0; + virtual void get_current_cell(srslte_cell_t *cell, uint32_t *current_earfcn = NULL) = 0; virtual void get_config(phy_cfg_t *phy_cfg) = 0; virtual void set_config(phy_cfg_t *phy_cfg) = 0; virtual void set_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *dedicated) = 0; @@ -529,6 +531,11 @@ public: virtual void set_config_tdd(LIBLTE_RRC_TDD_CONFIG_STRUCT *tdd) = 0; virtual void set_config_64qam_en(bool enable) = 0; + /* Measurements interface */ + virtual void meas_reset() = 0; + virtual int meas_start(uint32_t earfcn, int pci = -1) = 0; + virtual int meas_stop(uint32_t earfcn, int pci = -1) = 0; + /* Cell search and selection procedures */ virtual void cell_search_start() = 0; virtual void cell_search_stop() = 0; diff --git a/lib/include/srslte/phy/common/phy_common.h b/lib/include/srslte/phy/common/phy_common.h index 4a1eeb27d..c55713cfc 100644 --- a/lib/include/srslte/phy/common/phy_common.h +++ b/lib/include/srslte/phy/common/phy_common.h @@ -301,7 +301,8 @@ SRSLTE_API int srslte_str2mimotype(char *mimo_type_str, SRSLTE_API char *srslte_mimotype2str(srslte_mimo_type_t mimo_type); -SRSLTE_API uint32_t srslte_tti_interval(uint32_t tti1, +/* Returns the interval tti1-tti2 mod 10240 */ +SRSLTE_API uint32_t srslte_tti_interval(uint32_t tti1, uint32_t tti2); #endif diff --git a/lib/include/srslte/phy/utils/ringbuffer.h b/lib/include/srslte/phy/utils/ringbuffer.h index acd2ae5e6..e590131ff 100644 --- a/lib/include/srslte/phy/utils/ringbuffer.h +++ b/lib/include/srslte/phy/utils/ringbuffer.h @@ -20,8 +20,9 @@ typedef struct { SRSLTE_API int srslte_ringbuffer_init(srslte_ringbuffer_t *q, int capacity); -SRSLTE_API void srslte_ringbuffer_free(srslte_ringbuffer_t *q, - int capacity); +SRSLTE_API void srslte_ringbuffer_free(srslte_ringbuffer_t *q); + +SRSLTE_API void srslte_ringbuffer_reset(srslte_ringbuffer_t *q); SRSLTE_API int srslte_ringbuffer_status(srslte_ringbuffer_t *q); diff --git a/lib/src/phy/CMakeLists.txt b/lib/src/phy/CMakeLists.txt index 572ff19c3..b52af7b1d 100644 --- a/lib/src/phy/CMakeLists.txt +++ b/lib/src/phy/CMakeLists.txt @@ -57,9 +57,5 @@ set(srslte_srcs $ add_library(srslte_phy STATIC ${srslte_srcs}) target_link_libraries(srslte_phy ${FFT_LIBRARIES}) -if(VOLK_FOUND) - target_link_libraries(srslte_phy ${VOLK_LIBRARIES}) -endif(VOLK_FOUND) - target_link_libraries(srslte_phy pthread m) install(TARGETS srslte_phy DESTINATION ${LIBRARY_DIR}) diff --git a/lib/src/phy/sync/sync.c b/lib/src/phy/sync/sync.c index ee2ba76d1..0fb1b819d 100644 --- a/lib/src/phy/sync/sync.c +++ b/lib/src/phy/sync/sync.c @@ -62,7 +62,6 @@ int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_o int ret = SRSLTE_ERROR_INVALID_INPUTS; if (q != NULL && - frame_size <= 307200 && fft_size_isvalid(fft_size)) { ret = SRSLTE_ERROR; diff --git a/lib/src/phy/utils/ringbuffer.c b/lib/src/phy/utils/ringbuffer.c index f7a10e2c5..400f80360 100644 --- a/lib/src/phy/utils/ringbuffer.c +++ b/lib/src/phy/utils/ringbuffer.c @@ -11,10 +11,9 @@ int srslte_ringbuffer_init(srslte_ringbuffer_t *q, int capacity) if (!q->buffer) { return -1; } - q->capacity = capacity; - q->count = 0; - q->wpm = 0; - q->rpm = 0; + + q->capacity = capacity; + srslte_ringbuffer_reset(q); pthread_mutex_init(&q->mutex, NULL); pthread_cond_init(&q->cvar, NULL); @@ -22,7 +21,7 @@ int srslte_ringbuffer_init(srslte_ringbuffer_t *q, int capacity) return 0; } -void srslte_ringbuffer_free(srslte_ringbuffer_t *q, int capacity) +void srslte_ringbuffer_free(srslte_ringbuffer_t *q) { if (q) { if (q->buffer) { @@ -34,6 +33,15 @@ void srslte_ringbuffer_free(srslte_ringbuffer_t *q, int capacity) } } +void srslte_ringbuffer_reset(srslte_ringbuffer_t *q) +{ + pthread_mutex_lock(&q->mutex); + q->count = 0; + q->wpm = 0; + q->rpm = 0; + pthread_mutex_unlock(&q->mutex); +} + int srslte_ringbuffer_status(srslte_ringbuffer_t *q) { return q->count; @@ -44,7 +52,7 @@ int srslte_ringbuffer_write(srslte_ringbuffer_t *q, void *p, int nof_bytes) uint8_t *ptr = (uint8_t*) p; int w_bytes = nof_bytes; pthread_mutex_lock(&q->mutex); - if (q->count + w_bytes >= q->capacity) { + if (q->count + w_bytes > q->capacity) { w_bytes = q->capacity - q->count; fprintf(stderr, "Buffer overrun: lost %d bytes\n", nof_bytes - w_bytes); } diff --git a/srsue/hdr/phy/phch_common.h b/srsue/hdr/phy/phch_common.h index 39e9e9685..f3c36d994 100644 --- a/srsue/hdr/phy/phch_common.h +++ b/srsue/hdr/phy/phch_common.h @@ -65,7 +65,9 @@ namespace srsue { float avg_snr_db; float avg_noise; float avg_rsrp; - + + uint32_t serving_cell_report_period; + phch_common(uint32_t max_mutex = 3); void init(phy_interface_rrc::phy_cfg_t *config, phy_args_t *args, diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index bb23bb5b5..e35610c0b 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -27,10 +27,13 @@ #ifndef UEPHYRECV_H #define UEPHYRECV_H +#include + #include "srslte/srslte.h" #include "srslte/common/log.h" #include "srslte/common/threads.h" #include "srslte/common/thread_pool.h" +#include "srslte/common/tti_sync_cv.h" #include "srslte/radio/radio_multi.h" #include "phy/prach.h" #include "phy/phch_worker.h" @@ -39,7 +42,8 @@ namespace srsue { -typedef _Complex float cf_t; +typedef _Complex float cf_t; + class phch_recv : public thread { @@ -61,14 +65,17 @@ public: void cell_search_next(bool reset = false); bool cell_select(uint32_t earfcn, srslte_cell_t cell); + void meas_reset(); + int meas_start(uint32_t earfcn, int pci); + int meas_stop(uint32_t earfcn, int pci); + uint32_t get_current_tti(); bool status_is_sync(); void set_time_adv_sec(float time_adv_sec); - void get_current_cell(srslte_cell_t *cell); + void get_current_cell(srslte_cell_t *cell, uint32_t *earfcn = NULL); - void scell_enable(bool enable); const static int MUTEX_X_WORKER = 4; @@ -125,13 +132,13 @@ private: // Class to synchronize system frame number class sfn_sync { public: - typedef enum {IDLE, SFN_FOUND, ERROR, TIMEOUT} ret_code; + typedef enum {IDLE, SFN_FOUND, SFX0_FOUND, ERROR, TIMEOUT} ret_code; ~sfn_sync(); void init(srslte_ue_sync_t *ue_sync, cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, uint32_t timeout = SYNC_SFN_TIMEOUT); void reset(); bool set_cell(srslte_cell_t cell); - ret_code run_subframe(srslte_cell_t *cell, uint32_t *tti_cnt); + ret_code run_subframe(srslte_cell_t *cell, uint32_t *tti_cnt, bool sfidx_only = false); private: srslte::log *log_h; @@ -145,74 +152,106 @@ private: // Class to perform cell measurements class measure { + + // TODO: This class could early stop once the variance between the last N measurements is below 3GPP requirements + public: typedef enum {IDLE, MEASURE_OK, ERROR} ret_code; ~measure(); - void init(srslte_ue_sync_t *ue_sync, cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, + void init(cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, uint32_t nof_rx_antennas, uint32_t nof_subframes = RSRP_MEASURE_NOF_FRAMES); void reset(); void set_cell(srslte_cell_t cell); ret_code run_subframe(uint32_t sf_idx); + ret_code run_subframe_sync(srslte_ue_sync_t *ue_sync, uint32_t sf_idx); + ret_code run_multiple_subframes(cf_t *buffer, uint32_t sf_idx, uint32_t nof_sf); float rsrp(); float rsrq(); float snr(); - float cfo(); private: srslte::log *log_h; srslte_ue_dl_t ue_dl; - srslte_ue_sync_t *ue_sync; cf_t *buffer[SRSLTE_MAX_PORTS]; uint32_t cnt; uint32_t nof_subframes; - float mean_rsrp, mean_rsrq, mean_snr, mean_cfo; + uint32_t current_prb; + float mean_rsrp, mean_rsrq, mean_snr; const static int RSRP_MEASURE_NOF_FRAMES = 5; }; - // Class to receive secondary cell - class scell_recv : public thread { + class scell_recv { public: - void init(phch_recv *parent, srslte::log *log_h, uint32_t nof_rx_antennas, uint32_t prio, int cpu_affinity = -1); - void stop(); + const static int MAX_CELLS = 8; + typedef struct { + uint32_t pci; + float rsrp; + float rsrq; + uint32_t offset; + } cell_info_t; + void init(srslte::log *log_h); void reset(); - int recv(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time); - void write(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time); - bool is_enabled(); - void set_cell(srslte_cell_t scell); + int find_cells(cf_t *input_buffer, srslte_cell_t current_cell, uint32_t nof_sf, cell_info_t found_cells[MAX_CELLS]); private: - void run_thread(); - enum { - IDLE = 0, - SCELL_SELECT, - SCELL_MEASURE, - SCELL_CAMPING - } scell_state; + const static int DEFAULT_MEASUREMENT_LEN = 10; - srslte::log *log_h; - phch_recv *p; - bool running; - srslte_ringbuffer_t ring_buffer[SRSLTE_MAX_PORTS]; cf_t *sf_buffer[SRSLTE_MAX_PORTS]; - srslte_ue_sync_t ue_sync; - srslte_cell_t cell; - uint32_t nof_rx_antennas; - uint32_t current_sflen; + srslte::log *log_h; + srslte_sync_t sync_find; measure measure_p; - sfn_sync sfn_p; - uint32_t tti; }; + /* TODO: Intra-freq measurements can be improved by capturing 200 ms length signal and run cell search + + * measurements offline using sync object and finding multiple cells for each N_id_2 + */ + + // Class to perform intra-frequency measurements + class intra_measure : public thread { + public: + void init(phch_common *common, rrc_interface_phy *rrc, srslte::log *log_h); + void stop(); + void add_cell(int pci); + void rem_cell(int pci); + void set_primay_cell(uint32_t earfcn, srslte_cell_t cell); + void clear_cells(); + void write(uint32_t tti, cf_t *data, uint32_t nsamples); + private: + void run_thread(); + const static int CAPTURE_LEN_SF = 15; + const static int INTRA_FREQ_MEAS_PERIOD_MS = 200; + scell_recv scell; + rrc_interface_phy *rrc; + srslte::log *log_h; + phch_common *common; + uint32_t current_earfcn; + uint32_t current_sflen; + srslte_cell_t primary_cell; + std::vector active_pci; + + srslte::tti_sync_cv tti_sync; + + cf_t *search_buffer; + + scell_recv::cell_info_t info[scell_recv::MAX_CELLS]; + + bool running; + bool receive_enabled; + bool receiving; + uint32_t measure_tti; + uint32_t receive_cnt; + srslte_ringbuffer_t ring_buffer; + }; // Objects for internal use - scell_recv scell; measure measure_p; search search_p; sfn_sync sfn_p; + intra_measure intra_freq_meas; uint32_t current_sflen; int next_offset; diff --git a/srsue/hdr/phy/phy.h b/srsue/hdr/phy/phy.h index c75fbb90d..6a0e8891e 100644 --- a/srsue/hdr/phy/phy.h +++ b/srsue/hdr/phy/phy.h @@ -40,8 +40,8 @@ #include "srslte/interfaces/ue_interfaces.h" namespace srsue { - -typedef _Complex float cf_t; + +typedef _Complex float cf_t; class phy : public phy_interface_mac @@ -78,7 +78,6 @@ public: void set_earfcn(std::vector earfcns); void force_freq(float dl_freq, float ul_freq); - void scell_enable(bool enable); /********** RRC INTERFACE ********************/ void reset(); @@ -89,6 +88,10 @@ public: void cell_search_next(); bool cell_select(uint32_t earfcn, srslte_cell_t phy_cell); + void meas_reset(); + int meas_start(uint32_t earfcn, int pci); + int meas_stop(uint32_t earfcn, int pci); + /********** MAC INTERFACE ********************/ /* Functions to synchronize with a cell */ bool sync_status(); // this is also RRC interface @@ -133,7 +136,7 @@ public: float get_pathloss_db(); uint32_t get_current_tti(); - void get_current_cell(srslte_cell_t *cell); + void get_current_cell(srslte_cell_t *cell, uint32_t *current_earfcn = NULL); void start_plot(); diff --git a/srsue/hdr/ue.h b/srsue/hdr/ue.h index fa461d1c9..bfb38f14d 100644 --- a/srsue/hdr/ue.h +++ b/srsue/hdr/ue.h @@ -80,8 +80,6 @@ public: void pregenerate_signals(bool enable); - void test_scell(); - private: virtual ~ue(); diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index 3e2fb70dd..5ec484251 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -38,6 +38,7 @@ #include "srslte/common/threads.h" #include +#include using srslte::byte_buffer_t; @@ -80,6 +81,46 @@ public: void liblte_rrc_log(char *str); + + // NAS interface + void write_sdu(uint32_t lcid, byte_buffer_t *sdu); + + uint16_t get_mcc(); + + uint16_t get_mnc(); + + void enable_capabilities(); + void plmn_search(); + void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id); + + // PHY interface + void in_sync(); + void out_of_sync(); + void earfcn_end(); + void cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp); + void new_phy_meas(float rsrp, float rsrq, uint32_t tti, uint32_t earfcn, uint32_t pci); + + // MAC interface + void release_pucch_srs(); + void run_tti(uint32_t tti); + + void ra_problem(); + + // GW interface + bool is_connected(); + + bool have_drb(); + + // PDCP interface + void write_pdu(uint32_t lcid, byte_buffer_t *pdu); + + void write_pdu_bcch_bch(byte_buffer_t *pdu); + + void write_pdu_bcch_dlsch(byte_buffer_t *pdu); + + void write_pdu_pcch(byte_buffer_t *pdu); + + private: srslte::byte_buffer_pool *pool; srslte::log *rrc_log; @@ -90,7 +131,9 @@ private: nas_interface_rrc *nas; usim_interface_rrc *usim; - srslte::bit_buffer_t bit_buf; + void send_ul_dcch_msg(byte_buffer_t *pdu = NULL); + LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg; + srslte::bit_buffer_t bit_buf; pthread_mutex_t mutex; @@ -166,42 +209,6 @@ private: bool thread_running; void run_thread(); - // NAS interface - void write_sdu(uint32_t lcid, byte_buffer_t *sdu); - - uint16_t get_mcc(); - - uint16_t get_mnc(); - - void enable_capabilities(); - void plmn_search(); - void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id); - - // PHY interface - void in_sync(); - void out_of_sync(); - void earfcn_end(); - void cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp); - - // MAC interface - void release_pucch_srs(); - - void ra_problem(); - - // GW interface - bool is_connected(); - - bool have_drb(); - - // PDCP interface - void write_pdu(uint32_t lcid, byte_buffer_t *pdu); - - void write_pdu_bcch_bch(byte_buffer_t *pdu); - - void write_pdu_bcch_dlsch(byte_buffer_t *pdu); - - void write_pdu_pcch(byte_buffer_t *pdu); - // Radio bearers typedef enum{ RB_ID_SRB0 = 0, @@ -226,6 +233,97 @@ private: } } + // Measurements sub-class + class rrc_meas { + public: + void init(rrc *parent); + void reset(); + void parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *meas_config); + void new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, float rsrq, uint32_t tti); + void run_tti(uint32_t tti); + bool timer_expired(uint32_t timer_id); + private: + + const static int NOF_MEASUREMENTS = 3; + + typedef enum {RSRP = 0, RSRQ = 1, BOTH = 2} quantity_t; + + typedef struct { + uint32_t pci; + float q_offset; + } meas_cell_t; + + typedef struct { + uint32_t earfcn; + float q_offset; + std::map cells; + } meas_obj_t; + + typedef struct { + uint32_t interval; + uint32_t max_cell; + uint32_t amount; + quantity_t trigger_quantity; + quantity_t report_quantity; + LIBLTE_RRC_EVENT_EUTRA_STRUCT event; + enum {EVENT, PERIODIC} trigger_type; + } report_cfg_t; + + typedef struct { + float ms[NOF_MEASUREMENTS]; + bool triggered; + bool timer_enter_triggered; + bool timer_exit_triggered; + uint32_t enter_tti; + uint32_t exit_tti; + } meas_value_t; + + typedef struct { + uint32_t nof_reports_sent; + uint32_t report_id; + uint32_t object_id; + bool triggered; + uint32_t periodic_timer; + std::map cell_values; // Value for each PCI in this object + } meas_t; + + std::map objects; + std::map reports_cfg; + std::map active; + + rrc *parent; + srslte::log *log_h; + phy_interface_rrc *phy; + srslte::mac_interface_timers *mac_timers; + + uint32_t filter_k_rsrp, filter_k_rsrq; + float filter_a[NOF_MEASUREMENTS]; + + meas_value_t pcell_measurement; + + bool s_measure_enabled; + float s_measure_value; + + void stop_reports_object(uint32_t object_id); + void remove_meas_object(uint32_t object_id); + void remove_meas_report(uint32_t report_id); + void remove_meas_id(uint32_t meas_id); + void calculate_triggers(uint32_t tti); + void update_phy(); + void L3_filter(meas_value_t *value, float rsrp[NOF_MEASUREMENTS]); + bool find_earfcn_cell(uint32_t earfcn, uint32_t pci, meas_obj_t **object, int *cell_idx); + float range_to_value(quantity_t quant, uint8_t range); + uint8_t value_to_range(quantity_t quant, float value); + bool process_event(LIBLTE_RRC_EVENT_EUTRA_STRUCT *event, uint32_t tti, + bool enter_condition, bool exit_condition, + meas_t *m, meas_value_t *cell); + + void generate_report(uint32_t meas_id); + }; + + rrc_meas measurements; + + // RLC interface void max_retx_attempted(); diff --git a/srsue/src/mac/mac.cc b/srsue/src/mac/mac.cc index f8d10bb34..66adb5b0b 100644 --- a/srsue/src/mac/mac.cc +++ b/srsue/src/mac/mac.cc @@ -180,6 +180,8 @@ void mac::run_thread() { ra_procedure.start_mac_order(); } ra_procedure.step(tti); + + rrc_h->run_tti(tti); } } diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 92745edb8..0cd31a3d6 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -398,7 +398,6 @@ int main(int argc, char *argv[]) pthread_t input; pthread_create(&input, NULL, &input_loop, &args); - bool scell_done = false; bool plot_started = false; bool signals_pregenerated = false; @@ -408,10 +407,6 @@ int main(int argc, char *argv[]) ue->pregenerate_signals(true); signals_pregenerated = true; } - if (!scell_done) { - ((srsue::ue*) ue)->test_scell(); - scell_done = true; - } if (!plot_started && args.gui.enable) { ue->start_plot(); plot_started = true; diff --git a/srsue/src/phy/phch_common.cc b/srsue/src/phy/phch_common.cc index d956ddd15..416f146ac 100644 --- a/srsue/src/phy/phch_common.cc +++ b/srsue/src/phy/phch_common.cc @@ -59,6 +59,9 @@ phch_common::phch_common(uint32_t max_mutex_) : tx_mutex(max_mutex_) rx_gain_offset = 0; sr_last_tx_tti = -1; cur_pusch_power = 0; + + serving_cell_report_period = 20; + bzero(zeros, 50000*sizeof(cf_t)); // FIXME: This is an ungly fix to avoid the TX filters to empty diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 91d2cd482..126c4a2f6 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -25,11 +25,10 @@ */ #include -#include +#include #include "srslte/srslte.h" #include "srslte/common/log.h" #include "phy/phch_worker.h" -#include "phy/phch_common.h" #include "phy/phch_recv.h" #define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) @@ -41,13 +40,8 @@ namespace srsue { int radio_recv_callback(void *obj, cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time) { return ((phch_recv*) obj)->radio_recv_fnc(data, nsamples, rx_time); - } -int scell_recv_callback(void *obj, cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time) { - return ((phch_recv*) obj)->scell_recv_fnc(data, nsamples, rx_time); -} - double callback_set_rx_gain(void *h, double gain) { srslte::radio_multi *radio_handler = (srslte::radio_multi *) h; return radio_handler->set_rx_gain_th(gain); @@ -94,10 +88,10 @@ void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_ma sfn_p.init(&ue_sync, sf_buffer, log_h); // Initialize measurement class for the primary cell - measure_p.init(&ue_sync, sf_buffer, log_h, nof_rx_antennas); + measure_p.init(sf_buffer, log_h, nof_rx_antennas); - // Start scell - scell.init(this, log_h, nof_rx_antennas_, prio-1, sync_cpu_affinity); + // Start intra-frequency measurement + intra_freq_meas.init(worker_com, rrc, log_h); reset(); @@ -120,7 +114,7 @@ phch_recv::~phch_recv() { void phch_recv::stop() { - + intra_freq_meas.stop(); running = false; wait_thread_finish(); } @@ -223,6 +217,7 @@ bool phch_recv::set_cell() { measure_p.set_cell(cell); sfn_p.set_cell(cell); worker_com->set_cell(cell); + intra_freq_meas.set_primay_cell(current_earfcn, cell); for (uint32_t i = 0; i < workers_pool->get_nof_workers(); i++) { if (!((phch_worker *) workers_pool->get_worker(i))->set_cell(cell)) { @@ -464,10 +459,13 @@ bool phch_recv::status_is_sync() { return phy_state == CELL_CAMP; } -void phch_recv::get_current_cell(srslte_cell_t *cell_) { +void phch_recv::get_current_cell(srslte_cell_t *cell_, uint32_t *earfcn) { if (cell_) { memcpy(cell_, &cell, sizeof(srslte_cell_t)); } + if (earfcn) { + *earfcn = current_earfcn; + } } int phch_recv::radio_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time) @@ -480,10 +478,6 @@ int phch_recv::radio_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, s next_offset = nsamples; } - if (offset <= 0) { - scell.write(data, nsamples, rx_time); - } - log_h->debug("SYNC: received %d samples from radio\n", nsamples); return nsamples; @@ -492,19 +486,6 @@ int phch_recv::radio_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, s } } -int phch_recv::scell_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time) -{ - return scell.recv(data, nsamples, rx_time); -} - -void phch_recv::scell_enable(bool enable) -{ - srslte_cell_t target_cell; - memcpy(&target_cell, &cell, sizeof(srslte_cell_t)); - target_cell.id++; - scell.set_cell(target_cell); -} - @@ -587,7 +568,7 @@ void phch_recv::run_thread() } break; case CELL_MEASURE: - switch(measure_p.run_subframe(sf_idx)) + switch(measure_p.run_subframe_sync(&ue_sync, sf_idx)) { case measure::MEASURE_OK: log_h->info("SYNC: Measured OK. Camping on cell PCI=%d...\n", cell.id); @@ -643,6 +624,9 @@ void phch_recv::run_thread() worker_com->cur_radio_power = SRSLTE_MIN(SRSLTE_PC_MAX, worker_com->pathloss+worker_com->p0_preamble); } workers_pool->start_worker(worker); + + intra_freq_meas.write(tti, buffer[0], SRSLTE_SF_LEN_PRB(cell.nof_prb)); + break; case 0: log_h->error("SYNC: Sync error. Sending out-of-sync to RRC\n"); @@ -789,8 +773,8 @@ phch_recv::search::ret_code phch_recv::search::run(srslte_cell_t *cell) return CELL_NOT_FOUND; } // Save result - cell->id = found_cells[max_peak_cell].cell_id; - cell->cp = found_cells[max_peak_cell].cp; + cell->id = found_cells[max_peak_cell].cell_id; + cell->cp = found_cells[max_peak_cell].cp; float cfo = found_cells[max_peak_cell].cfo; printf("\n"); @@ -864,7 +848,7 @@ void phch_recv::sfn_sync::init(srslte_ue_sync_t *ue_sync, cf_t *buffer[SRSLTE_MA this->buffer[i] = buffer[i]; } - if (srslte_ue_mib_init(&ue_mib, SRSLTE_MAX_PRB)) { + if (srslte_ue_mib_init(&ue_mib, this->buffer, SRSLTE_MAX_PRB)) { Error("SYNC: Initiating UE MIB decoder\n"); } } @@ -885,7 +869,7 @@ void phch_recv::sfn_sync::reset() cnt = 0; } -phch_recv::sfn_sync::ret_code phch_recv::sfn_sync::run_subframe(srslte_cell_t *cell, uint32_t *tti_cnt) +phch_recv::sfn_sync::ret_code phch_recv::sfn_sync::run_subframe(srslte_cell_t *cell, uint32_t *tti_cnt, bool sfidx_only) { uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; @@ -899,10 +883,19 @@ phch_recv::sfn_sync::ret_code phch_recv::sfn_sync::run_subframe(srslte_cell_t *c if (ret == 1) { if (srslte_ue_sync_get_sfidx(ue_sync) == 0) { + + // Skip MIB decoding if we are only interested in subframe 0 + if (sfidx_only) { + if (tti_cnt) { + *tti_cnt = 0; + } + return SFX0_FOUND; + } + int sfn_offset = 0; Info("SYNC: Trying to decode MIB... SNR=%.1f dB\n", 10*log10(srslte_chest_dl_get_snr(&ue_mib.chest))); - int n = srslte_ue_mib_decode(&ue_mib, buffer[0], bch_payload, NULL, &sfn_offset); + int n = srslte_ue_mib_decode(&ue_mib, bch_payload, NULL, &sfn_offset); if (n < 0) { Error("SYNC: Error decoding MIB while synchronising SFN"); return ERROR; @@ -944,16 +937,15 @@ phch_recv::sfn_sync::ret_code phch_recv::sfn_sync::run_subframe(srslte_cell_t *c /********* * Measurement class */ -void phch_recv::measure::init(srslte_ue_sync_t *ue_sync, cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, uint32_t nof_rx_antennas, uint32_t nof_subrames) +void phch_recv::measure::init(cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, uint32_t nof_rx_antennas, uint32_t nof_subframes) { this->log_h = log_h; - this->nof_subframes = nof_subrames; - this->ue_sync = ue_sync; + this->nof_subframes = nof_subframes; for (int i=0;ibuffer[i] = buffer[i]; } - if (srslte_ue_dl_init(&ue_dl, SRSLTE_MAX_PRB, nof_rx_antennas)) { + if (srslte_ue_dl_init(&ue_dl, this->buffer, SRSLTE_MAX_PRB, nof_rx_antennas)) { Error("SYNC: Initiating ue_dl_measure\n"); return; } @@ -969,11 +961,11 @@ void phch_recv::measure::reset() { mean_rsrp = 0; mean_rsrq = 0; mean_snr = 0; - mean_cfo = 0; } void phch_recv::measure::set_cell(srslte_cell_t cell) { + current_prb = cell.nof_prb; if (srslte_ue_dl_set_cell(&ue_dl, cell)) { Error("SYNC: Setting cell: initiating ue_dl_measure\n"); } @@ -981,59 +973,75 @@ void phch_recv::measure::set_cell(srslte_cell_t cell) } float phch_recv::measure::rsrp() { - return 10*log10(mean_rsrp/1000); + return mean_rsrp; } float phch_recv::measure::rsrq() { - return 10*log10(mean_rsrq); + return mean_rsrq; } float phch_recv::measure::snr() { - return 10*log10(mean_snr); -} - -float phch_recv::measure::cfo() { - return mean_cfo; + return mean_snr; } -phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx) +phch_recv::measure::ret_code phch_recv::measure::run_subframe_sync(srslte_ue_sync_t *ue_sync, uint32_t sf_idx) { int sync_res = srslte_ue_sync_zerocopy_multi(ue_sync, buffer); if (sync_res == 1) { - uint32_t cfi = 0; - - if (srslte_ue_dl_decode_fft_estimate(&ue_dl, buffer, sf_idx, &cfi)) { - log_h->error("SYNC: Measuring RSRP: Estimating channel\n"); - return ERROR; - } + return run_subframe(sf_idx); + } else { + log_h->error("SYNC: Measuring RSRP: Sync error\n"); + return ERROR; + } - float rsrp = srslte_chest_dl_get_rsrp(&ue_dl.chest); - float rsrq = srslte_chest_dl_get_rsrq(&ue_dl.chest); - float snr = srslte_chest_dl_get_snr(&ue_dl.chest); - float cfo = srslte_ue_sync_get_cfo(ue_sync); + return IDLE; +} - mean_rsrp = SRSLTE_VEC_CMA(rsrp, mean_rsrp, cnt); - mean_rsrq = SRSLTE_VEC_CMA(rsrq, mean_rsrq, cnt); - mean_snr = SRSLTE_VEC_CMA(snr, mean_snr, cnt); - mean_cfo = SRSLTE_VEC_CMA(cfo, mean_cfo, cnt); - cnt++; +phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *input_buffer, + uint32_t sf_idx, + uint32_t nof_sf) +{ + uint32_t sf_len = SRSLTE_SF_LEN_PRB(current_prb); - log_h->info("SYNC: Measuring RSRP %d/%d, sf_idx=%d, RSRP=%.1f dBm, SNR=%.1f dB\n", - cnt, RSRP_MEASURE_NOF_FRAMES, sf_idx, - 10*log10(rsrp/1000), 10*log10(snr)); + ret_code ret = IDLE; - if (cnt >= nof_subframes) { - return MEASURE_OK; + for (uint32_t i=0;ierror("SYNC: Measuring RSRP: Sync error\n"); + } + return ret; +} + +phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx) +{ + uint32_t cfi = 0; + if (srslte_ue_dl_decode_fft_estimate(&ue_dl, buffer, sf_idx, &cfi)) { + log_h->error("SYNC: Measuring RSRP: Estimating channel\n"); return ERROR; } - return IDLE; -} + float rsrp = 10*log10(srslte_chest_dl_get_rsrp(&ue_dl.chest)) + 30; + float rsrq = 10*log10(srslte_chest_dl_get_rsrq(&ue_dl.chest)); + float snr = 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest)); + + mean_rsrp = SRSLTE_VEC_CMA(rsrp, mean_rsrp, cnt); + mean_rsrq = SRSLTE_VEC_CMA(rsrq, mean_rsrq, cnt); + mean_snr = SRSLTE_VEC_CMA(snr, mean_snr, cnt); + cnt++; + log_h->info("SYNC: Measuring RSRP %d/%d, sf_idx=%d, RSRP=%.1f dBm, SNR=%.1f dB\n", + cnt, nof_subframes, sf_idx, + rsrp, snr); + if (cnt >= nof_subframes) { + return MEASURE_OK; + } else { + return IDLE; + } +} @@ -1044,164 +1052,246 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx) * Secondary cell receiver */ -void phch_recv::scell_recv::init(phch_recv *parent, srslte::log *log_h, uint32_t nof_rx_antennas, uint32_t prio, int cpu_affinity) +void phch_recv::scell_recv::init(srslte::log *log_h) { - this->p = parent; this->log_h = log_h; - this->nof_rx_antennas = nof_rx_antennas; - // Create the ringbuffer for secondary cell reception - for (int i=0;irrc = rrc; + this->log_h = log_h; + this->common = common; + receive_enabled = false; + + // Start scell + scell.init(log_h); + + search_buffer = (cf_t*) srslte_vec_malloc(CAPTURE_LEN_SF*SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB)*sizeof(cf_t)); + + if (srslte_ringbuffer_init(&ring_buffer, sizeof(cf_t)*50*SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB))) { + return; + } + + running = true; + start(); } -void phch_recv::scell_recv::set_cell(srslte_cell_t scell) { - printf("SCELL: set scell to select, id=%d, prb=%d\n", scell.id, scell.nof_prb); +void phch_recv::intra_measure::stop() { + running = false; + tti_sync.increase(); + wait_thread_finish(); +} - memcpy(&cell, &scell, sizeof(srslte_cell_t)); +void phch_recv::intra_measure::set_primay_cell(uint32_t earfcn, srslte_cell_t cell) { + this->current_earfcn = earfcn; current_sflen = SRSLTE_SF_LEN_PRB(cell.nof_prb); - srslte_ue_sync_set_cell(&ue_sync, scell); - measure_p.set_cell(scell); - sfn_p.set_cell(scell); + memcpy(&this->primary_cell, &cell, sizeof(srslte_cell_t)); +} - scell_state = SCELL_SELECT; +void phch_recv::intra_measure::clear_cells() { + active_pci.clear(); + receive_enabled = false; } -bool phch_recv::scell_recv::is_enabled() -{ - return scell_state != IDLE; +void phch_recv::intra_measure::add_cell(int pci) { + if (std::find(active_pci.begin(), active_pci.end(), pci) == active_pci.end()) { + active_pci.push_back(pci); + receive_enabled = true; + Info("INTRA: Starting intra-frequency measurement for pci=%d\n", pci); + } else { + Warning("INTRA: Requested to start already existing intra-frequency measurement for PCI=%d\n", pci); + } } -int phch_recv::scell_recv::recv(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time) -{ - if (is_enabled()) - { - uint32_t read_samples = nsamples; - if (read_samples > current_sflen) { - read_samples = current_sflen; - } - if (nsamples < 10) { - read_samples = 0; - } - int n = 0; - for (uint32_t i=0;idebug("SCELL: tti=%d, read %d/%d samples from buffer, buffer size=%d\n", - tti, read_samples,nsamples, srslte_ringbuffer_status(&ring_buffer[0])); +void phch_recv::intra_measure::rem_cell(int pci) { + std::vector::iterator newEnd = std::remove(active_pci.begin(), active_pci.end(), pci); - return nsamples; + if (newEnd != active_pci.end()) { + active_pci.erase(newEnd, active_pci.end()); + if (active_pci.size() == 0) { + receive_enabled = false; + } + Info("INTRA: Stopping intra-frequency measurement for pci=%d. Number of cells: %d\n", pci, active_pci.size()); } else { - Error("SCELL: Reception not enabled\n"); - return -1; + Warning("INTRA: Requested to stop non-existing intra-frequency measurement for PCI=%d\n", pci); } } -void phch_recv::scell_recv::write(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time) -{ - if (is_enabled()) { - for (uint32_t i = 0; i < nof_rx_antennas; i++) { - srslte_ringbuffer_write(&ring_buffer[i], data[i], sizeof(cf_t) * nsamples); +void phch_recv::intra_measure::write(uint32_t tti, cf_t *data, uint32_t nsamples) { + if (receive_enabled) { + if ((tti%INTRA_FREQ_MEAS_PERIOD_MS) == 0) { + receiving = true; + receive_cnt = 0; + measure_tti = tti; + } + if (receiving == true) { + if (srslte_ringbuffer_write(&ring_buffer, data, nsamples*sizeof(cf_t)) < (int) (nsamples*sizeof(cf_t))) { + receiving = false; + srslte_ringbuffer_reset(&ring_buffer); + } else { + receive_cnt++; + if (receive_cnt == CAPTURE_LEN_SF) { + tti_sync.increase(); + } + } } + } } -void phch_recv::scell_recv::run_thread() +void phch_recv::intra_measure::run_thread() { while(running) { - switch(scell_state) { - case IDLE: - usleep(1000); - break; - case SCELL_SELECT: + if (running) { + tti_sync.wait(); + } - switch (sfn_p.run_subframe(&cell, &tti)) - { - case sfn_sync::SFN_FOUND: - log_h->info("SCELL: SFN Sync OK. Camping on cell PCI=%d...\n", cell.id); - sfn_p.reset(); - scell_state = SCELL_MEASURE; - break; - case sfn_sync::TIMEOUT: - log_h->info("SCELL: SFN sync timeout\n"); - break; - case sfn_sync::IDLE: - break; - default: - p->radio_error(); - break; - } + if (running) { + Info("INTRA: Running intra-frequency measurement for %d cells\n", active_pci.size()); - break; - case SCELL_MEASURE: - switch (measure_p.run_subframe(tti%10)) { - case measure::MEASURE_OK: - log_h->info("SCELL: Measured OK TTI=%5d, RSRP=%.1f dBm, RSRQ=%.1f dB, SNR=%3.1f dB, CFO=%.1f KHz, Buff=%d\n", - tti, measure_p.rsrp(), measure_p.rsrq(), measure_p.snr(), measure_p.cfo()/1000, - srslte_ringbuffer_status(&ring_buffer[0])); - measure_p.reset(); - break; - case measure::IDLE: - break; - default: - p->radio_error(); - break; - } - break; + // Read 5 ms data from buffer + srslte_ringbuffer_read(&ring_buffer, search_buffer, CAPTURE_LEN_SF*current_sflen*sizeof(cf_t)); + int found_cells = scell.find_cells(search_buffer, primary_cell, CAPTURE_LEN_SF, info); + receiving = false; + srslte_ringbuffer_reset(&ring_buffer); + + for (int i=0;irx_gain_offset; + rrc->new_phy_meas(info[i].rsrp, info[i].rsrq, measure_tti, current_earfcn, info[i].pci); + } + // Look for other cells not found automatically } - // Increase TTI counter - tti = (tti+1) % 10240; } } diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index cf0eab94c..5d93d94a4 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -1210,8 +1210,8 @@ void phch_worker::update_measurements() { float snr_ema_coeff = phy->args->snr_ema_coeff; if (chest_done) { - /* Compute ADC/RX gain offset every 20 ms */ - if ((tti%20) == 0 || phy->rx_gain_offset == 0) { + /* Compute ADC/RX gain offset every ~10s */ + if (tti== 0 || phy->rx_gain_offset == 0) { float rx_gain_offset = 0; if (phy->get_radio()->has_rssi() && phy->args->rssi_sensor_enabled) { float rssi_all_signal = srslte_chest_dl_get_rssi(&ue_dl.chest); @@ -1224,7 +1224,7 @@ void phch_worker::update_measurements() rx_gain_offset = phy->get_radio()->get_rx_gain(); } if (phy->rx_gain_offset) { - phy->rx_gain_offset = SRSLTE_VEC_EMA(phy->rx_gain_offset, rx_gain_offset, 0.1); + phy->rx_gain_offset = SRSLTE_VEC_EMA(phy->rx_gain_offset, rx_gain_offset, 0.5); } else { phy->rx_gain_offset = rx_gain_offset; } @@ -1246,15 +1246,16 @@ void phch_worker::update_measurements() float rsrp = 10*log10(srslte_chest_dl_get_rsrp(&ue_dl.chest)) + 30 - phy->rx_gain_offset; float rssi = 10*log10(srslte_chest_dl_get_rssi(&ue_dl.chest)) + 30 - phy->rx_gain_offset; - // TODO: Send UE measurements to RRC where filtering is done. Now do filtering here + // Serving cell measurements are averaged over DEFAULT_MEAS_PERIOD_MS then sent to RRC if (isnormal(rsrp)) { if (!phy->avg_rsrp_db) { phy->avg_rsrp_db = rsrp; } else { - uint32_t k = 4; // Set by RRC reconfiguration message - float coeff = pow(0.5,(float) k/4); - phy->avg_rsrp_db = SRSLTE_VEC_EMA(phy->avg_rsrp_db, rsrp, coeff); + phy->avg_rsrp_db = SRSLTE_VEC_EMA(phy->avg_rsrp_db, rsrp, 0.8); } + if ((tti%phy->serving_cell_report_period) == 0) { + phy->rrc->new_phy_meas(phy->avg_rsrp_db, phy->avg_rsrq_db, tti); + } } // Compute PL float tx_crs_power = phy->config->common.pdsch_cnfg.rs_power; diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 2c140c191..7d3b8f311 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -243,15 +243,22 @@ void phy::cell_search_next() sf_recv.cell_search_next(); } -void phy::scell_enable(bool enable) -{ - sf_recv.scell_enable(enable); -} - void phy::sync_reset() { sf_recv.reset_sync(); } +void phy::meas_reset() { + sf_recv.meas_reset(); +} + +int phy::meas_start(uint32_t earfcn, int pci) { + return sf_recv.meas_start(earfcn, pci); +} + +int phy::meas_stop(uint32_t earfcn, int pci) { + return sf_recv.meas_stop(earfcn, pci); +} + bool phy::cell_select(uint32_t earfcn, srslte_cell_t phy_cell) { return sf_recv.cell_select(earfcn, phy_cell); @@ -288,9 +295,9 @@ void phy::pdcch_ul_search_reset() workers_common.set_ul_rnti(SRSLTE_RNTI_USER, 0); } -void phy::get_current_cell(srslte_cell_t *cell) +void phy::get_current_cell(srslte_cell_t *cell, uint32_t *current_earfcn) { - sf_recv.get_current_cell(cell); + sf_recv.get_current_cell(cell, current_earfcn); } void phy::prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm) diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index c97958316..a99281e6f 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -215,11 +215,6 @@ void ue::pregenerate_signals(bool enable) phy.enable_pregen_signals(enable); } -void ue::test_scell() -{ - phy.scell_enable(true); -}; - void ue::stop() { if(started) diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 10373dcf2..434f931f3 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -109,6 +109,8 @@ void rrc::init(phy_interface_rrc *phy_, set_rrc_default(); set_phy_default(); set_mac_default(); + + measurements.init(this); } void rrc::stop() { @@ -116,6 +118,10 @@ void rrc::stop() { wait_thread_finish(); } +void rrc::run_tti(uint32_t tti) { + measurements.run_tti(tti); +} + rrc_state_t rrc::get_state() { return state; } @@ -418,6 +424,10 @@ void rrc::select_next_cell_in_plmn() { rrc_log->info("No more known cells...\n"); } +void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, uint32_t earfcn, uint32_t pci) { + measurements.new_phy_meas(earfcn, pci, rsrp, rsrq, tti); +} + void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { // find if cell_id-earfcn combination already exists @@ -562,7 +572,8 @@ void rrc::timer_expired(uint32_t timeout_id) { } else if (timeout_id == t301) { rrc_log->info("Timer T301 expired: Going to RRC IDLE\n"); state = RRC_STATE_LEAVE_CONNECTED; - } else { + // fw to measurement + } else if (!measurements.timer_expired(timeout_id)) { rrc_log->error("Timeout from unknown timer id %d\n", timeout_id); } } @@ -717,32 +728,22 @@ void rrc::con_restablish_cell_reselected() void rrc::send_con_restablish_complete() { rrc_log->debug("Preparing RRC Connection Reestablishment Complete\n"); - LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg; + + rrc_log->console("RRC Connected\n"); + state = RRC_STATE_CONNECTED; // Prepare ConnectionSetupComplete packet ul_dcch_msg.msg_type = LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_REEST_COMPLETE; ul_dcch_msg.msg.rrc_con_reest_complete.rrc_transaction_id = transaction_id; - liblte_rrc_pack_ul_dcch_msg(&ul_dcch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf); - // Byte align and pack the message bits for PDCP - if ((bit_buf.N_bits % 8) != 0) { - for (uint32_t i = 0; i < 8 - (bit_buf.N_bits % 8); i++) - bit_buf.msg[bit_buf.N_bits + i] = 0; - bit_buf.N_bits += 8 - (bit_buf.N_bits % 8); - } - byte_buffer_t *pdcp_buf = pool_allocate;; - srslte_bit_pack_vector(bit_buf.msg, pdcp_buf->msg, bit_buf.N_bits); - pdcp_buf->N_bytes = bit_buf.N_bits / 8; - - state = RRC_STATE_CONNECTED; - rrc_log->console("RRC Connected\n"); - rrc_log->info("Sending RRC Connection Reestablishment Complete\n"); - pdcp->write_sdu(RB_ID_SRB1, pdcp_buf); + send_ul_dcch_msg(); } void rrc::send_con_setup_complete(byte_buffer_t *nas_msg) { rrc_log->debug("Preparing RRC Connection Setup Complete\n"); - LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg; + + state = RRC_STATE_CONNECTED; + rrc_log->console("RRC Connected\n"); // Prepare ConnectionSetupComplete packet ul_dcch_msg.msg_type = LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_SETUP_COMPLETE; @@ -751,96 +752,38 @@ void rrc::send_con_setup_complete(byte_buffer_t *nas_msg) { ul_dcch_msg.msg.rrc_con_setup_complete.selected_plmn_id = 1; memcpy(ul_dcch_msg.msg.rrc_con_setup_complete.dedicated_info_nas.msg, nas_msg->msg, nas_msg->N_bytes); ul_dcch_msg.msg.rrc_con_setup_complete.dedicated_info_nas.N_bytes = nas_msg->N_bytes; - liblte_rrc_pack_ul_dcch_msg(&ul_dcch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf); - // Byte align and pack the message bits for PDCP - if ((bit_buf.N_bits % 8) != 0) { - for (uint32_t i = 0; i < 8 - (bit_buf.N_bits % 8); i++) - bit_buf.msg[bit_buf.N_bits + i] = 0; - bit_buf.N_bits += 8 - (bit_buf.N_bits % 8); - } - byte_buffer_t *pdcp_buf = pool_allocate;; - srslte_bit_pack_vector(bit_buf.msg, pdcp_buf->msg, bit_buf.N_bits); - pdcp_buf->N_bytes = bit_buf.N_bits / 8; - pdcp_buf->set_timestamp(); - - state = RRC_STATE_CONNECTED; - rrc_log->console("RRC Connected\n"); - rrc_log->info("Sending RRC Connection Setup Complete\n"); - pdcp->write_sdu(RB_ID_SRB1, pdcp_buf); + send_ul_dcch_msg(); } void rrc::send_ul_info_transfer(uint32_t lcid, byte_buffer_t *sdu) { rrc_log->debug("Preparing RX Info Transfer\n"); - LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg; // Prepare RX INFO packet ul_dcch_msg.msg_type = LIBLTE_RRC_UL_DCCH_MSG_TYPE_UL_INFO_TRANSFER; ul_dcch_msg.msg.ul_info_transfer.dedicated_info_type = LIBLTE_RRC_UL_INFORMATION_TRANSFER_TYPE_NAS; memcpy(ul_dcch_msg.msg.ul_info_transfer.dedicated_info.msg, sdu->msg, sdu->N_bytes); ul_dcch_msg.msg.ul_info_transfer.dedicated_info.N_bytes = sdu->N_bytes; - liblte_rrc_pack_ul_dcch_msg(&ul_dcch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf); - - // Reset and reuse sdu buffer - byte_buffer_t *pdu = sdu; - pdu->reset(); - - // Byte align and pack the message bits for PDCP - if ((bit_buf.N_bits % 8) != 0) { - for (uint32_t i = 0; i < 8 - (bit_buf.N_bits % 8); i++) - bit_buf.msg[bit_buf.N_bits + i] = 0; - bit_buf.N_bits += 8 - (bit_buf.N_bits % 8); - } - srslte_bit_pack_vector(bit_buf.msg, pdu->msg, bit_buf.N_bits); - pdu->N_bytes = bit_buf.N_bits / 8; - pdu->set_timestamp(); - pdu->set_timestamp(); - rrc_log->info("Sending RX Info Transfer\n"); - pdcp->write_sdu(lcid, pdu); + send_ul_dcch_msg(sdu); } void rrc::send_security_mode_complete(uint32_t lcid, byte_buffer_t *pdu) { rrc_log->debug("Preparing Security Mode Complete\n"); - LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg; + ul_dcch_msg.msg_type = LIBLTE_RRC_UL_DCCH_MSG_TYPE_SECURITY_MODE_COMPLETE; ul_dcch_msg.msg.security_mode_complete.rrc_transaction_id = transaction_id; - liblte_rrc_pack_ul_dcch_msg(&ul_dcch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf); - // Byte align and pack the message bits for PDCP - if ((bit_buf.N_bits % 8) != 0) { - for (uint32_t i = 0; i < 8 - (bit_buf.N_bits % 8); i++) - bit_buf.msg[bit_buf.N_bits + i] = 0; - bit_buf.N_bits += 8 - (bit_buf.N_bits % 8); - } - srslte_bit_pack_vector(bit_buf.msg, pdu->msg, bit_buf.N_bits); - pdu->N_bytes = bit_buf.N_bits / 8; - pdu->set_timestamp(); - - rrc_log->info("Sending Security Mode Complete\n"); - pdcp->write_sdu(lcid, pdu); + send_ul_dcch_msg(pdu); } void rrc::send_rrc_con_reconfig_complete(uint32_t lcid, byte_buffer_t *pdu) { rrc_log->debug("Preparing RRC Connection Reconfig Complete\n"); - LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg; ul_dcch_msg.msg_type = LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_RECONFIG_COMPLETE; ul_dcch_msg.msg.rrc_con_reconfig_complete.rrc_transaction_id = transaction_id; - liblte_rrc_pack_ul_dcch_msg(&ul_dcch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf); - // Byte align and pack the message bits for PDCP - if ((bit_buf.N_bits % 8) != 0) { - for (uint32_t i = 0; i < 8 - (bit_buf.N_bits % 8); i++) - bit_buf.msg[bit_buf.N_bits + i] = 0; - bit_buf.N_bits += 8 - (bit_buf.N_bits % 8); - } - srslte_bit_pack_vector(bit_buf.msg, pdu->msg, bit_buf.N_bits); - pdu->N_bytes = bit_buf.N_bits / 8; - pdu->set_timestamp(); - - rrc_log->info("Sending RRC Connection Reconfig Complete\n"); - pdcp->write_sdu(lcid, pdu); + send_ul_dcch_msg(); } @@ -854,7 +797,7 @@ void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGU printf("received con reconfig no rr confg present\n"); } if (reconfig->meas_cnfg_present) { - //TODO: handle meas_cnfg + measurements.parse_meas_config(&reconfig->meas_cnfg); } if (reconfig->mob_ctrl_info_present) { //TODO: handle mob_ctrl_info @@ -864,7 +807,7 @@ void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGU byte_buffer_t *nas_sdu; for (i = 0; i < reconfig->N_ded_info_nas; i++) { - nas_sdu = pool_allocate;; + nas_sdu = pool_allocate; memcpy(nas_sdu->msg, &reconfig->ded_info_nas_list[i].msg, reconfig->ded_info_nas_list[i].N_bytes); nas_sdu->N_bytes = reconfig->ded_info_nas_list[i].N_bytes; nas->write_pdu(lcid, nas_sdu); @@ -1051,6 +994,33 @@ void rrc::write_pdu_pcch(byte_buffer_t *pdu) { * * *******************************************************************************/ +void rrc::send_ul_dcch_msg(byte_buffer_t *pdu) +{ + liblte_rrc_pack_ul_dcch_msg(&ul_dcch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf); + + // Byte align and pack the message bits for PDCP + if ((bit_buf.N_bits % 8) != 0) { + for (uint32_t i = 0; i < 8 - (bit_buf.N_bits % 8); i++) + bit_buf.msg[bit_buf.N_bits + i] = 0; + bit_buf.N_bits += 8 - (bit_buf.N_bits % 8); + } + // Reset and reuse sdu buffer if provided + byte_buffer_t *pdcp_buf = pdu; + + if (pdcp_buf) { + pdcp_buf->reset(); + } else { + pdcp_buf = pool_allocate; + } + + srslte_bit_pack_vector(bit_buf.msg, pdcp_buf->msg, bit_buf.N_bits); + pdcp_buf->N_bytes = bit_buf.N_bits / 8; + pdcp_buf->set_timestamp(); + + rrc_log->info("Sending %s\n", liblte_rrc_ul_dcch_msg_type_text[ul_dcch_msg.msg_type]); + pdcp->write_sdu(RB_ID_SRB1, pdcp_buf); +} + void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) { rrc_log->info_hex(sdu->msg, sdu->N_bytes, "RX %s SDU", get_rb_name(lcid).c_str()); switch (state) { @@ -1764,4 +1734,582 @@ void rrc::set_rrc_default() { } + + + + + + + + + + + + + + + + + +/************************************************************************ + * + * + * RRC Measurements + * + * + ************************************************************************/ + +void rrc::rrc_meas::init(rrc *parent) { + this->parent = parent; + this->log_h = parent->rrc_log; + this->phy = parent->phy; + this->mac_timers = parent->mac_timers; + s_measure_enabled = false; + reset(); +} + +void rrc::rrc_meas::reset() +{ + bzero(&pcell_measurement, sizeof(meas_value_t)); + filter_k_rsrp = liblte_rrc_filter_coefficient_num[LIBLTE_RRC_FILTER_COEFFICIENT_FC4]; + filter_k_rsrq = liblte_rrc_filter_coefficient_num[LIBLTE_RRC_FILTER_COEFFICIENT_FC4]; + objects.clear(); + active.clear(); + reports_cfg.clear(); + phy->meas_reset(); +} + +/* L3 filtering 5.5.3.2 */ +void rrc::rrc_meas::L3_filter(meas_value_t *value, float values[NOF_MEASUREMENTS]) +{ + for (int i=0;ims[i]) { + value->ms[i] = SRSLTE_VEC_EMA(values[i], value->ms[i], filter_a[i]); + } else { + value->ms[i] = values[i]; + } + } +} + +void rrc::rrc_meas::new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, float rsrq, uint32_t tti) +{ + log_h->info("MEAS: New measurement earfcn=%d, pci=%d, rsrp=%f, rsrq=%f, tti=%d\n", earfcn, pci, rsrp, rsrq, tti); + + float values[NOF_MEASUREMENTS] = {rsrp, rsrq}; + // This indicates serving cell + if (earfcn == 0) { + L3_filter(&pcell_measurement, values); + } else { + // Save PHY measurement for all active measurements whose earfcn/pci matches + for(std::map::iterator iter=active.begin(); iter!=active.end(); ++iter) { + meas_t *m = &iter->second; + if (objects[m->object_id].earfcn == earfcn) { + // If it's a newly discovered cell, add it to objects + if (!m->cell_values.count(pci)) { + uint32_t cell_idx = objects[m->object_id].cells.size(); + objects[m->object_id].cells[cell_idx].pci = pci; + objects[m->object_id].cells[cell_idx].q_offset = 0; + } + // Update or add cell + L3_filter(&m->cell_values[pci], values); + return; + } + } + parent->rrc_log->warning("MEAS: Received measurement from unknown EARFCN=%d\n", earfcn); + } +} + +void rrc::rrc_meas::run_tti(uint32_t tti) { + // Measurement Report Triggering Section 5.5.4 + calculate_triggers(tti); +} + +bool rrc::rrc_meas::find_earfcn_cell(uint32_t earfcn, uint32_t pci, meas_obj_t **object, int *cell_idx) { + if (object) { + *object = NULL; + } + for (std::map::iterator obj = objects.begin(); obj != objects.end(); ++obj) { + if (obj->second.earfcn == earfcn) { + if (object) { + *object = &obj->second; + } + for (std::map::iterator c = obj->second.cells.begin(); c != obj->second.cells.end(); ++c) { + if (c->second.pci == pci) { + if (cell_idx) { + *cell_idx = c->first; + return true; + } + } + } + // return true if cell idx not found but frequency is found + if (cell_idx) { + *cell_idx = -1; + } + return true; + } + } + return false; +} + +/* Generate report procedure 5.5.5 */ +void rrc::rrc_meas::generate_report(uint32_t meas_id) +{ + parent->ul_dcch_msg.msg_type = LIBLTE_RRC_UL_DCCH_MSG_TYPE_MEASUREMENT_REPORT; + LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *report = &parent->ul_dcch_msg.msg.measurement_report; + + bzero(report, sizeof(LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT)); + + meas_t *m = &active[meas_id]; + report_cfg_t *cfg = &reports_cfg[m->report_id]; + + report->meas_id = meas_id; + report->pcell_rsrp_result = value_to_range(RSRP, pcell_measurement.ms[RSRP]); + report->pcell_rsrq_result = value_to_range(RSRQ, pcell_measurement.ms[RSRQ]); + + log_h->console("MEAS: Generate report MeasId=%d, rsrp=%f rsrq=%f\n", + report->meas_id, pcell_measurement.ms[RSRP], pcell_measurement.ms[RSRQ]); + + // TODO: report up to 8 best cells + for (std::map::iterator cell = m->cell_values.begin(); cell != m->cell_values.end(); ++cell) + { + if (cell->second.triggered && report->meas_result_neigh_cells.eutra.n_result < 8) + { + LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT *rc = &report->meas_result_neigh_cells.eutra.result_eutra_list[report->meas_result_neigh_cells.eutra.n_result]; + + rc->phys_cell_id = cell->first; + rc->meas_result.have_rsrp = cfg->report_quantity==RSRP || cfg->report_quantity==BOTH; + rc->meas_result.have_rsrq = cfg->report_quantity==RSRQ || cfg->report_quantity==BOTH; + rc->meas_result.rsrp_result = value_to_range(RSRP, cell->second.ms[RSRP]); + rc->meas_result.rsrq_result = value_to_range(RSRQ, cell->second.ms[RSRQ]); + + log_h->console("MEAS: Add neigh=%d, pci=%d, rsrp=%f, rsrq=%f\n", + report->meas_result_neigh_cells.eutra.n_result, rc->phys_cell_id, + cell->second.ms[RSRP], cell->second.ms[RSRQ]); + + report->meas_result_neigh_cells.eutra.n_result++; + } + } + report->have_meas_result_neigh_cells = report->meas_result_neigh_cells.eutra.n_result > 0; + + m->nof_reports_sent++; + mac_timers->timer_get(m->periodic_timer)->stop(); + + if (m->nof_reports_sent < cfg->amount) { + mac_timers->timer_get(m->periodic_timer)->reset(); + mac_timers->timer_get(m->periodic_timer)->run(); + } else { + if (cfg->trigger_type == report_cfg_t::PERIODIC) { + m->triggered = false; + } + } + + // Send to lower layers + parent->send_ul_dcch_msg(); +} + +/* Handle entering/leaving event conditions 5.5.4.1 */ +bool rrc::rrc_meas::process_event(LIBLTE_RRC_EVENT_EUTRA_STRUCT *event, uint32_t tti, + bool enter_condition, bool exit_condition, + meas_t *m, meas_value_t *cell) +{ + bool generate_report = false; + if (enter_condition && (!m->triggered || !cell->triggered)) { + if (!cell->timer_enter_triggered) { + cell->timer_enter_triggered = true; + cell->enter_tti = tti; + } else if (srslte_tti_interval(tti, cell->enter_tti) >= event->time_to_trigger) { + m->triggered = true; + cell->triggered = true; + m->nof_reports_sent = 0; + generate_report = true; + } + } else if (exit_condition) { + if (!cell->timer_exit_triggered) { + cell->timer_exit_triggered = true; + cell->exit_tti = tti; + } else if (srslte_tti_interval(tti, cell->exit_tti) >= event->time_to_trigger) { + m->triggered = false; + cell->triggered = false; + mac_timers->timer_get(m->periodic_timer)->stop(); + if (event) { + if (event->event_id == LIBLTE_RRC_EVENT_ID_EUTRA_A3 && event->event_a3.report_on_leave) { + generate_report = true; + } + } + } + } + if (!enter_condition) { + cell->timer_enter_triggered = false; + } + if (!enter_condition) { + cell->timer_exit_triggered = false; + } + return generate_report; +} + +/* Calculate trigger conditions for each cell 5.5.4 */ +void rrc::rrc_meas::calculate_triggers(uint32_t tti) +{ + float Ofp = 0, Ocp = 0; + meas_obj_t *serving_object = NULL; + int serving_cell_idx = 0; + + // Get serving cell + if (active.size()) { + uint32_t current_earfcn = 0; + srslte_cell_t current_cell; + phy->get_current_cell(¤t_cell, ¤t_earfcn); + if (find_earfcn_cell(current_earfcn, current_cell.id, &serving_object, &serving_cell_idx)) { + Ofp = serving_object->q_offset; + if (serving_cell_idx >= 0) { + Ocp = serving_object->cells[serving_cell_idx].q_offset; + } + } else { + log_h->warning("Can't find current eafcn=%d, pci=%d in objects list. Using Ofp=0, Ocp=0\n", current_earfcn, current_cell.id); + } + } + + for (std::map::iterator m = active.begin(); m != active.end(); ++m) { + report_cfg_t *cfg = &reports_cfg[m->second.report_id]; + float hyst = 0.5*cfg->event.hysteresis; + float Mp = pcell_measurement.ms[cfg->trigger_quantity]; + + LIBLTE_RRC_EVENT_ID_EUTRA_ENUM event_id = cfg->event.event_id; + const char *event_str = liblte_rrc_event_id_eutra_text[event_id]; + + bool gen_report = false; + + if (cfg->trigger_type == report_cfg_t::EVENT) { + + // A1 & A2 are for serving cell only + if (event_id < LIBLTE_RRC_EVENT_ID_EUTRA_A3) { + + bool enter_condition; + bool exit_condition; + if (event_id == LIBLTE_RRC_EVENT_ID_EUTRA_A1) { + enter_condition = Mp - hyst > range_to_value(cfg->trigger_quantity, cfg->event.event_a1.eutra.range); + exit_condition = Mp + hyst < range_to_value(cfg->trigger_quantity, cfg->event.event_a1.eutra.range); + } else { + enter_condition = Mp + hyst < range_to_value(cfg->trigger_quantity, cfg->event.event_a1.eutra.range); + exit_condition = Mp - hyst > range_to_value(cfg->trigger_quantity, cfg->event.event_a1.eutra.range); + } + gen_report |= process_event(&cfg->event, tti, enter_condition, exit_condition, + &m->second, &m->second.cell_values[serving_cell_idx]); + + // Rest are evaluated for every cell in frequency + } else { + meas_obj_t *obj = &objects[m->second.object_id]; + for (std::map::iterator cell = obj->cells.begin(); cell != obj->cells.end(); ++cell) { + float Ofn = obj->q_offset; + float Ocn = cell->second.q_offset; + float Mn = m->second.cell_values[cell->second.pci].ms[cfg->trigger_quantity]; + float Off=0, th=0, th1=0, th2=0; + bool enter_condition = false; + bool exit_condition = false; + switch (event_id) { + case LIBLTE_RRC_EVENT_ID_EUTRA_A3: + Off = 0.5*cfg->event.event_a3.offset; + enter_condition = Mn + Ofn + Ocn - hyst > Mp + Ofp + Ocp + Off; + exit_condition = Mn + Ofn + Ocn + hyst < Mp + Ofp + Ocp + Off; + break; + case LIBLTE_RRC_EVENT_ID_EUTRA_A4: + th = range_to_value(cfg->trigger_quantity, cfg->event.event_a4.eutra.range); + enter_condition = Mn + Ofn + Ocn - hyst > th; + exit_condition = Mn + Ofn + Ocn + hyst < th; + break; + case LIBLTE_RRC_EVENT_ID_EUTRA_A5: + th1 = range_to_value(cfg->trigger_quantity, cfg->event.event_a5.eutra1.range); + th2 = range_to_value(cfg->trigger_quantity, cfg->event.event_a5.eutra2.range); + enter_condition = (Mp + hyst < th1) && (Mn + Ofn + Ocn - hyst > th2); + exit_condition = (Mp - hyst > th1) && (Mn + Ofn + Ocn + hyst < th2); + break; + default: + log_h->error("Error event %s not implemented\n", event_str); + } + gen_report |= process_event(&cfg->event, tti, enter_condition, exit_condition, + &m->second, &m->second.cell_values[cell->second.pci]); + } + } + } + if (gen_report) { + generate_report(m->first); + } + } +} + +// 5.5.4.1 expiry of periodical reporting timer +bool rrc::rrc_meas::timer_expired(uint32_t timer_id) { + for (std::map::iterator iter = active.begin(); iter != active.end(); ++iter) { + if (iter->second.periodic_timer == timer_id) { + generate_report(iter->first); + return true; + } + } + return false; +} + +void rrc::rrc_meas::stop_reports_object(uint32_t object_id) { + for (std::map::iterator iter = active.begin(); iter != active.end(); ++iter) { + meas_t *m = &iter->second; + if (m->object_id == object_id) { + mac_timers->timer_get(m->periodic_timer)->stop(); + m->triggered = false; + } + } +} + +void rrc::rrc_meas::remove_meas_object(uint32_t object_id) { + // CHECKME: Is the delete from the map correct? + for(std::map::iterator iter=active.begin(); iter!=active.end(); ++iter) { + meas_t m = iter->second; + if (m.object_id == object_id) { + remove_meas_id(iter->first); + } + } +} + +void rrc::rrc_meas::remove_meas_report(uint32_t report_id) { + // CHECKME: Is the delete from the map correct? + for(std::map::iterator iter=active.begin(); iter!=active.end(); ++iter) { + meas_t m = iter->second; + if (m.report_id == report_id) { + remove_meas_id(iter->first); + } + } +} + +void rrc::rrc_meas::remove_meas_id(uint32_t meas_id) { + mac_timers->timer_get(active[meas_id].periodic_timer)->stop(); + mac_timers->timer_release_id(active[meas_id].periodic_timer); + active.erase(meas_id); + log_h->info("MEAS: Removed measId=%d\n", meas_id); +} + +/* Parses MeasConfig object from RRCConnectionReconfiguration message and applies configuration + * as per section 5.5.2 + */ +void rrc::rrc_meas::parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *cfg) +{ + + // Measurement identity removal 5.5.2.2 + for (uint32_t i=0;iN_meas_id_to_remove;i++) { + remove_meas_id(cfg->meas_id_to_remove_list[i]); + } + + // Measurement identity addition/modification 5.5.2.3 + if (cfg->meas_id_to_add_mod_list_present) { + for (uint32_t i=0;imeas_id_to_add_mod_list.N_meas_id;i++) { + LIBLTE_RRC_MEAS_ID_TO_ADD_MOD_STRUCT *measId = &cfg->meas_id_to_add_mod_list.meas_id_list[i]; + // Stop the timer if the entry exists or create the timer if not + if (active.count(measId->meas_id)) { + mac_timers->timer_get(active[measId->meas_id].periodic_timer)->stop(); + } else { + active[measId->meas_id].periodic_timer = mac_timers->timer_get_unique_id(); + } + active[measId->meas_id].object_id = measId->meas_obj_id; + active[measId->meas_id].report_id = measId->rep_cnfg_id; + log_h->info("MEAS: Added measId=%d, measObjectId=%d, reportConfigId=%d\n", + measId->meas_id, measId->meas_obj_id, measId->rep_cnfg_id); + } + } + + // Measurement object removal 5.5.2.4 + for (uint32_t i=0;iN_meas_obj_to_remove;i++) { + objects.erase(cfg->meas_obj_to_remove_list[i]); + remove_meas_object(cfg->meas_obj_to_remove_list[i]); + log_h->info("MEAS: Removed measObjectId=%d\n", cfg->meas_obj_to_remove_list[i]); + } + + // Measurement object addition/modification Section 5.5.2.5 + if (cfg->meas_obj_to_add_mod_list_present) { + for (uint32_t i=0;imeas_obj_to_add_mod_list.N_meas_obj;i++) { + if (cfg->meas_obj_to_add_mod_list.meas_obj_list[i].meas_obj_type == LIBLTE_RRC_MEAS_OBJECT_TYPE_EUTRA) { + LIBLTE_RRC_MEAS_OBJECT_EUTRA_STRUCT *src_obj = &cfg->meas_obj_to_add_mod_list.meas_obj_list[i].meas_obj_eutra; + + // Access the object if exists or create it + meas_obj_t *dst_obj = &objects[cfg->meas_obj_to_add_mod_list.meas_obj_list[i].meas_obj_id]; + + dst_obj->earfcn = src_obj->carrier_freq;; + if (src_obj->offset_freq_not_default) { + dst_obj->q_offset = liblte_rrc_q_offset_range_num[src_obj->offset_freq]; + } else { + dst_obj->q_offset = 0; + } + + if (src_obj->black_cells_to_remove_list_present) { + for (uint32_t j=0;jblack_cells_to_remove_list.N_cell_idx;j++) { + dst_obj->cells.erase(src_obj->black_cells_to_remove_list.cell_idx[j]); + } + } + + for (uint32_t j=0;jN_cells_to_add_mod;j++) { + dst_obj->cells[src_obj->cells_to_add_mod_list[j].cell_idx].q_offset = liblte_rrc_q_offset_range_num[src_obj->cells_to_add_mod_list[j].cell_offset]; + dst_obj->cells[src_obj->cells_to_add_mod_list[j].cell_idx].pci = src_obj->cells_to_add_mod_list[j].pci; + + log_h->info("MEAS: Added measObjectId=%d, earfcn=%d, q_offset=%f, pci=%d, offset_cell=%f\n", + cfg->meas_obj_to_add_mod_list.meas_obj_list[i].meas_obj_id, dst_obj->earfcn, dst_obj->q_offset, + dst_obj->cells[src_obj->cells_to_add_mod_list[j].cell_idx].q_offset, + dst_obj->cells[src_obj->cells_to_add_mod_list[j].cell_idx].pci); + + } + + // Untrigger reports and stop timers + stop_reports_object(cfg->meas_obj_to_add_mod_list.meas_obj_list[i].meas_obj_id); + + // TODO: Blackcells + // TODO: meassubframepattern + + } else { + log_h->warning("MEAS: Unsupported MeasObject type %s\n", + liblte_rrc_meas_object_type_text[cfg->meas_obj_to_add_mod_list.meas_obj_list[i].meas_obj_type]); + } + } + } + + // Reporting configuration removal 5.5.2.6 + for (uint32_t i=0;iN_rep_cnfg_to_remove;i++) { + reports_cfg.erase(cfg->rep_cnfg_to_remove_list[i]); + remove_meas_report(cfg->rep_cnfg_to_remove_list[i]); + log_h->info("MEAS: Removed reportConfigId=%d\n", cfg->rep_cnfg_to_remove_list[i]); + } + + // Reporting configuration addition/modification 5.5.2.7 + if (cfg->rep_cnfg_to_add_mod_list_present) { + for (uint32_t i=0;irep_cnfg_to_add_mod_list.N_rep_cnfg;i++) { + if (cfg->rep_cnfg_to_add_mod_list.rep_cnfg_list[i].rep_cnfg_type == LIBLTE_RRC_REPORT_CONFIG_TYPE_EUTRA) { + LIBLTE_RRC_REPORT_CONFIG_EUTRA_STRUCT *src_rep = &cfg->rep_cnfg_to_add_mod_list.rep_cnfg_list[i].rep_cnfg_eutra; + // Access the object if exists or create it + report_cfg_t *dst_rep = &reports_cfg[cfg->rep_cnfg_to_add_mod_list.rep_cnfg_list[i].rep_cnfg_id]; + + dst_rep->trigger_type = src_rep->trigger_type==LIBLTE_RRC_TRIGGER_TYPE_EUTRA_EVENT?report_cfg_t::EVENT:report_cfg_t::PERIODIC; + dst_rep->event = src_rep->event; + dst_rep->amount = liblte_rrc_report_amount_num[src_rep->report_amount]; + dst_rep->interval = liblte_rrc_report_interval_num[src_rep->report_interval]; + dst_rep->max_cell = src_rep->max_report_cells; + dst_rep->trigger_quantity = (quantity_t) src_rep->trigger_quantity; + dst_rep->report_quantity = src_rep->report_quantity==LIBLTE_RRC_REPORT_QUANTITY_SAME_AS_TRIGGER_QUANTITY?dst_rep->trigger_quantity:BOTH; + + log_h->info("MEAS: Added reportConfigId=%d, event=%s, amount=%d, interval=%d\n", + cfg->rep_cnfg_to_add_mod_list.rep_cnfg_list[i].rep_cnfg_id, + liblte_rrc_event_id_eutra_text[dst_rep->event.event_id], + dst_rep->amount, dst_rep->interval); + + // Reset reports counter + for(std::map::iterator iter=active.begin(); iter!=active.end(); ++iter) { + meas_t m = iter->second; + if (m.report_id == cfg->rep_cnfg_to_add_mod_list.rep_cnfg_list[i].rep_cnfg_id) { + iter->second.nof_reports_sent = 0; + m.triggered = false; + mac_timers->timer_get(m.periodic_timer)->stop(); + } + } + } else { + log_h->warning("MEAS: Unsupported reportConfigType %s\n", liblte_rrc_report_config_type_text[cfg->rep_cnfg_to_add_mod_list.rep_cnfg_list[i].rep_cnfg_type]); + } + } + } + + // Quantity configuration 5.5.2.8 + if (cfg->quantity_cnfg_present && cfg->quantity_cnfg.qc_eutra_present) { + if (cfg->quantity_cnfg.qc_eutra.fc_rsrp_not_default) { + filter_k_rsrp = liblte_rrc_filter_coefficient_num[cfg->quantity_cnfg.qc_eutra.fc_rsrp]; + } else { + filter_k_rsrp = liblte_rrc_filter_coefficient_num[LIBLTE_RRC_FILTER_COEFFICIENT_FC4]; + } + if (cfg->quantity_cnfg.qc_eutra.fc_rsrq_not_default) { + filter_k_rsrq = liblte_rrc_filter_coefficient_num[cfg->quantity_cnfg.qc_eutra.fc_rsrq]; + } else { + filter_k_rsrq = liblte_rrc_filter_coefficient_num[LIBLTE_RRC_FILTER_COEFFICIENT_FC4]; + } + filter_a[RSRP] = pow(0.5, (float) filter_k_rsrp/4); + filter_a[RSRQ] = pow(0.5, (float) filter_k_rsrq/4); + + log_h->info("MEAS: Quantity configuration k_rsrp=%d, k_rsrq=%d\n", filter_k_rsrp, filter_k_rsrq); + } + + // S-Measure + if (cfg->s_meas_present) { + if (cfg->s_meas) { + s_measure_enabled = true; + s_measure_value = range_to_value(RSRP, cfg->s_meas); + } else { + s_measure_enabled = false; + } + } + + update_phy(); +} + +/* Instruct PHY to start measurement */ +void rrc::rrc_meas::update_phy() +{ + phy->meas_reset(); + if (pcell_measurement.ms[RSRP] < s_measure_value || !s_measure_enabled) { + for(std::map::iterator iter=active.begin(); iter!=active.end(); ++iter) { + meas_t m = iter->second; + meas_obj_t o = objects[m.object_id]; + // Instruct PHY to look for neighbour cells on this frequency + phy->meas_start(o.earfcn); + for(std::map::iterator iter=o.cells.begin(); iter!=o.cells.end(); ++iter) { + // Instruct PHY to look for cells IDs on this frequency + phy->meas_start(o.earfcn, iter->second.pci); + } + } + } +} + + +uint8_t rrc::rrc_meas::value_to_range(quantity_t quant, float value) { + uint8_t range = 0; + switch(quant) { + case RSRP: + if (value < -140) { + range = 0; + } else if (-140 <= value && value < -44) { + range = 1 + (uint8_t) (value + 140); + } else { + range = 97; + } + break; + case RSRQ: + if (value < -19.5) { + range = 0; + } else if (-19.5 <= value && value < -3) { + range = 1 + (uint8_t) (2*(value + 19.5)); + } else { + range = 34; + } + break; + case BOTH: + printf("Error quantity both not supported in value_to_range\n"); + break; + } + return range; +} + +float rrc::rrc_meas::range_to_value(quantity_t quant, uint8_t range) { + float val = 0; + switch(quant) { + case RSRP: + val = -140+(float) range; + break; + case RSRQ: + val = -19.5+(float) range/2; + break; + case BOTH: + printf("Error quantity both not supported in range_to_value\n"); + break; + } + return val; +} + + + + + + + + + + } // namespace srsue From 10bc2ee8a188f45c85c55f10934c22bb0e1da2f5 Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Mon, 20 Nov 2017 16:32:41 +0000 Subject: [PATCH 145/242] Fix for RLC AM polling condition --- lib/src/upper/rlc_am.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index f8abc0aef..7a7778a2f 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -395,7 +395,7 @@ bool rlc_am::poll_required() if(poll_retx()) return true; - if(tx_sdu_queue.size() == 0 && retx_queue.size() == 0) + if(tx_window.size() == 0 && retx_queue.size() == 0) return true; /* According to 5.2.2.1 in 36.322 v13.3.0 a poll should be requested if From 38ab9921f812daf317e29ed184aea41fb1e93566 Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Tue, 21 Nov 2017 09:06:48 +0000 Subject: [PATCH 146/242] Undoing unnecessary RLC fix --- lib/src/upper/rlc_am.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index 7a7778a2f..f8abc0aef 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -395,7 +395,7 @@ bool rlc_am::poll_required() if(poll_retx()) return true; - if(tx_window.size() == 0 && retx_queue.size() == 0) + if(tx_sdu_queue.size() == 0 && retx_queue.size() == 0) return true; /* According to 5.2.2.1 in 36.322 v13.3.0 a poll should be requested if From 91c9ddf244612e7235a67c969287d468cee7d9e7 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 21 Nov 2017 10:14:09 +0100 Subject: [PATCH 147/242] Added scaling factor to predecoder --- lib/include/srslte/phy/mimo/precoding.h | 48 +-- lib/include/srslte/phy/phch/pdsch.h | 6 + lib/include/srslte/phy/ue/ue_dl.h | 6 + .../phy/ch_estimation/test/chest_test_dl.c | 4 +- lib/src/phy/mimo/precoding.c | 394 +++++++++--------- lib/src/phy/mimo/test/precoder_test.c | 17 +- lib/src/phy/phch/pbch.c | 6 +- lib/src/phy/phch/pcfich.c | 6 +- lib/src/phy/phch/pdcch.c | 6 +- lib/src/phy/phch/pdsch.c | 17 +- lib/src/phy/phch/phich.c | 6 +- lib/src/phy/phch/pmch.c | 2 +- lib/src/phy/phch/pucch.c | 2 +- lib/src/phy/phch/pusch.c | 2 +- lib/src/phy/phch/test/pdsch_test.c | 6 +- lib/src/phy/ue/ue_dl.c | 7 +- 16 files changed, 291 insertions(+), 244 deletions(-) diff --git a/lib/include/srslte/phy/mimo/precoding.h b/lib/include/srslte/phy/mimo/precoding.h index 58fe22a40..f8463d1cb 100644 --- a/lib/include/srslte/phy/mimo/precoding.h +++ b/lib/include/srslte/phy/mimo/precoding.h @@ -49,18 +49,21 @@ */ SRSLTE_API int srslte_precoding_single(cf_t *x, cf_t *y, - int nof_symbols); + int nof_symbols, + float scaling); SRSLTE_API int srslte_precoding_diversity(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PORTS], int nof_ports, - int nof_symbols); + int nof_symbols, + float scaling); SRSLTE_API int srslte_precoding_cdd(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PORTS], int nof_layers, int nof_ports, - int nof_symbols); + int nof_symbols, + float scaling); SRSLTE_API int srslte_precoding_type(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PORTS], @@ -68,6 +71,7 @@ SRSLTE_API int srslte_precoding_type(cf_t *x[SRSLTE_MAX_LAYERS], int nof_ports, int codebook_idx, int nof_symbols, + float scaling, srslte_mimo_type_t type); /* Estimates the vector "x" based on the received signal "y" and the channel estimates "h" @@ -76,6 +80,7 @@ SRSLTE_API int srslte_predecoding_single(cf_t *y, cf_t *h, cf_t *x, int nof_symbols, + float scaling, float noise_estimate); SRSLTE_API int srslte_predecoding_single_multi(cf_t *y[SRSLTE_MAX_PORTS], @@ -83,42 +88,37 @@ SRSLTE_API int srslte_predecoding_single_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *x, int nof_rxant, int nof_symbols, + float scaling, float noise_estimate); SRSLTE_API int srslte_predecoding_diversity(cf_t *y, cf_t *h[SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], int nof_ports, - int nof_symbols); + int nof_symbols, + float scaling); SRSLTE_API int srslte_predecoding_diversity_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], int nof_rxant, int nof_ports, - int nof_symbols); - -SRSLTE_API int srslte_predecoding_type(cf_t *y, - cf_t *h[SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], - int nof_ports, - int nof_layers, - int nof_symbols, - srslte_mimo_type_t type, - float noise_estimate); + int nof_symbols, + float scaling); SRSLTE_API void srslte_predecoding_set_mimo_decoder (srslte_mimo_decoder_t _mimo_decoder); -SRSLTE_API int srslte_predecoding_type_multi(cf_t *y[SRSLTE_MAX_PORTS], - cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], - int nof_rxant, - int nof_ports, - int nof_layers, - int codebook_idx, - int nof_symbols, - srslte_mimo_type_t type, - float noise_estimate); +SRSLTE_API int srslte_predecoding_type(cf_t *y[SRSLTE_MAX_PORTS], + cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + cf_t *x[SRSLTE_MAX_LAYERS], + int nof_rxant, + int nof_ports, + int nof_layers, + int codebook_idx, + int nof_symbols, + srslte_mimo_type_t type, + float scaling, + float noise_estimate); SRSLTE_API int srslte_precoding_pmi_select(cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], uint32_t nof_symbols, diff --git a/lib/include/srslte/phy/phch/pdsch.h b/lib/include/srslte/phy/phch/pdsch.h index 459bcc209..dab900d77 100644 --- a/lib/include/srslte/phy/phch/pdsch.h +++ b/lib/include/srslte/phy/phch/pdsch.h @@ -65,6 +65,9 @@ typedef struct SRSLTE_API { uint16_t ue_rnti; bool is_ue; + /* Power allocation parameter 3GPP 36.213 Clause 5.2 Rho_b */ + float rho_a; + /* buffers */ // void buffers are shared for tx and rx cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; /* Channel estimation (Rx only) */ @@ -101,6 +104,9 @@ SRSLTE_API int srslte_pdsch_set_cell(srslte_pdsch_t *q, SRSLTE_API int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti); +SRSLTE_API void srslte_pdsch_set_power_allocation(srslte_pdsch_t *q, + float rho_a); + SRSLTE_API void srslte_pdsch_free_rnti(srslte_pdsch_t *q, uint16_t rnti); diff --git a/lib/include/srslte/phy/ue/ue_dl.h b/lib/include/srslte/phy/ue/ue_dl.h index 0486ad7d4..a60761a37 100644 --- a/lib/include/srslte/phy/ue/ue_dl.h +++ b/lib/include/srslte/phy/ue/ue_dl.h @@ -104,6 +104,9 @@ typedef struct SRSLTE_API { uint32_t pmi[SRSLTE_MAX_LAYERS]; uint32_t ri; + /* Power allocation parameter 3GPP 36.213 Clause 5.2 Rho_b */ + float rho_b; + srslte_dci_format_t dci_format; uint64_t pkt_errors; uint64_t pkts_total; @@ -244,6 +247,9 @@ SRSLTE_API int srslte_ue_dl_set_mbsfn_area_id(srslte_ue_dl_t *q, SRSLTE_API void srslte_ue_dl_set_non_mbsfn_region(srslte_ue_dl_t *q, uint8_t non_mbsfn_region_length); +SRSLTE_API void srslte_ue_dl_set_power_alloc(srslte_ue_dl_t *q, + float rho_a, + float rho_b); SRSLTE_API void srslte_ue_dl_save_signal(srslte_ue_dl_t *q, diff --git a/lib/src/phy/ch_estimation/test/chest_test_dl.c b/lib/src/phy/ch_estimation/test/chest_test_dl.c index 0f5a6d6ea..62f7e1c86 100644 --- a/lib/src/phy/ch_estimation/test/chest_test_dl.c +++ b/lib/src/phy/ch_estimation/test/chest_test_dl.c @@ -173,7 +173,7 @@ int main(int argc, char **argv) { gettimeofday(&t[1], NULL); for (int j=0;j<100;j++) { - srslte_predecoding_single(input, ce, output, num_re, 0); + srslte_predecoding_single(input, ce, output, num_re, 1.0f, 0); } gettimeofday(&t[2], NULL); get_time_interval(t); @@ -188,7 +188,7 @@ int main(int argc, char **argv) { gettimeofday(&t[1], NULL); for (int j=0;j<100;j++) { - srslte_predecoding_single(input, ce, output, num_re, srslte_chest_dl_get_noise_estimate(&est)); + srslte_predecoding_single(input, ce, output, num_re, 1.0f, srslte_chest_dl_get_noise_estimate(&est)); } gettimeofday(&t[2], NULL); get_time_interval(t); diff --git a/lib/src/phy/mimo/precoding.c b/lib/src/phy/mimo/precoding.c index 5d96bed27..31ba2ca0a 100644 --- a/lib/src/phy/mimo/precoding.c +++ b/lib/src/phy/mimo/precoding.c @@ -37,13 +37,13 @@ #ifdef LV_HAVE_SSE #include -int srslte_predecoding_single_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, int nof_rxant, int nof_symbols, float noise_estimate); -int srslte_predecoding_diversity2_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], int nof_rxant, int nof_symbols); +int srslte_predecoding_single_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, int nof_rxant, int nof_symbols, float scaling, float noise_estimate); +int srslte_predecoding_diversity2_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], int nof_rxant, int nof_symbols, float scaling); #endif #ifdef LV_HAVE_AVX #include -int srslte_predecoding_single_avx(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, int nof_rxant, int nof_symbols, float noise_estimate); +int srslte_predecoding_single_avx(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, int nof_rxant, int nof_symbols, float scaling, float noise_estimate); #endif #include "srslte/phy/utils/mat.h" @@ -59,7 +59,7 @@ static srslte_mimo_decoder_t mimo_decoder = SRSLTE_MIMO_DECODER_MMSE; #define PROD(a,b) _mm_addsub_ps(_mm_mul_ps(a,_mm_moveldup_ps(b)),_mm_mul_ps(_mm_shuffle_ps(a,a,0xB1),_mm_movehdup_ps(b))) -int srslte_predecoding_single_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, int nof_rxant, int nof_symbols, float noise_estimate) { +int srslte_predecoding_single_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, int nof_rxant, int nof_symbols, float scaling, float noise_estimate) { float *xPtr = (float*) x; const float *hPtr1 = (const float*) h[0]; @@ -122,7 +122,10 @@ int srslte_predecoding_single_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_ x1Val1 = _mm_div_ps(x1Val1, h1square); x2Val1 = _mm_div_ps(x2Val1, h2square); - + + x1Val1 = _mm_mul_ps(x1Val1, _mm_set1_ps(1/scaling)); + x2Val1 = _mm_mul_ps(x2Val1, _mm_set1_ps(1/scaling)); + _mm_store_ps(xPtr, x1Val1); xPtr+=4; _mm_store_ps(xPtr, x2Val1); xPtr+=4; @@ -134,7 +137,7 @@ int srslte_predecoding_single_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_ r += y[p][i]*conj(h[p][i]); hh += conj(h[p][i])*h[p][i]; } - x[i] = r/(hh+noise_estimate); + x[i] = scaling*r/(hh+noise_estimate); } return nof_symbols; } @@ -147,7 +150,7 @@ int srslte_predecoding_single_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_ -int srslte_predecoding_single_avx(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, int nof_rxant, int nof_symbols, float noise_estimate) { +int srslte_predecoding_single_avx(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, int nof_rxant, int nof_symbols, float scaling, float noise_estimate) { float *xPtr = (float*) x; const float *hPtr1 = (const float*) h[0]; @@ -160,6 +163,8 @@ int srslte_predecoding_single_avx(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_ __m256 noise = _mm256_set1_ps(noise_estimate); __m256 h1Val1, h2Val1, y1Val1, y2Val1, h12square, h1square, h2square, h1_p, h2_p, h1conj1, h2conj1, x1Val, x2Val; __m256 h1Val2, h2Val2, y1Val2, y2Val2, h1conj2, h2conj2; + __m256 avx_scaling = _mm256_set1_ps(1/scaling); + for (int i=0;i 32 && nof_rxant <= 2) { - return srslte_predecoding_single_avx(y, h, x, nof_rxant, nof_symbols, noise_estimate); + return srslte_predecoding_single_avx(y, h, x, nof_rxant, nof_symbols, scaling, noise_estimate); } else { - return srslte_predecoding_single_gen(y, h, x, nof_rxant, nof_symbols, noise_estimate); + return srslte_predecoding_single_gen(y, h, x, nof_rxant, nof_symbols, scaling, noise_estimate); } #else #ifdef LV_HAVE_SSE if (nof_symbols > 32 && nof_rxant <= 2) { - return srslte_predecoding_single_sse(y, h, x, nof_rxant, nof_symbols, noise_estimate); + return srslte_predecoding_single_sse(y, h, x, nof_rxant, nof_symbols, scaling, noise_estimate); } else { - return srslte_predecoding_single_gen(y, h, x, nof_rxant, nof_symbols, noise_estimate); + return srslte_predecoding_single_gen(y, h, x, nof_rxant, nof_symbols, scaling, noise_estimate); } #else - return srslte_predecoding_single_gen(y, h, x, nof_rxant, nof_symbols, noise_estimate); + return srslte_predecoding_single_gen(y, h, x, nof_rxant, nof_symbols, scaling, noise_estimate); #endif #endif } /* ZF/MMSE SISO equalizer x=y(h'h+no)^(-1)h' (ZF if n0=0.0)*/ -int srslte_predecoding_single_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, int nof_rxant, int nof_symbols, float noise_estimate) { +int srslte_predecoding_single_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, + int nof_rxant, int nof_symbols, float scaling, float noise_estimate) { #ifdef LV_HAVE_AVX if (nof_symbols > 32) { - return srslte_predecoding_single_avx(y, h, x, nof_rxant, nof_symbols, noise_estimate); + return srslte_predecoding_single_avx(y, h, x, nof_rxant, nof_symbols, scaling, noise_estimate); } else { - return srslte_predecoding_single_gen(y, h, x, nof_rxant, nof_symbols, noise_estimate); + return srslte_predecoding_single_gen(y, h, x, nof_rxant, nof_symbols, scaling, noise_estimate); } #else #ifdef LV_HAVE_SSE if (nof_symbols > 32) { - return srslte_predecoding_single_sse(y, h, x, nof_rxant, nof_symbols, noise_estimate); + return srslte_predecoding_single_sse(y, h, x, nof_rxant, nof_symbols, scaling, noise_estimate); } else { - return srslte_predecoding_single_gen(y, h, x, nof_rxant, nof_symbols, noise_estimate); + return srslte_predecoding_single_gen(y, h, x, nof_rxant, nof_symbols, scaling, noise_estimate); } #else - return srslte_predecoding_single_gen(y, h, x, nof_rxant, nof_symbols, noise_estimate); + return srslte_predecoding_single_gen(y, h, x, nof_rxant, nof_symbols, scaling, noise_estimate); #endif #endif } @@ -296,7 +305,7 @@ int srslte_predecoding_single_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MA /* C implementatino of the SFBC equalizer */ int srslte_predecoding_diversity_gen_(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], - int nof_rxant, int nof_ports, int nof_symbols, int symbol_start) + int nof_rxant, int nof_ports, int nof_symbols, int symbol_start, float scaling) { int i; if (nof_ports == 2) { @@ -321,6 +330,7 @@ int srslte_predecoding_diversity_gen_(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_ x0 += (conjf(h00) * r0 + h11 * conjf(r1)); x1 += (-h10 * conj(r0) + conj(h01) * r1); } + hh *= scaling; x[0][i] = x0 / hh * sqrt(2); x[1][i] = x1 / hh * sqrt(2); } @@ -351,6 +361,10 @@ int srslte_predecoding_diversity_gen_(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_ x2 += (conjf(h1) * r2 + h3 * conjf(r3)); x3 += (-h3 * conjf(r2) + conjf(h1) * r3); } + + hh02 *= scaling; + hh13 *= scaling; + x[0][i] = x0 / hh02 * sqrt(2); x[1][i] = x1 / hh02 * sqrt(2); x[2][i] = x2 / hh13 * sqrt(2); @@ -365,15 +379,15 @@ int srslte_predecoding_diversity_gen_(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_ int srslte_predecoding_diversity_gen(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], - int nof_rxant, int nof_ports, int nof_symbols) { - return srslte_predecoding_diversity_gen_(y, h, x, nof_rxant, nof_ports, nof_symbols, 0); + int nof_rxant, int nof_ports, int nof_symbols, float scaling) { + return srslte_predecoding_diversity_gen_(y, h, x, nof_rxant, nof_ports, nof_symbols, 0, scaling); } /* SSE implementation of the 2-port SFBC equalizer */ #ifdef LV_HAVE_SSE int srslte_predecoding_diversity2_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], - int nof_rxant, int nof_symbols) + int nof_rxant, int nof_symbols, float scaling) { float *x0Ptr = (float*) x[0]; float *x1Ptr = (float*) x[1]; @@ -385,7 +399,7 @@ int srslte_predecoding_diversity2_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_ const float *yPtr1 = (const float*) y[1]; __m128 conjugator = _mm_setr_ps(0, -0.f, 0, -0.f); - __m128 sqrt2 = _mm_setr_ps(sqrt(2), sqrt(2), sqrt(2), sqrt(2)); + __m128 sqrt2 = _mm_set1_ps(sqrtf(2)/scaling); __m128 h0Val_00, h0Val_10, h1Val_00, h1Val_10, h000, h00conj0, h010, h01conj0, h100, h110; __m128 h0Val_01, h0Val_11, h1Val_01, h1Val_11, h001, h00conj1, h011, h01conj1, h101, h111; @@ -474,13 +488,13 @@ int srslte_predecoding_diversity2_sse(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_ _mm_store_ps(x1Ptr, x1); x1Ptr+=4; } // Compute remaining symbols using generic implementation - srslte_predecoding_diversity_gen_(y, h, x, nof_rxant, 2, nof_symbols, 4*(nof_symbols/4)); + srslte_predecoding_diversity_gen_(y, h, x, nof_rxant, 2, nof_symbols, 4*(nof_symbols/4), scaling); return nof_symbols; } #endif int srslte_predecoding_diversity(cf_t *y_, cf_t *h_[SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], - int nof_ports, int nof_symbols) + int nof_ports, int nof_symbols, float scaling) { cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; cf_t *y[SRSLTE_MAX_PORTS]; @@ -493,47 +507,31 @@ int srslte_predecoding_diversity(cf_t *y_, cf_t *h_[SRSLTE_MAX_PORTS], cf_t *x[S #ifdef LV_HAVE_SSE if (nof_symbols > 32 && nof_ports == 2) { - return srslte_predecoding_diversity2_sse(y, h, x, nof_rxant, nof_symbols); + return srslte_predecoding_diversity2_sse(y, h, x, nof_rxant, nof_symbols, scaling); } else { - return srslte_predecoding_diversity_gen(y, h, x, nof_rxant, nof_ports, nof_symbols); + return srslte_predecoding_diversity_gen(y, h, x, nof_rxant, nof_ports, nof_symbols, scaling); } #else - return srslte_predecoding_diversity_gen(y, h, x, nof_rxant, nof_ports, nof_symbols); + return srslte_predecoding_diversity_gen(y, h, x, nof_rxant, nof_ports, nof_symbols, scaling); #endif } int srslte_predecoding_diversity_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], - int nof_rxant, int nof_ports, int nof_symbols) + int nof_rxant, int nof_ports, int nof_symbols, float scaling) { #ifdef LV_HAVE_SSE if (nof_symbols > 32 && nof_ports == 2) { - return srslte_predecoding_diversity2_sse(y, h, x, nof_rxant, nof_symbols); + return srslte_predecoding_diversity2_sse(y, h, x, nof_rxant, nof_symbols, scaling); } else { - return srslte_predecoding_diversity_gen(y, h, x, nof_rxant, nof_ports, nof_symbols); + return srslte_predecoding_diversity_gen(y, h, x, nof_rxant, nof_ports, nof_symbols, scaling); } #else - return srslte_predecoding_diversity_gen(y, h, x, nof_rxant, nof_ports, nof_symbols); + return srslte_predecoding_diversity_gen(y, h, x, nof_rxant, nof_ports, nof_symbols, scaling); #endif } - -int srslte_predecoding_type(cf_t *y_, cf_t *h_[SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], - int nof_ports, int nof_layers, int nof_symbols, srslte_mimo_type_t type, float noise_estimate) -{ - cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; - cf_t *y[SRSLTE_MAX_PORTS]; - uint32_t nof_rxant = 1; - - for (int i=0;i SRSLTE_MAX_PORTS) { fprintf(stderr, "Maximum number of ports is %d (nof_ports=%d)\n", SRSLTE_MAX_PORTS, @@ -1437,10 +1438,10 @@ int srslte_predecoding_type_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_ if (nof_layers >= 2 && nof_layers <= 4) { switch (mimo_decoder) { case SRSLTE_MIMO_DECODER_ZF: - return srslte_predecoding_ccd_zf(y, h, x, nof_rxant, nof_ports, nof_layers, nof_symbols); + return srslte_predecoding_ccd_zf(y, h, x, nof_rxant, nof_ports, nof_layers, nof_symbols, scaling); break; case SRSLTE_MIMO_DECODER_MMSE: - return srslte_predecoding_ccd_mmse(y, h, x, nof_rxant, nof_ports, nof_layers, nof_symbols, noise_estimate); + return srslte_predecoding_ccd_mmse(y, h, x, nof_rxant, nof_ports, nof_layers, nof_symbols, scaling, noise_estimate); break; } } else { @@ -1451,7 +1452,7 @@ int srslte_predecoding_type_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_ return -1; case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA: if (nof_ports == 1 && nof_layers == 1) { - return srslte_predecoding_single_multi(y, h[0], x[0], nof_rxant, nof_symbols, noise_estimate); + return srslte_predecoding_single_multi(y, h[0], x[0], nof_rxant, nof_symbols, scaling, noise_estimate); } else { fprintf(stderr, "Number of ports and layers must be 1 for transmission on single antenna ports (%d, %d)\n", nof_ports, nof_layers); @@ -1460,7 +1461,7 @@ int srslte_predecoding_type_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_ break; case SRSLTE_MIMO_TYPE_TX_DIVERSITY: if (nof_ports == nof_layers) { - return srslte_predecoding_diversity_multi(y, h, x, nof_rxant, nof_ports, nof_symbols); + return srslte_predecoding_diversity_multi(y, h, x, nof_rxant, nof_ports, nof_symbols, scaling); } else { fprintf(stderr, "Error number of layers must equal number of ports in transmit diversity\n"); @@ -1469,7 +1470,7 @@ int srslte_predecoding_type_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_ break; case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX: return srslte_predecoding_multiplex(y, h, x, nof_rxant, nof_ports, nof_layers, codebook_idx, nof_symbols, - noise_estimate); + scaling, noise_estimate); default: return SRSLTE_ERROR; } @@ -1487,12 +1488,16 @@ int srslte_predecoding_type_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_ * **************************************************/ -int srslte_precoding_single(cf_t *x, cf_t *y, int nof_symbols) { - memcpy(y, x, nof_symbols * sizeof(cf_t)); +int srslte_precoding_single(cf_t *x, cf_t *y, int nof_symbols, float scaling) { + if (scaling == 1.0f) { + memcpy(y, x, nof_symbols * sizeof(cf_t)); + } else { + srslte_vec_sc_prod_cfc(x, scaling, y, (uint32_t) nof_symbols); + } return nof_symbols; } int srslte_precoding_diversity(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PORTS], int nof_ports, - int nof_symbols) { + int nof_symbols, float scaling) { int i; if (nof_ports == 2) { for (i = 0; i < nof_symbols; i++) { @@ -1502,32 +1507,34 @@ int srslte_precoding_diversity(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PO y[1][2 * i + 1] = conjf(x[0][i]); } // normalize - srslte_vec_sc_prod_cfc(y[0], 1.0/sqrtf(2), y[0], 2*nof_symbols); - srslte_vec_sc_prod_cfc(y[1], 1.0/sqrtf(2), y[1], 2*nof_symbols); + srslte_vec_sc_prod_cfc(y[0], scaling/sqrtf(2), y[0], 2*nof_symbols); + srslte_vec_sc_prod_cfc(y[1], scaling/sqrtf(2), y[1], 2*nof_symbols); return 2 * i; } else if (nof_ports == 4) { + scaling /= sqrtf(2); + //int m_ap = (nof_symbols%4)?(nof_symbols*4-2):nof_symbols*4; int m_ap = 4 * nof_symbols; for (i = 0; i < m_ap / 4; i++) { - y[0][4 * i] = x[0][i] / sqrtf(2); + y[0][4 * i] = x[0][i] * scaling; y[1][4 * i] = 0; - y[2][4 * i] = -conjf(x[1][i]) / sqrtf(2); + y[2][4 * i] = -conjf(x[1][i]) * scaling; y[3][4 * i] = 0; - y[0][4 * i + 1] = x[1][i] / sqrtf(2); + y[0][4 * i + 1] = x[1][i] * scaling; y[1][4 * i + 1] = 0; - y[2][4 * i + 1] = conjf(x[0][i]) / sqrtf(2); + y[2][4 * i + 1] = conjf(x[0][i]) * scaling; y[3][4 * i + 1] = 0; y[0][4 * i + 2] = 0; - y[1][4 * i + 2] = x[2][i] / sqrtf(2); + y[1][4 * i + 2] = x[2][i] * scaling; y[2][4 * i + 2] = 0; - y[3][4 * i + 2] = -conjf(x[3][i]) / sqrtf(2); + y[3][4 * i + 2] = -conjf(x[3][i]) * scaling; y[0][4 * i + 3] = 0; - y[1][4 * i + 3] = x[3][i] / sqrtf(2); + y[1][4 * i + 3] = x[3][i] * scaling; y[2][4 * i + 3] = 0; - y[3][4 * i + 3] = conjf(x[2][i]) / sqrtf(2); + y[3][4 * i + 3] = conjf(x[2][i]) * scaling; } return 4 * i; } else { @@ -1538,9 +1545,9 @@ int srslte_precoding_diversity(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PO #ifdef LV_HAVE_AVX -int srslte_precoding_cdd_2x2_avx(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PORTS], int nof_symbols) +int srslte_precoding_cdd_2x2_avx(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PORTS], int nof_symbols, float scaling) { - __m256 norm_avx = _mm256_set1_ps(0.5f); + __m256 norm_avx = _mm256_set1_ps(0.5f * scaling); for (int i = 0; i < nof_symbols - 3; i += 4) { __m256 x0 = _mm256_load_ps((float*) &x[0][i]); __m256 x1 = _mm256_load_ps((float*) &x[1][i]); @@ -1563,9 +1570,9 @@ int srslte_precoding_cdd_2x2_avx(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_ #ifdef LV_HAVE_SSE -int srslte_precoding_cdd_2x2_sse(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PORTS], int nof_symbols) +int srslte_precoding_cdd_2x2_sse(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PORTS], int nof_symbols, float scaling) { - __m128 norm_sse = _mm_set1_ps(0.5f); + __m128 norm_sse = _mm_set1_ps(0.5f * scaling); for (int i = 0; i < nof_symbols - 1; i += 2) { __m128 x0 = _mm_load_ps((float*) &x[0][i]); __m128 x1 = _mm_load_ps((float*) &x[1][i]); @@ -1587,19 +1594,20 @@ int srslte_precoding_cdd_2x2_sse(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_ #endif /* LV_HAVE_SSE */ -int srslte_precoding_cdd_2x2_gen(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PORTS], int nof_symbols) +int srslte_precoding_cdd_2x2_gen(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PORTS], int nof_symbols, float scaling) { + scaling /= 2.0f; for (int i = 0; i < nof_symbols; i++) { - y[0][i] = (x[0][i]+x[1][i])/2.0f; - y[1][i] = (x[0][i]-x[1][i])/2.0f; + y[0][i] = (x[0][i]+x[1][i]) * scaling; + y[1][i] = (x[0][i]-x[1][i]) * scaling; i++; - y[0][i] = (x[0][i]+x[1][i])/2.0f; - y[1][i] = (-x[0][i]+x[1][i])/2.0f; + y[0][i] = (x[0][i]+x[1][i]) * scaling; + y[1][i] = (-x[0][i]+x[1][i]) * scaling; } return 2 * nof_symbols; } -int srslte_precoding_cdd(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PORTS], int nof_layers, int nof_ports, int nof_symbols) +int srslte_precoding_cdd(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PORTS], int nof_layers, int nof_ports, int nof_symbols, float scaling) { if (nof_ports == 2) { if (nof_layers != 2) { @@ -1607,12 +1615,12 @@ int srslte_precoding_cdd(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PORTS], return -1; } #ifdef LV_HAVE_AVX - return srslte_precoding_cdd_2x2_avx(x, y, nof_symbols); + return srslte_precoding_cdd_2x2_avx(x, y, nof_symbols, scaling); #else #ifdef LV_HAVE_SSE - return srslte_precoding_cdd_2x2_sse(x, y, nof_symbols); + return srslte_precoding_cdd_2x2_sse(x, y, nof_symbols, scaling); #else - return srslte_precoding_cdd_2x2_gen(x, y, nof_symbols); + return srslte_precoding_cdd_2x2_gen(x, y, nof_symbols, scaling); #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX */ } else if (nof_ports == 4) { @@ -1625,27 +1633,28 @@ int srslte_precoding_cdd(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PORTS], } int srslte_precoding_multiplex(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PORTS], int nof_layers, int nof_ports, - int codebook_idx, uint32_t nof_symbols) + int codebook_idx, uint32_t nof_symbols, float scaling) { int i = 0; if (nof_ports == 2) { if (nof_layers == 1) { + scaling /= sqrtf(2.0f); switch(codebook_idx) { case 0: - srslte_vec_sc_prod_cfc(x[0], 1.0f/sqrtf(2.0f), y[0], nof_symbols); - srslte_vec_sc_prod_cfc(x[0], 1.0f/sqrtf(2.0f), y[1], nof_symbols); + srslte_vec_sc_prod_cfc(x[0], scaling, y[0], nof_symbols); + srslte_vec_sc_prod_cfc(x[0], scaling, y[1], nof_symbols); break; case 1: - srslte_vec_sc_prod_cfc(x[0], 1.0f/sqrtf(2.0f), y[0], nof_symbols); - srslte_vec_sc_prod_cfc(x[0], -1.0f/sqrtf(2.0f), y[1], nof_symbols); + srslte_vec_sc_prod_cfc(x[0], scaling, y[0], nof_symbols); + srslte_vec_sc_prod_cfc(x[0], -scaling, y[1], nof_symbols); break; case 2: - srslte_vec_sc_prod_cfc(x[0], 1.0f/sqrtf(2.0f), y[0], nof_symbols); - srslte_vec_sc_prod_ccc(x[0], _Complex_I/sqrtf(2.0f), y[1], nof_symbols); + srslte_vec_sc_prod_cfc(x[0], scaling, y[0], nof_symbols); + srslte_vec_sc_prod_ccc(x[0], _Complex_I * scaling, y[1], nof_symbols); break; case 3: - srslte_vec_sc_prod_cfc(x[0], 1.0f/sqrtf(2.0f), y[0], nof_symbols); - srslte_vec_sc_prod_ccc(x[0], -_Complex_I/sqrtf(2.0f), y[1], nof_symbols); + srslte_vec_sc_prod_cfc(x[0], scaling, y[0], nof_symbols); + srslte_vec_sc_prod_ccc(x[0], -_Complex_I * scaling, y[1], nof_symbols); break; default: fprintf(stderr, "Invalid multiplex combination: codebook_idx=%d, nof_layers=%d, nof_ports=%d\n", @@ -1655,49 +1664,52 @@ int srslte_precoding_multiplex(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PO } else if (nof_layers == 2) { switch(codebook_idx) { case 0: - srslte_vec_sc_prod_cfc(x[0], 1.0f/sqrtf(2.0f), y[0], nof_symbols); - srslte_vec_sc_prod_cfc(x[1], 1.0f/sqrtf(2.0f), y[1], nof_symbols); + scaling /= sqrtf(2.0f); + srslte_vec_sc_prod_cfc(x[0], scaling, y[0], nof_symbols); + srslte_vec_sc_prod_cfc(x[1], scaling, y[1], nof_symbols); break; case 1: + scaling /= 2.0f; #ifdef LV_HAVE_AVX for (; i < nof_symbols - 3; i += 4) { - __m256 x0 = _mm256_load_ps((float*)&x[0][i]); - __m256 x1 = _mm256_load_ps((float*)&x[1][i]); + __m256 x0 = _mm256_load_ps((float *) &x[0][i]); + __m256 x1 = _mm256_load_ps((float *) &x[1][i]); - __m256 y0 = _mm256_mul_ps(_mm256_set1_ps(0.5f), _mm256_add_ps(x0, x1)); - __m256 y1 = _mm256_mul_ps(_mm256_set1_ps(0.5f), _mm256_sub_ps(x0, x1)); + __m256 y0 = _mm256_mul_ps(_mm256_set1_ps(scaling), _mm256_add_ps(x0, x1)); + __m256 y1 = _mm256_mul_ps(_mm256_set1_ps(scaling), _mm256_sub_ps(x0, x1)); - _mm256_store_ps((float*)&y[0][i], y0); - _mm256_store_ps((float*)&y[1][i], y1); + _mm256_store_ps((float *) &y[0][i], y0); + _mm256_store_ps((float *) &y[1][i], y1); } #endif /* LV_HAVE_AVX */ #ifdef LV_HAVE_SSE for (; i < nof_symbols - 1; i += 2) { - __m128 x0 = _mm_load_ps((float*)&x[0][i]); - __m128 x1 = _mm_load_ps((float*)&x[1][i]); + __m128 x0 = _mm_load_ps((float *) &x[0][i]); + __m128 x1 = _mm_load_ps((float *) &x[1][i]); - __m128 y0 = _mm_mul_ps(_mm_set1_ps(0.5f), _mm_add_ps(x0, x1)); - __m128 y1 = _mm_mul_ps(_mm_set1_ps(0.5f), _mm_sub_ps(x0, x1)); + __m128 y0 = _mm_mul_ps(_mm_set1_ps(scaling), _mm_add_ps(x0, x1)); + __m128 y1 = _mm_mul_ps(_mm_set1_ps(scaling), _mm_sub_ps(x0, x1)); - _mm_store_ps((float*)&y[0][i], y0); - _mm_store_ps((float*)&y[1][i], y1); + _mm_store_ps((float *) &y[0][i], y0); + _mm_store_ps((float *) &y[1][i], y1); } #endif /* LV_HAVE_SSE */ for (; i < nof_symbols; i++) { - y[0][i] = 0.5f*x[0][i] + 0.5f*x[1][i]; - y[1][i] = 0.5f*x[0][i] - 0.5f*x[1][i]; + y[0][i] = (x[0][i] + x[1][i]) * scaling; + y[1][i] = (x[0][i] - x[1][i]) * scaling; } break; case 2: + scaling /= 2.0f; #ifdef LV_HAVE_AVX for (; i < nof_symbols - 3; i += 4) { __m256 x0 = _mm256_load_ps((float*)&x[0][i]); __m256 x1 = _mm256_load_ps((float*)&x[1][i]); - __m256 y0 = _mm256_mul_ps(_mm256_set1_ps(0.5f), _mm256_add_ps(x0, x1)); - __m256 y1 = _mm256_mul_ps(_mm256_set1_ps(0.5f), _MM256_MULJ_PS(_mm256_sub_ps(x0, x1))); + __m256 y0 = _mm256_mul_ps(_mm256_set1_ps(scaling), _mm256_add_ps(x0, x1)); + __m256 y1 = _mm256_mul_ps(_mm256_set1_ps(scaling), _MM256_MULJ_PS(_mm256_sub_ps(x0, x1))); _mm256_store_ps((float*)&y[0][i], y0); _mm256_store_ps((float*)&y[1][i], y1); @@ -1709,8 +1721,8 @@ int srslte_precoding_multiplex(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PO __m128 x0 = _mm_load_ps((float*)&x[0][i]); __m128 x1 = _mm_load_ps((float*)&x[1][i]); - __m128 y0 = _mm_mul_ps(_mm_set1_ps(0.5f), _mm_add_ps(x0, x1)); - __m128 y1 = _mm_mul_ps(_mm_set1_ps(0.5f), _MM_MULJ_PS(_mm_sub_ps(x0, x1))); + __m128 y0 = _mm_mul_ps(_mm_set1_ps(scaling), _mm_add_ps(x0, x1)); + __m128 y1 = _mm_mul_ps(_mm_set1_ps(scaling), _MM_MULJ_PS(_mm_sub_ps(x0, x1))); _mm_store_ps((float*)&y[0][i], y0); _mm_store_ps((float*)&y[1][i], y1); @@ -1718,8 +1730,8 @@ int srslte_precoding_multiplex(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PO #endif /* LV_HAVE_SSE */ for (; i < nof_symbols; i++) { - y[0][i] = 0.5f*x[0][i] + 0.5f*x[1][i]; - y[1][i] = 0.5f*_Complex_I*x[0][i] - 0.5f*_Complex_I*x[1][i]; + y[0][i] = (x[0][i] + x[1][i])*scaling; + y[1][i] = (_Complex_I*x[0][i] - _Complex_I*x[1][i])*scaling; } break; case 3: @@ -1739,7 +1751,7 @@ int srslte_precoding_multiplex(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PO /* 36.211 v10.3.0 Section 6.3.4 */ int srslte_precoding_type(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PORTS], int nof_layers, - int nof_ports, int codebook_idx, int nof_symbols, srslte_mimo_type_t type) { + int nof_ports, int codebook_idx, int nof_symbols, float scaling, srslte_mimo_type_t type) { if (nof_ports > SRSLTE_MAX_PORTS) { fprintf(stderr, "Maximum number of ports is %d (nof_ports=%d)\n", SRSLTE_MAX_PORTS, @@ -1754,10 +1766,10 @@ int srslte_precoding_type(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PORTS], switch (type) { case SRSLTE_MIMO_TYPE_CDD: - return srslte_precoding_cdd(x, y, nof_layers, nof_ports, nof_symbols); + return srslte_precoding_cdd(x, y, nof_layers, nof_ports, nof_symbols, scaling); case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA: if (nof_ports == 1 && nof_layers == 1) { - return srslte_precoding_single(x[0], y[0], nof_symbols); + return srslte_precoding_single(x[0], y[0], nof_symbols, scaling); } else { fprintf(stderr, "Number of ports and layers must be 1 for transmission on single antenna ports\n"); @@ -1766,14 +1778,14 @@ int srslte_precoding_type(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PORTS], break; case SRSLTE_MIMO_TYPE_TX_DIVERSITY: if (nof_ports == nof_layers) { - return srslte_precoding_diversity(x, y, nof_ports, nof_symbols); + return srslte_precoding_diversity(x, y, nof_ports, nof_symbols, scaling); } else { fprintf(stderr, "Error number of layers must equal number of ports in transmit diversity\n"); return -1; } case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX: - return srslte_precoding_multiplex(x, y, nof_layers, nof_ports, codebook_idx, nof_symbols); + return srslte_precoding_multiplex(x, y, nof_layers, nof_ports, codebook_idx, (uint32_t) nof_symbols, scaling); default: return SRSLTE_ERROR; } diff --git a/lib/src/phy/mimo/test/precoder_test.c b/lib/src/phy/mimo/test/precoder_test.c index 1bbd9e3c0..589e3d51c 100644 --- a/lib/src/phy/mimo/test/precoder_test.c +++ b/lib/src/phy/mimo/test/precoder_test.c @@ -44,14 +44,16 @@ int nof_layers = 1, nof_tx_ports = 1, nof_rx_ports = 1, nof_re = 1; char *mimo_type_name = NULL; char decoder_type_name [16] = "zf"; float snr_db = 100.0f; +float scaling = 0.1f; void usage(char *prog) { printf( "Usage: %s -m [single|diversity|multiplex|cdd] -l [nof_layers] -p [nof_tx_ports]\n" - " -r [nof_rx_ports]\n", prog); + " -r [nof_rx_ports] -g [scaling]\n", prog); printf("\t-n num_symbols [Default %d]\n", nof_symbols); printf("\t-c codebook_idx [Default %d]\n", codebook_idx); printf("\t-s SNR in dB [Default %.1fdB]*\n", snr_db); + printf("\t-g Scaling [Default %.1f]*\n", scaling); printf("\t-d decoder type [zf|mmse] [Default %s]\n", decoder_type_name); printf("\n"); printf("* Performance test example:\n\t for snr in {0..20..1}; do ./precoding_test -m single -s $snr; done; \n\n", decoder_type_name); @@ -59,7 +61,7 @@ void usage(char *prog) { void parse_args(int argc, char **argv) { int opt; - while ((opt = getopt(argc, argv, "mplnrcds")) != -1) { + while ((opt = getopt(argc, argv, "mplnrcdsg")) != -1) { switch (opt) { case 'n': nof_symbols = atoi(argv[optind]); @@ -85,6 +87,9 @@ void parse_args(int argc, char **argv) { case 's': snr_db = (float) atof(argv[optind]); break; + case 'g': + scaling = (float) atof(argv[optind]); + break; default: usage(argv[0]); exit(-1); @@ -149,7 +154,7 @@ void populate_channel(srslte_mimo_type_t type, cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_ static void awgn(cf_t *y[SRSLTE_MAX_PORTS], uint32_t n, float snr) { int i; - float std_dev = powf(10, - (snr + 3.0f) / 20.0f); + float std_dev = powf(10, - (snr + 3.0f) / 20.0f) * scaling; for (i = 0; i < nof_rx_ports; i++) { srslte_ch_awgn_c(y[i], y[i], std_dev, n); @@ -250,7 +255,7 @@ int main(int argc, char **argv) { } /* Execute Precoding (Tx) */ - if (srslte_precoding_type(x, y, nof_layers, nof_tx_ports, codebook_idx, nof_symbols, type) < 0) { + if (srslte_precoding_type(x, y, nof_layers, nof_tx_ports, codebook_idx, nof_symbols, scaling, type) < 0) { fprintf(stderr, "Error layer mapper encoder\n"); exit(-1); } @@ -285,8 +290,8 @@ int main(int argc, char **argv) { /* predecoding / equalization */ struct timeval t[3]; gettimeofday(&t[1], NULL); - srslte_predecoding_type_multi(r, h, xr, nof_rx_ports, nof_tx_ports, nof_layers, - codebook_idx, nof_re, type, powf(10, -snr_db/10)); + srslte_predecoding_type(r, h, xr, nof_rx_ports, nof_tx_ports, nof_layers, + codebook_idx, nof_re, type, scaling, powf(10, -snr_db / 10)); gettimeofday(&t[2], NULL); get_time_interval(t); diff --git a/lib/src/phy/phch/pbch.c b/lib/src/phy/phch/pbch.c index 2eaa20501..c72b12c60 100644 --- a/lib/src/phy/phch/pbch.c +++ b/lib/src/phy/phch/pbch.c @@ -497,10 +497,10 @@ int srslte_pbch_decode(srslte_pbch_t *q, cf_t *slot1_symbols, cf_t *ce_slot1[SRS /* in control channels, only diversity is supported */ if (nant == 1) { /* no need for layer demapping */ - srslte_predecoding_single(q->symbols[0], q->ce[0], q->d, q->nof_symbols, noise_estimate); + srslte_predecoding_single(q->symbols[0], q->ce[0], q->d, q->nof_symbols, 1.0f, noise_estimate); } else { srslte_predecoding_diversity(q->symbols[0], q->ce, x, nant, - q->nof_symbols); + q->nof_symbols, 1.0f); srslte_layerdemap_diversity(x, q->d, nant, q->nof_symbols / nant); } @@ -591,7 +591,7 @@ int srslte_pbch_encode(srslte_pbch_t *q, uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_ if (q->cell.nof_ports > 1) { srslte_layermap_diversity(q->d, x, q->cell.nof_ports, q->nof_symbols); srslte_precoding_diversity(x, q->symbols, q->cell.nof_ports, - q->nof_symbols / q->cell.nof_ports); + q->nof_symbols / q->cell.nof_ports, 1.0f); } else { memcpy(q->symbols[0], q->d, q->nof_symbols * sizeof(cf_t)); } diff --git a/lib/src/phy/phch/pcfich.c b/lib/src/phy/phch/pcfich.c index d960504fe..7269000a8 100644 --- a/lib/src/phy/phch/pcfich.c +++ b/lib/src/phy/phch/pcfich.c @@ -219,9 +219,9 @@ int srslte_pcfich_decode_multi(srslte_pcfich_t *q, cf_t *sf_symbols[SRSLTE_MAX_P /* in control channels, only diversity is supported */ if (q->cell.nof_ports == 1) { /* no need for layer demapping */ - srslte_predecoding_single_multi(q_symbols, q_ce[0], q->d, q->nof_rx_antennas, q->nof_symbols, noise_estimate); + srslte_predecoding_single_multi(q_symbols, q_ce[0], q->d, q->nof_rx_antennas, q->nof_symbols, 1.0f, noise_estimate); } else { - srslte_predecoding_diversity_multi(q_symbols, q_ce, x, q->nof_rx_antennas, q->cell.nof_ports, q->nof_symbols); + srslte_predecoding_diversity_multi(q_symbols, q_ce, x, q->nof_rx_antennas, q->cell.nof_ports, q->nof_symbols, 1.0f); srslte_layerdemap_diversity(x, q->d, q->cell.nof_ports, q->nof_symbols / q->cell.nof_ports); } @@ -278,7 +278,7 @@ int srslte_pcfich_encode(srslte_pcfich_t *q, uint32_t cfi, cf_t *slot_symbols[SR /* layer mapping & precoding */ if (q->cell.nof_ports > 1) { srslte_layermap_diversity(q->d, x, q->cell.nof_ports, q->nof_symbols); - srslte_precoding_diversity(x, q_symbols, q->cell.nof_ports, q->nof_symbols / q->cell.nof_ports); + srslte_precoding_diversity(x, q_symbols, q->cell.nof_ports, q->nof_symbols / q->cell.nof_ports, 1.0f); } else { memcpy(q->symbols[0], q->d, q->nof_symbols * sizeof(cf_t)); } diff --git a/lib/src/phy/phch/pdcch.c b/lib/src/phy/phch/pdcch.c index 215324e6b..58d5bf6db 100644 --- a/lib/src/phy/phch/pdcch.c +++ b/lib/src/phy/phch/pdcch.c @@ -485,9 +485,9 @@ int srslte_pdcch_extract_llr_multi(srslte_pdcch_t *q, cf_t *sf_symbols[SRSLTE_MA /* in control channels, only diversity is supported */ if (q->cell.nof_ports == 1) { /* no need for layer demapping */ - srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, q->nof_rx_antennas, nof_symbols, noise_estimate/2); + srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, q->nof_rx_antennas, nof_symbols, 1.0f, noise_estimate/2); } else { - srslte_predecoding_diversity_multi(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, nof_symbols); + srslte_predecoding_diversity_multi(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, nof_symbols, 1.0f); srslte_layerdemap_diversity(x, q->d, q->cell.nof_ports, nof_symbols / q->cell.nof_ports); } @@ -618,7 +618,7 @@ int srslte_pdcch_encode(srslte_pdcch_t *q, srslte_dci_msg_t *msg, srslte_dci_loc /* layer mapping & precoding */ if (q->cell.nof_ports > 1) { srslte_layermap_diversity(q->d, x, q->cell.nof_ports, nof_symbols); - srslte_precoding_diversity(x, q->symbols, q->cell.nof_ports, nof_symbols / q->cell.nof_ports); + srslte_precoding_diversity(x, q->symbols, q->cell.nof_ports, nof_symbols / q->cell.nof_ports, 1.0f); } else { memcpy(q->symbols[0], q->d, nof_symbols * sizeof(cf_t)); } diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index b984adee3..3fb57fbbd 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -386,6 +386,12 @@ int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti) { return SRSLTE_SUCCESS; } +void srslte_pdsch_set_power_allocation(srslte_pdsch_t *q, float rho_a) { + if (q) { + q->rho_a = rho_a; + } +} + void srslte_pdsch_free_rnti(srslte_pdsch_t* q, uint16_t rnti) { uint32_t rnti_idx = q->is_ue?0:rnti; @@ -680,9 +686,14 @@ int srslte_pdsch_decode(srslte_pdsch_t *q, memset(&x[cfg->nof_layers], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - cfg->nof_layers)); } + float pdsch_scaling = 1.0f; + if (q->rho_a != 0.0f) { + pdsch_scaling = 1/q->rho_a; + } + // Pre-decoder - 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) { + if (srslte_predecoding_type(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, pdsch_scaling, noise_estimate)<0) { return -1; } @@ -822,7 +833,7 @@ int srslte_pdsch_encode(srslte_pdsch_t *q, /* Precode */ srslte_precoding_type(x, q->symbols, cfg->nof_layers, q->cell.nof_ports, cfg->codebook_idx, - nof_symbols, cfg->mimo_type); + nof_symbols, 1.0f, cfg->mimo_type); } else { memcpy(q->symbols[0], q->d[0], cfg->nbits[0].nof_re * sizeof(cf_t)); } diff --git a/lib/src/phy/phch/phich.c b/lib/src/phy/phch/phich.c index 14a0d5426..37b8e1b7a 100644 --- a/lib/src/phy/phch/phich.c +++ b/lib/src/phy/phch/phich.c @@ -239,9 +239,9 @@ int srslte_phich_decode(srslte_phich_t *q, cf_t *sf_symbols[SRSLTE_MAX_PORTS], /* in control channels, only diversity is supported */ if (q->cell.nof_ports == 1) { /* no need for layer demapping */ - srslte_predecoding_single_multi(q_sf_symbols, q_ce[0], q->d0, q->nof_rx_antennas, SRSLTE_PHICH_MAX_NSYMB, noise_estimate); + srslte_predecoding_single_multi(q_sf_symbols, q_ce[0], q->d0, q->nof_rx_antennas, SRSLTE_PHICH_MAX_NSYMB, 1.0f, noise_estimate); } else { - srslte_predecoding_diversity_multi(q_sf_symbols, q_ce, x, q->nof_rx_antennas, q->cell.nof_ports, SRSLTE_PHICH_MAX_NSYMB); + srslte_predecoding_diversity_multi(q_sf_symbols, q_ce, x, q->nof_rx_antennas, q->cell.nof_ports, SRSLTE_PHICH_MAX_NSYMB, 1.0f); srslte_layerdemap_diversity(x, q->d0, q->cell.nof_ports, SRSLTE_PHICH_MAX_NSYMB / q->cell.nof_ports); } DEBUG("Recv!!: \n", 0); @@ -405,7 +405,7 @@ int srslte_phich_encode(srslte_phich_t *q, uint8_t ack, uint32_t ngroup, uint32_ if (q->cell.nof_ports > 1) { srslte_layermap_diversity(q->d0, x, q->cell.nof_ports, SRSLTE_PHICH_MAX_NSYMB); srslte_precoding_diversity(x, symbols_precoding, q->cell.nof_ports, - SRSLTE_PHICH_MAX_NSYMB / q->cell.nof_ports); + SRSLTE_PHICH_MAX_NSYMB / q->cell.nof_ports, 1.0f); /**FIXME: According to 6.9.2, Precoding for 4 tx ports is different! */ } else { memcpy(q->sf_symbols[0], q->d0, SRSLTE_PHICH_MAX_NSYMB * sizeof(cf_t)); diff --git a/lib/src/phy/phch/pmch.c b/lib/src/phy/phch/pmch.c index aa7fd77b1..c1c322f34 100644 --- a/lib/src/phy/phch/pmch.c +++ b/lib/src/phy/phch/pmch.c @@ -378,7 +378,7 @@ int srslte_pmch_decode_multi(srslte_pmch_t *q, } // No tx diversity in MBSFN - srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, q->nof_rx_antennas, cfg->nbits[0].nof_re, noise_estimate); + srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, q->nof_rx_antennas, cfg->nbits[0].nof_re, 1.0f, noise_estimate); if (SRSLTE_VERBOSE_ISDEBUG()) { DEBUG("SAVED FILE subframe.dat: received subframe symbols\n"); diff --git a/lib/src/phy/phch/pucch.c b/lib/src/phy/phch/pucch.c index 498d34f3a..f9c6bebc1 100644 --- a/lib/src/phy/phch/pucch.c +++ b/lib/src/phy/phch/pucch.c @@ -787,7 +787,7 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format, } // Equalization - srslte_predecoding_single(q->z_tmp, q->ce, q->z, nof_re, noise_estimate); + srslte_predecoding_single(q->z_tmp, q->ce, q->z, nof_re, 1.0f, noise_estimate); // Perform ML-decoding float corr=0, corr_max=-1e9; diff --git a/lib/src/phy/phch/pusch.c b/lib/src/phy/phch/pusch.c index ba1195507..a8c6064fc 100644 --- a/lib/src/phy/phch/pusch.c +++ b/lib/src/phy/phch/pusch.c @@ -596,7 +596,7 @@ int srslte_pusch_decode(srslte_pusch_t *q, } // Equalization - srslte_predecoding_single(q->d, q->ce, q->z, cfg->nbits.nof_re, noise_estimate); + srslte_predecoding_single(q->d, q->ce, q->z, cfg->nbits.nof_re, 1.0f, noise_estimate); // DFT predecoding srslte_dft_precoding(&q->dft_precoding, q->z, q->d, cfg->grant.L_prb, cfg->nbits.nof_symb); diff --git a/lib/src/phy/phch/test/pdsch_test.c b/lib/src/phy/phch/test/pdsch_test.c index b97e8b299..0b18d8b10 100644 --- a/lib/src/phy/phch/test/pdsch_test.c +++ b/lib/src/phy/phch/test/pdsch_test.c @@ -53,7 +53,7 @@ srslte_cell_t cell = { char mimo_type_str [32] = "single"; srslte_mimo_type_t mimo_type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA; -uint32_t cfi = 2; +uint32_t cfi = 1; uint32_t mcs[SRSLTE_MAX_CODEWORDS] = {0, 0}; uint32_t subframe = 1; int rv_idx[SRSLTE_MAX_CODEWORDS] = {0, 1}; @@ -496,7 +496,9 @@ int main(int argc, char **argv) { if (grant.tb_en[tb]) { for (int byte = 0; byte < grant.mcs[tb].tbs / 8; byte++) { if (data_tx[tb][byte] != data_rx[tb][byte]) { - ERROR("Found BYTE error in TB %d (%02X != %02X), quiting...", tb, data_tx[tb][byte], data_rx[tb][byte]); + ERROR("Found BYTE (%d) error in TB %d (%02X != %02X), quiting...", byte, tb, data_tx[tb][byte], data_rx[tb][byte]); + printf("Tx: "); srslte_vec_fprint_byte(stdout, data_tx[tb], grant.mcs[tb].tbs / 8); + printf("Rx: "); srslte_vec_fprint_byte(stdout, data_rx[tb], grant.mcs[tb].tbs / 8); ret = SRSLTE_ERROR; goto quit; } diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index 1c3b79440..137756da1 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -308,7 +308,12 @@ void srslte_ue_dl_set_non_mbsfn_region(srslte_ue_dl_t *q, srslte_ofdm_set_non_mbsfn_region(&q->fft_mbsfn, non_mbsfn_region_length); } - +void srslte_ue_dl_set_power_alloc (srslte_ue_dl_t *q, float rho_a, float rho_b) { + if (q) { + srslte_pdsch_set_power_allocation(&q->pdsch, rho_a); + q->rho_b = rho_b; + } +} void srslte_ue_dl_reset(srslte_ue_dl_t *q) { for(int i = 0; i < SRSLTE_MAX_CODEWORDS; i++){ From 4ecd73c984fa2887f41b10a11849639eee76d30e Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 21 Nov 2017 11:51:18 +0100 Subject: [PATCH 148/242] Added power allocation p_a in UE --- lib/include/srslte/asn1/liblte_rrc.h | 2 +- lib/src/phy/phch/pdsch.c | 2 +- srsue/src/phy/phch_worker.cc | 8 ++++++++ srsue/src/upper/rrc.cc | 2 ++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/include/srslte/asn1/liblte_rrc.h b/lib/include/srslte/asn1/liblte_rrc.h index c5c3b60e2..d508f3697 100644 --- a/lib/include/srslte/asn1/liblte_rrc.h +++ b/lib/include/srslte/asn1/liblte_rrc.h @@ -3926,7 +3926,7 @@ typedef enum{ }LIBLTE_RRC_PDSCH_CONFIG_P_A_ENUM; static const char liblte_rrc_pdsch_config_p_a_text[LIBLTE_RRC_PDSCH_CONFIG_P_A_N_ITEMS][20] = { "-6", "-4.77", "-3", "-1.77", "0", "1", "2", "3"}; -static const double liblte_rrc_pdsch_config_p_a_num[LIBLTE_RRC_PDSCH_CONFIG_P_A_N_ITEMS] = {-6, -4.77, -3, -1.77, 0, 1, 2, 3}; +static const float liblte_rrc_pdsch_config_p_a_num[LIBLTE_RRC_PDSCH_CONFIG_P_A_N_ITEMS] = {-6, -4.77f, -3, -1.77f, 0, 1, 2, 3}; // Structs // PDSCH Config Common struct defined above // Functions diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index 3fb57fbbd..f9899ef99 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -688,7 +688,7 @@ int srslte_pdsch_decode(srslte_pdsch_t *q, float pdsch_scaling = 1.0f; if (q->rho_a != 0.0f) { - pdsch_scaling = 1/q->rho_a; + pdsch_scaling = q->rho_a; } // Pre-decoder diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 97fad0720..529dd92f2 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -601,6 +601,14 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL valid_config = false; } + /* Set power allocation */ + float rho_a = 1.0f, rho_b = 1.0f; + if (phy->config->dedicated.pdsch_cnfg_ded < LIBLTE_RRC_PDSCH_CONFIG_P_A_N_ITEMS) { + float rho_a_db = liblte_rrc_pdsch_config_p_a_num[(int) phy->config->dedicated.pdsch_cnfg_ded]; + rho_a = powf(10.0f, rho_a_db / 20.0f) * sqrtf(2.0f); + } + srslte_ue_dl_set_power_alloc(&ue_dl, rho_a, rho_b); + Debug("DL Buffer TTI %d: Decoding PDSCH\n", tti); /* Setup PDSCH configuration for this CFI, SFIDX and RVIDX */ diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 7b4bef710..0127514f7 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -1472,8 +1472,10 @@ void rrc::apply_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT } if (phy_cnfg->pdsch_cnfg_ded_present) { current_cfg->pdsch_cnfg_ded = phy_cnfg->pdsch_cnfg_ded; + rrc_log->info("Set PDSCH-Config=%s (present)\n", liblte_rrc_pdsch_config_p_a_text[(int) current_cfg->pdsch_cnfg_ded]); } else if (apply_defaults) { current_cfg->pdsch_cnfg_ded = LIBLTE_RRC_PDSCH_CONFIG_P_A_DB_0; + rrc_log->info("Set PDSCH-Config=%s (default)\n", liblte_rrc_pdsch_config_p_a_text[(int) current_cfg->pdsch_cnfg_ded]); } if (phy_cnfg->cqi_report_cnfg_present) { From 58aac96a6e0597615fab0c18db56b1ee383d8a43 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 21 Nov 2017 16:11:08 +0100 Subject: [PATCH 149/242] Added Power Allocation from HL in UE side --- lib/include/srslte/phy/phch/pdsch_cfg.h | 7 +++++++ lib/src/phy/ue/ue_dl.c | 28 ++++++++++++++++++++++++- srsue/src/phy/phch_worker.cc | 9 ++++++-- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/lib/include/srslte/phy/phch/pdsch_cfg.h b/lib/include/srslte/phy/phch/pdsch_cfg.h index 63b3fefcc..569d1ef7e 100644 --- a/lib/include/srslte/phy/phch/pdsch_cfg.h +++ b/lib/include/srslte/phy/phch/pdsch_cfg.h @@ -39,6 +39,13 @@ #include "srslte/phy/fec/softbuffer.h" #include "srslte/phy/fec/cbsegm.h" +/* 3GPP 36.213 Table 5.2-1: The cell-specific ratio rho_B / rho_A for 1, 2, or 4 cell specific antenna ports */ +static const float pdsch_cfg_cell_specific_ratio_table[2][4] = + { /* One antenna port */ {1.0f / 1.0f, 4.0f / 5.0f, 3.0f / 5.0f, 2.0f / 5.0f}, + /* Two or more antenna port */ {5.0f / 4.0f, 1.0f / 1.0f, 3.0f / 4.0f, 1.0f / 2.0f} + }; + + typedef struct SRSLTE_API { srslte_cbsegm_t cb_segm[SRSLTE_MAX_CODEWORDS]; srslte_ra_dl_grant_t grant; diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index 137756da1..494eecba7 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -308,10 +308,36 @@ void srslte_ue_dl_set_non_mbsfn_region(srslte_ue_dl_t *q, srslte_ofdm_set_non_mbsfn_region(&q->fft_mbsfn, non_mbsfn_region_length); } -void srslte_ue_dl_set_power_alloc (srslte_ue_dl_t *q, float rho_a, float rho_b) { +void srslte_ue_dl_set_power_alloc(srslte_ue_dl_t *q, float rho_a, float rho_b) { if (q) { srslte_pdsch_set_power_allocation(&q->pdsch, rho_a); q->rho_b = rho_b; + + uint32_t nof_symbols_slot = SRSLTE_CP_NSYMB(q->cell.cp); + uint32_t nof_re_symbol = SRSLTE_NRE * q->cell.nof_prb; + + /* Apply rho_b if required according to 3GPP 36.213 Table 5.2-2 */ + if (rho_b != 0.0f && rho_b != 1.0f) { + float scaling = 1.0f / rho_b; + for (uint32_t i = 0; i < q->nof_rx_antennas; i++) { + for (uint32_t j = 0; j < 2; j++) { + cf_t *ptr; + ptr = q->sf_symbols_m[i] + nof_re_symbol * (j * nof_symbols_slot + 0); + srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol); + if (q->cell.cp == SRSLTE_CP_NORM) { + ptr = q->sf_symbols_m[i] + nof_re_symbol * (j * nof_symbols_slot + 4); + srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol); + } else { + ptr = q->sf_symbols_m[i] + nof_re_symbol * (j * nof_symbols_slot + 3); + srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol); + } + if (q->cell.nof_ports == 4) { + ptr = q->sf_symbols_m[i] + nof_re_symbol * (j * nof_symbols_slot + 1); + srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol); + } + } + } + } } } diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 529dd92f2..7b4ec48bd 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -601,11 +601,16 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL valid_config = false; } - /* Set power allocation */ + /* Set power allocation according to 3GPP 36.213 clause 5.2 Downlink power allocation */ float rho_a = 1.0f, rho_b = 1.0f; if (phy->config->dedicated.pdsch_cnfg_ded < LIBLTE_RRC_PDSCH_CONFIG_P_A_N_ITEMS) { float rho_a_db = liblte_rrc_pdsch_config_p_a_num[(int) phy->config->dedicated.pdsch_cnfg_ded]; - rho_a = powf(10.0f, rho_a_db / 20.0f) * sqrtf(2.0f); + rho_a = powf(10.0f, rho_a_db / 20.0f) * ((cell.nof_ports == 1) ? 1.0f : sqrtf(2.0f)); + } + if (phy->config->common.pdsch_cnfg.p_b < 4) { + uint32_t idx0 = (cell.nof_ports == 1) ? 0 : 1; + float cell_specific_ratio = pdsch_cfg_cell_specific_ratio_table[idx0][phy->config->common.pdsch_cnfg.p_b]; + rho_b = sqrtf(cell_specific_ratio); } srslte_ue_dl_set_power_alloc(&ue_dl, rho_a, rho_b); From 91e706d4d195767cfd4073ec1fd0438ca54c84b4 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 22 Nov 2017 12:23:46 +0100 Subject: [PATCH 150/242] Fixes #107: srslte_simd_f_sqrt NaN solved if input is 0 --- lib/include/srslte/phy/utils/simd.h | 7 ++++++- lib/src/phy/utils/test/vector_test.c | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/include/srslte/phy/utils/simd.h b/lib/include/srslte/phy/utils/simd.h index 09e9cff8e..a9a79c486 100644 --- a/lib/include/srslte/phy/utils/simd.h +++ b/lib/include/srslte/phy/utils/simd.h @@ -449,7 +449,12 @@ static inline simd_f_t srslte_simd_f_sqrt(simd_f_t a) { #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); + float32x4_t result = vmulq_f32(a,sqrt_reciprocal); + + /* Detect zeros in NEON 1/sqrtf for preventing NaN */ + float32x4_t zeros = vmovq_n_f32(0); /* Zero vector */ + uint32x4_t mask = vceqq_f32(a, zeros); /* Zero vector mask */ + return vbslq_f32(mask, zeros, result); /* Force zero results and return */ #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ diff --git a/lib/src/phy/utils/test/vector_test.c b/lib/src/phy/utils/test/vector_test.c index 4ebed9862..9058e8813 100644 --- a/lib/src/phy/utils/test/vector_test.c +++ b/lib/src/phy/utils/test/vector_test.c @@ -502,6 +502,7 @@ TEST(srslte_vec_abs_cf, for (int i = 0; i < block_size; i++) { x[i] = RANDOM_CF(); } + x[0] = 0.0f; TEST_CALL(srslte_vec_abs_cf(x, z, block_size)) From 176dae270c28862d60bf3ac142293bf942d0782d Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 22 Nov 2017 16:00:07 +0100 Subject: [PATCH 151/242] Fixes #105. Added backtrace print in 'srsLTE.backtrace.crash' --- lib/examples/cell_measurement.c | 2 + lib/examples/cell_search.c | 2 + lib/examples/pdsch_enodeb.c | 2 + lib/examples/pdsch_ue.c | 2 + lib/include/srslte/phy/utils/debug.h | 2 + lib/src/phy/utils/debug.c | 61 ++++++++++++++++++++++++++++ srsenb/src/main.cc | 2 + srsue/src/main.cc | 3 ++ 8 files changed, 76 insertions(+) diff --git a/lib/examples/cell_measurement.c b/lib/examples/cell_measurement.c index bfb8194df..6415257f0 100644 --- a/lib/examples/cell_measurement.c +++ b/lib/examples/cell_measurement.c @@ -163,6 +163,8 @@ int main(int argc, char **argv) { float cfo = 0; bool acks[SRSLTE_MAX_CODEWORDS] = {false}; + srslte_debug_handle_crash(argc, argv); + if (parse_args(&prog_args, argc, argv)) { exit(-1); } diff --git a/lib/examples/cell_search.c b/lib/examples/cell_search.c index 281e3d102..9ecc79c72 100644 --- a/lib/examples/cell_search.c +++ b/lib/examples/cell_search.c @@ -153,6 +153,8 @@ int main(int argc, char **argv) { uint32_t freq; uint32_t n_found_cells=0; + srslte_debug_handle_crash(argc, argv); + parse_args(argc, argv); printf("Opening RF device...\n"); diff --git a/lib/examples/pdsch_enodeb.c b/lib/examples/pdsch_enodeb.c index 1d807973c..fa5483003 100644 --- a/lib/examples/pdsch_enodeb.c +++ b/lib/examples/pdsch_enodeb.c @@ -701,6 +701,8 @@ int main(int argc, char **argv) { srslte_refsignal_t csr_refs; srslte_refsignal_t mbsfn_refs; + srslte_debug_handle_crash(argc, argv); + #ifdef DISABLE_RF if (argc < 3) { usage(argv[0]); diff --git a/lib/examples/pdsch_ue.c b/lib/examples/pdsch_ue.c index 681b75566..e8d4b1d00 100644 --- a/lib/examples/pdsch_ue.c +++ b/lib/examples/pdsch_ue.c @@ -341,6 +341,8 @@ int main(int argc, char **argv) { int sfn_offset; float cfo = 0; + srslte_debug_handle_crash(argc, argv); + parse_args(&prog_args, argc, argv); for (int i = 0; i< SRSLTE_MAX_CODEWORDS; i++) { diff --git a/lib/include/srslte/phy/utils/debug.h b/lib/include/srslte/phy/utils/debug.h index c88e1a3ce..11c7a23df 100644 --- a/lib/include/srslte/phy/utils/debug.h +++ b/lib/include/srslte/phy/utils/debug.h @@ -70,4 +70,6 @@ SRSLTE_API extern int srslte_verbose; #define ERROR(_fmt, ...) fprintf(stderr, "[ERROR in %s]:" _fmt "\n", __FUNCTION__, ##__VA_ARGS__) #endif /* CMAKE_BUILD_TYPE==Debug */ +void srslte_debug_handle_crash(int argc, char **argv); + #endif // DEBUG_H diff --git a/lib/src/phy/utils/debug.c b/lib/src/phy/utils/debug.c index 423abee6c..7cb9c0f11 100644 --- a/lib/src/phy/utils/debug.c +++ b/lib/src/phy/utils/debug.c @@ -24,7 +24,14 @@ * */ +#include +#include +#include +#include +#include + #include "srslte/phy/utils/debug.h" +#include "srslte/version.h" int srslte_verbose = 0; @@ -37,3 +44,57 @@ void get_time_interval(struct timeval * tdata) { tdata[0].tv_usec += 1000000; } } + +const static char crash_file_name[] = "./srsLTE.backtrace.crash"; +static int bt_argc; +static char **bt_argv; + +static void crash_handler(int sig) { + void *array[128]; + int size; + + /* Get all stack traces */ + size = backtrace(array, 128); + + FILE *f = fopen(crash_file_name, "a"); + if (!f) { + printf("srsLTE crashed... we could not save backtrace in '%s'...\n", crash_file_name); + } else { + char **symbols = backtrace_symbols(array, size); + + time_t lnTime; + struct tm *stTime; + char strdate[32]; + + time(&lnTime); + stTime = localtime(&lnTime); + + strftime(strdate, 32, "%d/%m/%Y %H:%M:%S", stTime); + + fprintf(f, "--- command='"); + for (int i = 0; i < bt_argc; i++) { + fprintf(f, "%s%s", (i == 0) ? "" : " ", bt_argv[i]); + } + fprintf(f, "' version=%s signal=%d date='%s' ---\n", SRSLTE_VERSION_STRING, sig, strdate); + + for (int i = 0; i < size; i++) { + fprintf(f, "\t%s\n", symbols[i]); + } + fprintf(f, "\n"); + + printf("srsLTE crashed... backtrace saved in '%s'...\n", crash_file_name); + fclose(f); + } + printf("--- exiting ---\n"); + exit(1); +} + +void srslte_debug_handle_crash(int argc, char **argv) { + bt_argc = argc; + bt_argv = argv; + + signal(SIGSEGV, crash_handler); + signal(SIGABRT, crash_handler); + signal(SIGILL, crash_handler); + signal(SIGFPE, crash_handler); +} diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 528878388..5cc4f5b1c 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -350,6 +350,8 @@ int main(int argc, char *argv[]) metrics_stdout metrics; enb *enb = enb::get_instance(); + srslte_debug_handle_crash(argc, argv); + cout << "--- Software Radio Systems LTE eNodeB ---" << endl << endl; parse_args(&args, argc, argv); diff --git a/srsue/src/main.cc b/srsue/src/main.cc index cc0b07043..f1edaaf75 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -374,6 +374,9 @@ int main(int argc, char *argv[]) srslte::metrics_hub metricshub; signal(SIGINT, sig_int_handler); all_args_t args; + + srslte_debug_handle_crash(argc, argv); + parse_args(&args, argc, argv); srsue_instance_type_t type = LTE; From 6196c096afbdf4174d334431a06964f23d62b091 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 23 Nov 2017 12:36:16 +0100 Subject: [PATCH 152/242] Use CP-based CFO estimation only for DL and UL. Estimate every subframe. Calibrated EMA to 0.3 highest valid for low SNR --- lib/include/srslte/phy/sync/sync.h | 4 ++++ lib/include/srslte/phy/ue/ue_sync.h | 7 +++++- lib/src/phy/sync/sync.c | 24 ++++++++++---------- lib/src/phy/ue/ue_sync.c | 34 +++++++++++++++++++++++++++++ srsue/src/main.cc | 2 +- srsue/src/phy/phch_worker.cc | 1 + srsue/ue.conf.example | 2 +- 7 files changed, 60 insertions(+), 14 deletions(-) diff --git a/lib/include/srslte/phy/sync/sync.h b/lib/include/srslte/phy/sync/sync.h index 1c70b2449..135a19160 100644 --- a/lib/include/srslte/phy/sync/sync.h +++ b/lib/include/srslte/phy/sync/sync.h @@ -139,6 +139,10 @@ SRSLTE_API srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, uint32_t find_offset, uint32_t *peak_position); +SRSLTE_API float srslte_sync_cfo_estimate(srslte_sync_t *q, + cf_t *input, + int find_offset); + /* Estimates the CP length */ SRSLTE_API srslte_cp_t srslte_sync_detect_cp(srslte_sync_t *q, cf_t *input, diff --git a/lib/include/srslte/phy/ue/ue_sync.h b/lib/include/srslte/phy/ue/ue_sync.h index e5877dd23..0d12f846c 100644 --- a/lib/include/srslte/phy/ue/ue_sync.h +++ b/lib/include/srslte/phy/ue/ue_sync.h @@ -88,7 +88,12 @@ typedef struct SRSLTE_API { bool file_mode; float file_cfo; srslte_cfo_t file_cfo_correct; - + + bool mean_cfo_isunset; + float cfo; + float mean_cfo; + float cfo_ema_alpha; + srslte_ue_sync_state_t state; uint32_t frame_len; diff --git a/lib/src/phy/sync/sync.c b/lib/src/phy/sync/sync.c index ee2ba76d1..849b64b3b 100644 --- a/lib/src/phy/sync/sync.c +++ b/lib/src/phy/sync/sync.c @@ -587,19 +587,21 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t DEBUG("Not enough room to detect CP length. Peak position: %d\n", peak_pos); } } - - if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) { - float cfo2 = srslte_pss_synch_cfo_compute(&q->pss, &input[find_offset + peak_pos - q->fft_size]); - if (q->mean_cfo2_isunset) { - q->mean_cfo2 = cfo2; - q->mean_cfo2_isunset = true; + + if (q->enable_cfo_corr) { + if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) { + float cfo2 = srslte_pss_synch_cfo_compute(&q->pss, &input[find_offset + peak_pos - q->fft_size]); + if (q->mean_cfo2_isunset) { + q->mean_cfo2 = cfo2; + q->mean_cfo2_isunset = true; + } else { + q->mean_cfo2 = SRSLTE_VEC_EMA(cfo2, q->mean_cfo2, q->cfo_ema_alpha); + } + + ret = SRSLTE_SYNC_FOUND; } else { - q->mean_cfo2 = SRSLTE_VEC_EMA(cfo2, q->mean_cfo2, q->cfo_ema_alpha); + ret = SRSLTE_SYNC_FOUND_NOSPACE; } - - ret = SRSLTE_SYNC_FOUND; - } else { - ret = SRSLTE_SYNC_FOUND_NOSPACE; } } else { ret = SRSLTE_SYNC_NOFOUND; diff --git a/lib/src/phy/ue/ue_sync.c b/lib/src/phy/ue/ue_sync.c index e9c02ca8b..e4caf8e0b 100644 --- a/lib/src/phy/ue/ue_sync.c +++ b/lib/src/phy/ue/ue_sync.c @@ -47,6 +47,10 @@ #define DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD 0 #define DEFAULT_SFO_EMA_COEFF 0.1 + +//#define DO_CFO_IN_SYNC + + cf_t dummy_buffer0[15*2048/2]; cf_t dummy_buffer1[15*2048/2]; @@ -182,6 +186,9 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q, q->sample_offset_correct_period = DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD; q->sfo_ema = DEFAULT_SFO_EMA_COEFF; + q->mean_cfo_isunset = true; + q->mean_cfo = 0; + q->cfo_ema_alpha = 0.4; q->max_prb = max_prb; if (search_cell) { @@ -218,6 +225,11 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q, } } +#ifndef DO_CFO_IN_SYNC + // Disable CFO correction in sync object and do it here every subframe + srslte_sync_set_cfo_enable(&q->strack, false); +#endif + ret = SRSLTE_SUCCESS; } @@ -362,6 +374,7 @@ uint32_t srslte_ue_sync_peak_idx(srslte_ue_sync_t *q) { 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); + q->cfo_ema_alpha = ema; } srslte_ue_sync_state_t srslte_ue_sync_get_state(srslte_ue_sync_t *q) { @@ -377,7 +390,11 @@ void srslte_ue_sync_cfo_i_detec_en(srslte_ue_sync_t *q, bool enable) { } float srslte_ue_sync_get_cfo(srslte_ue_sync_t *q) { +#ifdef DO_CFO_IN_SYNC return 15000 * srslte_sync_get_cfo(&q->strack); +#else + return 15000 * q->mean_cfo; +#endif } void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q, float cfo) { @@ -662,6 +679,23 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE q->sf_idx = (q->sf_idx + q->nof_recv_sf) % 10; +#ifndef DO_CFO_IN_SYNC + /* We found that CP-based correction performs better in low SNR than PSS-based. + * + * Estimate, average and correct here instead of inside sync object + */ + q->cfo = srslte_sync_cfo_estimate(&q->strack, input_buffer[0], 0); + if (q->mean_cfo_isunset) { + q->mean_cfo = q->cfo; + q->mean_cfo_isunset = false; + } else { + /* compute exponential moving average CFO */ + q->mean_cfo = SRSLTE_VEC_EMA(q->cfo, q->mean_cfo, q->cfo_ema_alpha); + } + srslte_cfo_correct(&q->strack.cfocorr2, input_buffer[0], input_buffer[0], -q->mean_cfo / q->fft_size); + +#endif + /* Every SF idx 0 and 5, find peak around known position q->peak_idx */ if (q->sf_idx == 0 || q->sf_idx == 5) { diff --git a/srsue/src/main.cc b/srsue/src/main.cc index cc0b07043..d357a8e44 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -208,7 +208,7 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { "Tolerance (in Hz) for digial CFO compensation.") ("expert.cfo_ema", - bpo::value(&args->expert.phy.cfo_ema)->default_value(0.4), + bpo::value(&args->expert.phy.cfo_ema)->default_value(0.3), "CFO Exponential Moving Average coefficient. Lower makes it more robust to noise " "but vulnerable to periodic interruptions due to VCO corrections.") diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 7b4ec48bd..54dbb057e 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -128,6 +128,7 @@ bool phch_worker::init(uint32_t max_prb, srslte::log *log_h) srslte_ue_ul_set_normalization(&ue_ul, true); srslte_ue_ul_set_cfo_enable(&ue_ul, true); + srslte_ue_ul_set_cfo_tol(&ue_ul, phy->args->cfo_correct_tol_hz); mem_initiated = true; diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index 867221e87..3373c562f 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -172,7 +172,7 @@ enable = false #attach_enable_64qam = false #nof_phy_threads = 2 #equalizer_mode = mmse -#cfo_ema = 0.4 +#cfo_ema = 0.3 #cfo_integer_enabled = false #cfo_correct_tol_hz = 50 #time_correct_period = 5 From 8b6bd607a720f610b97bd4b5eacf384e68c0f5e8 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 23 Nov 2017 12:38:44 +0100 Subject: [PATCH 153/242] Fixed and tested AGC --- lib/src/phy/agc/agc.c | 12 ++++++------ lib/src/phy/rf/rf_imp.c | 3 ++- lib/src/phy/ue/ue_sync.c | 2 ++ srsue/src/phy/phch_recv.cc | 10 +++++----- srsue/src/ue.cc | 8 +++++--- 5 files changed, 20 insertions(+), 15 deletions(-) diff --git a/lib/src/phy/agc/agc.c b/lib/src/phy/agc/agc.c index 3134de729..42a6ef09d 100644 --- a/lib/src/phy/agc/agc.c +++ b/lib/src/phy/agc/agc.c @@ -117,7 +117,7 @@ void srslte_agc_lock(srslte_agc_t *q, bool enable) { void srslte_agc_process(srslte_agc_t *q, cf_t *signal, uint32_t len) { if (!q->lock) { float gain_db = 10*log10(q->gain); - float gain_uhd_db = 1.0; + float gain_uhd_db = 50.0; //float gain_uhd = 1.0; float y = 0; // Apply current gain to input signal @@ -125,12 +125,12 @@ void srslte_agc_process(srslte_agc_t *q, cf_t *signal, uint32_t len) { srslte_vec_sc_prod_cfc(signal, q->gain, signal, len); } else { if (gain_db < 0) { - gain_db = 0.0; + gain_db = 5.0; } if (isinf(gain_db) || isnan(gain_db)) { - gain_db = 10.0; + gain_db = 40.0; } else { - gain_uhd_db = q->set_gain_callback(q->uhd_handler, gain_db); + gain_uhd_db = q->set_gain_callback(q->uhd_handler, gain_db); q->gain = pow(10, gain_uhd_db/10); } } @@ -166,7 +166,7 @@ void srslte_agc_process(srslte_agc_t *q, cf_t *signal, uint32_t len) { } } - double gg = 1.0; + double gg = 1.0; if (q->isfirst) { q->y_out = y; q->isfirst = false; @@ -177,7 +177,7 @@ void srslte_agc_process(srslte_agc_t *q, cf_t *signal, uint32_t len) { gg = expf(-0.5*q->bandwidth*logf(q->y_out/q->target)); q->gain *= gg; } - DEBUG("AGC gain: %.2f (%.2f) y_out=%.3f, y=%.3f target=%.1f gg=%.2f\n", gain_db, gain_uhd_db, q->y_out, y, q->target, gg); + DEBUG("AGC gain: %.2f (%.2f) y_out=%.3f, y=%.3f target=%.1f gg=%.2f\n", gain_db, gain_uhd_db, q->y_out, y, q->target, gg); } } } diff --git a/lib/src/phy/rf/rf_imp.c b/lib/src/phy/rf/rf_imp.c index c1074ebc5..05f064932 100644 --- a/lib/src/phy/rf/rf_imp.c +++ b/lib/src/phy/rf/rf_imp.c @@ -41,7 +41,7 @@ int rf_get_available_devices(char **devnames, int max_strlen) { double srslte_rf_set_rx_gain_th(srslte_rf_t *rf, double gain) { - if (gain > rf->new_rx_gain + 0.5 || gain < rf->new_rx_gain - 0.5) { + if (gain > rf->new_rx_gain + 2 || gain < rf->new_rx_gain - 2) { pthread_mutex_lock(&rf->mutex); rf->new_rx_gain = gain; pthread_cond_signal(&rf->cond); @@ -69,6 +69,7 @@ static void* thread_gain_fcn(void *h) { srslte_rf_set_rx_gain(h, rf->cur_rx_gain); } if (rf->tx_gain_same_rx) { + printf("setting also tx\n"); srslte_rf_set_tx_gain(h, rf->cur_rx_gain+rf->tx_rx_gain_offset); } pthread_mutex_unlock(&rf->mutex); diff --git a/lib/src/phy/ue/ue_sync.c b/lib/src/phy/ue/ue_sync.c index e4caf8e0b..d11811cf3 100644 --- a/lib/src/phy/ue/ue_sync.c +++ b/lib/src/phy/ue/ue_sync.c @@ -122,6 +122,8 @@ int srslte_ue_sync_start_agc(srslte_ue_sync_t *q, double (set_gain_callback)(voi q->do_agc = n==0?true:false; if (q->do_agc) { srslte_agc_set_gain(&q->agc, init_gain_value); + srslte_agc_set_target(&q->agc, 0.3); + srslte_agc_set_bandwidth(&q->agc, 0.8); } return n; } diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 8a69a7f76..b527f66cf 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -57,8 +57,9 @@ int radio_recv_wrapper_cs(void *obj, cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsam } double callback_set_rx_gain(void *h, double gain) { - srslte::radio_multi *radio_handler = (srslte::radio_multi *) h; - return radio_handler->set_rx_gain_th(gain); + phch_recv *obj = (phch_recv*) h; + srslte::radio_multi *radio_h = obj->radio_h; + return radio_h->set_rx_gain_th(gain); } @@ -100,6 +101,7 @@ void phch_recv:: init(srslte::radio_multi *_radio_handler, mac_interface_phy *_ // Set options defined in expert section set_ue_sync_opts(&cs.ue_sync); + last_gain = 40; if (do_agc) { srslte_ue_sync_start_agc(&cs.ue_sync, callback_set_rx_gain, last_gain); } @@ -553,8 +555,6 @@ bool phch_recv::cell_select(uint32_t earfcn, srslte_cell_t cell) { current_earfcn = earfcn; - printf("cell select called set frequency\n"); - if (set_frequency()) { this->cell = cell; log_h->info("Cell Select: Configuring cell...\n"); @@ -670,7 +670,7 @@ void phch_recv::run_thread() { switch (cell_sync_sfn()) { case 1: - srslte_ue_sync_set_agc_period(&ue_sync, 20); + srslte_ue_sync_set_agc_period(&ue_sync, 4); if (!cell_search_in_progress) { phy_state = CELL_CAMP; log_h->info("Sync OK. Camping on cell PCI=%d...\n", cell.id); diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index ca56db556..029ad9255 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -117,7 +117,11 @@ bool ue::init(all_args_t *args_) // Init layers - // PHY initis in background, start before radio + if (args->rf.rx_gain < 0) { + phy.set_agc_enable(true); + } + + // PHY initis in background, start before radio args->expert.phy.nof_rx_ant = args->rf.nof_rx_ant; phy.init(&radio, &mac, &rrc, phy_log, &args->expert.phy); @@ -160,8 +164,6 @@ bool ue::init(all_args_t *args_) if (args->rf.rx_gain < 0) { radio.start_agc(false); - radio.set_tx_rx_gain_offset(10); - phy.set_agc_enable(true); } else { radio.set_rx_gain(args->rf.rx_gain); } From dc65e4243c92dec32504881b2b6c68f7c590dd45 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 23 Nov 2017 13:25:40 +0100 Subject: [PATCH 154/242] print build info to log and on stdout --- CMakeLists.txt | 6 +++ cmake/modules/SRSLTEbuildinfo.cmake.in | 21 ++++++++++ lib/include/srslte/build_info.h.in | 56 ++++++++++++++++++++++++++ lib/src/common/CMakeLists.txt | 4 +- srsue/src/ue.cc | 7 ++++ 5 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 cmake/modules/SRSLTEbuildinfo.cmake.in create mode 100644 lib/include/srslte/build_info.h.in diff --git a/CMakeLists.txt b/CMakeLists.txt index bead502f9..855df3a04 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,12 @@ if(NOT CMAKE_BUILD_TYPE) endif(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "") +# Generate CMake to include build information +configure_file( + ${CMAKE_SOURCE_DIR}/cmake/modules/SRSLTEbuildinfo.cmake.in + ${CMAKE_BINARY_DIR}/SRSLTEbuildinfo.cmake +) + ######################################################################## # Options ######################################################################## diff --git a/cmake/modules/SRSLTEbuildinfo.cmake.in b/cmake/modules/SRSLTEbuildinfo.cmake.in new file mode 100644 index 000000000..d8715afbc --- /dev/null +++ b/cmake/modules/SRSLTEbuildinfo.cmake.in @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 2.6) + +execute_process( +COMMAND git rev-parse --abbrev-ref HEAD +WORKING_DIRECTORY "@CMAKE_SOURCE_DIR@" +OUTPUT_VARIABLE GIT_BRANCH +OUTPUT_STRIP_TRAILING_WHITESPACE +) + +execute_process( +COMMAND git log -1 --format=%h +WORKING_DIRECTORY "@CMAKE_SOURCE_DIR@" +OUTPUT_VARIABLE GIT_COMMIT_HASH +OUTPUT_STRIP_TRAILING_WHITESPACE +) + +message(STATUS "Generating build_info.h") +configure_file( + @CMAKE_SOURCE_DIR@/lib/include/srslte/build_info.h.in + @CMAKE_BINARY_DIR@/lib/include/srslte/build_info.h +) diff --git a/lib/include/srslte/build_info.h.in b/lib/include/srslte/build_info.h.in new file mode 100644 index 000000000..a8acb306b --- /dev/null +++ b/lib/include/srslte/build_info.h.in @@ -0,0 +1,56 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2015 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of the srsLTE library. + * + * 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/. + * + */ + +#ifndef BUILD_INFO_ +#define BUILD_INFO_ + +# ifdef __cplusplus +extern "C" { +# endif + +#ifdef NDEBUG + static char build_mode[] = "Release"; +#else + static char build_mode[] = "Debug"; +#endif + +// the configured build options for srsLTE +static char build_info[] = "commit @GIT_COMMIT_HASH@ on branch @GIT_BRANCH@"; + +SRSLTE_API char* srslte_get_build_info() { + return build_info; +}; + +SRSLTE_API char* srslte_get_build_mode() { + return build_mode; +} + +# ifdef __cplusplus +} +# endif + +#endif // BUILD_INFO_ diff --git a/lib/src/common/CMakeLists.txt b/lib/src/common/CMakeLists.txt index 723085e24..010f8f730 100644 --- a/lib/src/common/CMakeLists.txt +++ b/lib/src/common/CMakeLists.txt @@ -22,7 +22,9 @@ file(GLOB CXX_SOURCES "*.cc") file(GLOB C_SOURCES "*.c") add_library(srslte_common STATIC ${C_SOURCES} ${CXX_SOURCES}) +add_custom_target(gen_build_info COMMAND cmake -P ${CMAKE_BINARY_DIR}/SRSLTEbuildinfo.cmake) +add_dependencies(srslte_common gen_build_info) + target_include_directories(srslte_common PUBLIC ${SEC_INCLUDE_DIRS}) target_link_libraries(srslte_common ${SEC_LIBRARIES}) install(TARGETS srslte_common DESTINATION ${LIBRARY_DIR}) - diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index 029ad9255..7cb9ebaa1 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -32,7 +32,9 @@ #include #include #include +#include #include +#include "srslte/build_info.h" using namespace srslte; @@ -51,6 +53,10 @@ ue::~ue() bool ue::init(all_args_t *args_) { + std::stringstream ss; + ss << "Built in " << srslte_get_build_mode() << " mode using " << srslte_get_build_info() << "." << std::endl << std::endl; + std::cout << ss.str(); + args = args_; if (!args->log.filename.compare("stdout")) { @@ -58,6 +64,7 @@ bool ue::init(all_args_t *args_) } else { logger_file.init(args->log.filename); logger_file.log("\n\n"); + logger_file.log(ss.str().c_str()); logger = &logger_file; } From d9b9ae9454d36451c865aa9efcdbd030f72ac4e1 Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Thu, 23 Nov 2017 18:42:08 +0000 Subject: [PATCH 155/242] Fix for GUTI pack bug, add support for integrity with attach req --- lib/include/srslte/asn1/liblte_mme.h | 4 ++++ lib/src/asn1/liblte_mme.cc | 26 ++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/lib/include/srslte/asn1/liblte_mme.h b/lib/include/srslte/asn1/liblte_mme.h index 15799f7ca..977f309ce 100644 --- a/lib/include/srslte/asn1/liblte_mme.h +++ b/lib/include/srslte/asn1/liblte_mme.h @@ -2721,6 +2721,10 @@ typedef struct{ // Functions LIBLTE_ERROR_ENUM liblte_mme_pack_attach_request_msg(LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req, LIBLTE_BYTE_MSG_STRUCT *msg); +LIBLTE_ERROR_ENUM liblte_mme_pack_attach_request_msg(LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req, + uint8 sec_hdr_type, + uint32 count, + LIBLTE_BYTE_MSG_STRUCT *msg); LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req); diff --git a/lib/src/asn1/liblte_mme.cc b/lib/src/asn1/liblte_mme.cc index 4447b001f..215ffd838 100644 --- a/lib/src/asn1/liblte_mme.cc +++ b/lib/src/asn1/liblte_mme.cc @@ -1411,9 +1411,9 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_eps_mobile_id_ie(LIBLTE_MME_EPS_MOBILE_ID_STRU **ie_ptr = (((eps_mobile_id->guti.mnc/10) % 10) << 4) | ((eps_mobile_id->guti.mnc/100) % 10); *ie_ptr += 1; } - **ie_ptr = (eps_mobile_id->guti.mme_group_id >> 8) & 0x0F; + **ie_ptr = (eps_mobile_id->guti.mme_group_id >> 8) & 0xFF; *ie_ptr += 1; - **ie_ptr = eps_mobile_id->guti.mme_group_id & 0x0F; + **ie_ptr = eps_mobile_id->guti.mme_group_id & 0xFF; *ie_ptr += 1; **ie_ptr = eps_mobile_id->guti.mme_code; *ie_ptr += 1; @@ -5518,6 +5518,14 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_reject_msg(LIBLTE_BYTE_MSG_STRUCT *********************************************************************/ LIBLTE_ERROR_ENUM liblte_mme_pack_attach_request_msg(LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req, LIBLTE_BYTE_MSG_STRUCT *msg) +{ + return liblte_mme_pack_attach_request_msg(attach_req, LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS, 0, msg); +} + +LIBLTE_ERROR_ENUM liblte_mme_pack_attach_request_msg(LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req, + uint8 sec_hdr_type, + uint32 count, + LIBLTE_BYTE_MSG_STRUCT *msg) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint8 *msg_ptr = msg->msg; @@ -5525,6 +5533,20 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_attach_request_msg(LIBLTE_MME_ATTACH_REQUEST_M if(attach_req != NULL && msg != NULL) { + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + // Protocol Discriminator and Security Header Type *msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); msg_ptr++; From 4877c7ab074e0303d72260646323cad014a7fd17 Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Thu, 23 Nov 2017 18:42:48 +0000 Subject: [PATCH 156/242] Adding support for GUTI attach --- lib/include/srslte/interfaces/ue_interfaces.h | 18 +- srsue/hdr/upper/nas.h | 62 +- srsue/hdr/upper/rrc.h | 12 - srsue/hdr/upper/usim.h | 30 +- srsue/src/main.cc | 7 +- srsue/src/upper/nas.cc | 691 ++++++++++++++---- srsue/src/upper/rrc.cc | 104 +-- srsue/src/upper/usim.cc | 58 +- 8 files changed, 675 insertions(+), 307 deletions(-) diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index 88dfd285c..f083c89e2 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -52,16 +52,20 @@ class ue_interface class usim_interface_nas { public: - virtual void get_imsi_vec(uint8_t* imsi_, uint32_t n) = 0; - virtual void get_imei_vec(uint8_t* imei_, uint32_t n) = 0; - virtual int get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id) = 0; + virtual std::string get_imsi_str() = 0; + virtual std::string get_imei_str() = 0; + virtual bool get_imsi_vec(uint8_t* imsi_, uint32_t n) = 0; + virtual bool get_imei_vec(uint8_t* imei_, uint32_t n) = 0; + virtual bool get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id) = 0; virtual void generate_authentication_response(uint8_t *rand, uint8_t *autn_enb, uint16_t mcc, uint16_t mnc, bool *net_valid, - uint8_t *res) = 0; - virtual void generate_nas_keys(uint8_t *k_nas_enc, + uint8_t *res, + uint8_t *k_asme) = 0; + virtual void generate_nas_keys(uint8_t *k_asme, + uint8_t *k_nas_enc, uint8_t *k_nas_int, srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo, srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0; @@ -71,7 +75,8 @@ public: class usim_interface_rrc { public: - virtual void generate_as_keys(uint32_t count_ul, + virtual void generate_as_keys(uint8_t *k_asme, + uint32_t count_ul, uint8_t *k_rrc_enc, uint8_t *k_rrc_int, uint8_t *k_up_enc, @@ -104,6 +109,7 @@ public: virtual void write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu) = 0; virtual uint32_t get_ul_count() = 0; virtual bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) = 0; + virtual bool get_k_asme(uint8_t *k_asme_, uint32_t n) = 0; virtual void plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) = 0; virtual void plmn_search_end() = 0; }; diff --git a/srsue/hdr/upper/nas.h b/srsue/hdr/upper/nas.h index e743165fb..d79eddea8 100644 --- a/srsue/hdr/upper/nas.h +++ b/srsue/hdr/upper/nas.h @@ -57,6 +57,9 @@ static const char emm_state_text[EMM_STATE_N_ITEMS][100] = {"NULL", "DEREGISTERED INITIATED", "TRACKING AREA UPDATE INITIATED"}; +static const bool eia_caps[8] = {false, true, true, false, false, false, false, false}; +static const bool eea_caps[8] = {true, false, false, false, false, false, false, false}; + typedef enum { PLMN_NOT_SELECTED = 0, PLMN_SELECTED @@ -80,16 +83,12 @@ public: // RRC interface void notify_connection_setup(); - void write_pdu(uint32_t lcid, byte_buffer_t *pdu); - uint32_t get_ul_count(); - bool is_attached(); bool is_attaching(); - bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi); - + bool get_k_asme(uint8_t *k_asme_, uint32_t n); void plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code); void plmn_search_end(); @@ -115,72 +114,73 @@ private: std::vector known_plmns; - // Save short MAC + LIBLTE_MME_EMM_INFORMATION_MSG_STRUCT emm_info; // Identifiers LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti; - bool is_guti_set; + bool have_guti; + + // Security context + struct nas_sec_ctxt{ + uint8_t ksi; + uint8_t k_asme[32]; + uint32_t tx_count; + uint32_t rx_count; + srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo; + srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo; + }; + + bool have_ctxt; + nas_sec_ctxt ctxt; uint32_t ip_addr; uint8_t eps_bearer_id; uint8_t transaction_id; - // NAS counters - incremented for each security-protected message recvd/sent - uint32_t count_ul; - uint32_t count_dl; - // Security - uint8_t ksi; uint8_t k_nas_enc[32]; uint8_t k_nas_int[32]; - srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo; - srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo; - - void integrity_generate(uint8_t *key_128, + void integrity_generate(uint8_t integ_algo, + uint8_t *key_128, uint32_t count, uint8_t rb_id, uint8_t direction, uint8_t *msg, uint32_t msg_len, uint8_t *mac); - void integrity_check(); - void cipher_encrypt(); - void cipher_decrypt(); + bool check_cap_replay(LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT *caps); // Parsers void parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu); - void parse_attach_reject(uint32_t lcid, byte_buffer_t *pdu); - void parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu); - void parse_authentication_reject(uint32_t lcid, byte_buffer_t *pdu); - void parse_identity_request(uint32_t lcid, byte_buffer_t *pdu); - void parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu); - void parse_service_reject(uint32_t lcid, byte_buffer_t *pdu); - void parse_esm_information_request(uint32_t lcid, byte_buffer_t *pdu); - void parse_emm_information(uint32_t lcid, byte_buffer_t *pdu); // Senders void send_attach_request(); - void send_identity_response(); - void send_service_request(); - void send_esm_information_response(); - void gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg); + void send_security_mode_reject(uint8_t cause); + + // guti persistence file + bool read_guti_file(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT *guti); + bool write_guti_file(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti); + + // security context persistence file + bool read_ctxt_file(nas_sec_ctxt *ctxt); + bool write_ctxt_file(nas_sec_ctxt ctxt); }; } // namespace srsue diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index 37ab941cd..d561b0f1c 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -40,8 +40,6 @@ #include typedef struct { - bool stmsi_attach; - LIBLTE_RRC_S_TMSI_STRUCT stmsi_value; uint32_t ue_category; uint32_t feature_group; uint8_t supported_bands[LIBLTE_RRC_BAND_N_ITEMS]; @@ -198,21 +196,16 @@ private: // MAC interface void release_pucch_srs(); - void ra_problem(); // GW interface bool is_connected(); - bool have_drb(); // PDCP interface void write_pdu(uint32_t lcid, byte_buffer_t *pdu); - void write_pdu_bcch_bch(byte_buffer_t *pdu); - void write_pdu_bcch_dlsch(byte_buffer_t *pdu); - void write_pdu_pcch(byte_buffer_t *pdu); // Radio bearers @@ -280,11 +273,6 @@ private: void set_mac_default(); void set_rrc_default(); void set_bearers(); - - // s-tmsi persistent file - bool read_stimsi_file(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi); - bool write_stimsi_file(LIBLTE_RRC_S_TMSI_STRUCT s_tmsi); - }; } // namespace srsue diff --git a/srsue/hdr/upper/usim.h b/srsue/hdr/upper/usim.h index fea15ba68..73acd5594 100644 --- a/srsue/hdr/upper/usim.h +++ b/srsue/hdr/upper/usim.h @@ -1,4 +1,4 @@ -/** +/** * * \section COPYRIGHT * @@ -59,24 +59,30 @@ public: void stop(); // NAS interface - void get_imsi_vec(uint8_t* imsi_, uint32_t n); - void get_imei_vec(uint8_t* imei_, uint32_t n); - int get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id); + std::string get_imsi_str(); + std::string get_imei_str(); + + bool get_imsi_vec(uint8_t* imsi_, uint32_t n); + bool get_imei_vec(uint8_t* imei_, uint32_t n); + bool get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id); void generate_authentication_response(uint8_t *rand, uint8_t *autn_enb, uint16_t mcc, uint16_t mnc, bool *net_valid, - uint8_t *res); + uint8_t *res, + uint8_t *k_asme); - void generate_nas_keys(uint8_t *k_nas_enc, + void generate_nas_keys(uint8_t *k_asme, + uint8_t *k_nas_enc, uint8_t *k_nas_int, srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo, srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo); // RRC interface - void generate_as_keys(uint32_t count_ul, + void generate_as_keys(uint8_t *k_asme, + uint32_t count_ul, uint8_t *k_rrc_enc, uint8_t *k_rrc_int, uint8_t *k_up_enc, @@ -91,13 +97,15 @@ private: uint16_t mcc, uint16_t mnc, bool *net_valid, - uint8_t *res); + uint8_t *res, + uint8_t *k_asme); void gen_auth_res_xor( uint8_t *rand, uint8_t *autn_enb, uint16_t mcc, uint16_t mnc, bool *net_valid, - uint8_t *res); + uint8_t *res, + uint8_t *k_asme); void str_to_hex(std::string str, uint8_t *hex); srslte::log *usim_log; @@ -110,6 +118,9 @@ private: uint64_t imei; uint8_t k[16]; + std::string imsi_str; + std::string imei_str; + // Security variables uint8_t rand[16]; uint8_t ck[16]; @@ -117,7 +128,6 @@ private: uint8_t ak[6]; uint8_t mac[8]; uint8_t autn[16]; - uint8_t k_asme[32]; uint8_t k_enb[32]; bool initiated; diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 59d6360c7..b9717d93e 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -77,17 +77,12 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { "Transmission time advance") ("rf.burst_preamble_us", bpo::value(&args->rf.burst_preamble)->default_value("auto"), "Transmission time advance") - ("rrc.stmsi_attach", bpo::value(&args->rrc.stmsi_attach)->default_value(false),"If enabled, always tries first an S-TMSI attach using the\n" - "S-TMSI value stored in .stimsi file generated in previous run") - ("rrc.mmec_value", bpo::value(&args->rrc.stmsi_value.mmec)->default_value(0), "If defined (non-zero), overwrites the value stored in .stimsi file") - ("rrc.mtmsi_value", bpo::value(&args->rrc.stmsi_value.m_tmsi)->default_value(0), "If defined (non-zero), overwrites the value stored in .stimsi file") - ("rrc.feature_group", bpo::value(&args->rrc.feature_group)->default_value(0xe6041c00), "Hex value of the featureGroupIndicators field in the" "UECapabilityInformation message. Default 0xe6041c00") ("rrc.ue_category", bpo::value(&args->ue_category_str)->default_value("4"), "UE Category (1 to 5)") - ("pcap.enable", bpo::value(&args->pcap.enable)->default_value(false), + ("pcap.enable", bpo::value(&args->pcap.enable)->default_value(false), "Enable MAC packet captures for wireshark") ("pcap.filename", bpo::value(&args->pcap.filename)->default_value("ue.pcap"), "MAC layer capture filename") diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index d8bd40c6e..2b01efcec 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -25,6 +25,11 @@ */ +#include +#include +#include +#include +#include #include "srslte/asn1/liblte_rrc.h" #include "upper/nas.h" #include "srslte/common/bcd_helpers.h" @@ -33,9 +38,78 @@ using namespace srslte; namespace srsue { +/********************************************************************* + * Conversion helpers + ********************************************************************/ +std::string hex_to_string(uint8_t *hex, int size) +{ + std::stringstream ss; + + ss << std::hex << std::setfill('0'); + for(int i=0; i(hex[i]); + } + return ss.str(); +} + +bool string_to_hex(std::string hex_str, uint8_t *hex, uint32_t len) +{ + static const char* const lut = "0123456789abcdef"; + uint32_t str_len = hex_str.length(); + if(str_len & 1) { + return false; // uneven hex_str length + } + if(str_len > len*2) { + return false; // not enough space in hex buffer + } + + for(uint32_t i=0; ifull_net_name_present) { + ss << info->full_net_name.name; + } + if(info->short_net_name_present) { + ss << " (" << info->short_net_name.name << ")"; + } + if(info->utc_and_local_time_zone_present) { + ss << " " << (int)info->utc_and_local_time_zone.day; + ss << "/" << (int)info->utc_and_local_time_zone.month; + ss << "/" << (int)info->utc_and_local_time_zone.year; + ss << " " << (int)info->utc_and_local_time_zone.hour; + ss << ":" << (int)info->utc_and_local_time_zone.minute; + ss << ":" << (int)info->utc_and_local_time_zone.second; + ss << " TZ:" << (int)info->utc_and_local_time_zone.tz; + } + return ss.str(); +} + + nas::nas() - : state(EMM_STATE_DEREGISTERED), plmn_selection(PLMN_SELECTED), is_guti_set(false), ip_addr(0), eps_bearer_id(0), - count_ul(0), count_dl(0) {} + : state(EMM_STATE_DEREGISTERED), plmn_selection(PLMN_SELECTED), have_guti(false), ip_addr(0), eps_bearer_id(0) +{ + ctxt.rx_count = 0; + ctxt.tx_count = 0; +} void nas::init(usim_interface_nas *usim_, rrc_interface_nas *rrc_, @@ -51,15 +125,26 @@ void nas::init(usim_interface_nas *usim_, state = EMM_STATE_DEREGISTERED; plmn_selection = PLMN_NOT_SELECTED; - if (usim->get_home_plmn_id(&home_plmn)) { + if (!usim->get_home_plmn_id(&home_plmn)) { nas_log->error("Getting Home PLMN Id from USIM. Defaulting to 001-01\n"); home_plmn.mcc = 61441; // This is 001 home_plmn.mnc = 65281; // This is 01 } cfg = cfg_; + + if((have_guti = read_guti_file(&guti))) { + if((have_ctxt = read_ctxt_file(&ctxt))) { + usim->generate_nas_keys(ctxt.k_asme, k_nas_enc, k_nas_int, + ctxt.cipher_algo, ctxt.integ_algo); + nas_log->debug_hex(k_nas_enc, 32, "NAS encryption key - k_nas_enc"); + nas_log->debug_hex(k_nas_int, 32, "NAS integrity key - k_nas_int"); + } + } } -void nas::stop() {} +void nas::stop() { + write_ctxt_file(ctxt); +} emm_state_t nas::get_state() { return state; @@ -207,11 +292,11 @@ void nas::write_pdu(uint32_t lcid, byte_buffer_t *pdu) { } uint32_t nas::get_ul_count() { - return count_ul; + return ctxt.tx_count; } bool nas::get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) { - if (is_guti_set) { + if (have_guti) { s_tmsi->mmec = guti.mme_code; s_tmsi->m_tmsi = guti.m_tmsi; return true; @@ -220,11 +305,26 @@ bool nas::get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) { } } +bool nas::get_k_asme(uint8_t *k_asme_, uint32_t n) { + if(!have_ctxt) { + nas_log->error("K_asme requested before security context established\n"); + return false; + } + if(NULL == k_asme_ || n < 32) { + nas_log->error("Invalid parameters to get_k_asme"); + return false; + } + + memcpy(k_asme_, ctxt.k_asme, 32); + return true; +} + /******************************************************************************* Security *******************************************************************************/ -void nas::integrity_generate(uint8_t *key_128, +void nas::integrity_generate(uint8_t integ_algo, + uint8_t *key_128, uint32_t count, uint8_t rb_id, uint8_t direction, @@ -269,6 +369,16 @@ void nas::cipher_decrypt() { } +bool nas::check_cap_replay(LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT *caps) +{ + for(uint32_t i=0; i<8; i++) { + if(caps->eea[i] != eea_caps[i] || caps->eia[i] != eia_caps[i]) { + return false; + } + } + return true; +} + /******************************************************************************* Parsers @@ -289,8 +399,8 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { //FIXME: Handle tai_list if (attach_accept.guti_present) { memcpy(&guti, &attach_accept.guti.guti, sizeof(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT)); - is_guti_set = true; - // TODO: log message to console + have_guti = true; + write_guti_file(guti); } if (attach_accept.lai_present) { } @@ -358,10 +468,9 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { state = EMM_STATE_REGISTERED; current_plmn = selecting_plmn; - count_dl++; + ctxt.rx_count++; // Send EPS bearer context accept and attach complete - count_ul++; act_def_eps_bearer_context_accept.eps_bearer_id = eps_bearer_id; act_def_eps_bearer_context_accept.proc_transaction_id = transaction_id; act_def_eps_bearer_context_accept.protocol_cnfg_opts_present = false; @@ -369,10 +478,11 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { &attach_complete.esm_msg); liblte_mme_pack_attach_complete_msg(&attach_complete, LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED, - count_ul, + ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT *) pdu); - integrity_generate(&k_nas_int[16], - count_ul, + integrity_generate(ctxt.integ_algo, + &k_nas_int[16], + ctxt.tx_count, lcid - 1, SECURITY_DIRECTION_UPLINK, &pdu->msg[5], @@ -384,6 +494,7 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { nas_log->info("Sending Attach Complete\n"); rrc->write_sdu(lcid, pdu); + ctxt.tx_count++; } else { nas_log->info("Not handling attach type %u\n", attach_accept.eps_attach_result); @@ -407,7 +518,7 @@ void nas::parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu) { LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT auth_req; LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT auth_res; - nas_log->info("Received Authentication Request\n");; + nas_log->info("Received Authentication Request\n"); liblte_mme_unpack_authentication_request_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &auth_req); // Reuse the pdu for the response message @@ -422,7 +533,15 @@ void nas::parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu) { bool net_valid; uint8_t res[16]; - usim->generate_authentication_response(auth_req.rand, auth_req.autn, mcc, mnc, &net_valid, res); + usim->generate_authentication_response(auth_req.rand, auth_req.autn, mcc, mnc, + &net_valid, res, ctxt.k_asme); + nas_log->info("Generated k_asme=%s\n", hex_to_string(ctxt.k_asme, 32).c_str()); + if(LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE == auth_req.nas_ksi.tsc_flag) { + ctxt.ksi = auth_req.nas_ksi.nas_ksi; + } else { + nas_log->error("NAS mapped security context not currently supported\n"); + nas_log->console("Warning: NAS mapped security context not currently supported\n"); + } if (net_valid) { nas_log->info("Network authentication successful\n"); @@ -438,9 +557,6 @@ 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) { @@ -451,108 +567,154 @@ void nas::parse_authentication_reject(uint32_t lcid, byte_buffer_t *pdu) { } void nas::parse_identity_request(uint32_t lcid, byte_buffer_t *pdu) { - nas_log->error("TODO:parse_identity_request\n"); + LIBLTE_MME_ID_REQUEST_MSG_STRUCT id_req; + LIBLTE_MME_ID_RESPONSE_MSG_STRUCT id_resp; + + liblte_mme_unpack_identity_request_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &id_req); + nas_log->info("Received Identity Request. ID type: %d\n", id_req.id_type); + + switch(id_req.id_type) { + case LIBLTE_MME_MOBILE_ID_TYPE_IMSI: + id_resp.mobile_id.type_of_id = LIBLTE_MME_MOBILE_ID_TYPE_IMSI; + usim->get_imsi_vec(id_resp.mobile_id.imsi, 15); + break; + case LIBLTE_MME_MOBILE_ID_TYPE_IMEI: + id_resp.mobile_id.type_of_id = LIBLTE_MME_MOBILE_ID_TYPE_IMEI; + usim->get_imei_vec(id_resp.mobile_id.imei, 15); + break; + default: + nas_log->error("Unhandled ID type: %d\n"); + pool->deallocate(pdu); + return; + } + + pdu->reset(); + liblte_mme_pack_identity_response_msg(&id_resp, (LIBLTE_BYTE_MSG_STRUCT *) pdu); + rrc->write_sdu(lcid, pdu); } -void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu) { - bool success; +void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu) +{ LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT sec_mode_cmd; LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT sec_mode_comp; - LIBLTE_MME_SECURITY_MODE_REJECT_MSG_STRUCT sec_mode_rej; - nas_log->info("Received Security Mode Command\n"); liblte_mme_unpack_security_mode_command_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &sec_mode_cmd); + nas_log->info("Received Security Mode Command ksi: %d, eea: %s, eia: %s\n", + sec_mode_cmd.nas_ksi.nas_ksi, + ciphering_algorithm_id_text[sec_mode_cmd.selected_nas_sec_algs.type_of_eea], + integrity_algorithm_id_text[sec_mode_cmd.selected_nas_sec_algs.type_of_eia]); - ksi = sec_mode_cmd.nas_ksi.nas_ksi; - cipher_algo = (CIPHERING_ALGORITHM_ID_ENUM) sec_mode_cmd.selected_nas_sec_algs.type_of_eea; - integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM) sec_mode_cmd.selected_nas_sec_algs.type_of_eia; - // FIXME: Handle nonce_ue, nonce_mme - // FIXME: Currently only handling ciphering EEA0 (null) and integrity EIA1,EIA2 - // FIXME: Use selected_nas_sec_algs to choose correct algos + if(sec_mode_cmd.nas_ksi.tsc_flag != LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE) { + nas_log->error("Mapped security context not supported\n"); + pool->deallocate(pdu); + return; + } - nas_log->debug("Security details: ksi=%d, eea=%s, eia=%s\n", - ksi, ciphering_algorithm_id_text[cipher_algo], integrity_algorithm_id_text[integ_algo]); + if(sec_mode_cmd.nas_ksi.nas_ksi != ctxt.ksi) + { + nas_log->warning("Sending Security Mode Reject due to key set ID mismatch\n"); + send_security_mode_reject(LIBLTE_MME_EMM_CAUSE_SECURITY_MODE_REJECTED_UNSPECIFIED); + pool->deallocate(pdu); + return; + } + // MME is setting up security context + // TODO: check nonce (not sent by Amari) - if (CIPHERING_ALGORITHM_ID_EEA0 != cipher_algo || - (INTEGRITY_ALGORITHM_ID_128_EIA2 != integ_algo && - INTEGRITY_ALGORITHM_ID_128_EIA1 != integ_algo) || - sec_mode_cmd.nas_ksi.tsc_flag != LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE) { - sec_mode_rej.emm_cause = LIBLTE_MME_EMM_CAUSE_UE_SECURITY_CAPABILITIES_MISMATCH; + // Check capabilities replay + if(!check_cap_replay(&sec_mode_cmd.ue_security_cap)) { nas_log->warning("Sending Security Mode Reject due to security capabilities mismatch\n"); - nas_log->console("Unsupported Security Mode Command settings: use ciphering algorithm EEA0 and integrity check EIA1 or EIA2.\n"); - success = false; - } else { - // Generate NAS encryption key and integrity protection key - usim->generate_nas_keys(k_nas_enc, k_nas_int, cipher_algo, integ_algo); - nas_log->debug_hex(k_nas_enc, 32, "NAS encryption key - k_nas_enc"); - nas_log->debug_hex(k_nas_int, 32, "NAS integrity key - k_nas_int"); - - // Check incoming MAC - uint8_t *inMAC = &pdu->msg[1]; - uint8_t genMAC[4]; - integrity_generate(&k_nas_int[16], - count_dl, - lcid - 1, - SECURITY_DIRECTION_DOWNLINK, - &pdu->msg[5], - pdu->N_bytes - 5, - genMAC); + send_security_mode_reject(LIBLTE_MME_EMM_CAUSE_UE_SECURITY_CAPABILITIES_MISMATCH); + pool->deallocate(pdu); + return; + } - nas_log->info_hex(inMAC, 4, "Incoming PDU MAC:"); - nas_log->info_hex(genMAC, 4, "Generated PDU MAC:"); + // Reset counterd (as per 24.301 5.4.3.2) + ctxt.rx_count = 0; + ctxt.tx_count = 0; - bool match = true; - for (int i = 0; i < 4; i++) { - if (inMAC[i] != genMAC[i]) { - match = false; - } - } - if (!match) { - sec_mode_rej.emm_cause = LIBLTE_MME_EMM_CAUSE_SECURITY_MODE_REJECTED_UNSPECIFIED; - nas_log->warning("Sending Security Mode Reject due to integrity check failure\n"); - success = false; - } else { + ctxt.cipher_algo = (CIPHERING_ALGORITHM_ID_ENUM) sec_mode_cmd.selected_nas_sec_algs.type_of_eea; + ctxt.integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM) sec_mode_cmd.selected_nas_sec_algs.type_of_eia; - if (sec_mode_cmd.imeisv_req_present && LIBLTE_MME_IMEISV_REQUESTED == sec_mode_cmd.imeisv_req) { - sec_mode_comp.imeisv_present = true; - sec_mode_comp.imeisv.type_of_id = LIBLTE_MME_MOBILE_ID_TYPE_IMEISV; - usim->get_imei_vec(sec_mode_comp.imeisv.imeisv, 15); - sec_mode_comp.imeisv.imeisv[14] = 5; - sec_mode_comp.imeisv.imeisv[15] = 3; - } else { - sec_mode_comp.imeisv_present = false; - } + // Check capabilities + if(!eea_caps[ctxt.cipher_algo] || !eia_caps[ctxt.integ_algo]) { + nas_log->warning("Sending Security Mode Reject due to security capabilities mismatch\n"); + send_security_mode_reject(LIBLTE_MME_EMM_CAUSE_UE_SECURITY_CAPABILITIES_MISMATCH); + pool->deallocate(pdu); + return; + } - // Reuse pdu for response - pdu->reset(); - liblte_mme_pack_security_mode_complete_msg(&sec_mode_comp, - LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED, - count_ul, - (LIBLTE_BYTE_MSG_STRUCT *) pdu); - integrity_generate(&k_nas_int[16], - count_ul, - lcid - 1, - SECURITY_DIRECTION_UPLINK, - &pdu->msg[5], - pdu->N_bytes - 5, - &pdu->msg[1]); - nas_log->info("Sending Security Mode Complete nas_count_ul=%d, RB=%s\n", - count_ul, - rrc->get_rb_name(lcid).c_str()); - success = true; + // Generate NAS keys + usim->generate_nas_keys(ctxt.k_asme, k_nas_enc, k_nas_int, ctxt.cipher_algo, ctxt.integ_algo); + nas_log->debug_hex(k_nas_enc, 32, "NAS encryption key - k_nas_enc"); + nas_log->debug_hex(k_nas_int, 32, "NAS integrity key - k_nas_int"); + + nas_log->debug("Generating integrity check. integ_algo:%d, count_dl:%d, lcid:%d\n", + ctxt.integ_algo, ctxt.rx_count, lcid); + + // Check incoming MAC + uint8_t *inMAC = &pdu->msg[1]; + uint8_t genMAC[4]; + integrity_generate(ctxt.integ_algo, + &k_nas_int[16], + ctxt.rx_count, + lcid - 1, + SECURITY_DIRECTION_DOWNLINK, + &pdu->msg[5], + pdu->N_bytes - 5, + genMAC); + + nas_log->info_hex(inMAC, 4, "Incoming PDU MAC:"); + nas_log->info_hex(genMAC, 4, "Generated PDU MAC:"); + + ctxt.rx_count++; + + bool match = true; + for (int i = 0; i < 4; i++) { + if (inMAC[i] != genMAC[i]) { + match = false; } } + if(!match) { + nas_log->warning("Sending Security Mode Reject due to integrity check failure\n"); + send_security_mode_reject(LIBLTE_MME_EMM_CAUSE_SECURITY_MODE_REJECTED_UNSPECIFIED); + pool->deallocate(pdu); + return; + } - count_dl++; + // Take security context into use + have_ctxt = true; - if (!success) { - // Reuse pdu for response - pdu->reset(); - liblte_mme_pack_security_mode_reject_msg(&sec_mode_rej, (LIBLTE_BYTE_MSG_STRUCT *) pdu); + if (sec_mode_cmd.imeisv_req_present && LIBLTE_MME_IMEISV_REQUESTED == sec_mode_cmd.imeisv_req) { + sec_mode_comp.imeisv_present = true; + sec_mode_comp.imeisv.type_of_id = LIBLTE_MME_MOBILE_ID_TYPE_IMEISV; + usim->get_imei_vec(sec_mode_comp.imeisv.imeisv, 15); + sec_mode_comp.imeisv.imeisv[14] = 5; + sec_mode_comp.imeisv.imeisv[15] = 3; + } else { + sec_mode_comp.imeisv_present = false; } - rrc->write_sdu(lcid, pdu); + // Send response + byte_buffer_t *sdu = pool_allocate; + liblte_mme_pack_security_mode_complete_msg(&sec_mode_comp, + LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED, + ctxt.tx_count, + (LIBLTE_BYTE_MSG_STRUCT *) sdu); + integrity_generate(ctxt.integ_algo, + &k_nas_int[16], + ctxt.tx_count, + lcid - 1, + SECURITY_DIRECTION_UPLINK, + &sdu->msg[5], + sdu->N_bytes - 5, + &sdu->msg[1]); + nas_log->info("Sending Security Mode Complete nas_current_ctxt.tx_count=%d, RB=%s\n", + ctxt.tx_count, + rrc->get_rb_name(lcid).c_str()); + rrc->write_sdu(lcid, sdu); + ctxt.tx_count++; + pool->deallocate(pdu); } void nas::parse_service_reject(uint32_t lcid, byte_buffer_t *pdu) { @@ -561,10 +723,15 @@ void nas::parse_service_reject(uint32_t lcid, byte_buffer_t *pdu) { void nas::parse_esm_information_request(uint32_t lcid, byte_buffer_t *pdu) { nas_log->error("TODO:parse_esm_information_request\n"); + } void nas::parse_emm_information(uint32_t lcid, byte_buffer_t *pdu) { - nas_log->error("TODO:parse_emm_information\n"); + liblte_mme_unpack_emm_information_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &emm_info); + std::string str = emm_info_str(&emm_info); + nas_log->info("Received EMM Information: %s\n", str.c_str()); + nas_log->console("%s\n", str.c_str()); + ctxt.rx_count++; } /******************************************************************************* @@ -579,25 +746,13 @@ void nas::send_attach_request() { attach_req.eps_attach_type = LIBLTE_MME_EPS_ATTACH_TYPE_EPS_ATTACH; for (i = 0; i < 8; i++) { - attach_req.ue_network_cap.eea[i] = false; - attach_req.ue_network_cap.eia[i] = false; + attach_req.ue_network_cap.eea[i] = eea_caps[i]; + attach_req.ue_network_cap.eia[i] = eia_caps[i]; } - attach_req.ue_network_cap.eea[0] = true; // EEA0 supported - attach_req.ue_network_cap.eia[0] = true; // EIA0 supported - attach_req.ue_network_cap.eia[1] = true; // EIA1 supported - attach_req.ue_network_cap.eia[2] = true; // EIA2 supported - - attach_req.ue_network_cap.uea_present = false; // UMTS encryption algos - attach_req.ue_network_cap.uia_present = false; // UMTS integrity algos - - attach_req.ms_network_cap_present = false; // A/Gb mode (2G) or Iu mode (3G) - - attach_req.eps_mobile_id.type_of_id = LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI; - usim->get_imsi_vec(attach_req.eps_mobile_id.imsi, 15); - - // ESM message (PDN connectivity request) for first default bearer - gen_pdn_connectivity_request(&attach_req.esm_msg); + attach_req.ue_network_cap.uea_present = false; // UMTS encryption algos + attach_req.ue_network_cap.uia_present = false; // UMTS integrity algos + attach_req.ms_network_cap_present = false; // A/Gb mode (2G) or Iu mode (3G) attach_req.old_p_tmsi_signature_present = false; attach_req.additional_guti_present = false; attach_req.last_visited_registered_tai_present = false; @@ -613,11 +768,47 @@ void nas::send_attach_request() { attach_req.device_properties_present = false; attach_req.old_guti_type_present = false; - // Pack the message - liblte_mme_pack_attach_request_msg(&attach_req, (LIBLTE_BYTE_MSG_STRUCT *) msg); + // ESM message (PDN connectivity request) for first default bearer + gen_pdn_connectivity_request(&attach_req.esm_msg); + + // GUTI or IMSI attach + if(have_guti && have_ctxt) { + attach_req.eps_mobile_id.type_of_id = LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI; + memcpy(&attach_req.eps_mobile_id.guti, &guti, sizeof(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT)); + attach_req.old_guti_type = LIBLTE_MME_GUTI_TYPE_NATIVE; + attach_req.old_guti_type_present = true; + attach_req.nas_ksi.tsc_flag = LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; + attach_req.nas_ksi.nas_ksi = ctxt.ksi; + nas_log->info("Requesting GUTI attach. " + "m_tmsi: %x, mcc: %x, mnc: %x, mme_group_id: %x, mme_code: %x\n", + guti.m_tmsi, guti.mcc, guti.mnc, guti.mme_group_id, guti.mme_code); + liblte_mme_pack_attach_request_msg(&attach_req, + LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY, + ctxt.tx_count, + (LIBLTE_BYTE_MSG_STRUCT *) msg); + + // Add MAC + integrity_generate(ctxt.integ_algo, + &k_nas_int[16], + ctxt.tx_count, + cfg.lcid-1, + SECURITY_DIRECTION_UPLINK, + &msg->msg[5], + msg->N_bytes - 5, + &msg->msg[1]); + } else { + attach_req.eps_mobile_id.type_of_id = LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI; + usim->get_imsi_vec(attach_req.eps_mobile_id.imsi, 15); + nas_log->info("Requesting IMSI attach. imsi: %s\n", usim->get_imsi_str()); + liblte_mme_pack_attach_request_msg(&attach_req, (LIBLTE_BYTE_MSG_STRUCT *) msg); + } nas_log->info("Sending attach request\n"); rrc->write_sdu(cfg.lcid, msg); + + if(have_ctxt) { + ctxt.tx_count++; + } } void nas::gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg) { @@ -641,27 +832,36 @@ void nas::gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg) { liblte_mme_pack_pdn_connectivity_request_msg(&pdn_con_req, msg); } +void nas::send_security_mode_reject(uint8_t cause) { + byte_buffer_t *msg = pool_allocate; + + LIBLTE_MME_SECURITY_MODE_REJECT_MSG_STRUCT sec_mode_rej; + sec_mode_rej.emm_cause = cause; + liblte_mme_pack_security_mode_reject_msg(&sec_mode_rej, (LIBLTE_BYTE_MSG_STRUCT *) msg); + rrc->write_sdu(cfg.lcid, msg); +} + void nas::send_identity_response() {} void nas::send_service_request() { byte_buffer_t *msg = pool_allocate; - count_ul++; // Pack the service request message directly msg->msg[0] = (LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); msg->N_bytes++; - msg->msg[1] = (ksi & 0x07) << 5; - msg->msg[1] |= count_ul & 0x1F; + msg->msg[1] = (ctxt.ksi & 0x07) << 5; + msg->msg[1] |= ctxt.tx_count & 0x1F; msg->N_bytes++; uint8_t mac[4]; - integrity_generate(&k_nas_int[16], - count_ul, - cfg.lcid-1, - SECURITY_DIRECTION_UPLINK, - &msg->msg[0], - 2, - &mac[0]); + integrity_generate(ctxt.integ_algo, + &k_nas_int[16], + ctxt.tx_count, + cfg.lcid-1, + SECURITY_DIRECTION_UPLINK, + &msg->msg[0], + 2, + &mac[0]); // Set the short MAC msg->msg[2] = mac[2]; msg->N_bytes++; @@ -669,8 +869,239 @@ void nas::send_service_request() { msg->N_bytes++; nas_log->info("Sending service request\n"); rrc->write_sdu(cfg.lcid, msg); + ctxt.tx_count++; } void nas::send_esm_information_response() {} +bool nas::read_guti_file(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT *guti) +{ + std::ifstream file; + std::string line; + if (!guti) { + return false; + } + + const char *m_tmsi_str = "m_tmsi="; + size_t m_tmsi_str_len = strlen(m_tmsi_str); + const char *mcc_str = "mcc="; + size_t mcc_str_len = strlen(mcc_str); + const char *mnc_str = "mnc="; + size_t mnc_str_len = strlen(mnc_str); + const char *mme_group_id_str = "mme_group_id="; + size_t mme_group_id_str_len = strlen(mme_group_id_str); + const char *mme_code_str = "mme_code="; + size_t mme_code_str_len = strlen(mme_code_str); + + file.open(".guti", std::ios::in); + if (file.is_open()) { + bool read_ok = true; + if (std::getline(file, line)) { + if (!line.substr(0,m_tmsi_str_len).compare(m_tmsi_str)) { + guti->m_tmsi = atoi(line.substr(m_tmsi_str_len).c_str()); + } else { + read_ok = false; + } + } else { + read_ok = false; + } + if (std::getline(file, line)) { + if (!line.substr(0,mcc_str_len).compare(mcc_str)) { + guti->mcc = atoi(line.substr(mcc_str_len).c_str()); + } else { + read_ok = false; + } + } else { + read_ok = false; + } + if (std::getline(file, line)) { + if (!line.substr(0,mnc_str_len).compare(mnc_str)) { + guti->mnc = atoi(line.substr(mnc_str_len).c_str()); + } else { + read_ok = false; + } + } else { + read_ok = false; + } + if (std::getline(file, line)) { + if (!line.substr(0,mme_group_id_str_len).compare(mme_group_id_str)) { + guti->mme_group_id = atoi(line.substr(mme_group_id_str_len).c_str()); + } else { + read_ok = false; + } + } else { + read_ok = false; + } + if (std::getline(file, line)) { + if (!line.substr(0,mme_code_str_len).compare(mme_code_str)) { + guti->mme_code = atoi(line.substr(mme_code_str_len).c_str()); + } else { + read_ok = false; + } + } else { + read_ok = false; + } + file.close(); + if (read_ok) { + nas_log->info("Read GUTI from file .guti. " + "m_tmsi: %x, mcc: %x, mnc: %x, mme_group_id: %x, mme_code: %x\n", + guti->m_tmsi, guti->mcc, guti->mnc, guti->mme_group_id, guti->mme_code); + return true; + } else { + nas_log->error("Invalid GUTI file format\n"); + return false; + } + } else { + return false; + } +} + +bool nas::write_guti_file(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti) { + std::ofstream file; + if (!have_guti) { + return false; + } + file.open(".guti", std::ios::out | std::ios::trunc); + if (file.is_open()) { + file << "m_tmsi=" << (int) guti.m_tmsi << std::endl; + file << "mcc=" << (int) guti.mcc << std::endl; + file << "mnc=" << (int) guti.mnc << std::endl; + file << "mme_group_id=" << (int) guti.mme_group_id << std::endl; + file << "mme_code=" << (int) guti.mme_code << std::endl; + nas_log->info("Saved GUTI to file .guti. " + "m_tmsi: %x, mcc: %x, mnc: %x, mme_group_id: %x, mme_code: %x\n", + guti.m_tmsi, guti.mcc, guti.mnc, guti.mme_group_id, guti.mme_code); + file.close(); + return true; + } else { + return false; + } +} + +bool nas::read_ctxt_file(nas_sec_ctxt *ctxt) +{ + std::ifstream file; + std::string line; + if (!ctxt) { + return false; + } + + const char *ksi_str = "ksi="; + size_t ksi_str_len = strlen(ksi_str); + const char *k_asme_str = "k_asme="; + size_t k_asme_str_len = strlen(k_asme_str); + const char *tx_count_str = "tx_count="; + size_t tx_count_str_len = strlen(tx_count_str); + const char *rx_count_str = "rx_count="; + size_t rx_count_str_len = strlen(rx_count_str); + const char *int_alg_str = "int_alg="; + size_t int_alg_str_len = strlen(int_alg_str); + const char *enc_alg_str = "enc_alg="; + size_t enc_alg_str_len = strlen(enc_alg_str); + + file.open(".ctxt", std::ios::in); + if (file.is_open()) { + bool read_ok = true; + if (std::getline(file, line)) { + if (!line.substr(0,ksi_str_len).compare(ksi_str)) { + ctxt->ksi = atoi(line.substr(ksi_str_len).c_str()); + } else { + read_ok = false; + } + } else { + read_ok = false; + } + if (std::getline(file, line)) { + if (!line.substr(0,k_asme_str_len).compare(k_asme_str)) { + std::string tmp = line.substr(k_asme_str_len); + if(!string_to_hex(tmp, ctxt->k_asme, 32)) { + read_ok = false; + } + } else { + read_ok = false; + } + } else { + read_ok = false; + } + if (std::getline(file, line)) { + if (!line.substr(0,tx_count_str_len).compare(tx_count_str)) { + ctxt->tx_count = atoi(line.substr(tx_count_str_len).c_str()); + } else { + read_ok = false; + } + } else { + read_ok = false; + } + if (std::getline(file, line)) { + if (!line.substr(0,rx_count_str_len).compare(rx_count_str)) { + ctxt->rx_count = atoi(line.substr(rx_count_str_len).c_str()); + } else { + read_ok = false; + } + } else { + read_ok = false; + } + if (std::getline(file, line)) { + if (!line.substr(0,int_alg_str_len).compare(int_alg_str)) { + ctxt->integ_algo = (srslte::INTEGRITY_ALGORITHM_ID_ENUM)atoi(line.substr(int_alg_str_len).c_str()); + } else { + read_ok = false; + } + } else { + read_ok = false; + } + if (std::getline(file, line)) { + if (!line.substr(0,enc_alg_str_len).compare(enc_alg_str)) { + ctxt->cipher_algo = (srslte::CIPHERING_ALGORITHM_ID_ENUM)atoi(line.substr(enc_alg_str_len).c_str()); + } else { + read_ok = false; + } + } else { + read_ok = false; + } + file.close(); + if (read_ok) { + nas_log->info("Read security ctxt from file .ctxt. " + "ksi: %x, k_asme: %s, " + "tx_count: %x, rx_count: %x, " + "int_alg: %d, enc_alg: %d\n", + ctxt->ksi, hex_to_string(ctxt->k_asme,32).c_str(), + ctxt->tx_count, ctxt->rx_count, + ctxt->integ_algo, ctxt->cipher_algo); + return true; + } else { + nas_log->error("Invalid security ctxt file format\n"); + return false; + } + } else { + return false; + } +} + +bool nas::write_ctxt_file(nas_sec_ctxt ctxt) +{ + std::ofstream file; + file.open(".ctxt", std::ios::out | std::ios::trunc); + if (file.is_open()) { + file << "ksi=" << (int) ctxt.ksi << std::endl; + file << "k_asme=" << hex_to_string(ctxt.k_asme, 32) << std::endl; + file << "tx_count=" << (int) ctxt.tx_count << std::endl; + file << "rx_count=" << (int) ctxt.rx_count << std::endl; + file << "int_alg=" << (int) ctxt.integ_algo << std::endl; + file << "enc_alg=" << (int) ctxt.cipher_algo << std::endl; + nas_log->info("Saved security ctxt to file .ctxt. " + "ksi: %x, k_asme: %s, " + "tx_count: %x, rx_count: %x, " + "int_alg: %d, enc_alg: %d\n", + ctxt.ksi, hex_to_string(ctxt.k_asme,32).c_str(), + ctxt.tx_count, ctxt.rx_count, + ctxt.integ_algo, ctxt.cipher_algo); + file.close(); + return true; + } else { + return false; + } +} + + } // namespace srsue diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index b33332f1d..665761a04 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -27,8 +27,9 @@ #include #include -#include #include +#include +#include #include "upper/rrc.h" #include "srslte/asn1/liblte_rrc.h" #include "srslte/common/security.h" @@ -99,7 +100,6 @@ void rrc::init(phy_interface_rrc *phy_, args.supported_bands[0] = 7; args.nof_supported_bands = 1; args.feature_group = 0xe6041c00; - args.stmsi_attach = false; t301 = mac_timers->timer_get_unique_id(); t310 = mac_timers->timer_get_unique_id(); @@ -117,6 +117,9 @@ void rrc::init(phy_interface_rrc *phy_, set_rrc_default(); set_phy_default(); set_mac_default(); + + // set seed for rand (used in attach) + srand(time(NULL)); } void rrc::stop() { @@ -592,66 +595,6 @@ void rrc::timer_expired(uint32_t timeout_id) { * *******************************************************************************/ -bool rrc::read_stimsi_file(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) { - std::ifstream file; - std::string line; - if (!s_tmsi) { - return false; - } - - const char *mmec_str = "mmec="; - size_t mmec_str_len = strlen(mmec_str); - const char *mtmsi_str = "mtmsi="; - size_t mtmsi_str_len = strlen(mtmsi_str); - - file.open(".stmsi", std::ios::in); - if (file.is_open()) { - bool read_ok = true; - if (std::getline(file, line)) { - if (!line.substr(0,mmec_str_len).compare(mmec_str)) { - s_tmsi->mmec = atoi(line.substr(5).c_str()); - } else { - read_ok = false; - } - } else { - read_ok = false; - } - if (std::getline(file, line)) { - if (!line.substr(0,mtmsi_str_len).compare(mtmsi_str)) { - s_tmsi->m_tmsi = atoi(line.substr(mtmsi_str_len).c_str()); - } else { - read_ok = false; - } - } else { - read_ok = false; - } - file.close(); - if (read_ok) { - rrc_log->info("Read S-TMSI value: %x:%x\n", s_tmsi->mmec, s_tmsi->m_tmsi); - return true; - } else { - rrc_log->error("Invalid s-tmsi persistent file format\n"); - return false; - } - } else { - return false; - } -} - -bool rrc::write_stimsi_file(LIBLTE_RRC_S_TMSI_STRUCT s_tmsi) { - std::ofstream file; - file.open(".stmsi", std::ios::out | std::ios::trunc); - if (file.is_open()) { - file << "mmec=" << (int) s_tmsi.mmec << std::endl; - file << "mtmsi=" << (int) s_tmsi.m_tmsi << std::endl; - rrc_log->info("Saved S-TMSI in persistent file: %x:%x\n", s_tmsi.mmec, s_tmsi.m_tmsi); - file.close(); - return true; - } else { - return false; - } -} - void rrc::send_con_request() { rrc_log->debug("Preparing RRC Connection Request\n"); LIBLTE_RRC_UL_CCCH_MSG_STRUCT ul_ccch_msg; @@ -659,30 +602,13 @@ void rrc::send_con_request() { // Prepare ConnectionRequest packet ul_ccch_msg.msg_type = LIBLTE_RRC_UL_CCCH_MSG_TYPE_RRC_CON_REQ; - bool valid_stmsi = false; - if (nas->get_s_tmsi(&s_tmsi) || (args.stmsi_attach && !first_stimsi_attempt)) { + if (nas->get_s_tmsi(&s_tmsi)) { ul_ccch_msg.msg.rrc_con_req.ue_id_type = LIBLTE_RRC_CON_REQ_UE_ID_TYPE_S_TMSI; - if (nas->get_s_tmsi(&s_tmsi)) { - ul_ccch_msg.msg.rrc_con_req.ue_id.s_tmsi = s_tmsi; - valid_stmsi = true; - } else { - first_stimsi_attempt = true; - if (args.stmsi_value.m_tmsi) { - ul_ccch_msg.msg.rrc_con_req.ue_id.s_tmsi = args.stmsi_value; - valid_stmsi = true; - } else { - if (!read_stimsi_file(&ul_ccch_msg.msg.rrc_con_req.ue_id.s_tmsi)) { - rrc_log->warning("Could not read S-TMSI from persistent file. Trying normal attach.\n"); - } else { - valid_stmsi = true; - } - } - } - } - if (!valid_stmsi) { + ul_ccch_msg.msg.rrc_con_req.ue_id.s_tmsi = s_tmsi; + } else { ul_ccch_msg.msg.rrc_con_req.ue_id_type = LIBLTE_RRC_CON_REQ_UE_ID_TYPE_RANDOM_VALUE; - ul_ccch_msg.msg.rrc_con_req.ue_id.random = 1000; + ul_ccch_msg.msg.rrc_con_req.ue_id.random = rand() % 2^40; } ul_ccch_msg.msg.rrc_con_req.cause = LIBLTE_RRC_CON_REQ_EST_CAUSE_MO_SIGNALLING; @@ -956,14 +882,6 @@ void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGU nas_sdu->N_bytes = reconfig->ded_info_nas_list[i].N_bytes; nas->write_pdu(lcid, nas_sdu); } - - // Get S-TMSI from NAS and store it in persistent file - LIBLTE_RRC_S_TMSI_STRUCT s_tmsi; - if (nas->get_s_tmsi(&s_tmsi)) { - if (!write_stimsi_file(s_tmsi)) { - rrc_log->warning("Could not store S-TMSI in persistent file\n"); - } - } } /* Actions upon reception of RRCConnectionRelease 5.3.8.3 */ @@ -1247,7 +1165,9 @@ void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu) { integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM) dl_dcch_msg.msg.security_mode_cmd.sec_algs.int_alg; // Configure PDCP for security - usim->generate_as_keys(nas->get_ul_count(), k_rrc_enc, k_rrc_int, k_up_enc, k_up_int, cipher_algo, integ_algo); + uint8_t k_asme[32]; + nas->get_k_asme(k_asme, 32); + usim->generate_as_keys(k_asme, nas->get_ul_count()-1, k_rrc_enc, k_rrc_int, k_up_enc, k_up_int, cipher_algo, integ_algo); pdcp->config_security(lcid, k_rrc_enc, k_rrc_int, cipher_algo, integ_algo); send_security_mode_complete(lcid, pdu); break; diff --git a/srsue/src/upper/usim.cc b/srsue/src/upper/usim.cc index e1d2c204f..7ae53988b 100644 --- a/srsue/src/upper/usim.cc +++ b/srsue/src/upper/usim.cc @@ -39,9 +39,11 @@ usim::usim() : initiated(false) void usim::init(usim_args_t *args, srslte::log *usim_log_) { usim_log = usim_log_; + imsi_str = args->imsi; + imei_str = args->imei; - const char *imsi_str = args->imsi.c_str(); - const char *imei_str = args->imei.c_str(); + const char *imsi_c = args->imsi.c_str(); + const char *imei_c = args->imei.c_str(); uint32_t i; if(32 == args->op.length()) { @@ -63,7 +65,7 @@ void usim::init(usim_args_t *args, srslte::log *usim_log_) for(i=0; i<15; i++) { imsi *= 10; - imsi += imsi_str[i] - '0'; + imsi += imsi_c[i] - '0'; } } else { usim_log->error("Invalid length for ISMI: %d should be %d", args->imsi.length(), 15); @@ -75,7 +77,7 @@ void usim::init(usim_args_t *args, srslte::log *usim_log_) for(i=0; i<15; i++) { imei *= 10; - imei += imei_str[i] - '0'; + imei += imei_c[i] - '0'; } } else { usim_log->error("Invalid length for IMEI: %d should be %d", args->imei.length(), 15); @@ -103,16 +105,25 @@ void usim::stop() NAS interface *******************************************************************************/ -void usim::get_imsi_vec(uint8_t* imsi_, uint32_t n) +std::string usim::get_imsi_str() +{ + return imsi_str; +} +std::string usim::get_imei_str() +{ + return imei_str; +} + +bool usim::get_imsi_vec(uint8_t* imsi_, uint32_t n) { if (!initiated) { fprintf(stderr, "USIM not initiated!\n"); - return; + return false; } if(NULL == imsi_ || n < 15) { usim_log->error("Invalid parameters to get_imsi_vec"); - return; + return false; } uint64_t temp = imsi; @@ -120,18 +131,19 @@ void usim::get_imsi_vec(uint8_t* imsi_, uint32_t n) imsi_[i] = temp % 10; temp /= 10; } + return true; } -void usim::get_imei_vec(uint8_t* imei_, uint32_t n) +bool usim::get_imei_vec(uint8_t* imei_, uint32_t n) { if (!initiated) { fprintf(stderr, "USIM not initiated!\n"); - return; + return false; } if(NULL == imei_ || n < 15) { usim_log->error("Invalid parameters to get_imei_vec"); - return; + return false; } uint64 temp = imei; @@ -140,13 +152,14 @@ void usim::get_imei_vec(uint8_t* imei_, uint32_t n) imei_[i] = temp % 10; temp /= 10; } + return true; } -int usim::get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id) +bool usim::get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id) { if (!initiated) { fprintf(stderr, "USIM not initiated!\n"); - return -1; + return false; } int mcc_len = 3; @@ -180,7 +193,7 @@ int usim::get_home_plmn_id(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *home_plmn_id) usim_log->info("Read Home PLMN Id=%s\n", plmn_id_to_string(*home_plmn_id).c_str()); - return 0; + return true; } void usim::generate_authentication_response(uint8_t *rand, @@ -188,16 +201,18 @@ void usim::generate_authentication_response(uint8_t *rand, uint16_t mcc, uint16_t mnc, bool *net_valid, - uint8_t *res) + uint8_t *res, + uint8_t *k_asme) { if(auth_algo_xor == auth_algo) { - gen_auth_res_xor(rand, autn_enb, mcc, mnc, net_valid, res); + gen_auth_res_xor(rand, autn_enb, mcc, mnc, net_valid, res, k_asme); } else { - gen_auth_res_milenage(rand, autn_enb, mcc, mnc, net_valid, res); + gen_auth_res_milenage(rand, autn_enb, mcc, mnc, net_valid, res, k_asme); } } -void usim::generate_nas_keys(uint8_t *k_nas_enc, +void usim::generate_nas_keys(uint8_t *k_asme, + uint8_t *k_nas_enc, uint8_t *k_nas_int, CIPHERING_ALGORITHM_ID_ENUM cipher_algo, INTEGRITY_ALGORITHM_ID_ENUM integ_algo) @@ -214,7 +229,8 @@ void usim::generate_nas_keys(uint8_t *k_nas_enc, RRC interface *******************************************************************************/ -void usim::generate_as_keys(uint32_t count_ul, +void usim::generate_as_keys(uint8_t *k_asme, + uint32_t count_ul, uint8_t *k_rrc_enc, uint8_t *k_rrc_int, uint8_t *k_up_enc, @@ -251,7 +267,8 @@ void usim::gen_auth_res_milenage( uint8_t *rand, uint16_t mcc, uint16_t mnc, bool *net_valid, - uint8_t *res) + uint8_t *res, + uint8_t *k_asme) { uint32_t i; uint8_t sqn[6]; @@ -320,7 +337,8 @@ void usim::gen_auth_res_xor(uint8_t *rand, uint16_t mcc, uint16_t mnc, bool *net_valid, - uint8_t *res) + uint8_t *res, + uint8_t *k_asme) { uint32_t i; uint8_t sqn[6]; From 408545dab85a7089199fd6ca09c59d232cb318b4 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 23 Nov 2017 19:46:34 +0100 Subject: [PATCH 157/242] X2 (constant NCC) working --- lib/examples/cell_measurement.c | 2 +- lib/examples/cell_search.c | 2 +- lib/examples/pdsch_ue.c | 2 +- lib/examples/usrp_capture.c | 2 +- lib/examples/usrp_capture_sync.c | 2 +- lib/examples/usrp_txrx.c | 2 +- lib/include/srslte/asn1/liblte_rrc.h | 1 + lib/include/srslte/common/liblte_security.h | 5 + lib/include/srslte/common/mac_pcap.h | 11 +- lib/include/srslte/common/security.h | 5 + .../srslte/interfaces/enb_interfaces.h | 1 + lib/include/srslte/interfaces/ue_interfaces.h | 25 +- lib/include/srslte/phy/rf/rf.h | 2 +- lib/include/srslte/radio/radio.h | 2 +- lib/include/srslte/upper/pdcp.h | 1 + lib/include/srslte/upper/pdcp_entity.h | 3 +- lib/include/srslte/upper/rlc.h | 2 + lib/include/srslte/upper/rlc_am.h | 1 + lib/include/srslte/upper/rlc_entity.h | 1 + lib/src/common/liblte_security.cc | 37 ++ lib/src/common/mac_pcap.cc | 8 +- lib/src/common/security.cc | 11 + lib/src/phy/phch/test/prach_test_usrp.c | 2 +- lib/src/phy/rf/rf_blade_imp.c | 2 +- lib/src/phy/rf/rf_blade_imp.h | 2 +- lib/src/phy/rf/rf_dev.h | 2 +- lib/src/phy/rf/rf_imp.c | 4 +- lib/src/phy/rf/rf_soapy_imp.c | 2 +- lib/src/phy/rf/rf_soapy_imp.h | 2 +- lib/src/phy/rf/rf_uhd_imp.c | 18 +- lib/src/phy/rf/rf_uhd_imp.h | 3 +- lib/src/phy/rf/rf_utils.c | 6 +- lib/src/phy/sync/test/pss_usrp.c | 2 +- lib/src/radio/radio.cc | 4 +- lib/src/upper/pdcp.cc | 8 + lib/src/upper/pdcp_entity.cc | 16 +- lib/src/upper/rlc.cc | 12 + lib/src/upper/rlc_entity.cc | 4 + srsenb/hdr/upper/pdcp.h | 5 +- srsenb/hdr/upper/rlc.h | 1 + srsenb/src/upper/pdcp.cc | 4 + srsenb/src/upper/rlc.cc | 8 + srsue/hdr/mac/mac.h | 9 +- srsue/hdr/mac/proc_ra.h | 325 ++++++++-------- srsue/hdr/phy/phch_common.h | 9 +- srsue/hdr/phy/phch_recv.h | 10 +- srsue/hdr/phy/phch_worker.h | 3 +- srsue/hdr/phy/phy.h | 1 + srsue/hdr/upper/rrc.h | 18 +- srsue/hdr/upper/rrc_common.h | 2 + srsue/hdr/upper/usim.h | 10 + srsue/src/mac/mac.cc | 29 ++ srsue/src/mac/mux.cc | 79 ++-- srsue/src/mac/proc_ra.cc | 36 +- srsue/src/phy/phch_common.cc | 62 ++- srsue/src/phy/phch_recv.cc | 82 +++- srsue/src/phy/phch_worker.cc | 14 +- srsue/src/phy/phy.cc | 19 +- srsue/src/upper/rrc.cc | 368 ++++++++++++++---- srsue/src/upper/usim.cc | 34 ++ 60 files changed, 956 insertions(+), 389 deletions(-) diff --git a/lib/examples/cell_measurement.c b/lib/examples/cell_measurement.c index bfb8194df..1fc5e1640 100644 --- a/lib/examples/cell_measurement.c +++ b/lib/examples/cell_measurement.c @@ -293,7 +293,7 @@ int main(int argc, char **argv) { return -1; } - srslte_rf_start_rx_stream(&rf); + srslte_rf_start_rx_stream(&rf, false); float rx_gain_offset = 0; diff --git a/lib/examples/cell_search.c b/lib/examples/cell_search.c index 281e3d102..e7740d892 100644 --- a/lib/examples/cell_search.c +++ b/lib/examples/cell_search.c @@ -219,7 +219,7 @@ int main(int argc, char **argv) { INFO("Setting sampling frequency %.2f MHz for PSS search\n", SRSLTE_CS_SAMP_FREQ/1000000); srslte_rf_set_rx_srate(&rf, SRSLTE_CS_SAMP_FREQ); INFO("Starting receiver...\n", 0); - srslte_rf_start_rx_stream(&rf); + srslte_rf_start_rx_stream(&rf, false); n = srslte_ue_cellsearch_scan(&cs, found_cells, NULL); if (n < 0) { diff --git a/lib/examples/pdsch_ue.c b/lib/examples/pdsch_ue.c index bf4414f08..ecff9267f 100644 --- a/lib/examples/pdsch_ue.c +++ b/lib/examples/pdsch_ue.c @@ -552,7 +552,7 @@ int main(int argc, char **argv) { #ifndef DISABLE_RF if (!prog_args.input_file_name) { - srslte_rf_start_rx_stream(&rf); + srslte_rf_start_rx_stream(&rf, false); } #endif diff --git a/lib/examples/usrp_capture.c b/lib/examples/usrp_capture.c index 02b543c0e..a0136e913 100644 --- a/lib/examples/usrp_capture.c +++ b/lib/examples/usrp_capture.c @@ -153,7 +153,7 @@ int main(int argc, char **argv) { printf("Correctly RX rate: %.2f MHz\n", srate*1e-6); srslte_rf_rx_wait_lo_locked(&rf); - srslte_rf_start_rx_stream(&rf); + srslte_rf_start_rx_stream(&rf, false); while((sample_count < nof_samples || nof_samples == -1) diff --git a/lib/examples/usrp_capture_sync.c b/lib/examples/usrp_capture_sync.c index bac17698a..613f26d84 100644 --- a/lib/examples/usrp_capture_sync.c +++ b/lib/examples/usrp_capture_sync.c @@ -158,7 +158,7 @@ int main(int argc, char **argv) { exit(-1); } srslte_rf_rx_wait_lo_locked(&rf); - srslte_rf_start_rx_stream(&rf); + srslte_rf_start_rx_stream(&rf, false); cell.cp = SRSLTE_CP_NORM; cell.id = N_id_2; diff --git a/lib/examples/usrp_txrx.c b/lib/examples/usrp_txrx.c index 508b4b397..42f610d65 100644 --- a/lib/examples/usrp_txrx.c +++ b/lib/examples/usrp_txrx.c @@ -175,7 +175,7 @@ int main(int argc, char **argv) { srslte_timestamp_t tstamp; - srslte_rf_start_rx_stream(&rf); + srslte_rf_start_rx_stream(&rf, false); uint32_t nframe=0; diff --git a/lib/include/srslte/asn1/liblte_rrc.h b/lib/include/srslte/asn1/liblte_rrc.h index 46f725ec3..cd0c3f087 100644 --- a/lib/include/srslte/asn1/liblte_rrc.h +++ b/lib/include/srslte/asn1/liblte_rrc.h @@ -2684,6 +2684,7 @@ typedef enum{ }LIBLTE_RRC_T304_ENUM; static const char liblte_rrc_t304_text[LIBLTE_RRC_T304_N_ITEMS][20] = { "50", "100", "150", "200", "500", "1000", "2000", "SPARE"}; +static const int32 liblte_rrc_t304_num[LIBLTE_RRC_T304_N_ITEMS] = {50, 100, 150, 200, 500, 1000, 2000, -1}; // Structs typedef struct{ uint8 p_b; diff --git a/lib/include/srslte/common/liblte_security.h b/lib/include/srslte/common/liblte_security.h index b49f7211b..2c6fdc50c 100644 --- a/lib/include/srslte/common/liblte_security.h +++ b/lib/include/srslte/common/liblte_security.h @@ -86,6 +86,11 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_enb(uint8 *k_asme, uint32 nas_count, uint8 *k_enb); +LIBLTE_ERROR_ENUM liblte_security_generate_k_enb_star(uint8 *k_enb, + uint32 pci, + uint32_t earfcn, + uint8 *k_enb_star); + /********************************************************************* Name: liblte_security_generate_k_nas diff --git a/lib/include/srslte/common/mac_pcap.h b/lib/include/srslte/common/mac_pcap.h index f441e1aed..26a8f20bb 100644 --- a/lib/include/srslte/common/mac_pcap.h +++ b/lib/include/srslte/common/mac_pcap.h @@ -35,10 +35,13 @@ namespace srslte { class mac_pcap { public: - mac_pcap() {enable_write=false; ue_id=0; pcap_file = NULL; }; + mac_pcap() {enable_write=false; ue_id=0; pcap_file = NULL; }; void enable(bool en); void open(const char *filename, uint32_t ue_id = 0); - void close(); + void close(); + + void set_ue_id(uint16_t ue_id); + void write_ul_crnti(uint8_t *pdu, uint32_t pdu_len_bytes, uint16_t crnti, uint32_t reTX, uint32_t tti); void write_dl_crnti(uint8_t *pdu, uint32_t pdu_len_bytes, uint16_t crnti, bool crc_ok, uint32_t tti); void write_dl_ranti(uint8_t *pdu, uint32_t pdu_len_bytes, uint16_t ranti, bool crc_ok, uint32_t tti); @@ -51,8 +54,8 @@ public: private: bool enable_write; FILE *pcap_file; - uint32_t ue_id; - void pack_and_write(uint8_t* pdu, uint32_t pdu_len_bytes, uint32_t reTX, bool crc_ok, uint32_t tti, + uint32_t ue_id; + void pack_and_write(uint8_t* pdu, uint32_t pdu_len_bytes, uint32_t reTX, bool crc_ok, uint32_t tti, uint16_t crnti_, uint8_t direction, uint8_t rnti_type); }; diff --git a/lib/include/srslte/common/security.h b/lib/include/srslte/common/security.h index 080f1848f..fd892e891 100644 --- a/lib/include/srslte/common/security.h +++ b/lib/include/srslte/common/security.h @@ -76,6 +76,11 @@ uint8_t security_generate_k_enb( uint8_t *k_asme, uint32_t nas_count, uint8_t *k_enb); +uint8_t security_generate_k_enb_star( uint8_t *k_enb, + uint32_t pci, + uint32_t earfcn, + uint8_t *k_enb_star); + uint8_t security_generate_k_nas( uint8_t *k_asme, CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, diff --git a/lib/include/srslte/interfaces/enb_interfaces.h b/lib/include/srslte/interfaces/enb_interfaces.h index 9c85814f8..eb3eb6c2e 100644 --- a/lib/include/srslte/interfaces/enb_interfaces.h +++ b/lib/include/srslte/interfaces/enb_interfaces.h @@ -147,6 +147,7 @@ public: /* PDCP calls RLC to push an RLC SDU. SDU gets placed into the RLC buffer and MAC pulls * RLC PDUs according to TB size. */ virtual void write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t *sdu) = 0; + virtual bool rb_is_um(uint16_t rnti, uint32_t lcid) = 0; }; // RLC interface for RRC diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index a4ecf1345..df2d74c33 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -78,6 +78,14 @@ public: uint8_t *k_up_int, srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo, srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0; + virtual void generate_as_keys_ho(uint32_t pci, + uint32_t earfcn, + uint8_t *k_rrc_enc, + uint8_t *k_rrc_int, + uint8_t *k_up_enc, + uint8_t *k_up_int, + srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo, + srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0; }; // GW interface for NAS @@ -133,6 +141,7 @@ public: class rrc_interface_mac : public rrc_interface_mac_common { public: + virtual void ho_ra_completed(bool ra_successful) = 0; virtual void release_pucch_srs() = 0; virtual void run_tti(uint32_t tti) = 0; }; @@ -192,6 +201,7 @@ public: class pdcp_interface_rrc { public: + virtual void reestablish() = 0; virtual void reset() = 0; virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu) = 0; virtual void add_bearer(uint32_t lcid, srslte::srslte_pdcp_config_t cnfg = srslte::srslte_pdcp_config_t()) = 0; @@ -218,6 +228,7 @@ class rlc_interface_rrc { public: virtual void reset() = 0; + virtual void reestablish() = 0; virtual void add_bearer(uint32_t lcid) = 0; virtual void add_bearer(uint32_t lcid, srslte::srslte_rlc_config_t cnfg) = 0; }; @@ -229,6 +240,7 @@ public: /* PDCP calls RLC to push an RLC SDU. SDU gets placed into the RLC buffer and MAC pulls * RLC PDUs according to TB size. */ virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu) = 0; + virtual bool rb_is_um(uint32_t lcid) = 0; }; //RLC interface for MAC @@ -392,8 +404,8 @@ public: LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT rach; LIBLTE_RRC_SCHEDULING_REQUEST_CONFIG_STRUCT sr; ul_harq_params_t ul_harq_params; - uint32_t prach_config_index; - } mac_cfg_t; + uint32_t prach_config_index; + } mac_cfg_t; /* Instructs the MAC to start receiving BCCH */ virtual void bcch_start_rx() = 0; @@ -408,7 +420,7 @@ public: virtual void setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD) = 0; virtual uint32_t get_current_tti() = 0; - + virtual void set_config(mac_cfg_t *mac_cfg) = 0; virtual void set_config_main(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT *main_cfg) = 0; virtual void set_config_rach(LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT *rach_cfg, uint32_t prach_config_index) = 0; @@ -417,10 +429,14 @@ public: virtual void get_rntis(ue_rnti_t *rntis) = 0; virtual void set_contention_id(uint64_t uecri) = 0; + virtual void set_ho_rnti(uint16_t crnti, uint16_t target_pci) = 0; + + virtual void start_noncont_ho(uint32_t preamble_index, uint32_t prach_mask) = 0; + virtual void start_cont_ho() = 0; - virtual void reconfiguration() = 0; virtual void reset() = 0; + virtual void wait_uplink() = 0; }; @@ -541,6 +557,7 @@ public: virtual void cell_search_stop() = 0; virtual void cell_search_next() = 0; virtual bool cell_select(uint32_t earfcn, srslte_cell_t cell) = 0; + virtual bool cell_handover(srslte_cell_t cell) = 0; /* Is the PHY downlink synchronized? */ virtual bool sync_status() = 0; diff --git a/lib/include/srslte/phy/rf/rf.h b/lib/include/srslte/phy/rf/rf.h index 860e0a257..afafc5cf2 100644 --- a/lib/include/srslte/phy/rf/rf.h +++ b/lib/include/srslte/phy/rf/rf.h @@ -95,7 +95,7 @@ SRSLTE_API void srslte_rf_set_tx_cal(srslte_rf_t *h, srslte_rf_cal_t *cal); SRSLTE_API void srslte_rf_set_rx_cal(srslte_rf_t *h, srslte_rf_cal_t *cal); -SRSLTE_API int srslte_rf_start_rx_stream(srslte_rf_t *h); +SRSLTE_API int srslte_rf_start_rx_stream(srslte_rf_t *h, bool now); SRSLTE_API int srslte_rf_stop_rx_stream(srslte_rf_t *h); diff --git a/lib/include/srslte/radio/radio.h b/lib/include/srslte/radio/radio.h index 329dd825a..3f961e2aa 100644 --- a/lib/include/srslte/radio/radio.h +++ b/lib/include/srslte/radio/radio.h @@ -117,7 +117,7 @@ namespace srslte { void start_trace(); void write_trace(std::string filename); - void start_rx(); + void start_rx(bool now = false); void stop_rx(); void set_tti(uint32_t tti); diff --git a/lib/include/srslte/upper/pdcp.h b/lib/include/srslte/upper/pdcp.h index ce6ece151..11880c61d 100644 --- a/lib/include/srslte/upper/pdcp.h +++ b/lib/include/srslte/upper/pdcp.h @@ -54,6 +54,7 @@ public: bool is_drb_enabled(uint32_t lcid); // RRC interface + void reestablish(); void reset(); void write_sdu(uint32_t lcid, byte_buffer_t *sdu); void add_bearer(uint32_t lcid, srslte_pdcp_config_t cnfg = srslte_pdcp_config_t()); diff --git a/lib/include/srslte/upper/pdcp_entity.h b/lib/include/srslte/upper/pdcp_entity.h index 0ff005d07..38190a428 100644 --- a/lib/include/srslte/upper/pdcp_entity.h +++ b/lib/include/srslte/upper/pdcp_entity.h @@ -69,6 +69,7 @@ public: uint32_t lcid_, srslte_pdcp_config_t cfg_); void reset(); + void reestablish(); bool is_active(); @@ -94,8 +95,8 @@ private: uint32_t lcid; srslte_pdcp_config_t cfg; - uint32_t rx_count; uint32_t tx_count; + uint32_t tx_sn; uint8_t k_rrc_enc[32]; uint8_t k_rrc_int[32]; diff --git a/lib/include/srslte/upper/rlc.h b/lib/include/srslte/upper/rlc.h index 349a7952d..ed5929542 100644 --- a/lib/include/srslte/upper/rlc.h +++ b/lib/include/srslte/upper/rlc.h @@ -64,6 +64,7 @@ public: // PDCP interface void write_sdu(uint32_t lcid, byte_buffer_t *sdu); + bool rb_is_um(uint32_t lcid); std::string get_rb_name(uint32_t lcid); // MAC interface @@ -76,6 +77,7 @@ public: void write_pdu_pcch(uint8_t *payload, uint32_t nof_bytes); // RRC interface + void reestablish(); void reset(); void empty_queue(); void add_bearer(uint32_t lcid); diff --git a/lib/include/srslte/upper/rlc_am.h b/lib/include/srslte/upper/rlc_am.h index cee0d5959..c0289956c 100644 --- a/lib/include/srslte/upper/rlc_am.h +++ b/lib/include/srslte/upper/rlc_am.h @@ -78,6 +78,7 @@ public: mac_interface_timers *mac_timers); void configure(srslte_rlc_config_t cnfg); void reset(); + void reestablish(); void stop(); void empty_queue(); diff --git a/lib/include/srslte/upper/rlc_entity.h b/lib/include/srslte/upper/rlc_entity.h index e9c41fa30..de4a396fe 100644 --- a/lib/include/srslte/upper/rlc_entity.h +++ b/lib/include/srslte/upper/rlc_entity.h @@ -56,6 +56,7 @@ public: void configure(srslte_rlc_config_t cnfg); void reset(); + void reestablish(); void stop(); void empty_queue(); bool active(); diff --git a/lib/src/common/liblte_security.cc b/lib/src/common/liblte_security.cc index 95f9617cd..e0cdd90d8 100644 --- a/lib/src/common/liblte_security.cc +++ b/lib/src/common/liblte_security.cc @@ -298,6 +298,43 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_enb(uint8 *k_asme, return(err); } +/********************************************************************* + Name: liblte_security_generate_k_enb_star + + Description: Generate the security key Kenb*. + + Document Reference: 33.401 v10.0.0 Annex A.5 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_security_generate_k_enb_star(uint8 *k_enb, + uint32 pci, + uint32_t earfcn, + uint8 *k_enb_star) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 s[9]; + + if (k_enb_star != NULL && + k_enb != NULL) { + // Construct S + s[0] = 0x13; // FC + s[1] = (pci >> 8) & 0xFF; // First byte of P0 + s[2] = pci & 0xFF; // Second byte of P0 + s[3] = 0x00; // First byte of L0 + s[4] = 0x02; // Second byte of L0 + s[5] = (earfcn >> 8) & 0xFF; // First byte of P0 + s[6] = earfcn & 0xFF; // Second byte of P0 + s[7] = 0x00; // First byte of L0 + s[8] = 0x02; // Second byte of L0 + + // Derive Kenb + sha256(k_enb, 32, s, 9, k_enb_star, 0); + + err = LIBLTE_SUCCESS; + } + + return (err); +} + /********************************************************************* Name: liblte_security_generate_k_nas diff --git a/lib/src/common/mac_pcap.cc b/lib/src/common/mac_pcap.cc index ff30670ed..c3bf3e1d4 100644 --- a/lib/src/common/mac_pcap.cc +++ b/lib/src/common/mac_pcap.cc @@ -41,8 +41,8 @@ void mac_pcap::enable(bool en) void mac_pcap::open(const char* filename, uint32_t ue_id) { pcap_file = MAC_LTE_PCAP_Open(filename); - ue_id = ue_id; - enable_write = true; + this->ue_id = ue_id; + enable_write = true; } void mac_pcap::close() { @@ -50,6 +50,10 @@ void mac_pcap::close() MAC_LTE_PCAP_Close(pcap_file); } +void mac_pcap::set_ue_id(uint16_t ue_id) { + this->ue_id = ue_id; +} + void mac_pcap::pack_and_write(uint8_t* pdu, uint32_t pdu_len_bytes, uint32_t reTX, bool crc_ok, uint32_t tti, uint16_t crnti, uint8_t direction, uint8_t rnti_type) { diff --git a/lib/src/common/security.cc b/lib/src/common/security.cc index f0ad1ce7e..93b197e7c 100644 --- a/lib/src/common/security.cc +++ b/lib/src/common/security.cc @@ -61,6 +61,17 @@ uint8_t security_generate_k_enb( uint8_t *k_asme, k_enb); } +uint8_t security_generate_k_enb_star( uint8_t *k_enb, + uint32_t pci, + uint32_t earfcn, + uint8_t *k_enb_star) +{ + return liblte_security_generate_k_enb_star(k_enb, + pci, + earfcn, + k_enb_star); +} + uint8_t security_generate_k_nas( uint8_t *k_asme, CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, diff --git a/lib/src/phy/phch/test/prach_test_usrp.c b/lib/src/phy/phch/test/prach_test_usrp.c index c0fae365c..c4edc343d 100644 --- a/lib/src/phy/phch/test/prach_test_usrp.c +++ b/lib/src/phy/phch/test/prach_test_usrp.c @@ -199,7 +199,7 @@ int main(int argc, char **argv) { srslte_timestamp_t tstamp; - srslte_rf_start_rx_stream(&rf); + srslte_rf_start_rx_stream(&rf, false); uint32_t nframe=0; while(nframedev)->srslte_rf_rx_wait_lo_locked(rf->handler); } -int srslte_rf_start_rx_stream(srslte_rf_t *rf) +int srslte_rf_start_rx_stream(srslte_rf_t *rf, bool now) { - return ((rf_dev_t*) rf->dev)->srslte_rf_start_rx_stream(rf->handler); + return ((rf_dev_t*) rf->dev)->srslte_rf_start_rx_stream(rf->handler, now); } int srslte_rf_stop_rx_stream(srslte_rf_t *rf) diff --git a/lib/src/phy/rf/rf_soapy_imp.c b/lib/src/phy/rf/rf_soapy_imp.c index 18c5b01cd..3e8d83eb8 100644 --- a/lib/src/phy/rf/rf_soapy_imp.c +++ b/lib/src/phy/rf/rf_soapy_imp.c @@ -114,7 +114,7 @@ void rf_soapy_set_rx_cal(void *h, srslte_rf_cal_t *cal) } -int rf_soapy_start_rx_stream(void *h) +int rf_soapy_start_rx_stream(void *h, bool now) { rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; if(handler->rx_stream_active == false){ diff --git a/lib/src/phy/rf/rf_soapy_imp.h b/lib/src/phy/rf/rf_soapy_imp.h index 19de4536c..18850e520 100644 --- a/lib/src/phy/rf/rf_soapy_imp.h +++ b/lib/src/phy/rf/rf_soapy_imp.h @@ -45,7 +45,7 @@ SRSLTE_API void rf_soapy_set_tx_cal(void *h, srslte_rf_cal_t *cal); SRSLTE_API void rf_soapy_set_rx_cal(void *h, srslte_rf_cal_t *cal); -SRSLTE_API int rf_soapy_start_rx_stream(void *h); +SRSLTE_API int rf_soapy_start_rx_stream(void *h, bool now); SRSLTE_API int rf_soapy_stop_rx_stream(void *h); diff --git a/lib/src/phy/rf/rf_uhd_imp.c b/lib/src/phy/rf/rf_uhd_imp.c index 29aec5b44..f5bed7362 100644 --- a/lib/src/phy/rf/rf_uhd_imp.c +++ b/lib/src/phy/rf/rf_uhd_imp.c @@ -219,21 +219,23 @@ void rf_uhd_set_rx_cal(void *h, srslte_rf_cal_t *cal) } -int rf_uhd_start_rx_stream(void *h) +int rf_uhd_start_rx_stream(void *h, bool now) { rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; uhd_stream_cmd_t stream_cmd = { .stream_mode = UHD_STREAM_MODE_START_CONTINUOUS, - .stream_now = false + .stream_now = now }; - uhd_usrp_get_time_now(handler->usrp, 0, &stream_cmd.time_spec_full_secs, &stream_cmd.time_spec_frac_secs); - stream_cmd.time_spec_frac_secs += 0.1; - if (stream_cmd.time_spec_frac_secs > 1) { - stream_cmd.time_spec_frac_secs -= 1; - stream_cmd.time_spec_full_secs += 1; + if (!now) { + uhd_usrp_get_time_now(handler->usrp, 0, &stream_cmd.time_spec_full_secs, &stream_cmd.time_spec_frac_secs); + stream_cmd.time_spec_frac_secs += 0.1; + if (stream_cmd.time_spec_frac_secs > 1) { + stream_cmd.time_spec_frac_secs -= 1; + stream_cmd.time_spec_full_secs += 1; + } } - uhd_rx_streamer_issue_stream_cmd(handler->rx_stream, &stream_cmd); + uhd_rx_streamer_issue_stream_cmd(handler->rx_stream, &stream_cmd); return 0; } diff --git a/lib/src/phy/rf/rf_uhd_imp.h b/lib/src/phy/rf/rf_uhd_imp.h index 2be799333..e3555fab3 100644 --- a/lib/src/phy/rf/rf_uhd_imp.h +++ b/lib/src/phy/rf/rf_uhd_imp.h @@ -49,7 +49,8 @@ SRSLTE_API void rf_uhd_set_tx_cal(void *h, srslte_rf_cal_t *cal); SRSLTE_API void rf_uhd_set_rx_cal(void *h, srslte_rf_cal_t *cal); -SRSLTE_API int rf_uhd_start_rx_stream(void *h); +SRSLTE_API int rf_uhd_start_rx_stream(void *h, + bool now); SRSLTE_API int rf_uhd_start_rx_stream_nsamples(void *h, uint32_t nsamples); diff --git a/lib/src/phy/rf/rf_utils.c b/lib/src/phy/rf/rf_utils.c index ce288b5c5..0ef082a23 100644 --- a/lib/src/phy/rf/rf_utils.c +++ b/lib/src/phy/rf/rf_utils.c @@ -60,7 +60,7 @@ int rf_rssi_scan(srslte_rf_t *rf, float *freqs, float *rssi, int nof_bands, doub srslte_rf_set_rx_freq(rf, f); srslte_rf_rx_wait_lo_locked(rf); usleep(10000); - srslte_rf_start_rx_stream(rf); + srslte_rf_start_rx_stream(rf, false); /* discard first samples */ for (j=0;j<2;j++) { @@ -122,7 +122,7 @@ int rf_mib_decoder(srslte_rf_t *rf, uint32_t nof_rx_antennas,cell_search_cfg_t * srslte_rf_set_rx_srate(rf, (float) srate); INFO("Starting receiver...\n", 0); - srslte_rf_start_rx_stream(rf); + srslte_rf_start_rx_stream(rf, false); // Set CFO if available if (cfo) { @@ -184,7 +184,7 @@ int rf_cell_search(srslte_rf_t *rf, uint32_t nof_rx_antennas, srslte_rf_set_rx_srate(rf, SRSLTE_CS_SAMP_FREQ); INFO("Starting receiver...\n", 0); - srslte_rf_start_rx_stream(rf); + srslte_rf_start_rx_stream(rf, false); /* Find a cell in the given N_id_2 or go through the 3 of them to find the strongest */ uint32_t max_peak_cell = 0; diff --git a/lib/src/phy/sync/test/pss_usrp.c b/lib/src/phy/sync/test/pss_usrp.c index 8e8377b83..25f8a07b3 100644 --- a/lib/src/phy/sync/test/pss_usrp.c +++ b/lib/src/phy/sync/test/pss_usrp.c @@ -198,7 +198,7 @@ int main(int argc, char **argv) { printf("N_id_2: %d\n", N_id_2); - srslte_rf_start_rx_stream(&rf); + srslte_rf_start_rx_stream(&rf, false); printf("Frame length %d samples\n", flen); printf("PSS detection threshold: %.2f\n", threshold); diff --git a/lib/src/radio/radio.cc b/lib/src/radio/radio.cc index 42d4143f9..66e28b1d3 100644 --- a/lib/src/radio/radio.cc +++ b/lib/src/radio/radio.cc @@ -392,9 +392,9 @@ void radio::set_tx_srate(double srate) tx_adv_sec = nsamples/cur_tx_srate; } -void radio::start_rx() +void radio::start_rx(bool now) { - srslte_rf_start_rx_stream(&rf_device); + srslte_rf_start_rx_stream(&rf_device, now); } void radio::stop_rx() diff --git a/lib/src/upper/pdcp.cc b/lib/src/upper/pdcp.cc index 0acc7f6bd..7b5de7e67 100644 --- a/lib/src/upper/pdcp.cc +++ b/lib/src/upper/pdcp.cc @@ -53,6 +53,14 @@ void pdcp::init(srsue::rlc_interface_pdcp *rlc_, srsue::rrc_interface_pdcp *rrc_ void pdcp::stop() {} +void pdcp::reestablish() { + for(uint32_t i=0;idebug("Init %s\n", rrc->get_rb_name(lcid).c_str()); } +// Reestablishment procedure: 36.323 5.2 +void pdcp_entity::reestablish() { + // For SRBs + if (cfg.is_control) { + tx_count = 0; + cfg.do_security = false; + } else { + if (rlc->rb_is_um(lcid)) { + tx_count = 0; + } + } +} + void pdcp_entity::reset() { active = false; @@ -80,6 +91,7 @@ void pdcp_entity::write_sdu(byte_buffer_t *sdu) pdcp_pack_control_pdu(tx_count, sdu); if(cfg.do_security) { + log->info("rrc_int[0]=0x%x, tx_count=%d\n", k_rrc_int[0], tx_count); integrity_generate(&k_rrc_int[16], tx_count, lcid-1, diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index f506ebc63..c86d1d989 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -95,6 +95,14 @@ void rlc::get_metrics(rlc_metrics_t &m) reset_metrics(); } +void rlc::reestablish() { + for(uint32_t i=0; iget_rb_name(lcid); diff --git a/lib/src/upper/rlc_entity.cc b/lib/src/upper/rlc_entity.cc index 5a351162a..81692889c 100644 --- a/lib/src/upper/rlc_entity.cc +++ b/lib/src/upper/rlc_entity.cc @@ -70,6 +70,10 @@ void rlc_entity::configure(srslte_rlc_config_t cnfg) rlc->configure(cnfg); } +void rlc_entity::reestablish() { + rlc->reset(); +} + void rlc_entity::reset() { rlc->reset(); diff --git a/srsenb/hdr/upper/pdcp.h b/srsenb/hdr/upper/pdcp.h index 228490312..8c5b05275 100644 --- a/srsenb/hdr/upper/pdcp.h +++ b/srsenb/hdr/upper/pdcp.h @@ -67,8 +67,9 @@ private: uint16_t rnti; srsenb::rlc_interface_pdcp *rlc; // rlc_interface_pdcp - void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu); - }; + void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu); + bool rb_is_um(uint32_t lcid); + }; class user_interface_gtpu : public srsue::gw_interface_pdcp { diff --git a/srsenb/hdr/upper/rlc.h b/srsenb/hdr/upper/rlc.h index abbf99516..b937cd216 100644 --- a/srsenb/hdr/upper/rlc.h +++ b/srsenb/hdr/upper/rlc.h @@ -54,6 +54,7 @@ public: // rlc_interface_pdcp void write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t *sdu); + bool rb_is_um(uint16_t rnti, uint32_t lcid); std::string get_rb_name(uint32_t lcid); // rlc_interface_mac diff --git a/srsenb/src/upper/pdcp.cc b/srsenb/src/upper/pdcp.cc index 027f04909..afd41976f 100644 --- a/srsenb/src/upper/pdcp.cc +++ b/srsenb/src/upper/pdcp.cc @@ -124,6 +124,10 @@ void pdcp::user_interface_rlc::write_sdu(uint32_t lcid, srslte::byte_buffer_t* s rlc->write_sdu(rnti, lcid, sdu); } +bool pdcp::user_interface_rlc::rb_is_um(uint32_t lcid) { + return rlc->rb_is_um(rnti, lcid); +} + void pdcp::user_interface_rrc::write_pdu(uint32_t lcid, srslte::byte_buffer_t* pdu) { rrc->write_pdu(rnti, lcid, pdu); diff --git a/srsenb/src/upper/rlc.cc b/srsenb/src/upper/rlc.cc index 6147597e3..fff674112 100644 --- a/srsenb/src/upper/rlc.cc +++ b/srsenb/src/upper/rlc.cc @@ -160,6 +160,14 @@ void rlc::write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* sdu) } } +bool rlc::rb_is_um(uint16_t rnti, uint32_t lcid) { + if (users.count(rnti)) { + return users[rnti].rlc->rb_is_um(lcid); + } else { + return false; + } +} + void rlc::user_interface::max_retx_attempted() { rrc->max_retx_attempted(rnti); diff --git a/srsue/hdr/mac/mac.h b/srsue/hdr/mac/mac.h index d19f668bf..b1b649de7 100644 --- a/srsue/hdr/mac/mac.h +++ b/srsue/hdr/mac/mac.h @@ -79,7 +79,8 @@ public: void pcch_stop_rx(); void setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD); void reconfiguration(); - void reset(); + void reset(); + void wait_uplink(); /******** set/get MAC configuration ****************/ void set_config(mac_cfg_t *mac_cfg); @@ -88,8 +89,12 @@ public: void set_config_rach(LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT *rach_cfg, uint32_t prach_config_index); void set_config_sr(LIBLTE_RRC_SCHEDULING_REQUEST_CONFIG_STRUCT *sr_cfg); void set_contention_id(uint64_t uecri); - + + void start_noncont_ho(uint32_t preamble_index, uint32_t prach_mask); + void start_cont_ho(); + void get_rntis(ue_rnti_t *rntis); + void set_ho_rnti(uint16_t crnti, uint16_t target_pci); void start_pcap(srslte::mac_pcap* pcap); diff --git a/srsue/hdr/mac/proc_ra.h b/srsue/hdr/mac/proc_ra.h index 2bd2dd807..de8a0671d 100644 --- a/srsue/hdr/mac/proc_ra.h +++ b/srsue/hdr/mac/proc_ra.h @@ -43,164 +43,175 @@ namespace srsue { class ra_proc : public srslte::timer_callback { - public: - ra_proc() : rar_pdu_msg(20) { - bzero(&softbuffer_rar, sizeof(srslte_softbuffer_rx_t)); - pcap = NULL; - backoff_interval_start = 0; - backoff_inteval = 0; - received_target_power_dbm = 0; - ra_rnti = 0; - current_ta = 0; - state = IDLE; - last_msg3_group = RA_GROUP_A; - msg3_transmitted = false; - first_rar_received = false; - phy_h = NULL; - log_h = NULL; - mac_cfg = NULL; - mux_unit = NULL; - demux_unit = NULL; - rrc = NULL; - transmitted_contention_id = 0; - transmitted_crnti = 0; - pdcch_to_crnti_received = PDCCH_CRNTI_NOT_RECEIVED; - started_by_pdcch = false; - rar_grant_nbytes = 0; - rar_grant_tti = 0; - msg3_flushed = false; - - time_alignment_timer = NULL; - contention_resolution_timer = NULL; - }; - - ~ra_proc(); - - void init(phy_interface_mac *phy_h, - rrc_interface_mac *rrc_, - srslte::log *log_h, - mac_interface_rrc::ue_rnti_t *rntis, - mac_interface_rrc::mac_cfg_t *mac_cfg, - srslte::timers::timer* time_alignment_timer_, - srslte::timers::timer* contention_resolution_timer_, - mux *mux_unit, - demux *demux_unit); - void reset(); - void start_pdcch_order(); - void start_mac_order(uint32_t msg_len_bits = 56); - void step(uint32_t tti); - bool is_successful(); - bool is_response_error(); - bool is_contention_resolution(); - void harq_retx(); - bool is_error(); - bool in_progress(); - void pdcch_to_crnti(bool contains_uplink_grant); - void timer_expired(uint32_t timer_id); - - void new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t* action); - void tb_decoded_ok(); - - void start_pcap(srslte::mac_pcap* pcap); +public: + ra_proc() : rar_pdu_msg(20) { + bzero(&softbuffer_rar, sizeof(srslte_softbuffer_rx_t)); + pcap = NULL; + backoff_interval_start = 0; + backoff_inteval = 0; + received_target_power_dbm = 0; + ra_rnti = 0; + current_ta = 0; + state = IDLE; + last_msg3_group = RA_GROUP_A; + msg3_transmitted = false; + first_rar_received = false; + phy_h = NULL; + log_h = NULL; + mac_cfg = NULL; + mux_unit = NULL; + demux_unit = NULL; + rrc = NULL; + transmitted_contention_id = 0; + transmitted_crnti = 0; + pdcch_to_crnti_received = PDCCH_CRNTI_NOT_RECEIVED; + started_by_pdcch = false; + rar_grant_nbytes = 0; + rar_grant_tti = 0; + msg3_flushed = false; + + noncontention_enabled = false; + next_preamble_idx = 0; + next_prach_mask = 0; + + time_alignment_timer = NULL; + contention_resolution_timer = NULL; + }; + + ~ra_proc(); + + void init(phy_interface_mac *phy_h, + rrc_interface_mac *rrc_, + srslte::log *log_h, + mac_interface_rrc::ue_rnti_t *rntis, + mac_interface_rrc::mac_cfg_t *mac_cfg, + srslte::timers::timer* time_alignment_timer_, + srslte::timers::timer* contention_resolution_timer_, + mux *mux_unit, + demux *demux_unit); + void reset(); + void start_pdcch_order(); + void start_mac_order(uint32_t msg_len_bits = 56, bool is_ho = false); + void step(uint32_t tti); + bool is_successful(); + bool is_response_error(); + bool is_contention_resolution(); + void harq_retx(); + bool is_error(); + bool in_progress(); + void pdcch_to_crnti(bool contains_uplink_grant); + void timer_expired(uint32_t timer_id); + + void new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t* action); + void tb_decoded_ok(); + + void start_noncont(uint32_t preamble_index, uint32_t prach_mask); + + void start_pcap(srslte::mac_pcap* pcap); private: - static bool uecrid_callback(void *arg, uint64_t uecri); - - bool contention_resolution_id_received(uint64_t uecri); - void process_timeadv_cmd(uint32_t ta_cmd); - void step_initialization(); - void step_resource_selection(); - void step_preamble_transmission(); - void step_pdcch_setup(); - void step_response_reception(); - void step_response_error(); - void step_backoff_wait(); - void step_contention_resolution(); - void step_completition(); - - // Buffer to receive RAR PDU - static const uint32_t MAX_RAR_PDU_LEN = 2048; - uint8_t rar_pdu_buffer[MAX_RAR_PDU_LEN]; - srslte::rar_pdu rar_pdu_msg; - - // Random Access parameters provided by higher layers defined in 5.1.1 - uint32_t configIndex; - uint32_t nof_preambles; - uint32_t nof_groupA_preambles; - uint32_t nof_groupB_preambles; - uint32_t messagePowerOffsetGroupB; - uint32_t messageSizeGroupA; - uint32_t responseWindowSize; - uint32_t powerRampingStep; - uint32_t preambleTransMax; - uint32_t iniReceivedTargetPower; - int delta_preamble_db; - uint32_t contentionResolutionTimer; - uint32_t maskIndex; - int preambleIndex; - uint32_t new_ra_msg_len; - - // Internal variables - uint32_t preambleTransmissionCounter; - uint32_t backoff_param_ms; - uint32_t sel_maskIndex; - uint32_t sel_preamble; - uint32_t backoff_interval_start; - uint32_t backoff_inteval; - int received_target_power_dbm; - uint32_t ra_rnti; - uint32_t current_ta; - - srslte_softbuffer_rx_t softbuffer_rar; - - enum { - IDLE = 0, - INITIALIZATION, // Section 5.1.1 - RESOURCE_SELECTION, // Section 5.1.2 - PREAMBLE_TRANSMISSION, // Section 5.1.3 - PDCCH_SETUP, - RESPONSE_RECEPTION, // Section 5.1.4 - RESPONSE_ERROR, - BACKOFF_WAIT, - CONTENTION_RESOLUTION, // Section 5.1.5 - COMPLETION, // Section 5.1.6 - COMPLETION_DONE, - RA_PROBLEM // Section 5.1.5 last part - } state; - - typedef enum {RA_GROUP_A, RA_GROUP_B} ra_group_t; - - ra_group_t last_msg3_group; - bool msg3_transmitted; - bool first_rar_received; - void read_params(); - - phy_interface_mac *phy_h; - srslte::log *log_h; - mux *mux_unit; - demux *demux_unit; - srslte::mac_pcap *pcap; - rrc_interface_mac *rrc; - - srslte::timers::timer *time_alignment_timer; - srslte::timers::timer *contention_resolution_timer; - - mac_interface_rrc::ue_rnti_t *rntis; - mac_interface_rrc::mac_cfg_t *mac_cfg; - - uint64_t transmitted_contention_id; - uint16_t transmitted_crnti; - - enum { - PDCCH_CRNTI_NOT_RECEIVED = 0, - PDCCH_CRNTI_UL_GRANT, - PDCCH_CRNTI_DL_GRANT - } pdcch_to_crnti_received; - - bool started_by_pdcch; - uint32_t rar_grant_nbytes; - uint32_t rar_grant_tti; - bool msg3_flushed; - bool rar_received; + static bool uecrid_callback(void *arg, uint64_t uecri); + + bool contention_resolution_id_received(uint64_t uecri); + void process_timeadv_cmd(uint32_t ta_cmd); + void step_initialization(); + void step_resource_selection(); + void step_preamble_transmission(); + void step_pdcch_setup(); + void step_response_reception(); + void step_response_error(); + void step_backoff_wait(); + void step_contention_resolution(); + void step_completition(); + + // Buffer to receive RAR PDU + static const uint32_t MAX_RAR_PDU_LEN = 2048; + uint8_t rar_pdu_buffer[MAX_RAR_PDU_LEN]; + srslte::rar_pdu rar_pdu_msg; + + // Random Access parameters provided by higher layers defined in 5.1.1 + uint32_t configIndex; + uint32_t nof_preambles; + uint32_t nof_groupA_preambles; + uint32_t nof_groupB_preambles; + uint32_t messagePowerOffsetGroupB; + uint32_t messageSizeGroupA; + uint32_t responseWindowSize; + uint32_t powerRampingStep; + uint32_t preambleTransMax; + uint32_t iniReceivedTargetPower; + int delta_preamble_db; + uint32_t contentionResolutionTimer; + uint32_t maskIndex; + int preambleIndex; + uint32_t new_ra_msg_len; + + bool noncontention_enabled; + uint32_t next_preamble_idx; + uint32_t next_prach_mask; + + // Internal variables + uint32_t preambleTransmissionCounter; + uint32_t backoff_param_ms; + uint32_t sel_maskIndex; + uint32_t sel_preamble; + uint32_t backoff_interval_start; + uint32_t backoff_inteval; + int received_target_power_dbm; + uint32_t ra_rnti; + uint32_t current_ta; + + srslte_softbuffer_rx_t softbuffer_rar; + + enum { + IDLE = 0, + INITIALIZATION, // Section 5.1.1 + RESOURCE_SELECTION, // Section 5.1.2 + PREAMBLE_TRANSMISSION, // Section 5.1.3 + PDCCH_SETUP, + RESPONSE_RECEPTION, // Section 5.1.4 + RESPONSE_ERROR, + BACKOFF_WAIT, + CONTENTION_RESOLUTION, // Section 5.1.5 + COMPLETION, // Section 5.1.6 + COMPLETION_DONE, + RA_PROBLEM // Section 5.1.5 last part + } state; + + typedef enum {RA_GROUP_A, RA_GROUP_B} ra_group_t; + + ra_group_t last_msg3_group; + bool msg3_transmitted; + bool first_rar_received; + void read_params(); + + phy_interface_mac *phy_h; + srslte::log *log_h; + mux *mux_unit; + demux *demux_unit; + srslte::mac_pcap *pcap; + rrc_interface_mac *rrc; + + srslte::timers::timer *time_alignment_timer; + srslte::timers::timer *contention_resolution_timer; + + mac_interface_rrc::ue_rnti_t *rntis; + mac_interface_rrc::mac_cfg_t *mac_cfg; + + uint64_t transmitted_contention_id; + uint16_t transmitted_crnti; + + enum { + PDCCH_CRNTI_NOT_RECEIVED = 0, + PDCCH_CRNTI_UL_GRANT, + PDCCH_CRNTI_DL_GRANT + } pdcch_to_crnti_received; + + bool ra_is_ho; + bool started_by_pdcch; + uint32_t rar_grant_nbytes; + uint32_t rar_grant_tti; + bool msg3_flushed; + bool rar_received; }; } // namespace srsue diff --git a/srsue/hdr/phy/phch_common.h b/srsue/hdr/phy/phch_common.h index f3c36d994..aa7c53ab7 100644 --- a/srsue/hdr/phy/phch_common.h +++ b/srsue/hdr/phy/phch_common.h @@ -64,9 +64,10 @@ namespace srsue { float rx_gain_offset; float avg_snr_db; float avg_noise; - float avg_rsrp; + float avg_rsrp; - uint32_t serving_cell_report_period; + bool pcell_meas_enabled; + uint32_t pcell_report_period; phch_common(uint32_t max_mutex = 3); void init(phy_interface_rrc::phy_cfg_t *config, @@ -92,7 +93,8 @@ namespace srsue { void set_pending_ack(uint32_t tti, uint32_t I_lowest, uint32_t n_dmrs); bool get_pending_ack(uint32_t tti); bool get_pending_ack(uint32_t tti, uint32_t *I_lowest, uint32_t *n_dmrs); - + bool is_any_pending_ack(); + void worker_end(uint32_t tti, bool tx_enable, cf_t *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time); void set_nof_mutex(uint32_t nof_mutex); @@ -112,6 +114,7 @@ namespace srsue { void get_sync_metrics(sync_metrics_t &m); void reset_ul(); + void reset(); private: diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index e35610c0b..93ace4d68 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -64,6 +64,7 @@ public: void cell_search_stop(); void cell_search_next(bool reset = false); bool cell_select(uint32_t earfcn, srslte_cell_t cell); + bool cell_handover(srslte_cell_t cell); void meas_reset(); int meas_start(uint32_t earfcn, int pci); @@ -97,11 +98,11 @@ private: bool set_cell(); void cell_search_inc(); - void resync_sfn(bool is_connected = false); + void resync_sfn(bool is_connected = false, bool rx_now = false); bool stop_sync(); void stop_rx(); - void start_rx(); + void start_rx(bool now = false); bool radio_is_rx; bool radio_is_resetting; @@ -169,6 +170,7 @@ private: float rsrp(); float rsrq(); float snr(); + void set_rx_gain_offset(float rx_gain_offset); private: srslte::log *log_h; srslte_ue_dl_t ue_dl; @@ -176,6 +178,7 @@ private: uint32_t cnt; uint32_t nof_subframes; uint32_t current_prb; + float rx_gain_offset; float mean_rsrp, mean_rsrq, mean_snr; const static int RSRP_MEASURE_NOF_FRAMES = 5; }; @@ -192,7 +195,7 @@ private: } cell_info_t; void init(srslte::log *log_h); void reset(); - int find_cells(cf_t *input_buffer, srslte_cell_t current_cell, uint32_t nof_sf, cell_info_t found_cells[MAX_CELLS]); + int find_cells(cf_t *input_buffer, float rx_gain_offset, srslte_cell_t current_cell, uint32_t nof_sf, cell_info_t found_cells[MAX_CELLS]); private: const static int DEFAULT_MEASUREMENT_LEN = 10; @@ -217,6 +220,7 @@ private: void rem_cell(int pci); void set_primay_cell(uint32_t earfcn, srslte_cell_t cell); void clear_cells(); + int get_offset(uint32_t pci); void write(uint32_t tti, cf_t *data, uint32_t nsamples); private: void run_thread(); diff --git a/srsue/hdr/phy/phch_worker.h b/srsue/hdr/phy/phch_worker.h index c26966c17..73547a9aa 100644 --- a/srsue/hdr/phy/phch_worker.h +++ b/srsue/hdr/phy/phch_worker.h @@ -146,7 +146,8 @@ private: srslte_uci_cfg_t uci_cfg; srslte_cqi_periodic_cfg_t period_cqi; srslte_ue_ul_powerctrl_t power_ctrl; - uint32_t I_sr; + uint32_t I_sr; + bool sr_configured; float cfo; bool rar_cqi_request; diff --git a/srsue/hdr/phy/phy.h b/srsue/hdr/phy/phy.h index 6a0e8891e..05edf31f9 100644 --- a/srsue/hdr/phy/phy.h +++ b/srsue/hdr/phy/phy.h @@ -87,6 +87,7 @@ public: void cell_search_stop(); void cell_search_next(); bool cell_select(uint32_t earfcn, srslte_cell_t phy_cell); + bool cell_handover(srslte_cell_t cell); void meas_reset(); int meas_start(uint32_t earfcn, int pci); diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index 5ec484251..5a49a9275 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -101,6 +101,7 @@ public: void new_phy_meas(float rsrp, float rsrq, uint32_t tti, uint32_t earfcn, uint32_t pci); // MAC interface + void ho_ra_completed(bool ra_successful); void release_pucch_srs(); void run_tti(uint32_t tti); @@ -143,6 +144,9 @@ private: bool reestablishment_in_progress; + bool pending_mob_reconf; + LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT mob_reconf; + // timeouts in ms uint32_t connecting_timeout; @@ -172,7 +176,7 @@ private: srslte::mac_interface_timers *mac_timers; uint32_t n310_cnt, N310; uint32_t n311_cnt, N311; - uint32_t t301, t310, t311; + uint32_t t301, t310, t311, t304; int ue_category; typedef struct { @@ -189,7 +193,6 @@ private: std::vector known_cells; cell_t *current_cell; - typedef enum { SI_ACQUIRE_IDLE = 0, SI_ACQUIRE_SIB1, @@ -242,6 +245,7 @@ private: void new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, float rsrq, uint32_t tti); void run_tti(uint32_t tti); bool timer_expired(uint32_t timer_id); + void ho_finish(); private: const static int NOF_MEASUREMENTS = 3; @@ -304,10 +308,12 @@ private: bool s_measure_enabled; float s_measure_value; + void stop_reports(meas_t *m); void stop_reports_object(uint32_t object_id); void remove_meas_object(uint32_t object_id); void remove_meas_report(uint32_t report_id); - void remove_meas_id(uint32_t meas_id); + void remove_meas_id(uint32_t measId); + void remove_meas_id(std::map::iterator it); void calculate_triggers(uint32_t tti); void update_phy(); void L3_filter(meas_value_t *value, float rsrp[NOF_MEASUREMENTS]); @@ -334,7 +340,7 @@ private: void send_con_setup_complete(byte_buffer_t *nas_msg); void send_ul_info_transfer(uint32_t lcid, byte_buffer_t *sdu); void send_security_mode_complete(uint32_t lcid, byte_buffer_t *pdu); - void send_rrc_con_reconfig_complete(uint32_t lcid, byte_buffer_t *pdu); + void send_rrc_con_reconfig_complete(byte_buffer_t *pdu); void send_rrc_ue_cap_info(uint32_t lcid, byte_buffer_t *pdu); // Parsers @@ -343,11 +349,15 @@ private: void parse_dl_info_transfer(uint32_t lcid, byte_buffer_t *pdu); // Helpers + void ho_prepare(); + void add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp); void rrc_connection_release(); void con_restablish_cell_reselected(); void radio_link_failure(); static void* start_sib_thread(void *rrc_); void sib_search(); + void apply_rr_config_common_dl(LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT *config); + void apply_rr_config_common_ul(LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT *config); void apply_sib2_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2); void handle_con_setup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *setup); void handle_con_reest(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT *setup); diff --git a/srsue/hdr/upper/rrc_common.h b/srsue/hdr/upper/rrc_common.h index 95b909620..6d1186812 100644 --- a/srsue/hdr/upper/rrc_common.h +++ b/srsue/hdr/upper/rrc_common.h @@ -38,6 +38,8 @@ typedef enum { RRC_STATE_CELL_SELECTED, RRC_STATE_CONNECTING, RRC_STATE_CONNECTED, + RRC_STATE_HO_PREPARE, + RRC_STATE_HO_PROCESS, RRC_STATE_LEAVE_CONNECTED, RRC_STATE_N_ITEMS, } rrc_state_t; diff --git a/srsue/hdr/upper/usim.h b/srsue/hdr/upper/usim.h index fea15ba68..3b122d416 100644 --- a/srsue/hdr/upper/usim.h +++ b/srsue/hdr/upper/usim.h @@ -84,6 +84,15 @@ public: srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo, srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo); + void generate_as_keys_ho(uint32_t pci, + uint32_t earfcn, + uint8_t *k_rrc_enc, + uint8_t *k_rrc_int, + uint8_t *k_up_enc, + uint8_t *k_up_int, + srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo, + srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo); + private: void gen_auth_res_milenage( uint8_t *rand, @@ -119,6 +128,7 @@ private: uint8_t autn[16]; uint8_t k_asme[32]; uint8_t k_enb[32]; + uint8_t k_enb_star[32]; bool initiated; diff --git a/srsue/src/mac/mac.cc b/srsue/src/mac/mac.cc index 66adb5b0b..e543c0fd5 100644 --- a/srsue/src/mac/mac.cc +++ b/srsue/src/mac/mac.cc @@ -110,6 +110,15 @@ void mac::reconfiguration() } +void mac::wait_uplink() { + int cnt=0; + Info("Waiting to uplink...\n"); + while(mux_unit.is_pending_any_sdu() && cnt<20) { + usleep(1000); + cnt++; + } +} + // Implement Section 5.9 void mac::reset() { @@ -371,11 +380,31 @@ void mac::get_rntis(ue_rnti_t* rntis) memcpy(rntis, &uernti, sizeof(ue_rnti_t)); } +void mac::set_ho_rnti(uint16_t crnti, uint16_t target_pci) { + phy_h->pdcch_dl_search_reset(); + phy_h->pdcch_ul_search_reset(); + uernti.crnti = crnti; + if (pcap) { + printf("set_ue_id=%d\n", target_pci); + pcap->set_ue_id(target_pci); + } +} + void mac::set_contention_id(uint64_t uecri) { uernti.contention_id = uecri; } +void mac::start_noncont_ho(uint32_t preamble_index, uint32_t prach_mask) +{ + ra_procedure.start_noncont(preamble_index, prach_mask); +} + +void mac::start_cont_ho() +{ + ra_procedure.start_mac_order(56, true); +} + void mac::get_config(mac_cfg_t* mac_cfg) { memcpy(mac_cfg, &config, sizeof(mac_cfg_t)); diff --git a/srsue/src/mac/mux.cc b/srsue/src/mac/mux.cc index e38300b87..2b92061e9 100644 --- a/srsue/src/mac/mux.cc +++ b/srsue/src/mac/mux.cc @@ -62,7 +62,9 @@ void mux::init(rlc_interface_mac *rlc_, srslte::log *log_h_, bsr_interface_mux * void mux::reset() { - lch.clear(); + for (uint32_t i=0;iset_c_rnti(pending_crnti_ce)) { Warning("Pending C-RNTI CE could not be inserted in MAC PDU\n"); } } } + } else { + is_rar = true; } pending_crnti_ce = 0; @@ -200,44 +207,48 @@ uint8_t* mux::pdu_get(uint8_t *payload, uint32_t pdu_sz, uint32_t tx_tti, uint32 } } - // Update buffer states for all logical channels - int sdu_space = pdu_msg.get_sdu_space(); - for (uint32_t i=0;iget_buffer_state(lch[i].id); - lch[i].sched_len = 0; - } - - // data from any Logical Channel, except data from UL-CCCH; - // first only those with positive Bj - for (uint32_t i=0;i= 0) { - lch[i].Bj -= lch[i].sched_len; + if (!is_rar) { + // Update buffer states for all logical channels + int sdu_space = pdu_msg.get_sdu_space(); + for (uint32_t i=0;iget_buffer_state(lch[i].id); + lch[i].sched_len = 0; + Info("lch[%d].buffer_len=%d\n",i,lch[i].buffer_len); + } + + + // data from any Logical Channel, except data from UL-CCCH; + // first only those with positive Bj + for (uint32_t i=0;i= 0) { + lch[i].Bj -= lch[i].sched_len; + } } } - } - // If resources remain, allocate regardless of their Bj value - for (uint32_t i=0;i 0) { - for (int i=(int)lch.size()-1;i>=0;i--) { - if (lch[i].sched_len > 0) { - lch[i].sched_len = -1; - break; + + // Maximize the grant utilization + if (lch.size() > 0) { + for (int i=(int)lch.size()-1;i>=0;i--) { + if (lch[i].sched_len > 0) { + lch[i].sched_len = -1; + break; + } } } - } - // Now allocate the SDUs from the RLC - for (uint32_t i=0;iinfo("Allocating scheduled lch=%d len=%d\n", lch[i].id, lch[i].sched_len); - allocate_sdu(lch[i].id, &pdu_msg, lch[i].sched_len); + // Now allocate the SDUs from the RLC + for (uint32_t i=0;iinfo("Allocating scheduled lch=%d len=%d\n", lch[i].id, lch[i].sched_len); + allocate_sdu(lch[i].id, &pdu_msg, lch[i].sched_len); + } } } @@ -262,7 +273,7 @@ uint8_t* mux::pdu_get(uint8_t *payload, uint32_t pdu_sz, uint32_t tx_tti, uint32 } pthread_mutex_unlock(&mutex); - + return ret; } diff --git a/srsue/src/mac/proc_ra.cc b/srsue/src/mac/proc_ra.cc index 4bceef2a5..18548be23 100644 --- a/srsue/src/mac/proc_ra.cc +++ b/srsue/src/mac/proc_ra.cc @@ -96,9 +96,15 @@ void ra_proc::read_params() { // Read initialization parameters configIndex = mac_cfg->prach_config_index; - preambleIndex = 0; // pass when called from higher layers for non-contention based RA - maskIndex = 0; // same - nof_preambles = liblte_rrc_number_of_ra_preambles_num[mac_cfg->rach.num_ra_preambles]; + if (noncontention_enabled) { + preambleIndex = next_preamble_idx; + maskIndex = next_prach_mask; + noncontention_enabled = false; + } else { + preambleIndex = 0; // pass when called from higher layers for non-contention based RA + maskIndex = 0; // same + } + nof_preambles = liblte_rrc_number_of_ra_preambles_num[mac_cfg->rach.num_ra_preambles]; if (mac_cfg->rach.preambles_group_a_cnfg.present) { nof_groupA_preambles = liblte_rrc_size_of_ra_preambles_group_a_num[mac_cfg->rach.preambles_group_a_cnfg.size_of_ra]; } else { @@ -386,8 +392,13 @@ void ra_proc::step_response_reception() { } } -void ra_proc::step_response_error() { - +void ra_proc::step_response_error() +{ + if (ra_is_ho) { + state = RA_PROBLEM; + rrc->ho_ra_completed(false); + return; + } preambleTransmissionCounter++; if (preambleTransmissionCounter >= preambleTransMax + 1) { rError("Maximum number of transmissions reached (%d)\n", preambleTransMax); @@ -495,8 +506,11 @@ void ra_proc::step_completition() { phy_h->set_crnti(rntis->crnti); - msg3_transmitted = false; + msg3_transmitted = false; state = COMPLETION_DONE; + if (ra_is_ho) { + rrc->ho_ra_completed(true); + } } void ra_proc::step(uint32_t tti_) @@ -536,9 +550,17 @@ void ra_proc::step(uint32_t tti_) } } -void ra_proc::start_mac_order(uint32_t msg_len_bits) +void ra_proc::start_noncont(uint32_t preamble_index, uint32_t prach_mask) { + next_preamble_idx = preamble_index; + next_prach_mask = prach_mask; + noncontention_enabled = true; + start_mac_order(56, true); +} + +void ra_proc::start_mac_order(uint32_t msg_len_bits, bool is_ho) { if (state == IDLE || state == COMPLETION_DONE || state == RA_PROBLEM) { + ra_is_ho = is_ho; started_by_pdcch = false; new_ra_msg_len = msg_len_bits; state = INITIALIZATION; diff --git a/srsue/src/phy/phch_common.cc b/srsue/src/phy/phch_common.cc index 416f146ac..961080a56 100644 --- a/srsue/src/phy/phch_common.cc +++ b/srsue/src/phy/phch_common.cc @@ -47,27 +47,7 @@ phch_common::phch_common(uint32_t max_mutex_) : tx_mutex(max_mutex_) mac = NULL; max_mutex = max_mutex_; nof_mutex = 0; - sr_enabled = false; - is_first_of_burst = true; - is_first_tx = true; - rar_grant_pending = false; - pathloss = 0; - cur_pathloss = 0; - cur_pusch_power = 0; - p0_preamble = 0; - cur_radio_power = 0; - rx_gain_offset = 0; - sr_last_tx_tti = -1; - cur_pusch_power = 0; - - serving_cell_report_period = 20; - bzero(zeros, 50000*sizeof(cf_t)); - - // FIXME: This is an ungly fix to avoid the TX filters to empty - for (int i=0;i<50000;i++) { - zeros[i] = 0.01*cexpf(((float) i/50000)*0.1*_Complex_I); - } bzero(&dl_metrics, sizeof(dl_metrics_t)); dl_metrics_read = true; dl_metrics_count = 0; @@ -77,6 +57,16 @@ phch_common::phch_common(uint32_t max_mutex_) : tx_mutex(max_mutex_) bzero(&sync_metrics, sizeof(sync_metrics_t)); sync_metrics_read = true; sync_metrics_count = 0; + + bzero(zeros, 50000*sizeof(cf_t)); + + // FIXME: This is an ugly fix to avoid the TX filters to empty + for (int i=0;i<50000;i++) { + zeros[i] = 0.01*cexpf(((float) i/50000)*0.1*_Complex_I); + } + + reset(); + } void phch_common::init(phy_interface_rrc::phy_cfg_t *_config, phy_args_t *_args, srslte::log *_log, srslte::radio *_radio, rrc_interface_phy *_rrc, mac_interface_phy *_mac) @@ -224,6 +214,15 @@ bool phch_common::get_pending_ack(uint32_t tti, uint32_t *I_lowest, uint32_t *n_ return pending_ack[TTIMOD(tti)].enabled; } +bool phch_common::is_any_pending_ack() { + for (int i=0;ierror("Cell HO: Can't find PCI=%d\n", cell.id); + return false; + } + + int cnt = 0; + while(worker_com->is_any_pending_ack() && cnt < 10) { + usleep(1000); + cnt++; + log_h->info("Cell HO: Waiting pending PHICH\n"); + } + + bool ret; + this->cell = cell; + Info("Cell HO: Stopping sync with current cell\n"); + worker_com->reset_ul(); + stop_sync(); + Info("Cell HO: Reconfiguring cell\n"); + if (set_cell()) { + Info("Cell HO: Synchronizing with new cell\n"); + resync_sfn(true, true); + ret = true; + } else { + log_h->error("Cell HO: Configuring cell PCI=%d\n", cell.id); + ret = false; + } + return ret; +} + bool phch_recv::cell_select(uint32_t earfcn, srslte_cell_t cell) { // Check if we are already camping in this cell @@ -373,7 +406,7 @@ bool phch_recv::cell_select(uint32_t earfcn, srslte_cell_t cell) { resync_sfn(); - usleep(500000); // Time offset we set start_rx to start receveing samples + usleep(500000); // Time offset we set start_rx to start receiving samples return true; } else { log_h->error("Cell Select: Configuring cell in EARFCN=%d, PCI=%d\n", earfcn, cell.id); @@ -443,10 +476,10 @@ void phch_recv::stop_rx() { radio_is_rx = false; } -void phch_recv::start_rx() { +void phch_recv::start_rx(bool now) { if (!radio_is_rx) { Info("SYNC: Starting RX streaming\n"); - radio_h->start_rx(); + radio_h->start_rx(now); } radio_is_rx = true; } @@ -626,7 +659,6 @@ void phch_recv::run_thread() workers_pool->start_worker(worker); intra_freq_meas.write(tti, buffer[0], SRSLTE_SF_LEN_PRB(cell.nof_prb)); - break; case 0: log_h->error("SYNC: Sync error. Sending out-of-sync to RRC\n"); @@ -984,6 +1016,10 @@ float phch_recv::measure::snr() { return mean_snr; } +void phch_recv::measure::set_rx_gain_offset(float rx_gain_offset) { + this->rx_gain_offset = rx_gain_offset; +} + phch_recv::measure::ret_code phch_recv::measure::run_subframe_sync(srslte_ue_sync_t *ue_sync, uint32_t sf_idx) { int sync_res = srslte_ue_sync_zerocopy_multi(ue_sync, buffer); @@ -1023,7 +1059,7 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx) return ERROR; } - float rsrp = 10*log10(srslte_chest_dl_get_rsrp(&ue_dl.chest)) + 30; + float rsrp = 10*log10(srslte_chest_dl_get_rsrp(&ue_dl.chest)) + 30 - rx_gain_offset; float rsrq = 10*log10(srslte_chest_dl_get_rsrq(&ue_dl.chest)); float snr = 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest)); @@ -1081,7 +1117,7 @@ void phch_recv::scell_recv::reset() measure_p.reset(); } -int phch_recv::scell_recv::find_cells(cf_t *input_buffer, srslte_cell_t current_cell, uint32_t nof_sf, cell_info_t cells[MAX_CELLS]) +int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, srslte_cell_t current_cell, uint32_t nof_sf, cell_info_t cells[MAX_CELLS]) { uint32_t fft_sz = srslte_symbol_sz(current_cell.nof_prb); uint32_t sf_len = SRSLTE_SF_LEN(fft_sz); @@ -1100,6 +1136,8 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, srslte_cell_t current_ srslte_cell_t found_cell; memcpy(&found_cell, ¤t_cell, sizeof(srslte_cell_t)); + measure_p.set_rx_gain_offset(rx_gain_offset); + for (uint32_t n_id_2=0;n_id_2<3;n_id_2++) { if (current_cell.id%3 != n_id_2) { @@ -1164,10 +1202,12 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, srslte_cell_t current_ void phch_recv::meas_reset() { // Stop all measurements intra_freq_meas.clear_cells(); + worker_com->pcell_meas_enabled = false; } int phch_recv::meas_start(uint32_t earfcn, int pci) { if (earfcn == current_earfcn) { + worker_com->pcell_meas_enabled = true; intra_freq_meas.add_cell(pci); return 0; } else { @@ -1199,7 +1239,7 @@ void phch_recv::intra_measure::init(phch_common *common, rrc_interface_phy *rrc, search_buffer = (cf_t*) srslte_vec_malloc(CAPTURE_LEN_SF*SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB)*sizeof(cf_t)); - if (srslte_ringbuffer_init(&ring_buffer, sizeof(cf_t)*50*SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB))) { + if (srslte_ringbuffer_init(&ring_buffer, sizeof(cf_t)*100*SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB))) { return; } @@ -1222,6 +1262,9 @@ void phch_recv::intra_measure::set_primay_cell(uint32_t earfcn, srslte_cell_t ce void phch_recv::intra_measure::clear_cells() { active_pci.clear(); receive_enabled = false; + receiving = false; + receive_cnt = 0; + srslte_ringbuffer_reset(&ring_buffer); } void phch_recv::intra_measure::add_cell(int pci) { @@ -1234,6 +1277,15 @@ void phch_recv::intra_measure::add_cell(int pci) { } } +int phch_recv::intra_measure::get_offset(uint32_t pci) { + for (int i=0;i::iterator newEnd = std::remove(active_pci.begin(), active_pci.end(), pci); @@ -1257,6 +1309,7 @@ void phch_recv::intra_measure::write(uint32_t tti, cf_t *data, uint32_t nsamples } if (receiving == true) { if (srslte_ringbuffer_write(&ring_buffer, data, nsamples*sizeof(cf_t)) < (int) (nsamples*sizeof(cf_t))) { + Warning("Error writing to ringbuffer\n"); receiving = false; srslte_ringbuffer_reset(&ring_buffer); } else { @@ -1282,12 +1335,11 @@ void phch_recv::intra_measure::run_thread() // Read 5 ms data from buffer srslte_ringbuffer_read(&ring_buffer, search_buffer, CAPTURE_LEN_SF*current_sflen*sizeof(cf_t)); - int found_cells = scell.find_cells(search_buffer, primary_cell, CAPTURE_LEN_SF, info); + int found_cells = scell.find_cells(search_buffer, common->rx_gain_offset, primary_cell, CAPTURE_LEN_SF, info); receiving = false; srslte_ringbuffer_reset(&ring_buffer); for (int i=0;irx_gain_offset; rrc->new_phy_meas(info[i].rsrp, info[i].rsrq, measure_tti, current_earfcn, info[i].pci); } // Look for other cells not found automatically diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 5d93d94a4..e811baefc 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -94,10 +94,11 @@ void phch_worker::reset() bzero(&pucch_sched, sizeof(srslte_pucch_sched_t)); bzero(&srs_cfg, sizeof(srslte_refsignal_srs_cfg_t)); bzero(&period_cqi, sizeof(srslte_cqi_periodic_cfg_t)); - I_sr = 0; + sr_configured = false; rnti_is_set = false; rar_cqi_request = false; - cfi = 0; + I_sr = 0; + cfi = 0; } void phch_worker::set_common(phch_common* phy_) @@ -801,7 +802,7 @@ void phch_worker::set_uci_ack(bool ack[SRSLTE_MAX_CODEWORDS], bool tb_en[SRSLTE_ void phch_worker::set_uci_sr() { uci_data.scheduling_request = false; - if (phy->sr_enabled) { + if (phy->sr_enabled && sr_configured) { uint32_t sr_tx_tti = TTI_TX(tti); // Get I_sr parameter if (srslte_ue_ul_sr_send_tti(I_sr, sr_tx_tti)) { @@ -944,7 +945,8 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui snprintf(timestr, 64, ", tot_time=%4d us", (int) logtime_start[0].tv_usec); #endif - Info("PUSCH: tti_tx=%d, alloc=(%d,%d), tbs=%d, mcs=%d, rv=%d, ack=%s, ri=%s, cfo=%.1f KHz%s\n", + uint8_t dummy[2] = {0,0}; + log_h->info_hex(payload?payload:dummy, payload?grant->mcs.tbs/8:1,"PUSCH: tti_tx=%d, alloc=(%d,%d), tbs=%d, mcs=%d, rv=%d, ack=%s, ri=%s, cfo=%.1f KHz%s\n", (tti+HARQ_DELAY_MS)%10240, grant->n_prb[0], grant->n_prb[0]+grant->L_prb, grant->mcs.tbs/8, grant->mcs.idx, rv, @@ -1144,7 +1146,7 @@ void phch_worker::set_ul_params(bool pregen_disabled) /* SR configuration */ I_sr = dedicated->sched_request_cnfg.sr_cnfg_idx; - + sr_configured = true; if (pregen_enabled && !pregen_disabled) { Info("Pre-generating UL signals worker=%d\n", get_id()); @@ -1253,7 +1255,7 @@ void phch_worker::update_measurements() } else { phy->avg_rsrp_db = SRSLTE_VEC_EMA(phy->avg_rsrp_db, rsrp, 0.8); } - if ((tti%phy->serving_cell_report_period) == 0) { + if ((tti%phy->pcell_report_period) == 0 && phy->pcell_meas_enabled) { phy->rrc->new_phy_meas(phy->avg_rsrp_db, phy->avg_rsrq_db, tti); } } diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 7d3b8f311..880f8e609 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -206,15 +206,11 @@ void phy::set_timeadv(uint32_t ta_cmd) { void phy::configure_prach_params() { - if (sf_recv.status_is_sync()) { - Debug("Configuring PRACH parameters\n"); - srslte_cell_t cell; - sf_recv.get_current_cell(&cell); - if (!prach_buffer.set_cell(cell)) { - Error("Configuring PRACH parameters\n"); - } - } else { - Error("Cell is not synchronized\n"); + Debug("Configuring PRACH parameters\n"); + srslte_cell_t cell; + sf_recv.get_current_cell(&cell); + if (!prach_buffer.set_cell(cell)) { + Error("Configuring PRACH parameters\n"); } } @@ -264,6 +260,10 @@ bool phy::cell_select(uint32_t earfcn, srslte_cell_t phy_cell) return sf_recv.cell_select(earfcn, phy_cell); } +bool phy::cell_handover(srslte_cell_t cell) { + return sf_recv.cell_handover(cell); +} + float phy::get_phr() { float phr = radio_handler->get_max_tx_power() - workers_common.cur_pusch_power; @@ -321,6 +321,7 @@ void phy::reset() for(uint32_t i=0;itimer_get_unique_id(); t310 = mac_timers->timer_get_unique_id(); t311 = mac_timers->timer_get_unique_id(); + t304 = mac_timers->timer_get_unique_id(); transaction_id = 0; @@ -105,6 +106,8 @@ void rrc::init(phy_interface_rrc *phy_, nof_sib1_trials = 0; last_win_start = 0; + pending_mob_reconf = false; + // Set default values for all layers set_rrc_default(); set_phy_default(); @@ -232,6 +235,13 @@ void rrc::run_thread() { case RRC_STATE_CONNECTED: // Take measurements, cell reselection, etc break; + case RRC_STATE_HO_PREPARE: + ho_prepare(); + state = RRC_STATE_HO_PROCESS; + break; + case RRC_STATE_HO_PROCESS: + // wait for HO to finish + break; case RRC_STATE_LEAVE_CONNECTED: usleep(60000); rrc_log->info("Leaving RRC_CONNECTED state\n"); @@ -412,6 +422,9 @@ void rrc::select_next_cell_in_plmn() { { last_selected_cell = i; current_cell = &known_cells[i]; + rrc_log->info("Selected cell PCI=%d, EARFCN=%d, Cell ID=0x%x, addr=0x%x\n", + current_cell->phy_cell.id, current_cell->earfcn, + current_cell->sib1.cell_id, current_cell); return; } else { rrc_log->warning("Selecting cell EARFCN=%d, Cell ID=0x%x.\n", @@ -433,17 +446,17 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { // find if cell_id-earfcn combination already exists for (uint32_t i = 0; i < known_cells.size(); i++) { if (earfcn == known_cells[i].earfcn && phy_cell.id == known_cells[i].phy_cell.id) { - known_cells[i].rsrp = rsrp; - known_cells[i].in_sync = true; current_cell = &known_cells[i]; - rrc_log->info("Updating cell EARFCN=%d, PCI=%d, RSRP=%.1f dBm\n", known_cells[i].earfcn, - known_cells[i].phy_cell.id, known_cells[i].rsrp); + current_cell->rsrp = rsrp; + current_cell->in_sync = true; + rrc_log->info("Updating cell EARFCN=%d, PCI=%d, RSRP=%.1f dBm\n", current_cell->earfcn, + current_cell->phy_cell.id, current_cell->rsrp); - if (!known_cells[i].has_valid_sib1) { + if (!current_cell->has_valid_sib1) { si_acquire_state = SI_ACQUIRE_SIB1; } else if (state == RRC_STATE_PLMN_SELECTION) { - for (uint32_t i = 0; i < current_cell->sib1.N_plmn_ids; i++) { - nas->plmn_found(current_cell->sib1.plmn_id[i].id, current_cell->sib1.tracking_area_code); + for (uint32_t j = 0; j < current_cell->sib1.N_plmn_ids; j++) { + nas->plmn_found(current_cell->sib1.plmn_id[j].id, current_cell->sib1.tracking_area_code); } usleep(5000); phy->cell_search_next(); @@ -465,9 +478,9 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { si_acquire_state = SI_ACQUIRE_SIB1; - rrc_log->info("New Cell: PCI=%d, PRB=%d, Ports=%d, EARFCN=%d, RSRP=%.1f dBm\n", - cell.phy_cell.id, cell.phy_cell.nof_prb, cell.phy_cell.nof_ports, - cell.earfcn, cell.rsrp); + rrc_log->info("New Cell: PCI=%d, PRB=%d, Ports=%d, EARFCN=%d, RSRP=%.1f dBm, addr=0x%x\n", + current_cell->phy_cell.id, current_cell->phy_cell.nof_prb, current_cell->phy_cell.nof_ports, + current_cell->earfcn, current_cell->rsrp, current_cell); } // PHY indicates that has gone through all known EARFCN @@ -480,7 +493,22 @@ void rrc::earfcn_end() { } } - +void rrc::add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp) { + for (uint32_t i = 0; i < known_cells.size(); i++) { + if (earfcn == known_cells[i].earfcn && pci == known_cells[i].phy_cell.id) { + known_cells[i].rsrp = rsrp; + return; + } + } + rrc_log->info("Added neighbour cell earfcn=%d, pci=%d, rsrp=%f\n", earfcn, pci, rsrp); + cell_t c; + bzero(&c, sizeof(cell_t)); + c.earfcn = earfcn; + c.rsrp = rsrp; + memcpy(&c.phy_cell, ¤t_cell->phy_cell, sizeof(srslte_cell_t)); + c.phy_cell.id = pci; + known_cells.push_back(c); +} @@ -572,6 +600,8 @@ void rrc::timer_expired(uint32_t timeout_id) { } else if (timeout_id == t301) { rrc_log->info("Timer T301 expired: Going to RRC IDLE\n"); state = RRC_STATE_LEAVE_CONNECTED; + } else if (timeout_id == t304) { + rrc_log->console("Timer T304 expired: Handover failed\n"); // fw to measurement } else if (!measurements.timer_expired(timeout_id)) { rrc_log->error("Timeout from unknown timer id %d\n", timeout_id); @@ -777,40 +807,134 @@ void rrc::send_security_mode_complete(uint32_t lcid, byte_buffer_t *pdu) { send_ul_dcch_msg(pdu); } -void rrc::send_rrc_con_reconfig_complete(uint32_t lcid, byte_buffer_t *pdu) { +void rrc::send_rrc_con_reconfig_complete(byte_buffer_t *pdu) { rrc_log->debug("Preparing RRC Connection Reconfig Complete\n"); ul_dcch_msg.msg_type = LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_RECONFIG_COMPLETE; ul_dcch_msg.msg.rrc_con_reconfig_complete.rrc_transaction_id = transaction_id; - send_ul_dcch_msg(); + send_ul_dcch_msg(pdu); +} + +void rrc::ho_prepare() { + if (pending_mob_reconf) { + rrc_log->info("Processing HO command to target PCell=%d\n", mob_reconf.mob_ctrl_info.target_pci); + + // Section 5.3.5.4 + mac_timers->timer_get(t310)->stop(); + mac_timers->timer_get(t304)->set(this, liblte_rrc_t304_num[mob_reconf.mob_ctrl_info.t304]); + if (mob_reconf.mob_ctrl_info.carrier_freq_eutra_present && + mob_reconf.mob_ctrl_info.carrier_freq_eutra.dl_carrier_freq != current_cell->earfcn) { + rrc_log->warning("Received mobilityControlInfo for inter-frequency handover\n"); + } + + phy->meas_reset(); + mac->wait_uplink(); + pdcp->reestablish(); + rlc->reestablish(); + mac->reset(); + phy->reset(); + mac->set_ho_rnti(mob_reconf.mob_ctrl_info.new_ue_id, mob_reconf.mob_ctrl_info.target_pci); + apply_rr_config_common_dl(&mob_reconf.mob_ctrl_info.rr_cnfg_common); + + uint32_t current_earfcn = 0; + phy->get_current_cell(NULL, ¤t_earfcn); + + bool found = false; + for (uint32_t i = 0; i < known_cells.size(); i++) { + rrc_log->info("cell[%d]=%d:%d, cur_earfcn=%d\n", i, known_cells[i].earfcn, known_cells[i].phy_cell.id, + current_cell->earfcn); + if (known_cells[i].earfcn == current_earfcn && + known_cells[i].phy_cell.id == mob_reconf.mob_ctrl_info.target_pci) { + rrc_log->info("Selecting new cell pci=%d\n", known_cells[i].phy_cell.id); + if (!phy->cell_handover(known_cells[i].phy_cell)) { + rrc_log->error("Could not synchronize with target cell pci=%d\n", known_cells[i].phy_cell.id); + } + found = true; + break; + } + } + if (!found) { + rrc_log->error("Could not find target cell pci=%d\n", mob_reconf.mob_ctrl_info.target_pci); + return; + } + + if (mob_reconf.mob_ctrl_info.rach_cnfg_ded_present) { + mac->start_noncont_ho(mob_reconf.mob_ctrl_info.rach_cnfg_ded.preamble_index, + mob_reconf.mob_ctrl_info.rach_cnfg_ded.prach_mask_index); + } else { + mac->start_cont_ho(); + } + + printf("ncc=%d\n", mob_reconf.sec_cnfg_ho.intra_lte.next_hop_chaining_count); + usim->generate_as_keys_ho(mob_reconf.mob_ctrl_info.target_pci, current_earfcn, + k_rrc_enc, k_rrc_int, k_up_enc, k_up_int, cipher_algo, integ_algo); + pdcp->config_security(1, k_rrc_enc, k_rrc_int, cipher_algo, integ_algo); + send_rrc_con_reconfig_complete(NULL); + } } +void rrc::ho_ra_completed(bool ra_successful) { + if (pending_mob_reconf) { + + measurements.ho_finish(); + + if (mob_reconf.meas_cnfg_present) { + measurements.parse_meas_config(&mob_reconf.meas_cnfg); + } + + if (ra_successful) { + mac_timers->timer_get(t304)->stop(); + + apply_rr_config_common_ul(&mob_reconf.mob_ctrl_info.rr_cnfg_common); + if (mob_reconf.rr_cnfg_ded_present) { + apply_rr_config_dedicated(&mob_reconf.rr_cnfg_ded); + } + } + + rrc_log->info("HO %ssuccessful\n", ra_successful?"":"un"); + rrc_log->console("HO %ssuccessful\n", ra_successful?"":"un"); + + pending_mob_reconf = false; + state = RRC_STATE_CONNECTED; + } else { + rrc_log->error("Received HO random access completed but no pending mobility reconfiguration info\n"); + } +} void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig, byte_buffer_t *pdu) { uint32_t i; - if (reconfig->rr_cnfg_ded_present) { - apply_rr_config_dedicated(&reconfig->rr_cnfg_ded); - } else { - printf("received con reconfig no rr confg present\n"); - } - if (reconfig->meas_cnfg_present) { - measurements.parse_meas_config(&reconfig->meas_cnfg); - } if (reconfig->mob_ctrl_info_present) { - //TODO: handle mob_ctrl_info - } - send_rrc_con_reconfig_complete(lcid, pdu); + rrc_log->info("Received HO command to target PCell=%d\n", reconfig->mob_ctrl_info.target_pci); + rrc_log->console("Received HO command to target PCell=%d\n", reconfig->mob_ctrl_info.target_pci); + + // store mobilityControlInfo + memcpy(&mob_reconf, reconfig, sizeof(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT)); + pending_mob_reconf = true; + + state = RRC_STATE_HO_PREPARE; + + } else { + // Section 5.3.5.3 + if (reconfig->rr_cnfg_ded_present) { + apply_rr_config_dedicated(&reconfig->rr_cnfg_ded); + } + if (reconfig->meas_cnfg_present) { + measurements.parse_meas_config(&reconfig->meas_cnfg); + } + + send_rrc_con_reconfig_complete(pdu); - byte_buffer_t *nas_sdu; - for (i = 0; i < reconfig->N_ded_info_nas; i++) { - nas_sdu = pool_allocate; - memcpy(nas_sdu->msg, &reconfig->ded_info_nas_list[i].msg, reconfig->ded_info_nas_list[i].N_bytes); - nas_sdu->N_bytes = reconfig->ded_info_nas_list[i].N_bytes; - nas->write_pdu(lcid, nas_sdu); + byte_buffer_t *nas_sdu; + for (i = 0; i < reconfig->N_ded_info_nas; i++) { + nas_sdu = pool_allocate; + memcpy(nas_sdu->msg, &reconfig->ded_info_nas_list[i].msg, reconfig->ded_info_nas_list[i].N_bytes); + nas_sdu->N_bytes = reconfig->ded_info_nas_list[i].N_bytes; + nas->write_pdu(lcid, nas_sdu); + } } } @@ -1022,7 +1146,7 @@ void rrc::send_ul_dcch_msg(byte_buffer_t *pdu) } void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) { - rrc_log->info_hex(sdu->msg, sdu->N_bytes, "RX %s SDU", get_rb_name(lcid).c_str()); + rrc_log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU", get_rb_name(lcid).c_str()); switch (state) { case RRC_STATE_CONNECTING: send_con_setup_complete(sdu); @@ -1037,8 +1161,8 @@ void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) { } void rrc::write_pdu(uint32_t lcid, byte_buffer_t *pdu) { - rrc_log->info_hex(pdu->msg, pdu->N_bytes, "TX %s PDU", get_rb_name(lcid).c_str()); - rrc_log->info("TX PDU Stack latency: %ld us\n", pdu->get_latency_us()); + rrc_log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU", get_rb_name(lcid).c_str()); + rrc_log->info("RX PDU Stack latency: %ld us\n", pdu->get_latency_us()); switch (lcid) { case RB_ID_SRB0: @@ -1049,7 +1173,7 @@ void rrc::write_pdu(uint32_t lcid, byte_buffer_t *pdu) { parse_dl_dcch(lcid, pdu); break; default: - rrc_log->error("TX PDU with invalid bearer id: %s", lcid); + rrc_log->error("RX PDU with invalid bearer id: %s", lcid); break; } } @@ -1265,6 +1389,54 @@ void rrc::send_rrc_ue_cap_info(uint32_t lcid, byte_buffer_t *pdu) { * *******************************************************************************/ +void rrc::apply_rr_config_common_dl(LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT *config) { + mac_interface_rrc::mac_cfg_t mac_cfg; + mac->get_config(&mac_cfg); + if (config->rach_cnfg_present) { + memcpy(&mac_cfg.rach, &config->rach_cnfg, sizeof(LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT)); + } + mac_cfg.prach_config_index = config->prach_cnfg.root_sequence_index; + mac_cfg.ul_harq_params.max_harq_msg3_tx = config->rach_cnfg.max_harq_msg3_tx; + + mac->set_config(&mac_cfg); + + phy_interface_rrc::phy_cfg_t phy_cfg; + phy->get_config(&phy_cfg); + phy_interface_rrc::phy_cfg_common_t *common = &phy_cfg.common; + + if (config->pdsch_cnfg_present) { + memcpy(&common->pdsch_cnfg, &config->pdsch_cnfg, sizeof(LIBLTE_RRC_PDSCH_CONFIG_COMMON_STRUCT)); + } + common->prach_cnfg.root_sequence_index = config->prach_cnfg.root_sequence_index; + if (config->prach_cnfg.prach_cnfg_info_present) { + memcpy(&common->prach_cnfg.prach_cnfg_info, &config->prach_cnfg.prach_cnfg_info, sizeof(LIBLTE_RRC_PRACH_CONFIG_INFO_STRUCT)); + } + + phy->set_config_common(common); +} + +void rrc::apply_rr_config_common_ul(LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT *config) { + phy_interface_rrc::phy_cfg_t phy_cfg; + phy->get_config(&phy_cfg); + phy_interface_rrc::phy_cfg_common_t *common = &phy_cfg.common; + + memcpy(&common->pusch_cnfg, &config->pusch_cnfg, sizeof(LIBLTE_RRC_PUSCH_CONFIG_COMMON_STRUCT)); + if (config->pucch_cnfg_present) { + memcpy(&common->pucch_cnfg, &config->pucch_cnfg, sizeof(LIBLTE_RRC_PUCCH_CONFIG_COMMON_STRUCT)); + } + if (config->ul_pwr_ctrl_present) { + memcpy(&common->ul_pwr_ctrl, &config->ul_pwr_ctrl, sizeof(LIBLTE_RRC_UL_POWER_CONTROL_COMMON_STRUCT)); + } + if (config->srs_ul_cnfg.present) { + memcpy(&common->srs_ul_cnfg, &config->srs_ul_cnfg, sizeof(LIBLTE_RRC_SRS_UL_CONFIG_COMMON_STRUCT)); + } else { + // default is release + common->srs_ul_cnfg.present = false; + } + phy->set_config_common(common); + phy->configure_ul_params(); +} + void rrc::apply_sib2_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2) { // Apply RACH timeAlginmentTimer configuration @@ -1800,6 +1972,9 @@ void rrc::rrc_meas::new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, floa if (earfcn == 0) { L3_filter(&pcell_measurement, values); } else { + // Add to known cells + parent->add_neighbour_cell(earfcn, pci, rsrp); + // Save PHY measurement for all active measurements whose earfcn/pci matches for(std::map::iterator iter=active.begin(); iter!=active.end(); ++iter) { meas_t *m = &iter->second; @@ -1815,6 +1990,7 @@ void rrc::rrc_meas::new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, floa return; } } + parent->rrc_log->warning("MEAS: Received measurement from unknown EARFCN=%d\n", earfcn); } } @@ -1866,7 +2042,7 @@ void rrc::rrc_meas::generate_report(uint32_t meas_id) report->pcell_rsrp_result = value_to_range(RSRP, pcell_measurement.ms[RSRP]); report->pcell_rsrq_result = value_to_range(RSRQ, pcell_measurement.ms[RSRQ]); - log_h->console("MEAS: Generate report MeasId=%d, rsrp=%f rsrq=%f\n", + log_h->info("MEAS: Generate report MeasId=%d, rsrp=%f rsrq=%f\n", report->meas_id, pcell_measurement.ms[RSRP], pcell_measurement.ms[RSRQ]); // TODO: report up to 8 best cells @@ -1882,7 +2058,7 @@ void rrc::rrc_meas::generate_report(uint32_t meas_id) rc->meas_result.rsrp_result = value_to_range(RSRP, cell->second.ms[RSRP]); rc->meas_result.rsrq_result = value_to_range(RSRQ, cell->second.ms[RSRQ]); - log_h->console("MEAS: Add neigh=%d, pci=%d, rsrp=%f, rsrq=%f\n", + log_h->info("MEAS: Add neigh=%d, pci=%d, rsrp=%f, rsrq=%f\n", report->meas_result_neigh_cells.eutra.n_result, rc->phys_cell_id, cell->second.ms[RSRP], cell->second.ms[RSRQ]); @@ -2037,6 +2213,26 @@ void rrc::rrc_meas::calculate_triggers(uint32_t tti) } } +// Procedure upon handover or reestablishment 5.5.6.1 +void rrc::rrc_meas::ho_finish() { + // Remove all measId with trigger periodic + std::map::iterator iter = active.begin(); + while (iter != active.end()) { + if (reports_cfg[iter->second.report_id].trigger_type == report_cfg_t::PERIODIC) { + remove_meas_id(iter++); + } else { + ++iter; + } + } + + //TODO: Inter-frequency handover + + // Stop all reports + for (std::map::iterator iter = active.begin(); iter != active.end(); ++iter) { + stop_reports(&iter->second); + } +} + // 5.5.4.1 expiry of periodical reporting timer bool rrc::rrc_meas::timer_expired(uint32_t timer_id) { for (std::map::iterator iter = active.begin(); iter != active.end(); ++iter) { @@ -2048,41 +2244,53 @@ bool rrc::rrc_meas::timer_expired(uint32_t timer_id) { return false; } +void rrc::rrc_meas::stop_reports(meas_t *m) { + mac_timers->timer_get(m->periodic_timer)->stop(); + m->triggered = false; +} + void rrc::rrc_meas::stop_reports_object(uint32_t object_id) { for (std::map::iterator iter = active.begin(); iter != active.end(); ++iter) { - meas_t *m = &iter->second; - if (m->object_id == object_id) { - mac_timers->timer_get(m->periodic_timer)->stop(); - m->triggered = false; + if (iter->second.object_id == object_id) { + stop_reports(&iter->second); } } } void rrc::rrc_meas::remove_meas_object(uint32_t object_id) { - // CHECKME: Is the delete from the map correct? - for(std::map::iterator iter=active.begin(); iter!=active.end(); ++iter) { - meas_t m = iter->second; - if (m.object_id == object_id) { - remove_meas_id(iter->first); + std::map::iterator iter = active.begin(); + while (iter != active.end()) { + if (iter->second.object_id == object_id) { + remove_meas_id(iter++); + } else { + ++iter; } } } void rrc::rrc_meas::remove_meas_report(uint32_t report_id) { - // CHECKME: Is the delete from the map correct? - for(std::map::iterator iter=active.begin(); iter!=active.end(); ++iter) { - meas_t m = iter->second; - if (m.report_id == report_id) { - remove_meas_id(iter->first); + std::map::iterator iter = active.begin(); + while (iter != active.end()) { + if (iter->second.report_id == report_id) { + remove_meas_id(iter++); + } else { + ++iter; } } } -void rrc::rrc_meas::remove_meas_id(uint32_t meas_id) { - mac_timers->timer_get(active[meas_id].periodic_timer)->stop(); - mac_timers->timer_release_id(active[meas_id].periodic_timer); - active.erase(meas_id); - log_h->info("MEAS: Removed measId=%d\n", meas_id); +void rrc::rrc_meas::remove_meas_id(uint32_t measId) { + mac_timers->timer_get(active[measId].periodic_timer)->stop(); + mac_timers->timer_release_id(active[measId].periodic_timer); + log_h->info("MEAS: Removed measId=%d\n", measId); + active.erase(measId); +} + +void rrc::rrc_meas::remove_meas_id(std::map::iterator it) { + mac_timers->timer_get(it->second.periodic_timer)->stop(); + mac_timers->timer_release_id(it->second.periodic_timer); + log_h->info("MEAS: Removed measId=%d\n", it->first); + active.erase(it); } /* Parses MeasConfig object from RRCConnectionReconfiguration message and applies configuration @@ -2091,28 +2299,6 @@ void rrc::rrc_meas::remove_meas_id(uint32_t meas_id) { void rrc::rrc_meas::parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *cfg) { - // Measurement identity removal 5.5.2.2 - for (uint32_t i=0;iN_meas_id_to_remove;i++) { - remove_meas_id(cfg->meas_id_to_remove_list[i]); - } - - // Measurement identity addition/modification 5.5.2.3 - if (cfg->meas_id_to_add_mod_list_present) { - for (uint32_t i=0;imeas_id_to_add_mod_list.N_meas_id;i++) { - LIBLTE_RRC_MEAS_ID_TO_ADD_MOD_STRUCT *measId = &cfg->meas_id_to_add_mod_list.meas_id_list[i]; - // Stop the timer if the entry exists or create the timer if not - if (active.count(measId->meas_id)) { - mac_timers->timer_get(active[measId->meas_id].periodic_timer)->stop(); - } else { - active[measId->meas_id].periodic_timer = mac_timers->timer_get_unique_id(); - } - active[measId->meas_id].object_id = measId->meas_obj_id; - active[measId->meas_id].report_id = measId->rep_cnfg_id; - log_h->info("MEAS: Added measId=%d, measObjectId=%d, reportConfigId=%d\n", - measId->meas_id, measId->meas_obj_id, measId->rep_cnfg_id); - } - } - // Measurement object removal 5.5.2.4 for (uint32_t i=0;iN_meas_obj_to_remove;i++) { objects.erase(cfg->meas_obj_to_remove_list[i]); @@ -2196,11 +2382,9 @@ void rrc::rrc_meas::parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *cfg) // Reset reports counter for(std::map::iterator iter=active.begin(); iter!=active.end(); ++iter) { - meas_t m = iter->second; - if (m.report_id == cfg->rep_cnfg_to_add_mod_list.rep_cnfg_list[i].rep_cnfg_id) { + if (iter->second.report_id == cfg->rep_cnfg_to_add_mod_list.rep_cnfg_list[i].rep_cnfg_id) { iter->second.nof_reports_sent = 0; - m.triggered = false; - mac_timers->timer_get(m.periodic_timer)->stop(); + stop_reports(&iter->second); } } } else { @@ -2227,6 +2411,28 @@ void rrc::rrc_meas::parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *cfg) log_h->info("MEAS: Quantity configuration k_rsrp=%d, k_rsrq=%d\n", filter_k_rsrp, filter_k_rsrq); } + // Measurement identity removal 5.5.2.2 + for (uint32_t i=0;iN_meas_id_to_remove;i++) { + remove_meas_id(cfg->meas_id_to_remove_list[i]); + } + + // Measurement identity addition/modification 5.5.2.3 + if (cfg->meas_id_to_add_mod_list_present) { + for (uint32_t i=0;imeas_id_to_add_mod_list.N_meas_id;i++) { + LIBLTE_RRC_MEAS_ID_TO_ADD_MOD_STRUCT *measId = &cfg->meas_id_to_add_mod_list.meas_id_list[i]; + // Stop the timer if the entry exists or create the timer if not + if (active.count(measId->meas_id)) { + mac_timers->timer_get(active[measId->meas_id].periodic_timer)->stop(); + } else { + active[measId->meas_id].periodic_timer = mac_timers->timer_get_unique_id(); + } + active[measId->meas_id].object_id = measId->meas_obj_id; + active[measId->meas_id].report_id = measId->rep_cnfg_id; + log_h->info("MEAS: Added measId=%d, measObjectId=%d, reportConfigId=%d\n", + measId->meas_id, measId->meas_obj_id, measId->rep_cnfg_id); + } + } + // S-Measure if (cfg->s_meas_present) { if (cfg->s_meas) { diff --git a/srsue/src/upper/usim.cc b/srsue/src/upper/usim.cc index e1d2c204f..842f9b361 100644 --- a/srsue/src/upper/usim.cc +++ b/srsue/src/upper/usim.cc @@ -222,6 +222,7 @@ void usim::generate_as_keys(uint32_t count_ul, CIPHERING_ALGORITHM_ID_ENUM cipher_algo, INTEGRITY_ALGORITHM_ID_ENUM integ_algo) { + // Generate K_enb security_generate_k_enb( k_asme, count_ul, @@ -242,6 +243,39 @@ void usim::generate_as_keys(uint32_t count_ul, k_up_int); } +void usim::generate_as_keys_ho(uint32_t pci, + uint32_t earfcn, + uint8_t *k_rrc_enc, + uint8_t *k_rrc_int, + uint8_t *k_up_enc, + uint8_t *k_up_int, + CIPHERING_ALGORITHM_ID_ENUM cipher_algo, + INTEGRITY_ALGORITHM_ID_ENUM integ_algo) +{ + + // Generate K_enb + security_generate_k_enb_star( k_enb, + pci, + earfcn, + k_enb_star); + + memcpy(k_enb, k_enb_star, 32); + + // Generate K_rrc_enc and K_rrc_int + security_generate_k_rrc( k_enb, + cipher_algo, + integ_algo, + k_rrc_enc, + k_rrc_int); + + // Generate K_up_enc and K_up_int + security_generate_k_up( k_enb, + cipher_algo, + integ_algo, + k_up_enc, + k_up_int); +} + /******************************************************************************* Helpers *******************************************************************************/ From d562a70261512ccf0096d638bffe7649a1ed499c Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 23 Nov 2017 21:55:49 +0100 Subject: [PATCH 158/242] fix USIM test --- srsue/test/upper/usim_test.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/srsue/test/upper/usim_test.cc b/srsue/test/upper/usim_test.cc index c8a248184..00003bc28 100644 --- a/srsue/test/upper/usim_test.cc +++ b/srsue/test/upper/usim_test.cc @@ -61,6 +61,7 @@ KASME : a8.27.57.5e.ea.1a.10.17.3a.a1.bf.ce.4b.0c.21.85.e0.51.ef.bd.91.7f.fe.f uint8_t rand_enb[] = {0x88, 0x38, 0xc3, 0x55, 0xc8, 0x78, 0xaa, 0x57, 0x21, 0x49, 0xfe, 0x69, 0xdb, 0x68, 0x6b, 0x5a}; uint8_t autn_enb[] = {0xd7, 0x44, 0x51, 0x9b, 0x25, 0xaa, 0x80, 0x00, 0x84, 0xba, 0x37, 0xb0, 0xf6, 0x73, 0x4d, 0xd1}; +uint8_t kasme[] = {0xa8, 0x27, 0x57, 0x5e, 0xea, 0x1a, 0x10, 0x17, 0x3a, 0xa1, 0xbf, 0xce, 0x4b, 0x0c, 0x21, 0x85, 0xe0, 0x51, 0xef, 0xbd, 0x91, 0x7f, 0xfe, 0xf5, 0x1f, 0x74, 0x29, 0x61, 0xf9, 0x03, 0x7a, 0x35}; uint16 mcc = 208; uint16 mnc = 93; @@ -74,14 +75,14 @@ int main(int argc, char **argv) usim_args_t args; args.algo = "milenage"; args.amf = "8000"; - args.imei = "35609204079301"; + args.imei = "356092040793011"; args.imsi = "208930000000001"; args.k = "8BAF473F2F8FD09487CCCBD7097C6862"; args.op = "11111111111111111111111111111111"; srsue::usim usim; usim.init(&args, &usim_log); - usim.generate_authentication_response(rand_enb, autn_enb, mcc, mnc, &net_valid, res); + usim.generate_authentication_response(rand_enb, autn_enb, mcc, mnc, &net_valid, res, kasme); assert(net_valid == true); } From 3ebda405801f87a466ce4003a4976d3dce8d9c80 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 23 Nov 2017 21:56:41 +0100 Subject: [PATCH 159/242] move build info to UE base class --- srsue/hdr/ue_base.h | 4 ++++ srsue/src/ue.cc | 9 +-------- srsue/src/ue_base.cc | 23 ++++++++++++++++++++++- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/srsue/hdr/ue_base.h b/srsue/hdr/ue_base.h index 13e2e4660..e23adf3d2 100644 --- a/srsue/hdr/ue_base.h +++ b/srsue/hdr/ue_base.h @@ -163,6 +163,10 @@ public: srslte::log_filter rf_log; rf_metrics_t rf_metrics; srslte::LOG_LEVEL_ENUM level(std::string l); + + std::string get_build_mode(); + std::string get_build_info(); + std::string get_build_string(); }; } // namespace srsue diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index 7cb9ebaa1..b7e744bd8 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -32,9 +32,6 @@ #include #include #include -#include -#include -#include "srslte/build_info.h" using namespace srslte; @@ -53,10 +50,6 @@ ue::~ue() bool ue::init(all_args_t *args_) { - std::stringstream ss; - ss << "Built in " << srslte_get_build_mode() << " mode using " << srslte_get_build_info() << "." << std::endl << std::endl; - std::cout << ss.str(); - args = args_; if (!args->log.filename.compare("stdout")) { @@ -64,7 +57,7 @@ bool ue::init(all_args_t *args_) } else { logger_file.init(args->log.filename); logger_file.log("\n\n"); - logger_file.log(ss.str().c_str()); + logger_file.log(get_build_string().c_str()); logger = &logger_file; } diff --git a/srsue/src/ue_base.cc b/srsue/src/ue_base.cc index 94b9b5155..4b2c372ae 100644 --- a/srsue/src/ue_base.cc +++ b/srsue/src/ue_base.cc @@ -24,13 +24,14 @@ * */ - #include "ue_base.h" #include "ue.h" #include "srslte/srslte.h" +#include "srslte/build_info.h" #include #include #include +#include #include #include @@ -58,6 +59,9 @@ ue_base* ue_base::get_instance(srsue_instance_type_t type) } ue_base::ue_base() { + // print build info + std::cout << std::endl << get_build_string() << std::endl; + // load FFTW wisdom srslte_dft_load(); } @@ -116,4 +120,21 @@ srslte::LOG_LEVEL_ENUM ue_base::level(std::string l) } } +std::string ue_base::get_build_mode() +{ + return std::string(srslte_get_build_mode()); +} + +std::string ue_base::get_build_info() +{ + return std::string(srslte_get_build_info()); +} + +std::string ue_base::get_build_string() +{ + std::stringstream ss; + ss << "Built in " << get_build_mode() << " mode using " << get_build_info() << "." << std::endl; + return ss.str(); +} + } // namespace srsue From 5b46174b5b01f41cd419870c1243d295c5cdf1d2 Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Wed, 1 Nov 2017 13:43:49 +0000 Subject: [PATCH 160/242] Adding RRC logic to receive all SIBs --- srsue/hdr/upper/rrc.h | 17 +++- srsue/src/upper/rrc.cc | 191 +++++++++++++++++++++++++---------------- 2 files changed, 133 insertions(+), 75 deletions(-) diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index 0e77e29b0..7b903f0d9 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -196,9 +196,13 @@ private: float rsrp; bool has_valid_sib1; bool has_valid_sib2; + bool has_valid_sib3; + bool has_valid_sib13; bool in_sync; - LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT sib1; - LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT sib2; + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT sib1; + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT sib2; + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT sib3; + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT sib13; } cell_t; std::vector known_cells; @@ -212,8 +216,9 @@ private: si_acquire_state_t si_acquire_state; void run_si_acquisition_procedure(); - uint32_t sib_start_tti(uint32_t tti, uint32_t period, uint32_t x); + uint32_t sib_start_tti(uint32_t tti, uint32_t period, uint32_t offset, uint32_t sf); uint32_t nof_sib1_trials; + uint16_t sysinfo_index; uint32_t last_win_start; void select_next_cell_in_plmn(); @@ -365,10 +370,16 @@ private: void rrc_connection_release(); void con_restablish_cell_reselected(); void radio_link_failure(); + static void* start_sib_thread(void *rrc_); void sib_search(); void apply_rr_config_common_dl(LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT *config); void apply_rr_config_common_ul(LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT *config); + void handle_sib1(); + void handle_sib2(); + void handle_sib3(); + void handle_sib13(); + void apply_sib2_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2); void handle_con_setup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *setup); void handle_con_reest(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT *setup); diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 39aa8825d..9f2f53f38 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -47,6 +47,7 @@ namespace srsue { rrc::rrc() :state(RRC_STATE_IDLE) ,drb_up(false) + ,sysinfo_index(0) { sync_reset_cnt = 0; n310_cnt = 0; @@ -204,12 +205,7 @@ void rrc::run_thread() { if (phy->sync_status()) { if (!current_cell->has_valid_sib1) { si_acquire_state = SI_ACQUIRE_SIB1; - } else if (!current_cell->has_valid_sib2) { - si_acquire_state = SI_ACQUIRE_SIB2; - } else { - apply_sib2_configs(¤t_cell->sib2); - si_acquire_state = SI_ACQUIRE_IDLE; - state = RRC_STATE_CELL_SELECTED; + sysinfo_index = 0; } } select_cell_timeout++; @@ -289,8 +285,8 @@ void rrc::run_thread() { // Determine SI messages scheduling as in 36.331 5.2.3 Acquisition of an SI message -uint32_t rrc::sib_start_tti(uint32_t tti, uint32_t period, uint32_t x) { - return (period * 10 * (1 + tti / (period * 10)) + x) % 10240; // the 1 means next opportunity +uint32_t rrc::sib_start_tti(uint32_t tti, uint32_t period, uint32_t offset, uint32_t sf) { + return (period*10*(1+tti/(period*10))+(offset*10)+sf)%10240; // the 1 means next opportunity } void rrc::run_si_acquisition_procedure() @@ -298,13 +294,14 @@ void rrc::run_si_acquisition_procedure() uint32_t tti; uint32_t si_win_start=0, si_win_len=0; uint16_t period; + uint32_t x, sf, offset; const int SIB1_SEARCH_TIMEOUT = 30; switch (si_acquire_state) { case SI_ACQUIRE_SIB1: // Instruct MAC to look for SIB1 tti = mac->get_current_tti(); - si_win_start = sib_start_tti(tti, 2, 5); + si_win_start = sib_start_tti(tti, 2, 0, 5); if (tti > last_win_start + 10) { last_win_start = si_win_start; mac->bcch_start_rx(si_win_start, 1); @@ -323,17 +320,30 @@ void rrc::run_si_acquisition_procedure() } break; case SI_ACQUIRE_SIB2: - // Instruct MAC to look for SIB2 only when selecting a cell - tti = mac->get_current_tti(); - period = liblte_rrc_si_periodicity_num[current_cell->sib1.sched_info[0].si_periodicity]; - si_win_start = sib_start_tti(tti, period, 0); - if (tti > last_win_start + 10) { - last_win_start = si_win_start; - si_win_len = liblte_rrc_si_window_length_num[current_cell->sib1.si_window_length]; + // Instruct MAC to look for next SIB + if(sysinfo_index < current_cell->sib1.N_sched_info) { + si_win_len = liblte_rrc_si_window_length_num[current_cell->sib1.si_window_length]; + x = sysinfo_index*si_win_len; + sf = x%10; + offset = x/10; + + tti = mac->get_current_tti(); + period = liblte_rrc_si_periodicity_num[current_cell->sib1.sched_info[sysinfo_index].si_periodicity]; + si_win_start = sib_start_tti(tti, period, offset, sf); + + if (tti > last_win_start + 10) { + last_win_start = si_win_start; + si_win_len = liblte_rrc_si_window_length_num[current_cell->sib1.si_window_length]; + + mac->bcch_start_rx(si_win_start, si_win_len); + rrc_log->debug("Instructed MAC to search for system info, win_start=%d, win_len=%d\n", + si_win_start, si_win_len); + } - mac->bcch_start_rx(si_win_start, si_win_len); - rrc_log->debug("Instructed MAC to search for SIB2, win_start=%d, win_len=%d\n", - si_win_start, si_win_len); + } else { + // We've received all SIBs, move on to connection request + si_acquire_state = SI_ACQUIRE_IDLE; + state = RRC_STATE_CELL_SELECTED; } break; default: @@ -984,6 +994,8 @@ void rrc::write_pdu_bcch_bch(byte_buffer_t *pdu) { } void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) { + mac->bcch_stop_rx(); + rrc_log->info_hex(pdu->msg, pdu->N_bytes, "BCCH DLSCH message received."); rrc_log->info("BCCH DLSCH message Stack latency: %ld us\n", pdu->get_latency_us()); LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT dlsch_msg; @@ -992,74 +1004,104 @@ void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) { pool->deallocate(pdu); liblte_rrc_unpack_bcch_dlsch_msg((LIBLTE_BIT_MSG_STRUCT *) &bit_buf, &dlsch_msg); - if (dlsch_msg.N_sibs > 0) { - if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1 == dlsch_msg.sibs[0].sib_type && SI_ACQUIRE_SIB1 == si_acquire_state) { - mac->bcch_stop_rx(); - - // Handle SIB1 - memcpy(¤t_cell->sib1, &dlsch_msg.sibs[0].sib.sib1, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT)); + for(uint32_t i=0; iinfo("Processing SIB: %d\n", liblte_rrc_sys_info_block_type_num[dlsch_msg.sibs[i].sib_type]); - rrc_log->info("SIB1 received, CellID=%d, si_window=%d, sib2_period=%d\n", - current_cell->sib1.cell_id & 0xfff, - liblte_rrc_si_window_length_num[current_cell->sib1.si_window_length], - liblte_rrc_si_periodicity_num[current_cell->sib1.sched_info[0].si_periodicity]); + if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1 == dlsch_msg.sibs[i].sib_type && SI_ACQUIRE_SIB1 == si_acquire_state) { + memcpy(¤t_cell->sib1, &dlsch_msg.sibs[i].sib.sib1, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT)); + current_cell->has_valid_sib1 = true; + handle_sib1(); + } else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2 == dlsch_msg.sibs[i].sib_type && !current_cell->has_valid_sib2) { + memcpy(¤t_cell->sib2, &dlsch_msg.sibs[i].sib.sib2, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT)); + current_cell->has_valid_sib2 = true; + handle_sib2(); + } else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3 == dlsch_msg.sibs[i].sib_type && !current_cell->has_valid_sib3) { + memcpy(¤t_cell->sib3, &dlsch_msg.sibs[i].sib.sib3, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT)); + current_cell->has_valid_sib3 = true; + handle_sib3(); + }else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13 == dlsch_msg.sibs[i].sib_type && !current_cell->has_valid_sib13) { + memcpy(¤t_cell->sib13, &dlsch_msg.sibs[0].sib.sib13, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT)); + current_cell->has_valid_sib13 = true; + handle_sib13(); + } + } + if(current_cell->has_valid_sib2) { + sysinfo_index++; + } +} +void rrc::handle_sib1() +{ + rrc_log->info("SIB1 received, CellID=%d, si_window=%d, sib2_period=%d\n", + current_cell->sib1.cell_id&0xfff, + liblte_rrc_si_window_length_num[current_cell->sib1.si_window_length], + liblte_rrc_si_periodicity_num[current_cell->sib1.sched_info[0].si_periodicity]); + + // Print SIB scheduling info + uint32_t i,j; + for(i=0;isib1.N_sched_info;i++){ + for(j=0;jsib1.sched_info[i].N_sib_mapping_info;j++){ + LIBLTE_RRC_SIB_TYPE_ENUM t = current_cell->sib1.sched_info[i].sib_mapping_info[j].sib_type; + LIBLTE_RRC_SI_PERIODICITY_ENUM p = current_cell->sib1.sched_info[i].si_periodicity; + rrc_log->debug("SIB scheduling info, sib_type=%d, si_periodicity=%d\n", + liblte_rrc_sib_type_num[t], + liblte_rrc_si_periodicity_num[p]); + } + } - // Set TDD Config - if (current_cell->sib1.tdd) { - phy->set_config_tdd(¤t_cell->sib1.tdd_cnfg); - } + // Set TDD Config + if(current_cell->sib1.tdd) { + phy->set_config_tdd(¤t_cell->sib1.tdd_cnfg); + } - current_cell->has_valid_sib1 = true; + current_cell->has_valid_sib1 = true; - // Send PLMN and TAC to NAS - std::stringstream ss; - for (uint32_t i = 0; i < current_cell->sib1.N_plmn_ids; i++) { - nas->plmn_found(current_cell->sib1.plmn_id[i].id, current_cell->sib1.tracking_area_code); - } + // Send PLMN and TAC to NAS + std::stringstream ss; + for (uint32_t i = 0; i < current_cell->sib1.N_plmn_ids; i++) { + nas->plmn_found(current_cell->sib1.plmn_id[i].id, current_cell->sib1.tracking_area_code); + } - // Jump to next state - switch(state) { - case RRC_STATE_CELL_SELECTING: - si_acquire_state = SI_ACQUIRE_SIB2; - break; - case RRC_STATE_PLMN_SELECTION: - si_acquire_state = SI_ACQUIRE_IDLE; - rrc_log->info("SI Acquisition done. Searching next cell...\n"); - usleep(5000); - phy->cell_search_next(); - break; - default: - si_acquire_state = SI_ACQUIRE_IDLE; - } + // Jump to next state + switch(state) { + case RRC_STATE_CELL_SELECTING: + si_acquire_state = SI_ACQUIRE_SIB2; + break; + case RRC_STATE_PLMN_SELECTION: + si_acquire_state = SI_ACQUIRE_IDLE; + rrc_log->info("SI Acquisition done. Searching next cell...\n"); + usleep(5000); + phy->cell_search_next(); + break; + default: + si_acquire_state = SI_ACQUIRE_IDLE; + } +} - } else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2 == dlsch_msg.sibs[0].sib_type && - SI_ACQUIRE_SIB2 == si_acquire_state) { - mac->bcch_stop_rx(); +void rrc::handle_sib2() +{ + rrc_log->info("SIB2 received\n"); - // Handle SIB2 - memcpy(¤t_cell->sib2, &dlsch_msg.sibs[0].sib.sib2, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT)); - rrc_log->info("SIB2 received\n"); + apply_sib2_configs(¤t_cell->sib2); +} - apply_sib2_configs(¤t_cell->sib2); +void rrc::handle_sib3() +{ + rrc_log->info("SIB3 received\n"); +} - current_cell->has_valid_sib2 = true; +void rrc::handle_sib13() +{ + rrc_log->info("SIB13 received\n"); - // Jump to next state - switch(state) { - case RRC_STATE_CELL_SELECTING: - si_acquire_state = SI_ACQUIRE_IDLE; - state = RRC_STATE_CELL_SELECTED; - break; - default: - si_acquire_state = SI_ACQUIRE_IDLE; - } - } - } +// mac->set_config_mbsfn_sib13(¤t_cell->sib13.mbsfn_area_info_list_r9[0], +// current_cell->sib13.mbsfn_area_info_list_r9_size, +// ¤t_cell->sib13.mbsfn_notification_config); } + /******************************************************************************* * * @@ -1449,6 +1491,11 @@ void rrc::apply_sib2_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2) { memcpy(&cfg.rach, &sib2->rr_config_common_sib.rach_cnfg, sizeof(LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT)); cfg.prach_config_index = sib2->rr_config_common_sib.prach_cnfg.root_sequence_index; cfg.ul_harq_params.max_harq_msg3_tx = cfg.rach.max_harq_msg3_tx; + // Apply MBSFN configuration +// cfg.mbsfn_subfr_cnfg_list_size = sib2->mbsfn_subfr_cnfg_list_size; +// for(uint8_t i=0;imbsfn_subfr_cnfg_list_size;i++) { +// memcpy(&cfg.mbsfn_subfr_cnfg_list[i], &sib2->mbsfn_subfr_cnfg_list[i], sizeof(LIBLTE_RRC_MBSFN_SUBFRAME_CONFIG_STRUCT)); +// } mac->set_config(&cfg); From a604cfb99bb40365b75dbb4f268bb2898ccce42b Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Thu, 9 Nov 2017 13:05:50 +0000 Subject: [PATCH 161/242] Fix for RRC reconnection --- srsue/src/upper/rrc.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 9f2f53f38..45e030294 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -206,6 +206,12 @@ void rrc::run_thread() { if (!current_cell->has_valid_sib1) { si_acquire_state = SI_ACQUIRE_SIB1; sysinfo_index = 0; + } else if (!current_cell->has_valid_sib2) { + si_acquire_state = SI_ACQUIRE_SIB2; + } else { + apply_sib2_configs(¤t_cell->sib2); + si_acquire_state = SI_ACQUIRE_IDLE; + state = RRC_STATE_CELL_SELECTED; } } select_cell_timeout++; From 8447c965e3b9b1a940ca353eb46af5aa3b51be32 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 25 Nov 2017 10:40:53 +0100 Subject: [PATCH 162/242] Fixing RSRP measurements --- lib/include/srslte/interfaces/ue_interfaces.h | 5 +- lib/src/phy/ch_estimation/chest_dl.c | 4 +- srsue/hdr/phy/phy.h | 3 + srsue/hdr/upper/rrc.h | 21 +++++++ srsue/src/mac/mux.cc | 2 - srsue/src/phy/phch_recv.cc | 30 ++++++--- srsue/src/phy/phy.cc | 12 ++++ srsue/src/upper/rrc.cc | 61 ++++++++++++++----- 8 files changed, 110 insertions(+), 28 deletions(-) diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index 294606bb5..2713e2a6e 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -546,7 +546,10 @@ public: } phy_cfg_t; virtual void get_current_cell(srslte_cell_t *cell, uint32_t *current_earfcn = NULL) = 0; - virtual void get_config(phy_cfg_t *phy_cfg) = 0; + virtual uint32_t get_current_earfcn() = 0; + virtual uint32_t get_current_pci() = 0; + + virtual void get_config(phy_cfg_t *phy_cfg) = 0; virtual void set_config(phy_cfg_t *phy_cfg) = 0; virtual void set_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *dedicated) = 0; virtual void set_config_common(phy_cfg_common_t *common) = 0; diff --git a/lib/src/phy/ch_estimation/chest_dl.c b/lib/src/phy/ch_estimation/chest_dl.c index 0f8ae8074..d76397cf0 100644 --- a/lib/src/phy/ch_estimation/chest_dl.c +++ b/lib/src/phy/ch_estimation/chest_dl.c @@ -435,7 +435,9 @@ void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, ui } /* Compute RSRP for the channel estimates in this port */ - q->rsrp[rxant_id][port_id] = srslte_vec_avg_power_cf(q->pilot_recv_signal, SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id)); + uint32_t npilots = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id); + float energy = cabsf(srslte_vec_acc_cc(q->pilot_estimates, npilots)/npilots); + q->rsrp[rxant_id][port_id] = energy*energy; if (port_id == 0) { /* compute rssi only for port 0 */ q->rssi[rxant_id][port_id] = srslte_chest_dl_rssi(q, input, port_id); diff --git a/srsue/hdr/phy/phy.h b/srsue/hdr/phy/phy.h index 05edf31f9..adc2abdca 100644 --- a/srsue/hdr/phy/phy.h +++ b/srsue/hdr/phy/phy.h @@ -137,7 +137,10 @@ public: float get_pathloss_db(); uint32_t get_current_tti(); + void get_current_cell(srslte_cell_t *cell, uint32_t *current_earfcn = NULL); + uint32_t get_current_earfcn(); + uint32_t get_current_pci(); void start_plot(); diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index 7b903f0d9..20b32477f 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -346,6 +346,27 @@ private: rrc_meas measurements; + // Cell selection/reselection functions/variables + typedef struct { + float Qrxlevmin; + float Qrxlevminoffset; + float Qqualmin; + float Qqualminoffset; + float s_intrasearchP; + float s_intrasearchQ; + float q_hyst; + float threshservinglow; + + } cell_resel_cfg_t; + + cell_resel_cfg_t cell_resel_cfg; + + float get_srxlev(float Qrxlevmeas); + float get_squal(float Qqualmeas); + void cell_reselection_eval(float rsrp, float rsrq); + + + // RLC interface void max_retx_attempted(); diff --git a/srsue/src/mac/mux.cc b/srsue/src/mac/mux.cc index d624d2d62..e6e136d2e 100644 --- a/srsue/src/mac/mux.cc +++ b/srsue/src/mac/mux.cc @@ -213,10 +213,8 @@ uint8_t* mux::pdu_get(uint8_t *payload, uint32_t pdu_sz, uint32_t tx_tti, uint32 for (uint32_t i=0;iget_buffer_state(lch[i].id); lch[i].sched_len = 0; - Info("lch[%d].buffer_len=%d\n",i,lch[i].buffer_len); } - // data from any Logical Channel, except data from UL-CCCH; // first only those with positive Bj for (uint32_t i=0;iinfo("SYNC: Measuring RSRP %d/%d, sf_idx=%d, RSRP=%.1f dBm, SNR=%.1f dB\n", - cnt, nof_subframes, sf_idx, - rsrp, snr); + cnt, nof_subframes, sf_idx, rsrp, snr); if (cnt >= nof_subframes) { return MEASURE_OK; @@ -1107,7 +1113,7 @@ void phch_recv::scell_recv::init(srslte::log *log_h) } srslte_sync_cp_en(&sync_find, false); srslte_sync_set_cfo_ema_alpha(&sync_find, 0.8); - srslte_sync_set_threshold(&sync_find, 2.0); + srslte_sync_set_threshold(&sync_find, 1.2); reset(); } @@ -1126,6 +1132,7 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, fprintf(stderr, "Error resizing sync\n"); return SRSLTE_ERROR; } + int nof_cells = 0; uint32_t peak_idx = 0; uint32_t sf_idx = 0; @@ -1143,7 +1150,9 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, if (current_cell.id%3 != n_id_2) { srslte_sync_set_N_id_2(&sync_find, n_id_2); - switch(srslte_sync_find(&sync_find, input_buffer, 0, &peak_idx)) { + srslte_sync_find_ret_t sync_res = srslte_sync_find(&sync_find, input_buffer, 0, &peak_idx); + + switch(sync_res) { case SRSLTE_SYNC_ERROR: return SRSLTE_ERROR; fprintf(stderr, "Error finding correlation peak\n"); @@ -1155,6 +1164,7 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, peak_idx, n_id_2, cell_id, sf_idx); found_cell.id = cell_id; + found_cell.nof_ports = 1; // Use port 0 only for measurement measure_p.set_cell(found_cell); offset = peak_idx-sf_len/2; @@ -1208,7 +1218,9 @@ void phch_recv::meas_reset() { int phch_recv::meas_start(uint32_t earfcn, int pci) { if (earfcn == current_earfcn) { worker_com->pcell_meas_enabled = true; - intra_freq_meas.add_cell(pci); + if (pci != (int) cell.id) { + intra_freq_meas.add_cell(pci); + } return 0; } else { Warning("INTRA: Inter-frequency measurements not supported (current EARFCN=%d, requested measurement for %d)\n", @@ -1331,7 +1343,7 @@ void phch_recv::intra_measure::run_thread() } if (running) { - Info("INTRA: Running intra-frequency measurement for %d cells\n", active_pci.size()); + Info("INTRA: Running intra-frequency measurements\n"); // Read 5 ms data from buffer srslte_ringbuffer_read(&ring_buffer, search_buffer, CAPTURE_LEN_SF*current_sflen*sizeof(cf_t)); diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 96949e94c..917c0b480 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -301,6 +301,18 @@ void phy::get_current_cell(srslte_cell_t *cell, uint32_t *current_earfcn) sf_recv.get_current_cell(cell, current_earfcn); } +uint32_t phy::get_current_pci() { + srslte_cell_t cell; + sf_recv.get_current_cell(&cell); + return cell.id; +} + +uint32_t phy::get_current_earfcn() { + uint32_t earfcn; + sf_recv.get_current_cell(NULL, &earfcn); + return earfcn; +} + void phy::prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm) { diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 45e030294..afa4bca96 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -255,6 +255,7 @@ void rrc::run_thread() { rrc_log->info("Leaving RRC_CONNECTED state\n"); drb_up = false; reestablishment_in_progress = false; + measurements.reset(); pdcp->reset(); rlc->reset(); phy->reset(); @@ -264,6 +265,11 @@ void rrc::run_thread() { mac->pcch_start_rx(); mac_timers->timer_get(t310)->stop(); mac_timers->timer_get(t311)->stop(); + + // Instruct PHY to measure serving cell for cell reselection + phy->meas_start(phy->get_current_earfcn(), phy->get_current_pci()); + + // Move to RRC_IDLE state = RRC_STATE_IDLE; break; default: @@ -460,7 +466,11 @@ void rrc::select_next_cell_in_plmn() { } void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, uint32_t earfcn, uint32_t pci) { - measurements.new_phy_meas(earfcn, pci, rsrp, rsrq, tti); + if (state == RRC_STATE_CONNECTED) { + measurements.new_phy_meas(earfcn, pci, rsrp, rsrq, tti); + } else { + cell_reselection_eval(rsrp, rsrq); + } } void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { @@ -493,6 +503,7 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { cell.earfcn = earfcn; cell.has_valid_sib1 = false; cell.has_valid_sib2 = false; + cell.has_valid_sib3 = false; known_cells.push_back(cell); // save current cell @@ -532,8 +543,31 @@ void rrc::add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp) { known_cells.push_back(c); } +// Cell reselection in IDLE Section 5.2.4 of 36.304 +void rrc::cell_reselection_eval(float rsrp, float rsrq) +{ + // Intra-frequency cell-reselection criteria + + if (get_srxlev(rsrp) > cell_resel_cfg.s_intrasearchP && get_squal(rsrq) > cell_resel_cfg.s_intrasearchQ) { + // UE may not perform intra-frequency measurements + phy->meas_reset(); + } else { + // UE must start intra-frequency measurements + phy->meas_start(phy->get_current_earfcn(), -1); + } + + // TODO: Inter-frequency cell reselection +} +float rrc::get_srxlev(float Qrxlevmeas) { + // TODO: Do max power limitation + float Pcompensation = 0; + return Qrxlevmeas - (cell_resel_cfg.Qrxlevmin + cell_resel_cfg.Qrxlevminoffset) - Pcompensation; +} +float rrc::get_squal(float Qqualmeas) { + return Qqualmeas - (cell_resel_cfg.Qqualmin + cell_resel_cfg.Qqualminoffset); +} @@ -865,14 +899,11 @@ void rrc::ho_prepare() { mac->set_ho_rnti(mob_reconf.mob_ctrl_info.new_ue_id, mob_reconf.mob_ctrl_info.target_pci); apply_rr_config_common_dl(&mob_reconf.mob_ctrl_info.rr_cnfg_common); - uint32_t current_earfcn = 0; - phy->get_current_cell(NULL, ¤t_earfcn); - bool found = false; for (uint32_t i = 0; i < known_cells.size(); i++) { rrc_log->info("cell[%d]=%d:%d, cur_earfcn=%d\n", i, known_cells[i].earfcn, known_cells[i].phy_cell.id, current_cell->earfcn); - if (known_cells[i].earfcn == current_earfcn && + if (known_cells[i].earfcn == phy->get_current_earfcn() && known_cells[i].phy_cell.id == mob_reconf.mob_ctrl_info.target_pci) { rrc_log->info("Selecting new cell pci=%d\n", known_cells[i].phy_cell.id); if (!phy->cell_handover(known_cells[i].phy_cell)) { @@ -895,7 +926,7 @@ void rrc::ho_prepare() { } printf("ncc=%d\n", mob_reconf.sec_cnfg_ho.intra_lte.next_hop_chaining_count); - usim->generate_as_keys_ho(mob_reconf.mob_ctrl_info.target_pci, current_earfcn, + usim->generate_as_keys_ho(mob_reconf.mob_ctrl_info.target_pci, phy->get_current_earfcn(), k_rrc_enc, k_rrc_int, k_up_enc, k_up_int, cipher_algo, integ_algo); pdcp->config_security(1, k_rrc_enc, k_rrc_int, cipher_algo, integ_algo); send_rrc_con_reconfig_complete(NULL); @@ -1094,6 +1125,8 @@ void rrc::handle_sib2() void rrc::handle_sib3() { rrc_log->info("SIB3 received\n"); + + } void rrc::handle_sib13() @@ -1591,8 +1624,8 @@ void rrc::apply_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT sizeof(LIBLTE_RRC_UL_POWER_CONTROL_DEDICATED_STRUCT)); } else if (apply_defaults) { current_cfg->ul_pwr_ctrl_ded.p0_ue_pusch = 0; - current_cfg->ul_pwr_ctrl_ded.delta_mcs_en = LIBLTE_RRC_DELTA_MCS_ENABLED_EN0; - current_cfg->ul_pwr_ctrl_ded.accumulation_en = true; + current_cfg->ul_pwr_ctrl_ded.delta_mcs_en = LIBLTE_RRC_DELTA_MCS_ENABLED_EN0; + current_cfg->ul_pwr_ctrl_ded.accumulation_en = true; current_cfg->ul_pwr_ctrl_ded.p0_ue_pucch = 0; current_cfg->ul_pwr_ctrl_ded.p_srs_offset = 7; } @@ -1741,7 +1774,7 @@ void rrc::apply_mac_config_dedicated(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT *mac_cnfg default_cfg.time_alignment_timer = mac_cnfg->time_alignment_timer; } - // Setup MAC configuration + // Setup MAC configuration mac->set_config_main(&default_cfg); // Update UL HARQ config @@ -2099,7 +2132,7 @@ void rrc::rrc_meas::generate_report(uint32_t meas_id) report->pcell_rsrp_result = value_to_range(RSRP, pcell_measurement.ms[RSRP]); report->pcell_rsrq_result = value_to_range(RSRQ, pcell_measurement.ms[RSRQ]); - log_h->info("MEAS: Generate report MeasId=%d, rsrp=%f rsrq=%f\n", + log_h->console("MEAS: Generate report MeasId=%d, rsrp=%f rsrq=%f\n", report->meas_id, pcell_measurement.ms[RSRP], pcell_measurement.ms[RSRQ]); // TODO: report up to 8 best cells @@ -2189,16 +2222,14 @@ void rrc::rrc_meas::calculate_triggers(uint32_t tti) // Get serving cell if (active.size()) { - uint32_t current_earfcn = 0; - srslte_cell_t current_cell; - phy->get_current_cell(¤t_cell, ¤t_earfcn); - if (find_earfcn_cell(current_earfcn, current_cell.id, &serving_object, &serving_cell_idx)) { + if (find_earfcn_cell(phy->get_current_earfcn(), phy->get_current_pci(), &serving_object, &serving_cell_idx)) { Ofp = serving_object->q_offset; if (serving_cell_idx >= 0) { Ocp = serving_object->cells[serving_cell_idx].q_offset; } } else { - log_h->warning("Can't find current eafcn=%d, pci=%d in objects list. Using Ofp=0, Ocp=0\n", current_earfcn, current_cell.id); + log_h->warning("Can't find current eafcn=%d, pci=%d in objects list. Using Ofp=0, Ocp=0\n", + phy->get_current_earfcn(), phy->get_current_pci()); } } From e035e248b822ee67847fd1c66149ad9d6e1a75c5 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 25 Nov 2017 23:01:11 +0100 Subject: [PATCH 163/242] Fix bug in sync when not correcting CFO --- lib/src/phy/sync/sync.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/lib/src/phy/sync/sync.c b/lib/src/phy/sync/sync.c index 849b64b3b..78e9ca383 100644 --- a/lib/src/phy/sync/sync.c +++ b/lib/src/phy/sync/sync.c @@ -539,7 +539,7 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t /* Correct CFO with the averaged CFO estimation */ srslte_cfo_correct(&q->cfocorr2, input, q->temp, -q->mean_cfo / q->fft_size); - input_cfo = q->temp; + input_cfo = q->temp; } /* If integer CFO is enabled, find max PSS correlation for shifted +1/0/-1 integer versions */ @@ -549,20 +549,21 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t srslte_vec_prod_ccc(input_cfo, q->cfo_i_corr[q->cfo_i<0?0:1], input_cfo, q->frame_size); INFO("Compensating cfo_i=%d\n", q->cfo_i); } - } else { - srslte_pss_synch_set_N_id_2(&q->pss, q->N_id_2); - peak_pos = srslte_pss_synch_find_pss(&q->pss, &input_cfo[find_offset], &q->peak_value); - // this compensates for the constant time shift caused by the low pass filter - if(q->decimate && peak_pos < 0) - { - peak_pos = 0 ;//peak_pos + q->decimate*(2);// replace 2 with q->filter_size -2; - } - if (peak_pos < 0) { - fprintf(stderr, "Error calling finding PSS sequence at : %d \n", peak_pos); - return SRSLTE_ERROR; - } } - + + srslte_pss_synch_set_N_id_2(&q->pss, q->N_id_2); + peak_pos = srslte_pss_synch_find_pss(&q->pss, &input_cfo[find_offset], &q->peak_value); + + // this compensates for the constant time shift caused by the low pass filter + if(q->decimate && peak_pos < 0) + { + peak_pos = 0 ;//peak_pos + q->decimate*(2);// replace 2 with q->filter_size -2; + } + if (peak_pos < 0) { + fprintf(stderr, "Error calling finding PSS sequence at : %d \n", peak_pos); + return SRSLTE_ERROR; + } + if (peak_position) { *peak_position = (uint32_t) peak_pos; } @@ -579,12 +580,15 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t /* If peak is over threshold, compute CFO and SSS */ if (q->peak_value >= q->threshold) { - + + ret = SRSLTE_SYNC_FOUND; + if (q->detect_cp) { if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) { srslte_sync_set_cp(q, srslte_sync_detect_cp(q, input_cfo, peak_pos + find_offset)); } else { DEBUG("Not enough room to detect CP length. Peak position: %d\n", peak_pos); + ret = SRSLTE_SYNC_FOUND_NOSPACE; } } @@ -597,8 +601,6 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t } else { q->mean_cfo2 = SRSLTE_VEC_EMA(cfo2, q->mean_cfo2, q->cfo_ema_alpha); } - - ret = SRSLTE_SYNC_FOUND; } else { ret = SRSLTE_SYNC_FOUND_NOSPACE; } From cfbea7a6c1f1ad0517e14aa6d595665cabd64572 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sun, 26 Nov 2017 00:36:06 +0100 Subject: [PATCH 164/242] Restored non-guru DFT interface. Removed input buffer from ue_dl interface --- lib/examples/cell_measurement.c | 2 +- lib/examples/pdsch_ue.c | 9 ++-- lib/include/srslte/phy/dft/ofdm.h | 8 +++ lib/include/srslte/phy/ue/ue_dl.h | 21 ++++---- lib/src/phy/dft/ofdm.c | 35 ++++++++++--- lib/src/phy/phch/test/pdsch_pdcch_file_test.c | 2 +- lib/src/phy/phch/test/pmch_file_test.c | 2 +- lib/src/phy/ue/ue_dl.c | 49 ++++++++++++++----- srsue/src/phy/phch_recv.cc | 2 +- srsue/src/phy/phch_worker.cc | 2 +- 10 files changed, 91 insertions(+), 41 deletions(-) diff --git a/lib/examples/cell_measurement.c b/lib/examples/cell_measurement.c index 333e9aaa4..268e87837 100644 --- a/lib/examples/cell_measurement.c +++ b/lib/examples/cell_measurement.c @@ -332,7 +332,7 @@ int main(int argc, char **argv) { case DECODE_SIB: /* We are looking for SI Blocks, search only in appropiate places */ if ((srslte_ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%2)==0)) { - n = srslte_ue_dl_decode(&ue_dl, sf_buffer, data, 0, sfn*10+srslte_ue_sync_get_sfidx(&ue_sync), acks); + n = srslte_ue_dl_decode(&ue_dl, data, 0, sfn*10+srslte_ue_sync_get_sfidx(&ue_sync), acks); if (n < 0) { fprintf(stderr, "Error decoding UE DL\n");fflush(stdout); return -1; diff --git a/lib/examples/pdsch_ue.c b/lib/examples/pdsch_ue.c index a655e090c..26c681346 100644 --- a/lib/examples/pdsch_ue.c +++ b/lib/examples/pdsch_ue.c @@ -663,26 +663,25 @@ int main(int argc, char **argv) { if(sfidx != 1 || prog_args.mbsfn_area_id < 0){ // Not an MBSFN subframe if (cell.nof_ports == 1) { /* Transmission mode 1 */ - n = srslte_ue_dl_decode(&ue_dl, sf_buffer, data, 0, sfn*10+srslte_ue_sync_get_sfidx(&ue_sync), acks); + n = srslte_ue_dl_decode(&ue_dl, data, 0, sfn*10+srslte_ue_sync_get_sfidx(&ue_sync), acks); } else { if (prog_args.rf_nof_rx_ant == 1) { /* Transmission mode 2 */ - n = srslte_ue_dl_decode(&ue_dl, sf_buffer, data, 1, sfn * 10 + srslte_ue_sync_get_sfidx(&ue_sync), + n = srslte_ue_dl_decode(&ue_dl, data, 1, sfn * 10 + srslte_ue_sync_get_sfidx(&ue_sync), acks); } else { /* Transmission mode 3 */ - n = srslte_ue_dl_decode(&ue_dl, sf_buffer, data, 2, sfn * 10 + srslte_ue_sync_get_sfidx(&ue_sync), + n = srslte_ue_dl_decode(&ue_dl, data, 2, sfn * 10 + srslte_ue_sync_get_sfidx(&ue_sync), acks); if (n < 1) { /* Transmission mode 4 */ - n = srslte_ue_dl_decode(&ue_dl, sf_buffer, data, 3, sfn * 10 + srslte_ue_sync_get_sfidx(&ue_sync), + n = srslte_ue_dl_decode(&ue_dl, data, 3, sfn * 10 + srslte_ue_sync_get_sfidx(&ue_sync), acks); } } } }else{ // MBSFN subframe n = srslte_ue_dl_decode_mbsfn(&ue_dl, - sf_buffer, data[0], sfn*10+srslte_ue_sync_get_sfidx(&ue_sync)); if(n>0){ diff --git a/lib/include/srslte/phy/dft/ofdm.h b/lib/include/srslte/phy/dft/ofdm.h index cba963ca4..e48c240b9 100644 --- a/lib/include/srslte/phy/dft/ofdm.h +++ b/lib/include/srslte/phy/dft/ofdm.h @@ -113,8 +113,16 @@ SRSLTE_API void srslte_ofdm_rx_free(srslte_ofdm_t *q); SRSLTE_API void srslte_ofdm_rx_slot(srslte_ofdm_t *q, int slot_in_sf); +SRSLTE_API void srslte_ofdm_rx_slot_ng(srslte_ofdm_t *q, + cf_t *input, + cf_t *output); + SRSLTE_API void srslte_ofdm_rx_sf(srslte_ofdm_t *q); +SRSLTE_API void srslte_ofdm_rx_sf_ng(srslte_ofdm_t *q, + cf_t *input, + cf_t *output); + SRSLTE_API int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp_type, cf_t *in_buffer, diff --git a/lib/include/srslte/phy/ue/ue_dl.h b/lib/include/srslte/phy/ue/ue_dl.h index a60761a37..02341c08d 100644 --- a/lib/include/srslte/phy/ue/ue_dl.h +++ b/lib/include/srslte/phy/ue/ue_dl.h @@ -131,7 +131,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], + cf_t *input[SRSLTE_MAX_PORTS], uint32_t max_prb, uint32_t nof_rx_antennas); @@ -141,20 +141,22 @@ SRSLTE_API int srslte_ue_dl_set_cell(srslte_ue_dl_t *q, srslte_cell_t cell); int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q, - cf_t *input[SRSLTE_MAX_PORTS], - uint32_t sf_idx, + uint32_t sf_idx, uint32_t *cfi); SRSLTE_API int srslte_ue_dl_decode_fft_estimate_mbsfn(srslte_ue_dl_t *q, - cf_t *input[SRSLTE_MAX_PORTS], - uint32_t sf_idx, + uint32_t sf_idx, uint32_t *cfi, srslte_sf_t sf_type); +SRSLTE_API int srslte_ue_dl_decode_fft_estimate_noguru(srslte_ue_dl_t *q, + cf_t *input[SRSLTE_MAX_PORTS], + uint32_t sf_idx, + uint32_t *cfi); -int srslte_ue_dl_decode_estimate(srslte_ue_dl_t *q, - uint32_t sf_idx, - uint32_t *cfi); +SRSLTE_API int srslte_ue_dl_decode_estimate(srslte_ue_dl_t *q, + uint32_t sf_idx, + uint32_t *cfi); SRSLTE_API int srslte_ue_dl_decode_estimate_mbsfn(srslte_ue_dl_t *q, uint32_t sf_idx, @@ -195,14 +197,12 @@ SRSLTE_API void srslte_ue_dl_set_sample_offset(srslte_ue_dl_t * q, float sample_offset); SRSLTE_API int srslte_ue_dl_decode(srslte_ue_dl_t *q, - cf_t *input[SRSLTE_MAX_PORTS], uint8_t *data[SRSLTE_MAX_CODEWORDS], uint32_t tm, uint32_t tti, bool acks[SRSLTE_MAX_CODEWORDS]); SRSLTE_API int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, - cf_t *input[SRSLTE_MAX_PORTS], uint8_t *data[SRSLTE_MAX_CODEWORDS], uint32_t tm, uint32_t tti, @@ -216,7 +216,6 @@ SRSLTE_API int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, * srslte_pmch_decode_multi */ SRSLTE_API int srslte_ue_dl_decode_mbsfn(srslte_ue_dl_t * q, - cf_t *input[SRSLTE_MAX_PORTS], uint8_t *data, uint32_t tti); diff --git a/lib/src/phy/dft/ofdm.c b/lib/src/phy/dft/ofdm.c index 8ea690bb5..e266023bb 100644 --- a/lib/src/phy/dft/ofdm.c +++ b/lib/src/phy/dft/ofdm.c @@ -380,15 +380,8 @@ void srslte_ofdm_tx_free(srslte_ofdm_t *q) { srslte_ofdm_free_(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, int slot_in_sf) { - cf_t *output = q->out_buffer + slot_in_sf * q->nof_re * q->nof_symbols; - -#ifdef AVOID_GURU +void srslte_ofdm_rx_slot_ng(srslte_ofdm_t *q, cf_t *input, cf_t *output) { 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); @@ -396,6 +389,16 @@ void srslte_ofdm_rx_slot(srslte_ofdm_t *q, int slot_in_sf) { input += q->symbol_sz; output += q->nof_re; } +} + +/* 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, int slot_in_sf) { + cf_t *output = q->out_buffer + slot_in_sf * q->nof_re * q->nof_symbols; + +#ifdef AVOID_GURU + srslte_ofdm_rx_slot_ng(q, q->in_buffer + slot_in_sf * q->slot_sz, q->out_buffer + slot_in_sf * q->nof_re * q->nof_symbols); #else float norm = 1.0f/sqrtf(q->fft_plan.size); cf_t *tmp = q->tmp + slot_in_sf * q->symbol_sz * q->nof_symbols; @@ -462,6 +465,22 @@ void srslte_ofdm_rx_sf(srslte_ofdm_t *q) { } } +void srslte_ofdm_rx_sf_ng(srslte_ofdm_t *q, cf_t *input, cf_t *output) { + uint32_t n; + if (q->freq_shift) { + 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_ng(q, &input[n*q->slot_sz], &output[n*q->nof_re*q->nof_symbols]); + } + } + else{ + 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. */ 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 0faf7eca1..ba662bc49 100644 --- a/lib/src/phy/phch/test/pdsch_pdcch_file_test.c +++ b/lib/src/phy/phch/test/pdsch_pdcch_file_test.c @@ -182,7 +182,7 @@ int main(int argc, char **argv) { srslte_filesource_read(&fsrc, input_buffer[0], flen); INFO("Reading %d samples sub-frame %d\n", flen, sf_idx); - ret = srslte_ue_dl_decode(&ue_dl, input_buffer, data, 0, sf_idx, acks); + ret = srslte_ue_dl_decode(&ue_dl, data, 0, sf_idx, acks); if(ret > 0) { printf("PDSCH Decoded OK!\n"); } else if (ret == 0) { diff --git a/lib/src/phy/phch/test/pmch_file_test.c b/lib/src/phy/phch/test/pmch_file_test.c index 6586b2ee9..1d0715caa 100644 --- a/lib/src/phy/phch/test/pmch_file_test.c +++ b/lib/src/phy/phch/test/pmch_file_test.c @@ -187,7 +187,7 @@ int main(int argc, char **argv) { srslte_filesource_read(&fsrc, input_buffer[0], flen); INFO("Reading %d samples sub-frame %d\n", flen, sf_idx); - ret = srslte_ue_dl_decode_mbsfn(&ue_dl, input_buffer, data[0], sf_idx); + ret = srslte_ue_dl_decode_mbsfn(&ue_dl, data[0], sf_idx); if(ret > 0) { printf("PMCH Decoded OK!\n"); } else if (ret < 0) { diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index 494eecba7..c5431cec9 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -359,20 +359,20 @@ void srslte_ue_dl_set_sample_offset(srslte_ue_dl_t * q, float sample_offset) { * - PDCCH decoding: Find DCI for RNTI given by previous call to srslte_ue_dl_set_rnti() * - PDSCH decoding: Decode TB scrambling with RNTI given by srslte_ue_dl_set_rnti() */ -int srslte_ue_dl_decode(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS], uint8_t *data[SRSLTE_MAX_CODEWORDS], +int srslte_ue_dl_decode(srslte_ue_dl_t *q, uint8_t *data[SRSLTE_MAX_CODEWORDS], uint32_t tm, uint32_t tti, bool acks[SRSLTE_MAX_CODEWORDS]) { - return srslte_ue_dl_decode_rnti(q, input, data, tm, tti, q->current_rnti, acks); + return srslte_ue_dl_decode_rnti(q, data, tm, tti, q->current_rnti, acks); } -int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS], uint32_t sf_idx, uint32_t *cfi){ +int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t *cfi){ - return srslte_ue_dl_decode_fft_estimate_mbsfn(q, input, sf_idx, cfi, SRSLTE_SF_NORM); + return srslte_ue_dl_decode_fft_estimate_mbsfn(q, sf_idx, cfi, SRSLTE_SF_NORM); } -int srslte_ue_dl_decode_fft_estimate_mbsfn(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS], uint32_t sf_idx, uint32_t *cfi, srslte_sf_t sf_type) +int srslte_ue_dl_decode_fft_estimate_mbsfn(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t *cfi, srslte_sf_t sf_type) { - if (input && q && cfi && sf_idx < SRSLTE_NSUBFRAMES_X_FRAME) { + if (q && cfi && sf_idx < SRSLTE_NSUBFRAMES_X_FRAME) { /* Run FFT for all subframe data */ for (int j=0;jnof_rx_antennas;j++) { @@ -398,6 +398,32 @@ int srslte_ue_dl_decode_fft_estimate_mbsfn(srslte_ue_dl_t *q, cf_t *input[SRSLTE return SRSLTE_ERROR_INVALID_INPUTS; } } + +int srslte_ue_dl_decode_fft_estimate_noguru(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS], uint32_t sf_idx, uint32_t *cfi) +{ + if (input && q && cfi && sf_idx < SRSLTE_NSUBFRAMES_X_FRAME) { + + /* Run FFT for all subframe data */ + for (int j=0;jnof_rx_antennas;j++) { + srslte_ofdm_rx_sf_ng(&q->fft[j], input[j], q->sf_symbols_m[j]); + + /* Correct SFO multiplying by complex exponential in the time domain */ + if (q->sample_offset) { + int nsym = SRSLTE_CP_NSYMB(q->cell.cp); + for (int i=0;i<2*nsym;i++) { + 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[j].symbol_sz); + } + } + } + return srslte_ue_dl_decode_estimate_mbsfn(q, sf_idx, cfi, SRSLTE_SF_NORM); + } else { + return SRSLTE_ERROR_INVALID_INPUTS; + } +} + int srslte_ue_dl_decode_estimate(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t *cfi) { return srslte_ue_dl_decode_estimate_mbsfn(q, sf_idx, cfi, SRSLTE_SF_NORM); @@ -468,7 +494,7 @@ int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint3 } } -int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS], +int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, uint8_t *data[SRSLTE_MAX_CODEWORDS], uint32_t tm, uint32_t tti, uint16_t rnti, bool acks[SRSLTE_MAX_CODEWORDS]) { srslte_mimo_type_t mimo_type; @@ -479,7 +505,7 @@ int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS], uint32_t cfi; uint32_t sf_idx = tti%10; - if ((ret = srslte_ue_dl_decode_fft_estimate_mbsfn(q, input, sf_idx, &cfi, SRSLTE_SF_NORM)) < 0) { + if ((ret = srslte_ue_dl_decode_fft_estimate_mbsfn(q, sf_idx, &cfi, SRSLTE_SF_NORM)) < 0) { return ret; } @@ -621,16 +647,15 @@ int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS], int srslte_ue_dl_decode_mbsfn(srslte_ue_dl_t * q, - cf_t *input[SRSLTE_MAX_PORTS], - uint8_t *data, - uint32_t tti) + uint8_t *data, + uint32_t tti) { srslte_ra_dl_grant_t grant; int ret = SRSLTE_ERROR; uint32_t cfi; uint32_t sf_idx = tti%10; - if ((ret = srslte_ue_dl_decode_fft_estimate_mbsfn(q, input, sf_idx, &cfi, SRSLTE_SF_MBSFN)) < 0) { + if ((ret = srslte_ue_dl_decode_fft_estimate_mbsfn(q, sf_idx, &cfi, SRSLTE_SF_MBSFN)) < 0) { return ret; } diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 8fc026ad9..3f6a2a019 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -1054,7 +1054,7 @@ phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *in phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx) { uint32_t cfi = 0; - if (srslte_ue_dl_decode_fft_estimate(&ue_dl, buffer, sf_idx, &cfi)) { + if (srslte_ue_dl_decode_fft_estimate(&ue_dl, sf_idx, &cfi)) { log_h->error("SYNC: Measuring RSRP: Estimating channel\n"); return ERROR; } diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 8c487bc48..ebb234539 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -420,7 +420,7 @@ bool phch_worker::extract_fft_and_pdcch_llr() { srslte_chest_dl_set_noise_alg(&ue_dl.chest, SRSLTE_NOISE_ALG_PSS); } - if (srslte_ue_dl_decode_fft_estimate(&ue_dl, signal_buffer, tti%10, &cfi) < 0) { + if (srslte_ue_dl_decode_fft_estimate(&ue_dl, tti%10, &cfi) < 0) { Error("Getting PDCCH FFT estimate\n"); return false; } From 38903de07cc64a29300bda06fb1593deba1f5b85 Mon Sep 17 00:00:00 2001 From: yagoda Date: Mon, 27 Nov 2017 11:10:50 +0000 Subject: [PATCH 165/242] adding simd xor functionality --- lib/include/srslte/phy/utils/simd.h | 115 +++++++++++++++++++++ lib/include/srslte/phy/utils/vector.h | 4 + lib/include/srslte/phy/utils/vector_simd.h | 4 + lib/src/phy/scrambling/scrambling.c | 6 +- lib/src/phy/utils/test/vector_test.c | 34 +++++- lib/src/phy/utils/vector.c | 4 + lib/src/phy/utils/vector_simd.c | 29 ++++++ 7 files changed, 190 insertions(+), 6 deletions(-) diff --git a/lib/include/srslte/phy/utils/simd.h b/lib/include/srslte/phy/utils/simd.h index a9a79c486..cec003886 100644 --- a/lib/include/srslte/phy/utils/simd.h +++ b/lib/include/srslte/phy/utils/simd.h @@ -1506,4 +1506,119 @@ static inline simd_s_t srslte_simd_convert_2f_s(simd_f_t a, simd_f_t b) { #endif /* SRSLTE_SIMD_F_SIZE && SRSLTE_SIMD_C16_SIZE */ +#if SRSLTE_SIMD_B_SIZE +/* Data types */ +#ifdef LV_HAVE_AVX512 +typedef __m512i simd_b_t; +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 +typedef __m256i simd_b_t; +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE +typedef __m128i simd_b_t; +#else /* HAVE_NEON */ +#ifdef HAVE_NEON +typedef int8x16_t simd_b_t; +#endif /* HAVE_NEON */ +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ + + + +static inline simd_b_t srslte_simd_b_load(int8_t *ptr){ +#ifdef LV_HAVE_AVX512 + return _mm512_load_si512(ptr); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_load_si256((__m256i*) ptr); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + return _mm_load_si128((__m128i*) ptr); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vld1q_s8(ptr); +#endif /* HAVE_NEON */ +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline simd_b_t srslte_simd_b_loadu(int8_t *ptr){ +#ifdef LV_HAVE_AVX512 + return _mm512_loadu_si512(ptr); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_loadu_si256((__m256i*) ptr); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + return _mm_loadu_si128((__m128i*) ptr); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vld1q_s8(ptr); +#endif /* HAVE_NEON */ +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline void srslte_simd_b_store(int8_t *ptr, simd_b_t simdreg) { +#ifdef LV_HAVE_AVX512 + _mm512_store_si512(ptr, simdreg); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + _mm256_store_si256((__m256i*) ptr, simdreg); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + _mm_store_si128((__m128i*) ptr, simdreg); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + vst1q_s8( ptr, simdreg); +#endif /* HAVE_NEON */ +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +static inline void srslte_simd_b_storeu(int8_t *ptr, simd_b_t simdreg) { +#ifdef LV_HAVE_AVX512 + _mm512_storeu_si512(ptr, simdreg); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + _mm256_storeu_si256((__m256i*) ptr, simdreg); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + _mm_storeu_si128((__m128i*) ptr, simdreg); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + vst1q_s8(ptr, simdreg); +#endif /* HAVE_NEON */ +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + + +static inline simd_b_t srslte_simd_b_xor(simd_b_t a, simd_b_t b) { + +#ifdef LV_HAVE_AVX512 + return _mm512_xor_epi32(a, b); +#else /* LV_HAVE_AVX512 */ +#ifdef LV_HAVE_AVX2 + return _mm256_xor_si256(a, b); +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE + return _mm_xor_si128 (a, b); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return veorq_s8(a, b); +#endif /* HAVE_NEON */ +#endif /* LV_HAVE_SSE */ +#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ +} + +#endif /*SRSLTE_SIMD_B_SIZE */ + + #endif //SRSLTE_SIMD_H_H diff --git a/lib/include/srslte/phy/utils/vector.h b/lib/include/srslte/phy/utils/vector.h index 4a5daefb3..7dad585a0 100644 --- a/lib/include/srslte/phy/utils/vector.h +++ b/lib/include/srslte/phy/utils/vector.h @@ -53,6 +53,10 @@ extern "C" { // Exponential moving average #define SRSLTE_VEC_EMA(data, average, alpha) ((alpha)*(data)+(1-alpha)*(average)) + +/*logical operations */ +SRSLTE_API void srslte_vec_xor_bbb(int8_t *x,int8_t *y,int8_t *z, uint32_t len); + /** Return the sum of all the elements */ SRSLTE_API float srslte_vec_acc_ff(float *x, uint32_t len); SRSLTE_API cf_t srslte_vec_acc_cc(cf_t *x, uint32_t len); diff --git a/lib/include/srslte/phy/utils/vector_simd.h b/lib/include/srslte/phy/utils/vector_simd.h index 294cff50f..468c5e11a 100644 --- a/lib/include/srslte/phy/utils/vector_simd.h +++ b/lib/include/srslte/phy/utils/vector_simd.h @@ -53,6 +53,10 @@ extern "C" { #endif /* LV_HAVE_AVX */ #endif /* LV_HAVE_AVX512 */ + +/*SIMD Logical operations*/ +SRSLTE_API void srslte_vec_xor_bbb_simd(int8_t *x, int8_t *y, int8_t *z, int len); + /* SIMD Basic vector math */ SRSLTE_API void srslte_vec_sum_sss_simd(int16_t *x, int16_t *y, int16_t *z, int len); diff --git a/lib/src/phy/scrambling/scrambling.c b/lib/src/phy/scrambling/scrambling.c index 42f16d1e8..ca0342905 100644 --- a/lib/src/phy/scrambling/scrambling.c +++ b/lib/src/phy/scrambling/scrambling.c @@ -60,10 +60,8 @@ void srslte_scrambling_c_offset(srslte_sequence_t *s, cf_t *data, int offset, in } void scrambling_b(uint8_t *c, uint8_t *data, int len) { - int i; - for (i = 0; i < len; i++) { - data[i] = (data[i] ^ c[i]); - } + + srslte_vec_xor_bbb((int8_t*)c,(int8_t*)data,(int8_t*)data,len); } void scrambling_b_word(uint8_t *c, uint8_t *data, int len) { diff --git a/lib/src/phy/utils/test/vector_test.c b/lib/src/phy/utils/test/vector_test.c index 9058e8813..a717a7537 100644 --- a/lib/src/phy/utils/test/vector_test.c +++ b/lib/src/phy/utils/test/vector_test.c @@ -47,8 +47,10 @@ bool verbose = false; #define MAX_FUNCTIONS (64) #define MAX_BLOCKS (16) + #define RANDOM_F() ((float)rand())/((float)RAND_MAX) #define RANDOM_S() ((int16_t)(rand() && 0x800F)) +#define RANDOM_B() ((int8_t)(rand() && 0x8008)) #define RANDOM_CF() (RANDOM_F() + _Complex_I*RANDOM_F()) #define TEST_CALL(TEST_CODE) gettimeofday(&start, NULL);\ @@ -87,6 +89,29 @@ float squared_error (cf_t a, cf_t b) { return diff_re*diff_re + diff_im*diff_im; } + TEST(srslte_vec_xor_bbb, + MALLOC(int8_t, x); + MALLOC(int8_t, y); + MALLOC(int8_t, z); + + cf_t gold = 0.0f; + for (int i = 0; i < block_size; i++) { + x[i] = RANDOM_B(); + y[i] = RANDOM_B(); + } + + TEST_CALL(srslte_vec_xor_bbb(x, y, z, block_size)) + + for (int i = 0; i < block_size; i++) { + gold = x[i] ^ y[i]; + mse += cabsf(gold - z[i]); + } + + free(x); + free(y); + free(z); +) + TEST(srslte_vec_acc_ff, MALLOC(float, x); float z; @@ -613,8 +638,8 @@ TEST(srslte_vec_div_fff, cf_t gold; for (int i = 0; i < block_size; i++) { - x[i] = RANDOM_F(); - y[i] = RANDOM_F(); + x[i] = RANDOM_F() + 0.0001; + y[i] = RANDOM_F()+ 0.0001; } TEST_CALL(srslte_vec_div_fff(x, y, z, block_size)) @@ -690,6 +715,11 @@ int main(int argc, char **argv) { for (uint32_t block_size = 1; block_size <= 1024*8; block_size *= 2) { func_count = 0; + + passed[func_count][size_count] = test_srslte_vec_xor_bbb(func_names[func_count], &timmings[func_count][size_count], block_size); + func_count++; + + passed[func_count][size_count] = test_srslte_vec_acc_ff(func_names[func_count], &timmings[func_count][size_count], block_size); func_count++; diff --git a/lib/src/phy/utils/vector.c b/lib/src/phy/utils/vector.c index 3bb7fb08f..5d5b6747a 100644 --- a/lib/src/phy/utils/vector.c +++ b/lib/src/phy/utils/vector.c @@ -37,6 +37,10 @@ +void srslte_vec_xor_bbb(int8_t *x,int8_t *y,int8_t *z, uint32_t len) { + srslte_vec_xor_bbb_simd(x, y, z, len); +} + // Used in PRACH detector, AGC and chest_dl for noise averaging float srslte_vec_acc_ff(float *x, uint32_t len) { return srslte_vec_acc_ff_simd(x, len); diff --git a/lib/src/phy/utils/vector_simd.c b/lib/src/phy/utils/vector_simd.c index 23c58cfce..c7bb7b1fc 100644 --- a/lib/src/phy/utils/vector_simd.c +++ b/lib/src/phy/utils/vector_simd.c @@ -37,6 +37,35 @@ #include "srslte/phy/utils/simd.h" +void srslte_vec_xor_bbb_simd(int8_t *x, int8_t *y, int8_t *z, int len) { + int i = 0; +#if SRSLTE_SIMD_B_SIZE + if (SRSLTE_IS_ALIGNED(x) && SRSLTE_IS_ALIGNED(y) && SRSLTE_IS_ALIGNED(z)) { + for (; i < len - SRSLTE_SIMD_B_SIZE + 1; i += SRSLTE_SIMD_B_SIZE) { + simd_b_t a = srslte_simd_b_load(&x[i]); + simd_b_t b = srslte_simd_b_load(&y[i]); + + simd_b_t r = srslte_simd_b_xor(a, b); + + srslte_simd_b_store(&z[i], r); + } + } else { + for (; i < len - SRSLTE_SIMD_B_SIZE + 1; i += SRSLTE_SIMD_B_SIZE) { + simd_b_t a = srslte_simd_b_loadu(&x[i]); + simd_b_t b = srslte_simd_b_loadu(&y[i]); + + simd_s_t r = srslte_simd_b_xor(a, b); + + srslte_simd_b_storeu(&z[i], r); + } + } +#endif /* SRSLTE_SIMD_B_SIZE */ + + for(; i < len; i++){ + z[i] = x[i] ^ y[i]; + } +} + int srslte_vec_dot_prod_sss_simd(int16_t *x, int16_t *y, int len) { int i = 0; int result = 0; From 3a0ab02264e52e1f6ff7c9ca6fc1d26c0209f2a2 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Mon, 27 Nov 2017 13:57:05 +0100 Subject: [PATCH 166/242] S1/X2 handover tested and working --- lib/examples/cell_measurement.c | 2 +- lib/include/srslte/common/liblte_security.h | 6 + lib/include/srslte/common/security.h | 4 + lib/include/srslte/interfaces/ue_interfaces.h | 1 + lib/include/srslte/phy/sync/sync.h | 1 + lib/src/common/liblte_security.cc | 28 ++++ lib/src/common/security.cc | 9 ++ lib/src/phy/sync/sync.c | 9 +- lib/src/phy/ue/ue_dl.c | 2 +- lib/src/phy/ue/ue_sync.c | 34 ++--- srsue/hdr/phy/phch_common.h | 7 +- srsue/hdr/phy/phch_recv.h | 3 +- srsue/hdr/upper/rrc.h | 5 +- srsue/hdr/upper/usim.h | 5 + srsue/src/mac/mac.cc | 1 - srsue/src/phy/phch_recv.cc | 126 ++++++++++++------ srsue/src/phy/phch_worker.cc | 55 ++++---- srsue/src/upper/rrc.cc | 88 ++++++++---- srsue/src/upper/usim.cc | 33 ++++- 19 files changed, 285 insertions(+), 134 deletions(-) diff --git a/lib/examples/cell_measurement.c b/lib/examples/cell_measurement.c index 268e87837..eec7548e4 100644 --- a/lib/examples/cell_measurement.c +++ b/lib/examples/cell_measurement.c @@ -369,7 +369,7 @@ int main(int argc, char **argv) { if ((nframes%100) == 0 || rx_gain_offset == 0) { if (srslte_rf_has_rssi(&rf)) { - rx_gain_offset = 10*log10(rssi*1000)-srslte_rf_get_rssi(&rf); + rx_gain_offset = 30+10*log10(rssi*1000)-srslte_rf_get_rssi(&rf); } else { rx_gain_offset = srslte_rf_get_rx_gain(&rf); } diff --git a/lib/include/srslte/common/liblte_security.h b/lib/include/srslte/common/liblte_security.h index 2c6fdc50c..79006dca9 100644 --- a/lib/include/srslte/common/liblte_security.h +++ b/lib/include/srslte/common/liblte_security.h @@ -91,6 +91,10 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_enb_star(uint8 *k_enb, uint32_t earfcn, uint8 *k_enb_star); +LIBLTE_ERROR_ENUM liblte_security_generate_nh( uint8_t *k_asme, + uint8_t *sync, + uint8_t *nh); + /********************************************************************* Name: liblte_security_generate_k_nas @@ -126,6 +130,8 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_nas(uint8 uint8 *k_nas_enc, uint8 *k_nas_int); + + /********************************************************************* Name: liblte_security_generate_k_rrc diff --git a/lib/include/srslte/common/security.h b/lib/include/srslte/common/security.h index fd892e891..386997326 100644 --- a/lib/include/srslte/common/security.h +++ b/lib/include/srslte/common/security.h @@ -81,6 +81,10 @@ uint8_t security_generate_k_enb_star( uint8_t *k_enb, uint32_t earfcn, uint8_t *k_enb_star); +uint8_t security_generate_nh( uint8_t *k_asme, + uint8_t *sync, + uint8_t *nh); + uint8_t security_generate_k_nas( uint8_t *k_asme, CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index 2713e2a6e..94a94dd0d 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -85,6 +85,7 @@ public: srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0; virtual void generate_as_keys_ho(uint32_t pci, uint32_t earfcn, + int ncc, uint8_t *k_rrc_enc, uint8_t *k_rrc_int, uint8_t *k_up_enc, diff --git a/lib/include/srslte/phy/sync/sync.h b/lib/include/srslte/phy/sync/sync.h index 135a19160..081b332c7 100644 --- a/lib/include/srslte/phy/sync/sync.h +++ b/lib/include/srslte/phy/sync/sync.h @@ -75,6 +75,7 @@ typedef struct SRSLTE_API { uint32_t frame_size; uint32_t max_offset; bool enable_cfo_corr; + bool enable_cfo_pss; bool mean_cfo2_isunset; bool mean_cfo_isunset; float mean_cfo; diff --git a/lib/src/common/liblte_security.cc b/lib/src/common/liblte_security.cc index e0cdd90d8..0c7626abc 100644 --- a/lib/src/common/liblte_security.cc +++ b/lib/src/common/liblte_security.cc @@ -335,6 +335,34 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_enb_star(uint8 *k_enb, return (err); } +LIBLTE_ERROR_ENUM liblte_security_generate_nh( uint8_t *k_asme, + uint8_t *sync, + uint8_t *nh) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 s[35]; + + if (k_asme != NULL && + sync != NULL && + nh != NULL) + { + // Construct S + s[0] = 0x12; // FC + for (int i=0;i<32;i++) { + s[1+i] = sync[i]; + } + s[33] = 0x00; // First byte of L0 + s[34] = 0x20, // Second byte of L0 + + // Derive NH + sha256(k_asme, 32, s, 35, nh, 0); + + err = LIBLTE_SUCCESS; + } + + return (err); +} + /********************************************************************* Name: liblte_security_generate_k_nas diff --git a/lib/src/common/security.cc b/lib/src/common/security.cc index 93b197e7c..404e88d34 100644 --- a/lib/src/common/security.cc +++ b/lib/src/common/security.cc @@ -72,6 +72,15 @@ uint8_t security_generate_k_enb_star( uint8_t *k_enb, k_enb_star); } +uint8_t security_generate_nh( uint8_t *k_asme, + uint8_t *sync, + uint8_t *nh) +{ + return liblte_security_generate_nh( k_asme, + sync, + nh); +} + uint8_t security_generate_k_nas( uint8_t *k_asme, CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, diff --git a/lib/src/phy/sync/sync.c b/lib/src/phy/sync/sync.c index 6faebfcad..34009fbad 100644 --- a/lib/src/phy/sync/sync.c +++ b/lib/src/phy/sync/sync.c @@ -554,8 +554,7 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t peak_pos = srslte_pss_synch_find_pss(&q->pss, &input_cfo[find_offset], &q->peak_value); // this compensates for the constant time shift caused by the low pass filter - if(q->decimate && peak_pos < 0) - { + if(q->decimate && peak_pos < 0) { peak_pos = 0 ;//peak_pos + q->decimate*(2);// replace 2 with q->filter_size -2; } if (peak_pos < 0) { @@ -591,17 +590,15 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t } } - if (q->enable_cfo_corr) { + if (q->enable_cfo_pss) { if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) { - float cfo2 = srslte_pss_synch_cfo_compute(&q->pss, &input[find_offset + peak_pos - q->fft_size]); + float cfo2 = srslte_pss_synch_cfo_compute(&q->pss, &input[find_offset + peak_pos - q->fft_size]); if (q->mean_cfo2_isunset) { q->mean_cfo2 = cfo2; q->mean_cfo2_isunset = true; } else { q->mean_cfo2 = SRSLTE_VEC_EMA(cfo2, q->mean_cfo2, q->cfo_ema_alpha); } - } else { - ret = SRSLTE_SYNC_FOUND_NOSPACE; } } } else { diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index c5431cec9..a9ecfe40f 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -401,7 +401,7 @@ int srslte_ue_dl_decode_fft_estimate_mbsfn(srslte_ue_dl_t *q, uint32_t sf_idx, u int srslte_ue_dl_decode_fft_estimate_noguru(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS], uint32_t sf_idx, uint32_t *cfi) { - if (input && q && cfi && sf_idx < SRSLTE_NSUBFRAMES_X_FRAME) { + if (input && q && sf_idx < SRSLTE_NSUBFRAMES_X_FRAME) { /* Run FFT for all subframe data */ for (int j=0;jnof_rx_antennas;j++) { diff --git a/lib/src/phy/ue/ue_sync.c b/lib/src/phy/ue/ue_sync.c index d11811cf3..8adf77dd6 100644 --- a/lib/src/phy/ue/ue_sync.c +++ b/lib/src/phy/ue/ue_sync.c @@ -682,19 +682,21 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE q->sf_idx = (q->sf_idx + q->nof_recv_sf) % 10; #ifndef DO_CFO_IN_SYNC - /* We found that CP-based correction performs better in low SNR than PSS-based. - * - * Estimate, average and correct here instead of inside sync object - */ - q->cfo = srslte_sync_cfo_estimate(&q->strack, input_buffer[0], 0); - if (q->mean_cfo_isunset) { - q->mean_cfo = q->cfo; - q->mean_cfo_isunset = false; - } else { - /* compute exponential moving average CFO */ - q->mean_cfo = SRSLTE_VEC_EMA(q->cfo, q->mean_cfo, q->cfo_ema_alpha); + if (q->correct_cfo) { + /* We found that CP-based correction performs better in low SNR than PSS-based. + * + * Estimate, average and correct here instead of inside sync object + */ + q->cfo = srslte_sync_cfo_estimate(&q->strack, input_buffer[0], 0); + if (q->mean_cfo_isunset) { + q->mean_cfo = q->cfo; + q->mean_cfo_isunset = false; + } else { + /* compute exponential moving average CFO */ + q->mean_cfo = SRSLTE_VEC_EMA(q->cfo, q->mean_cfo, q->cfo_ema_alpha); + } + srslte_cfo_correct(&q->strack.cfocorr2, input_buffer[0], input_buffer[0], -q->mean_cfo / q->fft_size); } - srslte_cfo_correct(&q->strack.cfocorr2, input_buffer[0], input_buffer[0], -q->mean_cfo / q->fft_size); #endif @@ -754,14 +756,6 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE q->frame_total_cnt++; } - if (q->correct_cfo) { - for (int i=0;inof_rx_antennas;i++) { - srslte_cfo_correct(&q->strack.cfocorr, - input_buffer[i], - input_buffer[i], - -srslte_sync_get_cfo(&q->strack) / q->fft_size); - } - } break; } diff --git a/srsue/hdr/phy/phch_common.h b/srsue/hdr/phy/phch_common.h index 39eb594bc..ecdedf63b 100644 --- a/srsue/hdr/phy/phch_common.h +++ b/srsue/hdr/phy/phch_common.h @@ -51,20 +51,19 @@ namespace srsue { phy_args_t *args; rrc_interface_phy *rrc; mac_interface_phy *mac; - srslte_ue_ul_t ue_ul; - + /* Power control variables */ float pathloss; float cur_pathloss; float p0_preamble; float cur_radio_power; float cur_pusch_power; - float avg_rsrp_db; + float avg_rsrp; + float avg_rsrp_dbm; float avg_rsrq_db; float rx_gain_offset; float avg_snr_db; float avg_noise; - float avg_rsrp; bool pcell_meas_enabled; uint32_t pcell_report_period; diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index eea156298..4f54580f1 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -167,7 +167,7 @@ private: void set_cell(srslte_cell_t cell); ret_code run_subframe(uint32_t sf_idx); ret_code run_subframe_sync(srslte_ue_sync_t *ue_sync, uint32_t sf_idx); - ret_code run_multiple_subframes(cf_t *buffer, uint32_t sf_idx, uint32_t nof_sf); + ret_code run_multiple_subframes(cf_t *buffer, uint32_t offset, uint32_t sf_idx, uint32_t nof_sf); float rsrp(); float rsrq(); float snr(); @@ -205,6 +205,7 @@ private: srslte::log *log_h; srslte_sync_t sync_find; + uint32_t current_fft_sz; measure measure_p; }; diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index 20b32477f..1f28f0000 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -205,8 +205,10 @@ private: LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT sib13; } cell_t; - std::vector known_cells; + const static int MAX_KNOWN_CELLS = 64; + cell_t known_cells[MAX_KNOWN_CELLS]; cell_t *current_cell; + void add_new_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp); typedef enum { SI_ACQUIRE_IDLE = 0, @@ -353,7 +355,6 @@ private: float Qqualmin; float Qqualminoffset; float s_intrasearchP; - float s_intrasearchQ; float q_hyst; float threshservinglow; diff --git a/srsue/hdr/upper/usim.h b/srsue/hdr/upper/usim.h index 6ad3acce5..cf5a4c820 100644 --- a/srsue/hdr/upper/usim.h +++ b/srsue/hdr/upper/usim.h @@ -92,6 +92,7 @@ public: void generate_as_keys_ho(uint32_t pci, uint32_t earfcn, + int ncc, uint8_t *k_rrc_enc, uint8_t *k_rrc_int, uint8_t *k_up_enc, @@ -137,9 +138,13 @@ private: uint8_t ak[6]; uint8_t mac[8]; uint8_t autn[16]; + uint8_t k_asme[32]; + uint8_t nh[32]; uint8_t k_enb[32]; uint8_t k_enb_star[32]; + uint32_t current_ncc; + bool initiated; }; diff --git a/srsue/src/mac/mac.cc b/srsue/src/mac/mac.cc index 368050f7d..42d7c4b96 100644 --- a/srsue/src/mac/mac.cc +++ b/srsue/src/mac/mac.cc @@ -385,7 +385,6 @@ void mac::set_ho_rnti(uint16_t crnti, uint16_t target_pci) { phy_h->pdcch_ul_search_reset(); uernti.crnti = crnti; if (pcap) { - printf("set_ue_id=%d\n", target_pci); pcap->set_ue_id(target_pci); } } diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 3f6a2a019..d9b1b7f72 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -52,6 +52,7 @@ phch_recv::phch_recv() { ul_freq = -1; bzero(&cell, sizeof(srslte_cell_t)); running = false; + worker_com = NULL; } void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_mac, rrc_interface_phy *_rrc, @@ -976,7 +977,7 @@ void phch_recv::measure::init(cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h for (int i=0;ibuffer[i] = buffer[i]; } - + if (srslte_ue_dl_init(&ue_dl, this->buffer, SRSLTE_MAX_PRB, nof_rx_antennas)) { Error("SYNC: Initiating ue_dl_measure\n"); return; @@ -1024,6 +1025,7 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe_sync(srslte_ue_syn { int sync_res = srslte_ue_sync_zerocopy_multi(ue_sync, buffer); if (sync_res == 1) { + log_h->info("SYNC: CFO=%.1f KHz\n", srslte_ue_sync_get_cfo(ue_sync)); return run_subframe(sf_idx); } else { log_h->error("SYNC: Measuring RSRP: Sync error\n"); @@ -1034,18 +1036,61 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe_sync(srslte_ue_syn } phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *input_buffer, + uint32_t offset, uint32_t sf_idx, - uint32_t nof_sf) + uint32_t max_sf) { uint32_t sf_len = SRSLTE_SF_LEN_PRB(current_prb); ret_code ret = IDLE; - for (uint32_t i=0;i= 0) { + + cf_t *buf_m[SRSLTE_MAX_PORTS]; + buf_m[0] = &input_buffer[test_offset]; + + uint32_t cfi; + if (srslte_ue_dl_decode_fft_estimate_noguru(&ue_dl, buf_m, sf_idx, &cfi)) { + Error("MEAS: Measuring RSRP: Estimating channel\n"); + return ERROR; + } + + float rsrp = srslte_chest_dl_get_rsrp(&ue_dl.chest); + if (rsrp > max_rsrp) { + max_rsrp = rsrp; + best_test_offset = test_offset; + found_best = true; + } + } + } + + offset = found_best?best_test_offset:offset; + if (offset >= 0 && offset < sf_len*max_sf) { + uint32_t nof_sf = (sf_len*max_sf - offset)/sf_len; + + Info("INTRA: fine-tuning offset: %d, found_best=%d, rem_sf=%d\n", offset, found_best, nof_sf); + + for (uint32_t i=0;ipcell_meas_enabled = false; + if (worker_com) { + worker_com->pcell_meas_enabled = false; + } } int phch_recv::meas_start(uint32_t earfcn, int pci) { @@ -1223,7 +1272,7 @@ int phch_recv::meas_start(uint32_t earfcn, int pci) { } return 0; } else { - Warning("INTRA: Inter-frequency measurements not supported (current EARFCN=%d, requested measurement for %d)\n", + Warning("INTRA: Inter-frequency measurements not supported (current EARFCN=%d, requested measurement for %d)\n", current_earfcn, earfcn); return -1; } @@ -1234,7 +1283,7 @@ int phch_recv::meas_stop(uint32_t earfcn, int pci) { intra_freq_meas.rem_cell(pci); return 0; } else { - Warning("INTRA: Inter-frequency measurements not supported (current EARFCN=%d, requested stop measurement for %d)\n", + Warning("INTRA: Inter-frequency measurements not supported (current EARFCN=%d, requested stop measurement for %d)\n", current_earfcn, earfcn); } return -1; @@ -1283,9 +1332,9 @@ void phch_recv::intra_measure::add_cell(int pci) { if (std::find(active_pci.begin(), active_pci.end(), pci) == active_pci.end()) { active_pci.push_back(pci); receive_enabled = true; - Info("INTRA: Starting intra-frequency measurement for pci=%d\n", pci); + Info("INTRA: Starting intra-frequency measurement for pci=%d\n", pci); } else { - Warning("INTRA: Requested to start already existing intra-frequency measurement for PCI=%d\n", pci); + Warning("INTRA: Requested to start already existing intra-frequency measurement for PCI=%d\n", pci); } } @@ -1306,9 +1355,9 @@ void phch_recv::intra_measure::rem_cell(int pci) { if (active_pci.size() == 0) { receive_enabled = false; } - Info("INTRA: Stopping intra-frequency measurement for pci=%d. Number of cells: %d\n", pci, active_pci.size()); + Info("INTRA: Stopping intra-frequency measurement for pci=%d. Number of cells: %d\n", pci, active_pci.size()); } else { - Warning("INTRA: Requested to stop non-existing intra-frequency measurement for PCI=%d\n", pci); + Warning("INTRA: Requested to stop non-existing intra-frequency measurement for PCI=%d\n", pci); } } @@ -1318,12 +1367,12 @@ void phch_recv::intra_measure::write(uint32_t tti, cf_t *data, uint32_t nsamples receiving = true; receive_cnt = 0; measure_tti = tti; + srslte_ringbuffer_reset(&ring_buffer); } if (receiving == true) { if (srslte_ringbuffer_write(&ring_buffer, data, nsamples*sizeof(cf_t)) < (int) (nsamples*sizeof(cf_t))) { Warning("Error writing to ringbuffer\n"); receiving = false; - srslte_ringbuffer_reset(&ring_buffer); } else { receive_cnt++; if (receive_cnt == CAPTURE_LEN_SF) { @@ -1343,13 +1392,12 @@ void phch_recv::intra_measure::run_thread() } if (running) { - Info("INTRA: Running intra-frequency measurements\n"); + Info("INTRA: Running intra-frequency measurements\n"); - // Read 5 ms data from buffer + // Read 15 ms data from buffer srslte_ringbuffer_read(&ring_buffer, search_buffer, CAPTURE_LEN_SF*current_sflen*sizeof(cf_t)); int found_cells = scell.find_cells(search_buffer, common->rx_gain_offset, primary_cell, CAPTURE_LEN_SF, info); receiving = false; - srslte_ringbuffer_reset(&ring_buffer); for (int i=0;inew_phy_meas(info[i].rsrp, info[i].rsrq, measure_tti, current_earfcn, info[i].pci); diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index ebb234539..5ae0b242a 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -221,7 +221,7 @@ void phch_worker::work_imp() /* Do FFT and extract PDCCH LLR, or quit if no actions are required in this subframe */ bool chest_ok = extract_fft_and_pdcch_llr(); - bool snr_th_ok = 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest))>1.0; + bool snr_th_ok = 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest))>-10.0; if (chest_ok && snr_th_ok) { @@ -381,7 +381,7 @@ void phch_worker::work_imp() log_h->debug("SYNC: Sending in-sync to RRC\n"); } else { phy->rrc->out_of_sync(); - log_h->debug("SNR=%.1f dB under threshold. Sending out-of-sync to RRC\n", + log_h->info("SNR=%.1f dB under threshold. Sending out-of-sync to RRC\n", 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest))); } } @@ -974,7 +974,7 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui #endif uint8_t dummy[2] = {0,0}; - log_h->info_hex(payload?payload:dummy, payload?grant->mcs.tbs/8:1,"PUSCH: tti_tx=%d, alloc=(%d,%d), tbs=%d, mcs=%d, rv=%d, ack=%s, ri=%s, cfo=%.1f KHz%s\n", + log_h->info("PUSCH: tti_tx=%d, alloc=(%d,%d), tbs=%d, mcs=%d, rv=%d, ack=%s, ri=%s, cfo=%.1f KHz%s\n", (tti+HARQ_DELAY_MS)%10240, grant->n_prb[0], grant->n_prb[0]+grant->L_prb, grant->mcs.tbs/8, grant->mcs.idx, rv, @@ -1244,52 +1244,49 @@ void phch_worker::update_measurements() if (tti== 0 || phy->rx_gain_offset == 0) { float rx_gain_offset = 0; if (phy->get_radio()->has_rssi() && phy->args->rssi_sensor_enabled) { - float rssi_all_signal = srslte_chest_dl_get_rssi(&ue_dl.chest); - if (rssi_all_signal) { - rx_gain_offset = 10*log10(rssi_all_signal)-phy->get_radio()->get_rssi(); - } else { - rx_gain_offset = 0; - } + float rssi_all_signal = 30+10*log10(srslte_vec_avg_power_cf(signal_buffer[0],SRSLTE_SF_LEN(srslte_symbol_sz(cell.nof_prb)))); + rx_gain_offset = 30+rssi_all_signal-phy->get_radio()->get_rssi(); } else { rx_gain_offset = phy->get_radio()->get_rx_gain(); } if (phy->rx_gain_offset) { - phy->rx_gain_offset = SRSLTE_VEC_EMA(phy->rx_gain_offset, rx_gain_offset, 0.5); + phy->rx_gain_offset = SRSLTE_VEC_EMA(rx_gain_offset, phy->rx_gain_offset, 0.5); } else { phy->rx_gain_offset = rx_gain_offset; } } // Average RSRQ - float cur_rsrq = 10*log10(srslte_chest_dl_get_rsrq(&ue_dl.chest)); - if (isnormal(cur_rsrq)) { - phy->avg_rsrq_db = SRSLTE_VEC_EMA(phy->avg_rsrq_db, cur_rsrq, snr_ema_coeff); + float rsrq_db = 10*log10(srslte_chest_dl_get_rsrq(&ue_dl.chest)); + if (isnormal(rsrq_db)) { + phy->avg_rsrq_db = SRSLTE_VEC_EMA(rsrq_db, phy->avg_rsrq_db, snr_ema_coeff); } - + // Average RSRP - float cur_rsrp = srslte_chest_dl_get_rsrp(&ue_dl.chest); - if (isnormal(cur_rsrp)) { - phy->avg_rsrp = SRSLTE_VEC_EMA(phy->avg_rsrp, cur_rsrp, snr_ema_coeff); + float rsrp_lin = srslte_chest_dl_get_rsrp(&ue_dl.chest); + if (isnormal(rsrp_lin)) { + phy->avg_rsrp = SRSLTE_VEC_EMA(rsrp_lin, phy->avg_rsrp, snr_ema_coeff); } /* Correct absolute power measurements by RX gain offset */ - float rsrp = 10*log10(srslte_chest_dl_get_rsrp(&ue_dl.chest)) + 30 - phy->rx_gain_offset; - float rssi = 10*log10(srslte_chest_dl_get_rssi(&ue_dl.chest)) + 30 - phy->rx_gain_offset; - + float rsrp_dbm = 10*log10(rsrp_lin) + 30 - phy->rx_gain_offset; + float rssi_db = 10*log10(srslte_chest_dl_get_rssi(&ue_dl.chest)) + 30 - phy->rx_gain_offset; + // Serving cell measurements are averaged over DEFAULT_MEAS_PERIOD_MS then sent to RRC - if (isnormal(rsrp)) { - if (!phy->avg_rsrp_db) { - phy->avg_rsrp_db = rsrp; + if (isnormal(rsrp_dbm)) { + if (!phy->avg_rsrp_dbm) { + phy->avg_rsrp_dbm= rsrp_dbm; } else { - phy->avg_rsrp_db = SRSLTE_VEC_EMA(phy->avg_rsrp_db, rsrp, 0.8); + phy->avg_rsrp_dbm = SRSLTE_VEC_EMA(rsrp_dbm, phy->avg_rsrp_dbm, snr_ema_coeff); } if ((tti%phy->pcell_report_period) == 0 && phy->pcell_meas_enabled) { - phy->rrc->new_phy_meas(phy->avg_rsrp_db, phy->avg_rsrq_db, tti); + phy->rrc->new_phy_meas(phy->avg_rsrp_dbm, phy->avg_rsrq_db, tti); } } + // Compute PL float tx_crs_power = phy->config->common.pdsch_cnfg.rs_power; - phy->pathloss = tx_crs_power - phy->avg_rsrp_db; + phy->pathloss = tx_crs_power - phy->avg_rsrp_dbm; // Average noise float cur_noise = srslte_chest_dl_get_noise_estimate(&ue_dl.chest); @@ -1297,7 +1294,7 @@ void phch_worker::update_measurements() if (!phy->avg_noise) { phy->avg_noise = cur_noise; } else { - phy->avg_noise = SRSLTE_VEC_EMA(phy->avg_noise, cur_noise, snr_ema_coeff); + phy->avg_noise = SRSLTE_VEC_EMA(cur_noise, phy->avg_noise, snr_ema_coeff); } } @@ -1306,9 +1303,9 @@ void phch_worker::update_measurements() // Store metrics dl_metrics.n = phy->avg_noise; - dl_metrics.rsrp = phy->avg_rsrp_db; + dl_metrics.rsrp = phy->avg_rsrp_dbm; dl_metrics.rsrq = phy->avg_rsrq_db; - dl_metrics.rssi = rssi; + dl_metrics.rssi = rssi_db; dl_metrics.pathloss = phy->pathloss; dl_metrics.sinr = phy->avg_snr_db; dl_metrics.turbo_iters = srslte_pdsch_last_noi(&ue_dl.pdsch); diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index afa4bca96..31ed25384 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -89,6 +89,8 @@ void rrc::init(phy_interface_rrc *phy_, state = RRC_STATE_IDLE; si_acquire_state = SI_ACQUIRE_IDLE; + bzero(known_cells, MAX_KNOWN_CELLS*sizeof(cell_t)); + thread_running = true; start(); @@ -433,7 +435,7 @@ void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) { } void rrc::select_next_cell_in_plmn() { - for (uint32_t i = last_selected_cell + 1; i < known_cells.size(); i++) { + for (uint32_t i = last_selected_cell + 1; i < MAX_KNOWN_CELLS && known_cells[i].earfcn; i++) { for (uint32_t j = 0; j < known_cells[i].sib1.N_plmn_ids; j++) { if (known_cells[i].sib1.plmn_id[j].id.mcc == selected_plmn_id.mcc || known_cells[i].sib1.plmn_id[j].id.mnc == selected_plmn_id.mnc) { @@ -476,7 +478,7 @@ void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, uint32_t earfcn, ui void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { // find if cell_id-earfcn combination already exists - for (uint32_t i = 0; i < known_cells.size(); i++) { + for (uint32_t i = 0; i < MAX_KNOWN_CELLS && known_cells[i].earfcn; i++) { if (earfcn == known_cells[i].earfcn && phy_cell.id == known_cells[i].phy_cell.id) { current_cell = &known_cells[i]; current_cell->rsrp = rsrp; @@ -497,17 +499,7 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { } } // add to list of known cells - cell_t cell; - cell.phy_cell = phy_cell; - cell.rsrp = rsrp; - cell.earfcn = earfcn; - cell.has_valid_sib1 = false; - cell.has_valid_sib2 = false; - cell.has_valid_sib3 = false; - known_cells.push_back(cell); - - // save current cell - current_cell = &known_cells.back(); + add_new_cell(earfcn, phy_cell, rsrp); si_acquire_state = SI_ACQUIRE_SIB1; @@ -516,6 +508,24 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { current_cell->earfcn, current_cell->rsrp, current_cell); } +void rrc::add_new_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { + int i=0; + while(ierror("Can't add more cells\n"); + return; + } + current_cell = &known_cells[i]; + current_cell->phy_cell = phy_cell; + current_cell->rsrp = rsrp; + current_cell->earfcn = earfcn; + current_cell->has_valid_sib1 = false; + current_cell->has_valid_sib2 = false; + current_cell->has_valid_sib3 = false; +} + // PHY indicates that has gone through all known EARFCN void rrc::earfcn_end() { rrc_log->debug("Finished searching cells in EARFCN set while in state %s\n", rrc_state_text[state]); @@ -527,20 +537,18 @@ void rrc::earfcn_end() { } void rrc::add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp) { - for (uint32_t i = 0; i < known_cells.size(); i++) { + for (uint32_t i = 0; i < MAX_KNOWN_CELLS && known_cells[i].earfcn; i++) { if (earfcn == known_cells[i].earfcn && pci == known_cells[i].phy_cell.id) { known_cells[i].rsrp = rsrp; return; } } rrc_log->info("Added neighbour cell earfcn=%d, pci=%d, rsrp=%f\n", earfcn, pci, rsrp); - cell_t c; - bzero(&c, sizeof(cell_t)); - c.earfcn = earfcn; - c.rsrp = rsrp; - memcpy(&c.phy_cell, ¤t_cell->phy_cell, sizeof(srslte_cell_t)); - c.phy_cell.id = pci; - known_cells.push_back(c); + + srslte_cell_t cell; + cell = current_cell->phy_cell; + cell.id = pci; + add_new_cell(earfcn, cell, rsrp); } // Cell reselection in IDLE Section 5.2.4 of 36.304 @@ -548,7 +556,7 @@ void rrc::cell_reselection_eval(float rsrp, float rsrq) { // Intra-frequency cell-reselection criteria - if (get_srxlev(rsrp) > cell_resel_cfg.s_intrasearchP && get_squal(rsrq) > cell_resel_cfg.s_intrasearchQ) { + if (get_srxlev(rsrp) > cell_resel_cfg.s_intrasearchP) { // UE may not perform intra-frequency measurements phy->meas_reset(); } else { @@ -900,9 +908,7 @@ void rrc::ho_prepare() { apply_rr_config_common_dl(&mob_reconf.mob_ctrl_info.rr_cnfg_common); bool found = false; - for (uint32_t i = 0; i < known_cells.size(); i++) { - rrc_log->info("cell[%d]=%d:%d, cur_earfcn=%d\n", i, known_cells[i].earfcn, known_cells[i].phy_cell.id, - current_cell->earfcn); + for (uint32_t i = 0; i < MAX_KNOWN_CELLS && known_cells[i].earfcn; i++) { if (known_cells[i].earfcn == phy->get_current_earfcn() && known_cells[i].phy_cell.id == mob_reconf.mob_ctrl_info.target_pci) { rrc_log->info("Selecting new cell pci=%d\n", known_cells[i].phy_cell.id); @@ -925,8 +931,13 @@ void rrc::ho_prepare() { mac->start_cont_ho(); } - printf("ncc=%d\n", mob_reconf.sec_cnfg_ho.intra_lte.next_hop_chaining_count); + int ncc = -1; + if (mob_reconf.sec_cnfg_ho_present) { + ncc = mob_reconf.sec_cnfg_ho.intra_lte.next_hop_chaining_count; + } + usim->generate_as_keys_ho(mob_reconf.mob_ctrl_info.target_pci, phy->get_current_earfcn(), + ncc, k_rrc_enc, k_rrc_int, k_up_enc, k_up_int, cipher_algo, integ_algo); pdcp->config_security(1, k_rrc_enc, k_rrc_int, cipher_algo, integ_algo); send_rrc_con_reconfig_complete(NULL); @@ -968,7 +979,8 @@ void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGU if (reconfig->mob_ctrl_info_present) { rrc_log->info("Received HO command to target PCell=%d\n", reconfig->mob_ctrl_info.target_pci); - rrc_log->console("Received HO command to target PCell=%d\n", reconfig->mob_ctrl_info.target_pci); + rrc_log->console("Received HO command to target PCell=%d, NCC=%d\n", + reconfig->mob_ctrl_info.target_pci, reconfig->sec_cnfg_ho.intra_lte.next_hop_chaining_count); // store mobilityControlInfo memcpy(&mob_reconf, reconfig, sizeof(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT)); @@ -1126,6 +1138,21 @@ void rrc::handle_sib3() { rrc_log->info("SIB3 received\n"); + LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *sib3 = ¤t_cell->sib3; + + // cellReselectionInfoCommon + cell_resel_cfg.q_hyst = liblte_rrc_q_hyst_num[sib3->q_hyst]; + + // cellReselectionServingFreqInfo + cell_resel_cfg.threshservinglow = 2*sib3->thresh_serving_low; + + // intraFreqCellReselectionInfo + cell_resel_cfg.Qrxlevmin = 2*sib3->q_rx_lev_min; + if (sib3->s_intra_search_present) { + cell_resel_cfg.s_intrasearchP = 2*sib3->s_intra_search; + } else { + cell_resel_cfg.s_intrasearchP = INFINITY; + } } @@ -2055,16 +2082,19 @@ void rrc::rrc_meas::L3_filter(meas_value_t *value, float values[NOF_MEASUREMENTS void rrc::rrc_meas::new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, float rsrq, uint32_t tti) { - log_h->info("MEAS: New measurement earfcn=%d, pci=%d, rsrp=%f, rsrq=%f, tti=%d\n", earfcn, pci, rsrp, rsrq, tti); - float values[NOF_MEASUREMENTS] = {rsrp, rsrq}; // This indicates serving cell if (earfcn == 0) { + + log_h->info("MEAS: New measurement serving cell, rsrp=%f, rsrq=%f, tti=%d\n", rsrp, rsrq, tti); + L3_filter(&pcell_measurement, values); } else { // Add to known cells parent->add_neighbour_cell(earfcn, pci, rsrp); + log_h->info("MEAS: New measurement earfcn=%d, pci=%d, rsrp=%f, rsrq=%f, tti=%d\n", earfcn, pci, rsrp, rsrq, tti); + // Save PHY measurement for all active measurements whose earfcn/pci matches for(std::map::iterator iter=active.begin(); iter!=active.end(); ++iter) { meas_t *m = &iter->second; diff --git a/srsue/src/upper/usim.cc b/srsue/src/upper/usim.cc index 305da7b25..c460404cc 100644 --- a/srsue/src/upper/usim.cc +++ b/srsue/src/upper/usim.cc @@ -244,6 +244,8 @@ void usim::generate_as_keys(uint8_t *k_asme, count_ul, k_enb); + memcpy(this->k_asme, k_asme, 32); + // Generate K_rrc_enc and K_rrc_int security_generate_k_rrc( k_enb, cipher_algo, @@ -257,10 +259,13 @@ void usim::generate_as_keys(uint8_t *k_asme, integ_algo, k_up_enc, k_up_int); + + current_ncc = 0; } void usim::generate_as_keys_ho(uint32_t pci, uint32_t earfcn, + int ncc, uint8_t *k_rrc_enc, uint8_t *k_rrc_int, uint8_t *k_up_enc, @@ -268,13 +273,39 @@ void usim::generate_as_keys_ho(uint32_t pci, CIPHERING_ALGORITHM_ID_ENUM cipher_algo, INTEGRITY_ALGORITHM_ID_ENUM integ_algo) { + uint8_t *enb_star_key = k_enb; + + if (ncc < 0) { + ncc = current_ncc; + } + + // Generate successive NH + while(current_ncc != (uint32_t) ncc) { + uint8_t *sync = NULL; + if (current_ncc) { + sync = nh; + } else { + sync = k_enb; + } + // Generate NH + security_generate_nh(k_asme, + sync, + nh); + + current_ncc++; + if (current_ncc == 7) { + current_ncc = 0; + } + enb_star_key = nh; + } // Generate K_enb - security_generate_k_enb_star( k_enb, + security_generate_k_enb_star( enb_star_key, pci, earfcn, k_enb_star); + // K_enb becomes K_enb* memcpy(k_enb, k_enb_star, 32); // Generate K_rrc_enc and K_rrc_int From aacd9e1e5b0f2af65c114809e0459c4a394539fc Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Mon, 27 Nov 2017 18:27:48 +0100 Subject: [PATCH 167/242] Revert "Use CP-based CFO estimation only for DL and UL. Estimate every subframe. Calibrated EMA to 0.3 highest valid for low SNR" This reverts commit 6196c096afbdf4174d334431a06964f23d62b091. --- lib/include/srslte/phy/sync/sync.h | 4 ---- lib/include/srslte/phy/ue/ue_sync.h | 7 +----- lib/src/phy/sync/sync.c | 24 +++++++++----------- lib/src/phy/ue/ue_sync.c | 34 ----------------------------- srsue/src/main.cc | 2 +- srsue/src/phy/phch_worker.cc | 1 - srsue/ue.conf.example | 2 +- 7 files changed, 13 insertions(+), 61 deletions(-) diff --git a/lib/include/srslte/phy/sync/sync.h b/lib/include/srslte/phy/sync/sync.h index 135a19160..1c70b2449 100644 --- a/lib/include/srslte/phy/sync/sync.h +++ b/lib/include/srslte/phy/sync/sync.h @@ -139,10 +139,6 @@ SRSLTE_API srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, uint32_t find_offset, uint32_t *peak_position); -SRSLTE_API float srslte_sync_cfo_estimate(srslte_sync_t *q, - cf_t *input, - int find_offset); - /* Estimates the CP length */ SRSLTE_API srslte_cp_t srslte_sync_detect_cp(srslte_sync_t *q, cf_t *input, diff --git a/lib/include/srslte/phy/ue/ue_sync.h b/lib/include/srslte/phy/ue/ue_sync.h index 0d12f846c..e5877dd23 100644 --- a/lib/include/srslte/phy/ue/ue_sync.h +++ b/lib/include/srslte/phy/ue/ue_sync.h @@ -88,12 +88,7 @@ typedef struct SRSLTE_API { bool file_mode; float file_cfo; srslte_cfo_t file_cfo_correct; - - bool mean_cfo_isunset; - float cfo; - float mean_cfo; - float cfo_ema_alpha; - + srslte_ue_sync_state_t state; uint32_t frame_len; diff --git a/lib/src/phy/sync/sync.c b/lib/src/phy/sync/sync.c index 78e9ca383..d1a477046 100644 --- a/lib/src/phy/sync/sync.c +++ b/lib/src/phy/sync/sync.c @@ -581,29 +581,25 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t /* If peak is over threshold, compute CFO and SSS */ if (q->peak_value >= q->threshold) { - ret = SRSLTE_SYNC_FOUND; - if (q->detect_cp) { if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) { srslte_sync_set_cp(q, srslte_sync_detect_cp(q, input_cfo, peak_pos + find_offset)); } else { DEBUG("Not enough room to detect CP length. Peak position: %d\n", peak_pos); - ret = SRSLTE_SYNC_FOUND_NOSPACE; } } - - if (q->enable_cfo_corr) { - if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) { - float cfo2 = srslte_pss_synch_cfo_compute(&q->pss, &input[find_offset + peak_pos - q->fft_size]); - if (q->mean_cfo2_isunset) { - q->mean_cfo2 = cfo2; - q->mean_cfo2_isunset = true; - } else { - q->mean_cfo2 = SRSLTE_VEC_EMA(cfo2, q->mean_cfo2, q->cfo_ema_alpha); - } + if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) { + float cfo2 = srslte_pss_synch_cfo_compute(&q->pss, &input[find_offset + peak_pos - q->fft_size]); + if (q->mean_cfo2_isunset) { + q->mean_cfo2 = cfo2; + q->mean_cfo2_isunset = true; } else { - ret = SRSLTE_SYNC_FOUND_NOSPACE; + q->mean_cfo2 = SRSLTE_VEC_EMA(cfo2, q->mean_cfo2, q->cfo_ema_alpha); } + + ret = SRSLTE_SYNC_FOUND; + } else { + ret = SRSLTE_SYNC_FOUND_NOSPACE; } } else { ret = SRSLTE_SYNC_NOFOUND; diff --git a/lib/src/phy/ue/ue_sync.c b/lib/src/phy/ue/ue_sync.c index d11811cf3..960d1de66 100644 --- a/lib/src/phy/ue/ue_sync.c +++ b/lib/src/phy/ue/ue_sync.c @@ -47,10 +47,6 @@ #define DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD 0 #define DEFAULT_SFO_EMA_COEFF 0.1 - -//#define DO_CFO_IN_SYNC - - cf_t dummy_buffer0[15*2048/2]; cf_t dummy_buffer1[15*2048/2]; @@ -188,9 +184,6 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q, q->sample_offset_correct_period = DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD; q->sfo_ema = DEFAULT_SFO_EMA_COEFF; - q->mean_cfo_isunset = true; - q->mean_cfo = 0; - q->cfo_ema_alpha = 0.4; q->max_prb = max_prb; if (search_cell) { @@ -227,11 +220,6 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q, } } -#ifndef DO_CFO_IN_SYNC - // Disable CFO correction in sync object and do it here every subframe - srslte_sync_set_cfo_enable(&q->strack, false); -#endif - ret = SRSLTE_SUCCESS; } @@ -376,7 +364,6 @@ uint32_t srslte_ue_sync_peak_idx(srslte_ue_sync_t *q) { 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); - q->cfo_ema_alpha = ema; } srslte_ue_sync_state_t srslte_ue_sync_get_state(srslte_ue_sync_t *q) { @@ -392,11 +379,7 @@ void srslte_ue_sync_cfo_i_detec_en(srslte_ue_sync_t *q, bool enable) { } float srslte_ue_sync_get_cfo(srslte_ue_sync_t *q) { -#ifdef DO_CFO_IN_SYNC return 15000 * srslte_sync_get_cfo(&q->strack); -#else - return 15000 * q->mean_cfo; -#endif } void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q, float cfo) { @@ -681,23 +664,6 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE q->sf_idx = (q->sf_idx + q->nof_recv_sf) % 10; -#ifndef DO_CFO_IN_SYNC - /* We found that CP-based correction performs better in low SNR than PSS-based. - * - * Estimate, average and correct here instead of inside sync object - */ - q->cfo = srslte_sync_cfo_estimate(&q->strack, input_buffer[0], 0); - if (q->mean_cfo_isunset) { - q->mean_cfo = q->cfo; - q->mean_cfo_isunset = false; - } else { - /* compute exponential moving average CFO */ - q->mean_cfo = SRSLTE_VEC_EMA(q->cfo, q->mean_cfo, q->cfo_ema_alpha); - } - srslte_cfo_correct(&q->strack.cfocorr2, input_buffer[0], input_buffer[0], -q->mean_cfo / q->fft_size); - -#endif - /* Every SF idx 0 and 5, find peak around known position q->peak_idx */ if (q->sf_idx == 0 || q->sf_idx == 5) { diff --git a/srsue/src/main.cc b/srsue/src/main.cc index b9717d93e..1c9b6edc6 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -203,7 +203,7 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { "Tolerance (in Hz) for digial CFO compensation.") ("expert.cfo_ema", - bpo::value(&args->expert.phy.cfo_ema)->default_value(0.3), + 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.") diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 54dbb057e..7b4ec48bd 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -128,7 +128,6 @@ bool phch_worker::init(uint32_t max_prb, srslte::log *log_h) srslte_ue_ul_set_normalization(&ue_ul, true); srslte_ue_ul_set_cfo_enable(&ue_ul, true); - srslte_ue_ul_set_cfo_tol(&ue_ul, phy->args->cfo_correct_tol_hz); mem_initiated = true; diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index 3373c562f..867221e87 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -172,7 +172,7 @@ enable = false #attach_enable_64qam = false #nof_phy_threads = 2 #equalizer_mode = mmse -#cfo_ema = 0.3 +#cfo_ema = 0.4 #cfo_integer_enabled = false #cfo_correct_tol_hz = 50 #time_correct_period = 5 From d34ce7441904e58987a1b68aa2b944eab2b0bbf4 Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Tue, 28 Nov 2017 13:01:38 +0000 Subject: [PATCH 168/242] NAS security context file tidy-up, usim_test minor edit --- srsue/hdr/upper/nas.h | 47 +++- srsue/src/upper/nas.cc | 433 ++++++++++++---------------------- srsue/test/upper/usim_test.cc | 6 +- 3 files changed, 189 insertions(+), 297 deletions(-) diff --git a/srsue/hdr/upper/nas.h b/srsue/hdr/upper/nas.h index d79eddea8..2e795098e 100644 --- a/srsue/hdr/upper/nas.h +++ b/srsue/hdr/upper/nas.h @@ -116,20 +116,18 @@ private: LIBLTE_MME_EMM_INFORMATION_MSG_STRUCT emm_info; - // Identifiers - LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti; - bool have_guti; - // Security context struct nas_sec_ctxt{ uint8_t ksi; uint8_t k_asme[32]; uint32_t tx_count; uint32_t rx_count; - srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo; - srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo; + srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo; + srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo; + LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti; }; + bool have_guti; bool have_ctxt; nas_sec_ctxt ctxt; @@ -174,13 +172,42 @@ private: void gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg); void send_security_mode_reject(uint8_t cause); - // guti persistence file - bool read_guti_file(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT *guti); - bool write_guti_file(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti); - // security context persistence file bool read_ctxt_file(nas_sec_ctxt *ctxt); bool write_ctxt_file(nas_sec_ctxt ctxt); + + // ctxt file helpers + std::string hex_to_string(uint8_t *hex, int size); + bool string_to_hex(std::string hex_str, uint8_t *hex, uint32_t len); + std::string emm_info_str(LIBLTE_MME_EMM_INFORMATION_MSG_STRUCT *info); + + template + bool readvar(std::istream &file, const char *key, T *var) + { + std::string line; + size_t len = strlen(key); + std::getline(file, line); + if(line.substr(0,len).compare(key)) { + return false; + } + *var = (T)atoi(line.substr(len).c_str()); + return true; + } + + bool readvar(std::istream &file, const char *key, uint8_t *var, int varlen) + { + std::string line; + size_t len = strlen(key); + std::getline(file, line); + if(line.substr(0,len).compare(key)) { + return false; + } + std::string tmp = line.substr(len); + if(!string_to_hex(tmp, var, varlen)) { + return false; + } + return true; + } }; } // namespace srsue diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index 2b01efcec..9c24cbf2e 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -38,71 +38,10 @@ using namespace srslte; namespace srsue { + /********************************************************************* - * Conversion helpers + * NAS ********************************************************************/ -std::string hex_to_string(uint8_t *hex, int size) -{ - std::stringstream ss; - - ss << std::hex << std::setfill('0'); - for(int i=0; i(hex[i]); - } - return ss.str(); -} - -bool string_to_hex(std::string hex_str, uint8_t *hex, uint32_t len) -{ - static const char* const lut = "0123456789abcdef"; - uint32_t str_len = hex_str.length(); - if(str_len & 1) { - return false; // uneven hex_str length - } - if(str_len > len*2) { - return false; // not enough space in hex buffer - } - - for(uint32_t i=0; ifull_net_name_present) { - ss << info->full_net_name.name; - } - if(info->short_net_name_present) { - ss << " (" << info->short_net_name.name << ")"; - } - if(info->utc_and_local_time_zone_present) { - ss << " " << (int)info->utc_and_local_time_zone.day; - ss << "/" << (int)info->utc_and_local_time_zone.month; - ss << "/" << (int)info->utc_and_local_time_zone.year; - ss << " " << (int)info->utc_and_local_time_zone.hour; - ss << ":" << (int)info->utc_and_local_time_zone.minute; - ss << ":" << (int)info->utc_and_local_time_zone.second; - ss << " TZ:" << (int)info->utc_and_local_time_zone.tz; - } - return ss.str(); -} - nas::nas() : state(EMM_STATE_DEREGISTERED), plmn_selection(PLMN_SELECTED), have_guti(false), ip_addr(0), eps_bearer_id(0) @@ -132,13 +71,13 @@ void nas::init(usim_interface_nas *usim_, } cfg = cfg_; - if((have_guti = read_guti_file(&guti))) { - if((have_ctxt = read_ctxt_file(&ctxt))) { - usim->generate_nas_keys(ctxt.k_asme, k_nas_enc, k_nas_int, - ctxt.cipher_algo, ctxt.integ_algo); - nas_log->debug_hex(k_nas_enc, 32, "NAS encryption key - k_nas_enc"); - nas_log->debug_hex(k_nas_int, 32, "NAS integrity key - k_nas_int"); - } + if((read_ctxt_file(&ctxt))) { + usim->generate_nas_keys(ctxt.k_asme, k_nas_enc, k_nas_int, + ctxt.cipher_algo, ctxt.integ_algo); + nas_log->debug_hex(k_nas_enc, 32, "NAS encryption key - k_nas_enc"); + nas_log->debug_hex(k_nas_int, 32, "NAS integrity key - k_nas_int"); + have_guti = true; + have_ctxt = true; } } @@ -151,8 +90,8 @@ emm_state_t nas::get_state() { } /******************************************************************************* -UE interface -*******************************************************************************/ + * UE interface + ******************************************************************************/ void nas::attach_request() { nas_log->info("Attach Request\n"); @@ -181,8 +120,8 @@ void nas::deattach_request() { } /******************************************************************************* -RRC interface -*******************************************************************************/ + * RRC interface + ******************************************************************************/ void nas::plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) { @@ -297,8 +236,8 @@ uint32_t nas::get_ul_count() { bool nas::get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) { if (have_guti) { - s_tmsi->mmec = guti.mme_code; - s_tmsi->m_tmsi = guti.m_tmsi; + s_tmsi->mmec = ctxt.guti.mme_code; + s_tmsi->m_tmsi = ctxt.guti.m_tmsi; return true; } else { return false; @@ -320,8 +259,8 @@ bool nas::get_k_asme(uint8_t *k_asme_, uint32_t n) { } /******************************************************************************* -Security -*******************************************************************************/ + * Security + ******************************************************************************/ void nas::integrity_generate(uint8_t integ_algo, uint8_t *key_128, @@ -381,8 +320,8 @@ bool nas::check_cap_replay(LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT *caps) /******************************************************************************* -Parsers -*******************************************************************************/ + * Parsers + ******************************************************************************/ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT attach_accept; @@ -398,21 +337,19 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { //FIXME: Handle t3412.unit //FIXME: Handle tai_list if (attach_accept.guti_present) { - memcpy(&guti, &attach_accept.guti.guti, sizeof(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT)); + memcpy(&ctxt.guti, &attach_accept.guti.guti, sizeof(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT)); have_guti = true; - write_guti_file(guti); - } - if (attach_accept.lai_present) { } + if (attach_accept.lai_present) {} if (attach_accept.ms_id_present) {} if (attach_accept.emm_cause_present) {} if (attach_accept.t3402_present) {} + if (attach_accept.t3412_ext_present) {} if (attach_accept.t3423_present) {} if (attach_accept.equivalent_plmns_present) {} if (attach_accept.emerg_num_list_present) {} if (attach_accept.eps_network_feature_support_present) {} if (attach_accept.additional_update_result_present) {} - if (attach_accept.t3412_ext_present) {} liblte_mme_unpack_activate_default_eps_bearer_context_request_msg(&attach_accept.esm_msg, &act_def_eps_bearer_context_req); @@ -735,8 +672,8 @@ void nas::parse_emm_information(uint32_t lcid, byte_buffer_t *pdu) { } /******************************************************************************* -Senders -*******************************************************************************/ + * Senders + ******************************************************************************/ void nas::send_attach_request() { LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT attach_req; @@ -774,14 +711,14 @@ void nas::send_attach_request() { // GUTI or IMSI attach if(have_guti && have_ctxt) { attach_req.eps_mobile_id.type_of_id = LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI; - memcpy(&attach_req.eps_mobile_id.guti, &guti, sizeof(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT)); + memcpy(&attach_req.eps_mobile_id.guti, &ctxt.guti, sizeof(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT)); attach_req.old_guti_type = LIBLTE_MME_GUTI_TYPE_NATIVE; attach_req.old_guti_type_present = true; attach_req.nas_ksi.tsc_flag = LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; attach_req.nas_ksi.nas_ksi = ctxt.ksi; nas_log->info("Requesting GUTI attach. " "m_tmsi: %x, mcc: %x, mnc: %x, mme_group_id: %x, mme_code: %x\n", - guti.m_tmsi, guti.mcc, guti.mnc, guti.mme_group_id, guti.mme_code); + ctxt.guti.m_tmsi, ctxt.guti.mcc, ctxt.guti.mnc, ctxt.guti.mme_group_id, ctxt.guti.mme_code); liblte_mme_pack_attach_request_msg(&attach_req, LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY, ctxt.tx_count, @@ -874,103 +811,94 @@ void nas::send_service_request() { void nas::send_esm_information_response() {} -bool nas::read_guti_file(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT *guti) + +/******************************************************************************* + * Security context persistence file + ******************************************************************************/ + +bool nas::read_ctxt_file(nas_sec_ctxt *ctxt) { std::ifstream file; - std::string line; - if (!guti) { + if(!ctxt) { return false; } - const char *m_tmsi_str = "m_tmsi="; - size_t m_tmsi_str_len = strlen(m_tmsi_str); - const char *mcc_str = "mcc="; - size_t mcc_str_len = strlen(mcc_str); - const char *mnc_str = "mnc="; - size_t mnc_str_len = strlen(mnc_str); - const char *mme_group_id_str = "mme_group_id="; - size_t mme_group_id_str_len = strlen(mme_group_id_str); - const char *mme_code_str = "mme_code="; - size_t mme_code_str_len = strlen(mme_code_str); - - file.open(".guti", std::ios::in); - if (file.is_open()) { - bool read_ok = true; - if (std::getline(file, line)) { - if (!line.substr(0,m_tmsi_str_len).compare(m_tmsi_str)) { - guti->m_tmsi = atoi(line.substr(m_tmsi_str_len).c_str()); - } else { - read_ok = false; - } - } else { - read_ok = false; - } - if (std::getline(file, line)) { - if (!line.substr(0,mcc_str_len).compare(mcc_str)) { - guti->mcc = atoi(line.substr(mcc_str_len).c_str()); - } else { - read_ok = false; - } - } else { - read_ok = false; - } - if (std::getline(file, line)) { - if (!line.substr(0,mnc_str_len).compare(mnc_str)) { - guti->mnc = atoi(line.substr(mnc_str_len).c_str()); - } else { - read_ok = false; - } - } else { - read_ok = false; - } - if (std::getline(file, line)) { - if (!line.substr(0,mme_group_id_str_len).compare(mme_group_id_str)) { - guti->mme_group_id = atoi(line.substr(mme_group_id_str_len).c_str()); - } else { - read_ok = false; - } - } else { - read_ok = false; - } - if (std::getline(file, line)) { - if (!line.substr(0,mme_code_str_len).compare(mme_code_str)) { - guti->mme_code = atoi(line.substr(mme_code_str_len).c_str()); - } else { - read_ok = false; - } - } else { - read_ok = false; - } + file.open(".ctxt", std::ios::in); + if(file.is_open()) { + if(!readvar(file, "m_tmsi=", &ctxt->guti.m_tmsi)) {return false;} + if(!readvar(file, "mcc=", &ctxt->guti.mcc)) {return false;} + if(!readvar(file, "mnc=", &ctxt->guti.mnc)) {return false;} + if(!readvar(file, "mme_group_id=", &ctxt->guti.mme_group_id)) {return false;} + if(!readvar(file, "mme_code=", &ctxt->guti.mme_code)) {return false;} + if(!readvar(file, "tx_count=", &ctxt->tx_count)) {return false;} + if(!readvar(file, "rx_count=", &ctxt->rx_count)) {return false;} + if(!readvar(file, "int_alg=", &ctxt->integ_algo)) {return false;} + if(!readvar(file, "enc_alg=", &ctxt->cipher_algo)) {return false;} + if(!readvar(file, "ksi=", &ctxt->ksi)) {return false;} + + if(!readvar(file, "k_asme=", ctxt->k_asme, 32)) {return false;} + file.close(); - if (read_ok) { - nas_log->info("Read GUTI from file .guti. " - "m_tmsi: %x, mcc: %x, mnc: %x, mme_group_id: %x, mme_code: %x\n", - guti->m_tmsi, guti->mcc, guti->mnc, guti->mme_group_id, guti->mme_code); - return true; - } else { - nas_log->error("Invalid GUTI file format\n"); - return false; - } + have_guti = true; + nas_log->info("Read GUTI from file " + "m_tmsi: %x, mcc: %x, mnc: %x, mme_group_id: %x, mme_code: %x\n", + ctxt->guti.m_tmsi, + ctxt->guti.mcc, + ctxt->guti.mnc, + ctxt->guti.mme_group_id, + ctxt->guti.mme_code); + have_ctxt = true; + nas_log->info("Read security ctxt from file .ctxt. " + "ksi: %x, k_asme: %s, tx_count: %x, rx_count: %x, int_alg: %d, enc_alg: %d\n", + ctxt->ksi, + hex_to_string(ctxt->k_asme,32).c_str(), + ctxt->tx_count, + ctxt->rx_count, + ctxt->integ_algo, + ctxt->cipher_algo); + return true; + } else { return false; } } -bool nas::write_guti_file(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti) { - std::ofstream file; - if (!have_guti) { +bool nas::write_ctxt_file(nas_sec_ctxt ctxt) +{ + if (!have_guti || !have_ctxt) { return false; } - file.open(".guti", std::ios::out | std::ios::trunc); + std::ofstream file; + file.open(".ctxt", std::ios::out | std::ios::trunc); if (file.is_open()) { - file << "m_tmsi=" << (int) guti.m_tmsi << std::endl; - file << "mcc=" << (int) guti.mcc << std::endl; - file << "mnc=" << (int) guti.mnc << std::endl; - file << "mme_group_id=" << (int) guti.mme_group_id << std::endl; - file << "mme_code=" << (int) guti.mme_code << std::endl; - nas_log->info("Saved GUTI to file .guti. " + file << "m_tmsi=" << (int) ctxt.guti.m_tmsi << std::endl; + file << "mcc=" << (int) ctxt.guti.mcc << std::endl; + file << "mnc=" << (int) ctxt.guti.mnc << std::endl; + file << "mme_group_id=" << (int) ctxt.guti.mme_group_id << std::endl; + file << "mme_code=" << (int) ctxt.guti.mme_code << std::endl; + file << "tx_count=" << (int) ctxt.tx_count << std::endl; + file << "rx_count=" << (int) ctxt.rx_count << std::endl; + file << "int_alg=" << (int) ctxt.integ_algo << std::endl; + file << "enc_alg=" << (int) ctxt.cipher_algo << std::endl; + file << "ksi=" << (int) ctxt.ksi << std::endl; + + file << "k_asme=" << hex_to_string(ctxt.k_asme, 32) << std::endl; + + nas_log->info("Saved GUTI to file " "m_tmsi: %x, mcc: %x, mnc: %x, mme_group_id: %x, mme_code: %x\n", - guti.m_tmsi, guti.mcc, guti.mnc, guti.mme_group_id, guti.mme_code); + ctxt.guti.m_tmsi, + ctxt.guti.mcc, + ctxt.guti.mnc, + ctxt.guti.mme_group_id, + ctxt.guti.mme_code); + nas_log->info("Saved security ctxt to file .ctxt. " + "ksi: %x, k_asme: %s, tx_count: %x, rx_count: %x, int_alg: %d, enc_alg: %d\n", + ctxt.ksi, + hex_to_string(ctxt.k_asme,32).c_str(), + ctxt.tx_count, + ctxt.rx_count, + ctxt.integ_algo, + ctxt.cipher_algo); file.close(); return true; } else { @@ -978,129 +906,66 @@ bool nas::write_guti_file(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti) { } } -bool nas::read_ctxt_file(nas_sec_ctxt *ctxt) +/********************************************************************* + * Conversion helpers + ********************************************************************/ +std::string nas::hex_to_string(uint8_t *hex, int size) { - std::ifstream file; - std::string line; - if (!ctxt) { - return false; - } + std::stringstream ss; - const char *ksi_str = "ksi="; - size_t ksi_str_len = strlen(ksi_str); - const char *k_asme_str = "k_asme="; - size_t k_asme_str_len = strlen(k_asme_str); - const char *tx_count_str = "tx_count="; - size_t tx_count_str_len = strlen(tx_count_str); - const char *rx_count_str = "rx_count="; - size_t rx_count_str_len = strlen(rx_count_str); - const char *int_alg_str = "int_alg="; - size_t int_alg_str_len = strlen(int_alg_str); - const char *enc_alg_str = "enc_alg="; - size_t enc_alg_str_len = strlen(enc_alg_str); + ss << std::hex << std::setfill('0'); + for(int i=0; i(hex[i]); + } + return ss.str(); +} - file.open(".ctxt", std::ios::in); - if (file.is_open()) { - bool read_ok = true; - if (std::getline(file, line)) { - if (!line.substr(0,ksi_str_len).compare(ksi_str)) { - ctxt->ksi = atoi(line.substr(ksi_str_len).c_str()); - } else { - read_ok = false; - } - } else { - read_ok = false; - } - if (std::getline(file, line)) { - if (!line.substr(0,k_asme_str_len).compare(k_asme_str)) { - std::string tmp = line.substr(k_asme_str_len); - if(!string_to_hex(tmp, ctxt->k_asme, 32)) { - read_ok = false; - } - } else { - read_ok = false; - } - } else { - read_ok = false; - } - if (std::getline(file, line)) { - if (!line.substr(0,tx_count_str_len).compare(tx_count_str)) { - ctxt->tx_count = atoi(line.substr(tx_count_str_len).c_str()); - } else { - read_ok = false; - } - } else { - read_ok = false; - } - if (std::getline(file, line)) { - if (!line.substr(0,rx_count_str_len).compare(rx_count_str)) { - ctxt->rx_count = atoi(line.substr(rx_count_str_len).c_str()); - } else { - read_ok = false; - } - } else { - read_ok = false; - } - if (std::getline(file, line)) { - if (!line.substr(0,int_alg_str_len).compare(int_alg_str)) { - ctxt->integ_algo = (srslte::INTEGRITY_ALGORITHM_ID_ENUM)atoi(line.substr(int_alg_str_len).c_str()); - } else { - read_ok = false; - } - } else { - read_ok = false; - } - if (std::getline(file, line)) { - if (!line.substr(0,enc_alg_str_len).compare(enc_alg_str)) { - ctxt->cipher_algo = (srslte::CIPHERING_ALGORITHM_ID_ENUM)atoi(line.substr(enc_alg_str_len).c_str()); - } else { - read_ok = false; - } - } else { - read_ok = false; +bool nas::string_to_hex(std::string hex_str, uint8_t *hex, uint32_t len) +{ + static const char* const lut = "0123456789abcdef"; + uint32_t str_len = hex_str.length(); + if(str_len & 1) { + return false; // uneven hex_str length + } + if(str_len > len*2) { + return false; // not enough space in hex buffer + } + for(uint32_t i=0; iinfo("Read security ctxt from file .ctxt. " - "ksi: %x, k_asme: %s, " - "tx_count: %x, rx_count: %x, " - "int_alg: %d, enc_alg: %d\n", - ctxt->ksi, hex_to_string(ctxt->k_asme,32).c_str(), - ctxt->tx_count, ctxt->rx_count, - ctxt->integ_algo, ctxt->cipher_algo); - return true; - } else { - nas_log->error("Invalid security ctxt file format\n"); - return false; + char b = hex_str[i+1]; + const char* q = std::lower_bound(lut, lut + 16, b); + if (*q != b) { + return false; // invalid char } - } else { - return false; + hex[i/2] = ((p - lut) << 4) | (q - lut); } + return true; } -bool nas::write_ctxt_file(nas_sec_ctxt ctxt) +std::string nas::emm_info_str(LIBLTE_MME_EMM_INFORMATION_MSG_STRUCT *info) { - std::ofstream file; - file.open(".ctxt", std::ios::out | std::ios::trunc); - if (file.is_open()) { - file << "ksi=" << (int) ctxt.ksi << std::endl; - file << "k_asme=" << hex_to_string(ctxt.k_asme, 32) << std::endl; - file << "tx_count=" << (int) ctxt.tx_count << std::endl; - file << "rx_count=" << (int) ctxt.rx_count << std::endl; - file << "int_alg=" << (int) ctxt.integ_algo << std::endl; - file << "enc_alg=" << (int) ctxt.cipher_algo << std::endl; - nas_log->info("Saved security ctxt to file .ctxt. " - "ksi: %x, k_asme: %s, " - "tx_count: %x, rx_count: %x, " - "int_alg: %d, enc_alg: %d\n", - ctxt.ksi, hex_to_string(ctxt.k_asme,32).c_str(), - ctxt.tx_count, ctxt.rx_count, - ctxt.integ_algo, ctxt.cipher_algo); - file.close(); - return true; - } else { - return false; + std::stringstream ss; + if(info->full_net_name_present) { + ss << info->full_net_name.name; + } + if(info->short_net_name_present) { + ss << " (" << info->short_net_name.name << ")"; } + if(info->utc_and_local_time_zone_present) { + ss << " " << (int)info->utc_and_local_time_zone.day; + ss << "/" << (int)info->utc_and_local_time_zone.month; + ss << "/" << (int)info->utc_and_local_time_zone.year; + ss << " " << (int)info->utc_and_local_time_zone.hour; + ss << ":" << (int)info->utc_and_local_time_zone.minute; + ss << ":" << (int)info->utc_and_local_time_zone.second; + ss << " TZ:" << (int)info->utc_and_local_time_zone.tz; + } + return ss.str(); } diff --git a/srsue/test/upper/usim_test.cc b/srsue/test/upper/usim_test.cc index 00003bc28..4ac468673 100644 --- a/srsue/test/upper/usim_test.cc +++ b/srsue/test/upper/usim_test.cc @@ -61,7 +61,6 @@ KASME : a8.27.57.5e.ea.1a.10.17.3a.a1.bf.ce.4b.0c.21.85.e0.51.ef.bd.91.7f.fe.f uint8_t rand_enb[] = {0x88, 0x38, 0xc3, 0x55, 0xc8, 0x78, 0xaa, 0x57, 0x21, 0x49, 0xfe, 0x69, 0xdb, 0x68, 0x6b, 0x5a}; uint8_t autn_enb[] = {0xd7, 0x44, 0x51, 0x9b, 0x25, 0xaa, 0x80, 0x00, 0x84, 0xba, 0x37, 0xb0, 0xf6, 0x73, 0x4d, 0xd1}; -uint8_t kasme[] = {0xa8, 0x27, 0x57, 0x5e, 0xea, 0x1a, 0x10, 0x17, 0x3a, 0xa1, 0xbf, 0xce, 0x4b, 0x0c, 0x21, 0x85, 0xe0, 0x51, 0xef, 0xbd, 0x91, 0x7f, 0xfe, 0xf5, 0x1f, 0x74, 0x29, 0x61, 0xf9, 0x03, 0x7a, 0x35}; uint16 mcc = 208; uint16 mnc = 93; @@ -71,18 +70,19 @@ int main(int argc, char **argv) srslte::log_filter usim_log("USIM"); bool net_valid; uint8_t res[16]; + uint8_t k_asme[32]; usim_args_t args; args.algo = "milenage"; args.amf = "8000"; - args.imei = "356092040793011"; + args.imei = "35609204079301"; args.imsi = "208930000000001"; args.k = "8BAF473F2F8FD09487CCCBD7097C6862"; args.op = "11111111111111111111111111111111"; srsue::usim usim; usim.init(&args, &usim_log); - usim.generate_authentication_response(rand_enb, autn_enb, mcc, mnc, &net_valid, res, kasme); + usim.generate_authentication_response(rand_enb, autn_enb, mcc, mnc, &net_valid, res, k_asme); assert(net_valid == true); } From 0d7af888222b2c6cd5fed406875ca082b7d457e5 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 28 Nov 2017 15:51:40 +0100 Subject: [PATCH 169/242] Add noise reduction in PSS before estimating CFO --- lib/include/srslte/phy/sync/pss.h | 16 ++-- lib/src/phy/sync/pss.c | 146 +++++++++++++++++------------- 2 files changed, 94 insertions(+), 68 deletions(-) diff --git a/lib/include/srslte/phy/sync/pss.h b/lib/include/srslte/phy/sync/pss.h index 9760a178c..d590cf2e6 100644 --- a/lib/include/srslte/phy/sync/pss.h +++ b/lib/include/srslte/phy/sync/pss.h @@ -70,9 +70,7 @@ /* Low-level API */ typedef struct SRSLTE_API { - - srslte_dft_plan_t dftp_input; - + #ifdef CONVOLUTION_FFT srslte_conv_fft_cc_t conv_fft; srslte_filt_cc_t filter; @@ -87,16 +85,22 @@ typedef struct SRSLTE_API { uint32_t N_id_2; uint32_t fft_size; cf_t *pss_signal_freq_full[3]; - + cf_t *pss_signal_time[3]; - + cf_t pss_signal_freq[3][SRSLTE_PSS_LEN]; // One sequence for each N_id_2 cf_t *tmp_input; cf_t *conv_output; float *conv_output_abs; - float ema_alpha; + float ema_alpha; float *conv_output_avg; float peak_value; + + srslte_dft_plan_t dftp_input; + srslte_dft_plan_t idftp_input; + cf_t tmp_fft[SRSLTE_SYMBOL_SZ_MAX]; + cf_t yr[SRSLTE_PSS_LEN]; + }srslte_pss_synch_t; typedef enum { PSS_TX, PSS_RX } pss_direction_t; diff --git a/lib/src/phy/sync/pss.c b/lib/src/phy/sync/pss.c index f7b35071d..9333567ff 100644 --- a/lib/src/phy/sync/pss.c +++ b/lib/src/phy/sync/pss.c @@ -137,9 +137,15 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, } srslte_dft_plan_set_mirror(&q->dftp_input, true); srslte_dft_plan_set_dc(&q->dftp_input, true); - srslte_dft_plan_set_norm(&q->dftp_input, true); - q->tmp_input = srslte_vec_malloc((buffer_size + frame_size*(q->decimate - 1)) * sizeof(cf_t)); + if (srslte_dft_plan(&q->idftp_input, fft_size, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)) { + fprintf(stderr, "Error creating DFT plan \n"); + goto clean_and_exit; + } + srslte_dft_plan_set_mirror(&q->idftp_input, true); + srslte_dft_plan_set_dc(&q->idftp_input, true); + + q->tmp_input = srslte_vec_malloc((buffer_size + frame_size*(q->decimate - 1)) * sizeof(cf_t)); if (!q->tmp_input) { fprintf(stderr, "Error allocating memory\n"); goto clean_and_exit; @@ -167,7 +173,7 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, } bzero(q->conv_output_abs, sizeof(float) * buffer_size); #endif - + for (N_id_2=0;N_id_2<3;N_id_2++) { q->pss_signal_time[N_id_2] = srslte_vec_malloc(buffer_size * sizeof(cf_t)); if (!q->pss_signal_time[N_id_2]) { @@ -178,14 +184,14 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, if (srslte_pss_synch_init_N_id_2(q->pss_signal_freq[N_id_2], q->pss_signal_time[N_id_2], N_id_2, fft_size, offset)) { fprintf(stderr, "Error initiating PSS detector for N_id_2=%d fft_size=%d\n", N_id_2, fft_size); goto clean_and_exit; - } + } bzero(&q->pss_signal_time[N_id_2][q->fft_size], q->frame_size * sizeof(cf_t)); - } + } #ifdef CONVOLUTION_FFT for(N_id_2=0; N_id_2<3; N_id_2++) - q->pss_signal_freq_full[N_id_2] = srslte_vec_malloc(buffer_size * sizeof(cf_t)); + q->pss_signal_freq_full[N_id_2] = srslte_vec_malloc(buffer_size * sizeof(cf_t)); if (srslte_conv_fft_cc_init(&q->conv_fft, frame_size, fft_size)) { fprintf(stderr, "Error initiating convolution FFT\n"); @@ -194,15 +200,15 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, for(int i=0; i<3; i++) { srslte_dft_run_c(&q->conv_fft.filter_plan, q->pss_signal_time[i], q->pss_signal_freq_full[i]); } - + #endif - + srslte_pss_synch_reset(q); - + ret = SRSLTE_SUCCESS; } -clean_and_exit: +clean_and_exit: if (ret == SRSLTE_ERROR) { srslte_pss_synch_free(q); } @@ -298,7 +304,7 @@ void srslte_pss_synch_free(srslte_pss_synch_t *q) { } #ifdef CONVOLUTION_FFT srslte_conv_fft_cc_free(&q->conv_fft); - + #endif if (q->tmp_input) { free(q->tmp_input); @@ -312,9 +318,10 @@ void srslte_pss_synch_free(srslte_pss_synch_t *q) { if (q->conv_output_avg) { free(q->conv_output_avg); } - + srslte_dft_plan_free(&q->dftp_input); - + srslte_dft_plan_free(&q->idftp_input); + if(q->decimate > 1) { srslte_filt_decim_cc_free(&q->filter); @@ -323,7 +330,7 @@ void srslte_pss_synch_free(srslte_pss_synch_t *q) { } - bzero(q, sizeof(srslte_pss_synch_t)); + bzero(q, sizeof(srslte_pss_synch_t)); } } @@ -379,7 +386,7 @@ void srslte_pss_put_slot(cf_t *pss_signal, cf_t *slot, uint32_t nof_prb, srslte_ void srslte_pss_get_slot(cf_t *slot, cf_t *pss_signal, uint32_t nof_prb, srslte_cp_t cp) { int k; k = (SRSLTE_CP_NSYMB(cp) - 1) * nof_prb * SRSLTE_NRE + nof_prb * SRSLTE_NRE / 2 - 31; - memcpy(pss_signal, &slot[k], SRSLTE_PSS_LEN * sizeof(cf_t)); + memcpy(pss_signal, &slot[k], SRSLTE_PSS_LEN * sizeof(cf_t)); } @@ -398,34 +405,34 @@ int srslte_pss_synch_set_N_id_2(srslte_pss_synch_t *q, uint32_t N_id_2) { /* Sets the weight factor alpha for the exponential moving average of the PSS correlation output */ void srslte_pss_synch_set_ema_alpha(srslte_pss_synch_t *q, float alpha) { - q->ema_alpha = alpha; + q->ema_alpha = alpha; } -/** Performs time-domain PSS correlation. +/** Performs time-domain PSS correlation. * Returns the index of the PSS correlation peak in a subframe. * The frame starts at corr_peak_pos-subframe_size/2. * The value of the correlation is stored in corr_peak_value. * * Input buffer must be subframe_size long. */ -int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_peak_value) +int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_peak_value) { int ret = SRSLTE_ERROR_INVALID_INPUTS; - - if (q != NULL && + + if (q != NULL && input != NULL) { uint32_t corr_peak_pos; uint32_t conv_output_len; - + if (!srslte_N_id_2_isvalid(q->N_id_2)) { fprintf(stderr, "Error finding PSS peak, Must set N_id_2 first\n"); return SRSLTE_ERROR; } /* Correlate input with PSS sequence - * + * * We do not reverse time-domain PSS signal because it's conjugate is symmetric. * The conjugate operation on pss_signal_time has been done in srslte_pss_synch_init_N_id_2 * This is why we can use FFT-based convolution @@ -442,7 +449,7 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe { conv_output_len = srslte_conv_fft_cc_run_opt(&q->conv_fft, q->tmp_input, q->pss_signal_freq_full[q->N_id_2], q->conv_output); } - + #else conv_output_len = srslte_conv_cc(input, q->pss_signal_time[q->N_id_2], q->conv_output, q->frame_size, q->fft_size); #endif @@ -450,19 +457,19 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe for (int i=0;iframe_size;i++) { q->conv_output[i] = srslte_vec_dot_prod_ccc(q->pss_signal_time[q->N_id_2], &input[i], q->fft_size); } - conv_output_len = q->frame_size; + conv_output_len = q->frame_size; } - + #ifdef SRSLTE_PSS_ABS_SQUARE srslte_vec_abs_square_cf(q->conv_output, q->conv_output_abs, conv_output_len-1); #else srslte_vec_abs_cf(q->conv_output, q->conv_output_abs, conv_output_len-1); #endif - + if (q->ema_alpha < 1.0 && q->ema_alpha > 0.0) { - srslte_vec_sc_prod_fff(q->conv_output_abs, q->ema_alpha, q->conv_output_abs, conv_output_len-1); - srslte_vec_sc_prod_fff(q->conv_output_avg, 1-q->ema_alpha, q->conv_output_avg, conv_output_len-1); + srslte_vec_sc_prod_fff(q->conv_output_abs, q->ema_alpha, q->conv_output_abs, conv_output_len-1); + srslte_vec_sc_prod_fff(q->conv_output_avg, 1-q->ema_alpha, q->conv_output_avg, conv_output_len-1); srslte_vec_sum_fff(q->conv_output_abs, q->conv_output_avg, q->conv_output_avg, conv_output_len-1); } else { @@ -470,43 +477,43 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe } /* Find maximum of the absolute value of the correlation */ corr_peak_pos = srslte_vec_max_fi(q->conv_output_avg, conv_output_len-1); - - // save absolute value + + // save absolute value q->peak_value = q->conv_output_avg[corr_peak_pos]; - -#ifdef SRSLTE_PSS_RETURN_PSR + +#ifdef SRSLTE_PSS_RETURN_PSR // Find second side lobe - + // Find end of peak lobe to the right int pl_ub = corr_peak_pos+1; while(q->conv_output_avg[pl_ub+1] <= q->conv_output_avg[pl_ub] && pl_ub < conv_output_len) { - pl_ub ++; + pl_ub ++; } // Find end of peak lobe to the left - int pl_lb; + int pl_lb; if (corr_peak_pos > 2) { pl_lb = corr_peak_pos-1; while(q->conv_output_avg[pl_lb-1] <= q->conv_output_avg[pl_lb] && pl_lb > 1) { - pl_lb --; - } + pl_lb --; + } } else { - pl_lb = 0; + pl_lb = 0; } - int sl_distance_right = conv_output_len-1-pl_ub; + int sl_distance_right = conv_output_len-1-pl_ub; if (sl_distance_right < 0) { - sl_distance_right = 0; + sl_distance_right = 0; } - int sl_distance_left = pl_lb; - + int sl_distance_left = pl_lb; + int sl_right = pl_ub+srslte_vec_max_fi(&q->conv_output_avg[pl_ub], sl_distance_right); - int sl_left = srslte_vec_max_fi(q->conv_output_avg, sl_distance_left); - float side_lobe_value = SRSLTE_MAX(q->conv_output_avg[sl_right], q->conv_output_avg[sl_left]); + int sl_left = srslte_vec_max_fi(q->conv_output_avg, sl_distance_left); + float side_lobe_value = SRSLTE_MAX(q->conv_output_avg[sl_right], q->conv_output_avg[sl_left]); if (corr_peak_value) { *corr_peak_value = q->conv_output_avg[corr_peak_pos]/side_lobe_value; - + if (*corr_peak_value < 10) - DEBUG("peak_pos=%2d, pl_ub=%2d, pl_lb=%2d, sl_right: %2d, sl_left: %2d, PSR: %.2f/%.2f=%.2f\n", corr_peak_pos, pl_ub, pl_lb, + DEBUG("peak_pos=%2d, pl_ub=%2d, pl_lb=%2d, sl_right: %2d, sl_left: %2d, PSR: %.2f/%.2f=%.2f\n", corr_peak_pos, pl_ub, pl_lb, sl_right,sl_left, q->conv_output_avg[corr_peak_pos], side_lobe_value,*corr_peak_value); } #else @@ -514,7 +521,7 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe *corr_peak_value = q->conv_output_avg[corr_peak_pos]; } #endif - + if(q->decimate >1) { int decimation_correction = (q->filter.num_taps - 2); @@ -524,23 +531,23 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe if (q->frame_size >= q->fft_size) { - ret = (int) corr_peak_pos; + ret = (int) corr_peak_pos; } else { ret = (int) corr_peak_pos + q->fft_size; } - } + } return ret; } -/* Computes frequency-domain channel estimation of the PSS symbol - * input signal is in the time-domain. - * ce is the returned frequency-domain channel estimates. +/* Computes frequency-domain channel estimation of the PSS symbol + * input signal is in the time-domain. + * ce is the returned frequency-domain channel estimates. */ int srslte_pss_synch_chest(srslte_pss_synch_t *q, cf_t *input, cf_t ce[SRSLTE_PSS_LEN]) { int ret = SRSLTE_ERROR_INVALID_INPUTS; cf_t input_fft[SRSLTE_SYMBOL_SZ_MAX]; - if (q != NULL && + if (q != NULL && input != NULL) { @@ -548,31 +555,46 @@ int srslte_pss_synch_chest(srslte_pss_synch_t *q, cf_t *input, cf_t ce[SRSLTE_PS fprintf(stderr, "Error finding PSS peak, Must set N_id_2 first\n"); return SRSLTE_ERROR; } - + /* Transform to frequency-domain */ srslte_dft_run_c(&q->dftp_input, input, input_fft); - + /* Compute channel estimate taking the PSS sequence as reference */ srslte_vec_prod_conj_ccc(&input_fft[(q->fft_size-SRSLTE_PSS_LEN)/2], q->pss_signal_freq[q->N_id_2], ce, SRSLTE_PSS_LEN); - + ret = SRSLTE_SUCCESS; } - return ret; + return ret; } +#define CLEAN_NOISE_DFT +//#define PSS_CFO_FREQ /* Returns the CFO estimation given a PSS received sequence * * Source: An Efficient CFO Estimation Algorithm for the Downlink of 3GPP-LTE * Feng Wang and Yu Zhu */ float srslte_pss_synch_cfo_compute(srslte_pss_synch_t* q, cf_t *pss_recv) { - cf_t y0, y1, yr; + cf_t y0, y1; + +#ifdef PSS_CFO_FREQ + + srslte_vec_prod_conj_ccc(&q->tmp_fft[q->fft_size/2-SRSLTE_PSS_LEN/2], q->pss_signal_freq[q->N_id_2], q->yr, SRSLTE_PSS_LEN); + y0 = srslte_vec_acc_cc(q->yr, SRSLTE_PSS_LEN/2); + y1 = srslte_vec_acc_cc(&q->yr[SRSLTE_PSS_LEN/2], SRSLTE_PSS_LEN/2); + +#else +#ifdef CLEAN_NOISE_DFT + // Eliminate noise + srslte_dft_run_c(&q->dftp_input, pss_recv, q->tmp_fft); + bzero(q->tmp_fft, sizeof(cf_t)*(q->fft_size/2-SRSLTE_PSS_LEN/2)); + bzero(&q->tmp_fft[q->fft_size/2+SRSLTE_PSS_LEN/2], sizeof(cf_t)*(q->fft_size/2-SRSLTE_PSS_LEN/2)); + srslte_dft_run_c(&q->idftp_input, q->tmp_fft, pss_recv); +#endif y0 = srslte_vec_dot_prod_ccc(q->pss_signal_time[q->N_id_2], pss_recv, q->fft_size/2); y1 = srslte_vec_dot_prod_ccc(&q->pss_signal_time[q->N_id_2][q->fft_size/2], &pss_recv[q->fft_size/2], q->fft_size/2); - - yr = conjf(y0) * y1; - - return atan2f(__imag__ yr, __real__ yr) / M_PI; +#endif + return carg(conjf(y0) * y1)/M_PI; } From 15a13043951a34402c3cc70d56af1c01b3691a64 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 28 Nov 2017 16:20:40 +0100 Subject: [PATCH 170/242] Revert "Add noise reduction in PSS before estimating CFO" This reverts commit 0d7af888222b2c6cd5fed406875ca082b7d457e5. --- lib/include/srslte/phy/sync/pss.h | 16 ++-- lib/src/phy/sync/pss.c | 146 +++++++++++++----------------- 2 files changed, 68 insertions(+), 94 deletions(-) diff --git a/lib/include/srslte/phy/sync/pss.h b/lib/include/srslte/phy/sync/pss.h index d590cf2e6..9760a178c 100644 --- a/lib/include/srslte/phy/sync/pss.h +++ b/lib/include/srslte/phy/sync/pss.h @@ -70,7 +70,9 @@ /* Low-level API */ typedef struct SRSLTE_API { - + + srslte_dft_plan_t dftp_input; + #ifdef CONVOLUTION_FFT srslte_conv_fft_cc_t conv_fft; srslte_filt_cc_t filter; @@ -85,22 +87,16 @@ typedef struct SRSLTE_API { uint32_t N_id_2; uint32_t fft_size; cf_t *pss_signal_freq_full[3]; - + cf_t *pss_signal_time[3]; - + cf_t pss_signal_freq[3][SRSLTE_PSS_LEN]; // One sequence for each N_id_2 cf_t *tmp_input; cf_t *conv_output; float *conv_output_abs; - float ema_alpha; + float ema_alpha; float *conv_output_avg; float peak_value; - - srslte_dft_plan_t dftp_input; - srslte_dft_plan_t idftp_input; - cf_t tmp_fft[SRSLTE_SYMBOL_SZ_MAX]; - cf_t yr[SRSLTE_PSS_LEN]; - }srslte_pss_synch_t; typedef enum { PSS_TX, PSS_RX } pss_direction_t; diff --git a/lib/src/phy/sync/pss.c b/lib/src/phy/sync/pss.c index 9333567ff..f7b35071d 100644 --- a/lib/src/phy/sync/pss.c +++ b/lib/src/phy/sync/pss.c @@ -137,15 +137,9 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, } srslte_dft_plan_set_mirror(&q->dftp_input, true); srslte_dft_plan_set_dc(&q->dftp_input, true); + srslte_dft_plan_set_norm(&q->dftp_input, true); - if (srslte_dft_plan(&q->idftp_input, fft_size, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)) { - fprintf(stderr, "Error creating DFT plan \n"); - goto clean_and_exit; - } - srslte_dft_plan_set_mirror(&q->idftp_input, true); - srslte_dft_plan_set_dc(&q->idftp_input, true); - - q->tmp_input = srslte_vec_malloc((buffer_size + frame_size*(q->decimate - 1)) * sizeof(cf_t)); + q->tmp_input = srslte_vec_malloc((buffer_size + frame_size*(q->decimate - 1)) * sizeof(cf_t)); if (!q->tmp_input) { fprintf(stderr, "Error allocating memory\n"); goto clean_and_exit; @@ -173,7 +167,7 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, } bzero(q->conv_output_abs, sizeof(float) * buffer_size); #endif - + for (N_id_2=0;N_id_2<3;N_id_2++) { q->pss_signal_time[N_id_2] = srslte_vec_malloc(buffer_size * sizeof(cf_t)); if (!q->pss_signal_time[N_id_2]) { @@ -184,14 +178,14 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, if (srslte_pss_synch_init_N_id_2(q->pss_signal_freq[N_id_2], q->pss_signal_time[N_id_2], N_id_2, fft_size, offset)) { fprintf(stderr, "Error initiating PSS detector for N_id_2=%d fft_size=%d\n", N_id_2, fft_size); goto clean_and_exit; - } + } bzero(&q->pss_signal_time[N_id_2][q->fft_size], q->frame_size * sizeof(cf_t)); - } + } #ifdef CONVOLUTION_FFT for(N_id_2=0; N_id_2<3; N_id_2++) - q->pss_signal_freq_full[N_id_2] = srslte_vec_malloc(buffer_size * sizeof(cf_t)); + q->pss_signal_freq_full[N_id_2] = srslte_vec_malloc(buffer_size * sizeof(cf_t)); if (srslte_conv_fft_cc_init(&q->conv_fft, frame_size, fft_size)) { fprintf(stderr, "Error initiating convolution FFT\n"); @@ -200,15 +194,15 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, for(int i=0; i<3; i++) { srslte_dft_run_c(&q->conv_fft.filter_plan, q->pss_signal_time[i], q->pss_signal_freq_full[i]); } - + #endif - + srslte_pss_synch_reset(q); - + ret = SRSLTE_SUCCESS; } -clean_and_exit: +clean_and_exit: if (ret == SRSLTE_ERROR) { srslte_pss_synch_free(q); } @@ -304,7 +298,7 @@ void srslte_pss_synch_free(srslte_pss_synch_t *q) { } #ifdef CONVOLUTION_FFT srslte_conv_fft_cc_free(&q->conv_fft); - + #endif if (q->tmp_input) { free(q->tmp_input); @@ -318,10 +312,9 @@ void srslte_pss_synch_free(srslte_pss_synch_t *q) { if (q->conv_output_avg) { free(q->conv_output_avg); } - + srslte_dft_plan_free(&q->dftp_input); - srslte_dft_plan_free(&q->idftp_input); - + if(q->decimate > 1) { srslte_filt_decim_cc_free(&q->filter); @@ -330,7 +323,7 @@ void srslte_pss_synch_free(srslte_pss_synch_t *q) { } - bzero(q, sizeof(srslte_pss_synch_t)); + bzero(q, sizeof(srslte_pss_synch_t)); } } @@ -386,7 +379,7 @@ void srslte_pss_put_slot(cf_t *pss_signal, cf_t *slot, uint32_t nof_prb, srslte_ void srslte_pss_get_slot(cf_t *slot, cf_t *pss_signal, uint32_t nof_prb, srslte_cp_t cp) { int k; k = (SRSLTE_CP_NSYMB(cp) - 1) * nof_prb * SRSLTE_NRE + nof_prb * SRSLTE_NRE / 2 - 31; - memcpy(pss_signal, &slot[k], SRSLTE_PSS_LEN * sizeof(cf_t)); + memcpy(pss_signal, &slot[k], SRSLTE_PSS_LEN * sizeof(cf_t)); } @@ -405,34 +398,34 @@ int srslte_pss_synch_set_N_id_2(srslte_pss_synch_t *q, uint32_t N_id_2) { /* Sets the weight factor alpha for the exponential moving average of the PSS correlation output */ void srslte_pss_synch_set_ema_alpha(srslte_pss_synch_t *q, float alpha) { - q->ema_alpha = alpha; + q->ema_alpha = alpha; } -/** Performs time-domain PSS correlation. +/** Performs time-domain PSS correlation. * Returns the index of the PSS correlation peak in a subframe. * The frame starts at corr_peak_pos-subframe_size/2. * The value of the correlation is stored in corr_peak_value. * * Input buffer must be subframe_size long. */ -int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_peak_value) +int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_peak_value) { int ret = SRSLTE_ERROR_INVALID_INPUTS; - - if (q != NULL && + + if (q != NULL && input != NULL) { uint32_t corr_peak_pos; uint32_t conv_output_len; - + if (!srslte_N_id_2_isvalid(q->N_id_2)) { fprintf(stderr, "Error finding PSS peak, Must set N_id_2 first\n"); return SRSLTE_ERROR; } /* Correlate input with PSS sequence - * + * * We do not reverse time-domain PSS signal because it's conjugate is symmetric. * The conjugate operation on pss_signal_time has been done in srslte_pss_synch_init_N_id_2 * This is why we can use FFT-based convolution @@ -449,7 +442,7 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe { conv_output_len = srslte_conv_fft_cc_run_opt(&q->conv_fft, q->tmp_input, q->pss_signal_freq_full[q->N_id_2], q->conv_output); } - + #else conv_output_len = srslte_conv_cc(input, q->pss_signal_time[q->N_id_2], q->conv_output, q->frame_size, q->fft_size); #endif @@ -457,19 +450,19 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe for (int i=0;iframe_size;i++) { q->conv_output[i] = srslte_vec_dot_prod_ccc(q->pss_signal_time[q->N_id_2], &input[i], q->fft_size); } - conv_output_len = q->frame_size; + conv_output_len = q->frame_size; } - + #ifdef SRSLTE_PSS_ABS_SQUARE srslte_vec_abs_square_cf(q->conv_output, q->conv_output_abs, conv_output_len-1); #else srslte_vec_abs_cf(q->conv_output, q->conv_output_abs, conv_output_len-1); #endif - + if (q->ema_alpha < 1.0 && q->ema_alpha > 0.0) { - srslte_vec_sc_prod_fff(q->conv_output_abs, q->ema_alpha, q->conv_output_abs, conv_output_len-1); - srslte_vec_sc_prod_fff(q->conv_output_avg, 1-q->ema_alpha, q->conv_output_avg, conv_output_len-1); + srslte_vec_sc_prod_fff(q->conv_output_abs, q->ema_alpha, q->conv_output_abs, conv_output_len-1); + srslte_vec_sc_prod_fff(q->conv_output_avg, 1-q->ema_alpha, q->conv_output_avg, conv_output_len-1); srslte_vec_sum_fff(q->conv_output_abs, q->conv_output_avg, q->conv_output_avg, conv_output_len-1); } else { @@ -477,43 +470,43 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe } /* Find maximum of the absolute value of the correlation */ corr_peak_pos = srslte_vec_max_fi(q->conv_output_avg, conv_output_len-1); - - // save absolute value + + // save absolute value q->peak_value = q->conv_output_avg[corr_peak_pos]; - -#ifdef SRSLTE_PSS_RETURN_PSR + +#ifdef SRSLTE_PSS_RETURN_PSR // Find second side lobe - + // Find end of peak lobe to the right int pl_ub = corr_peak_pos+1; while(q->conv_output_avg[pl_ub+1] <= q->conv_output_avg[pl_ub] && pl_ub < conv_output_len) { - pl_ub ++; + pl_ub ++; } // Find end of peak lobe to the left - int pl_lb; + int pl_lb; if (corr_peak_pos > 2) { pl_lb = corr_peak_pos-1; while(q->conv_output_avg[pl_lb-1] <= q->conv_output_avg[pl_lb] && pl_lb > 1) { - pl_lb --; - } + pl_lb --; + } } else { - pl_lb = 0; + pl_lb = 0; } - int sl_distance_right = conv_output_len-1-pl_ub; + int sl_distance_right = conv_output_len-1-pl_ub; if (sl_distance_right < 0) { - sl_distance_right = 0; + sl_distance_right = 0; } - int sl_distance_left = pl_lb; - + int sl_distance_left = pl_lb; + int sl_right = pl_ub+srslte_vec_max_fi(&q->conv_output_avg[pl_ub], sl_distance_right); - int sl_left = srslte_vec_max_fi(q->conv_output_avg, sl_distance_left); - float side_lobe_value = SRSLTE_MAX(q->conv_output_avg[sl_right], q->conv_output_avg[sl_left]); + int sl_left = srslte_vec_max_fi(q->conv_output_avg, sl_distance_left); + float side_lobe_value = SRSLTE_MAX(q->conv_output_avg[sl_right], q->conv_output_avg[sl_left]); if (corr_peak_value) { *corr_peak_value = q->conv_output_avg[corr_peak_pos]/side_lobe_value; - + if (*corr_peak_value < 10) - DEBUG("peak_pos=%2d, pl_ub=%2d, pl_lb=%2d, sl_right: %2d, sl_left: %2d, PSR: %.2f/%.2f=%.2f\n", corr_peak_pos, pl_ub, pl_lb, + DEBUG("peak_pos=%2d, pl_ub=%2d, pl_lb=%2d, sl_right: %2d, sl_left: %2d, PSR: %.2f/%.2f=%.2f\n", corr_peak_pos, pl_ub, pl_lb, sl_right,sl_left, q->conv_output_avg[corr_peak_pos], side_lobe_value,*corr_peak_value); } #else @@ -521,7 +514,7 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe *corr_peak_value = q->conv_output_avg[corr_peak_pos]; } #endif - + if(q->decimate >1) { int decimation_correction = (q->filter.num_taps - 2); @@ -531,23 +524,23 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe if (q->frame_size >= q->fft_size) { - ret = (int) corr_peak_pos; + ret = (int) corr_peak_pos; } else { ret = (int) corr_peak_pos + q->fft_size; } - } + } return ret; } -/* Computes frequency-domain channel estimation of the PSS symbol - * input signal is in the time-domain. - * ce is the returned frequency-domain channel estimates. +/* Computes frequency-domain channel estimation of the PSS symbol + * input signal is in the time-domain. + * ce is the returned frequency-domain channel estimates. */ int srslte_pss_synch_chest(srslte_pss_synch_t *q, cf_t *input, cf_t ce[SRSLTE_PSS_LEN]) { int ret = SRSLTE_ERROR_INVALID_INPUTS; cf_t input_fft[SRSLTE_SYMBOL_SZ_MAX]; - if (q != NULL && + if (q != NULL && input != NULL) { @@ -555,46 +548,31 @@ int srslte_pss_synch_chest(srslte_pss_synch_t *q, cf_t *input, cf_t ce[SRSLTE_PS fprintf(stderr, "Error finding PSS peak, Must set N_id_2 first\n"); return SRSLTE_ERROR; } - + /* Transform to frequency-domain */ srslte_dft_run_c(&q->dftp_input, input, input_fft); - + /* Compute channel estimate taking the PSS sequence as reference */ srslte_vec_prod_conj_ccc(&input_fft[(q->fft_size-SRSLTE_PSS_LEN)/2], q->pss_signal_freq[q->N_id_2], ce, SRSLTE_PSS_LEN); - + ret = SRSLTE_SUCCESS; } - return ret; + return ret; } -#define CLEAN_NOISE_DFT -//#define PSS_CFO_FREQ /* Returns the CFO estimation given a PSS received sequence * * Source: An Efficient CFO Estimation Algorithm for the Downlink of 3GPP-LTE * Feng Wang and Yu Zhu */ float srslte_pss_synch_cfo_compute(srslte_pss_synch_t* q, cf_t *pss_recv) { - cf_t y0, y1; - -#ifdef PSS_CFO_FREQ - - srslte_vec_prod_conj_ccc(&q->tmp_fft[q->fft_size/2-SRSLTE_PSS_LEN/2], q->pss_signal_freq[q->N_id_2], q->yr, SRSLTE_PSS_LEN); - y0 = srslte_vec_acc_cc(q->yr, SRSLTE_PSS_LEN/2); - y1 = srslte_vec_acc_cc(&q->yr[SRSLTE_PSS_LEN/2], SRSLTE_PSS_LEN/2); - -#else -#ifdef CLEAN_NOISE_DFT - // Eliminate noise - srslte_dft_run_c(&q->dftp_input, pss_recv, q->tmp_fft); - bzero(q->tmp_fft, sizeof(cf_t)*(q->fft_size/2-SRSLTE_PSS_LEN/2)); - bzero(&q->tmp_fft[q->fft_size/2+SRSLTE_PSS_LEN/2], sizeof(cf_t)*(q->fft_size/2-SRSLTE_PSS_LEN/2)); - srslte_dft_run_c(&q->idftp_input, q->tmp_fft, pss_recv); -#endif + cf_t y0, y1, yr; y0 = srslte_vec_dot_prod_ccc(q->pss_signal_time[q->N_id_2], pss_recv, q->fft_size/2); y1 = srslte_vec_dot_prod_ccc(&q->pss_signal_time[q->N_id_2][q->fft_size/2], &pss_recv[q->fft_size/2], q->fft_size/2); -#endif - return carg(conjf(y0) * y1)/M_PI; + + yr = conjf(y0) * y1; + + return atan2f(__imag__ yr, __real__ yr) / M_PI; } From 2fd2f151576c4ff19afb3c6ea2e8d9973aec070b Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 29 Nov 2017 11:30:10 +0100 Subject: [PATCH 171/242] Cell RS based CFO estimation --- .../srslte/phy/ch_estimation/chest_dl.h | 10 ++++- lib/src/phy/ch_estimation/chest_dl.c | 43 ++++++++++++++++--- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/lib/include/srslte/phy/ch_estimation/chest_dl.h b/lib/include/srslte/phy/ch_estimation/chest_dl.h index 0e43d113c..229495a9b 100644 --- a/lib/include/srslte/phy/ch_estimation/chest_dl.h +++ b/lib/include/srslte/phy/ch_estimation/chest_dl.h @@ -82,7 +82,11 @@ typedef struct { float rssi[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; float rsrp[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; float noise_estimate[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; - + float cfo; + + bool cfo_estimate_enable; + uint32_t cfo_estimate_sf_mask; + /* Use PSS for noise estimation in LS linear interpolation mode */ cf_t pss_signal[SRSLTE_PSS_LEN]; cf_t tmp_pss[SRSLTE_PSS_LEN]; @@ -144,8 +148,12 @@ SRSLTE_API int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, uint32_t port_id, uint32_t rxant_id); +SRSLTE_API void srslte_chest_dl_cfo_estimate_enable(srslte_chest_dl_t *q, bool enable, uint32_t mask); + SRSLTE_API float srslte_chest_dl_get_noise_estimate(srslte_chest_dl_t *q); +SRSLTE_API float srslte_chest_dl_get_cfo(srslte_chest_dl_t *q); + SRSLTE_API float srslte_chest_dl_get_snr(srslte_chest_dl_t *q); SRSLTE_API float srslte_chest_dl_get_rssi(srslte_chest_dl_t *q); diff --git a/lib/src/phy/ch_estimation/chest_dl.c b/lib/src/phy/ch_estimation/chest_dl.c index 0f8ae8074..60d62a004 100644 --- a/lib/src/phy/ch_estimation/chest_dl.c +++ b/lib/src/phy/ch_estimation/chest_dl.c @@ -410,6 +410,30 @@ float srslte_chest_dl_rssi(srslte_chest_dl_t *q, cf_t *input, uint32_t port_id) return rssi/nsymbols; } +// CFO estimation algorithm taken from "Carrier Frequency Synchronization in the +// Downlink of 3GPP LTE", Qi Wang, C. Mehlfuhrer, M. Rupp +float chest_estimate_cfo(srslte_chest_dl_t *q) +{ + float n = (float) srslte_symbol_sz(q->cell.nof_prb); + float ns = (float) SRSLTE_CP_NSYMB(q->cell.cp); + float ng = (float) SRSLTE_CP_LEN_NORM(1, n); + + uint32_t npilots = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, 0); + + // Compute angles between slots + for (int i=0;i<2;i++) { + srslte_vec_prod_conj_ccc(&q->pilot_estimates[i*npilots/4], + &q->pilot_estimates[(i+2)*npilots/4], + &q->tmp_noise[i*npilots/4], + npilots/4); + } + // Average all angles + cf_t sum = srslte_vec_acc_cc(q->tmp_noise, npilots/2); + + // Compute CFO + return -cargf(sum)*n/(ns*(n+ng))/2/M_PI; +} + void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id, uint32_t rxant_id, srslte_sf_t ch_mode){ if (ce != NULL) { /* Smooth estimates (if applicable) and interpolate */ @@ -433,6 +457,10 @@ void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, ui } } } + + if (q->cfo_estimate_enable && ((1<cfo_estimate_sf_mask)) { + q->cfo = chest_estimate_cfo(q); + } /* Compute RSRP for the channel estimates in this port */ q->rsrp[rxant_id][port_id] = srslte_vec_avg_power_cf(q->pilot_recv_signal, SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id)); @@ -451,8 +479,9 @@ int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, u srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->csr_refs.pilots[port_id/2][sf_idx], q->pilot_estimates, SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id)); + chest_interpolate_noise_est(q, input, ce, sf_idx, port_id, rxant_id, SRSLTE_SF_NORM); - + return 0; } int srslte_chest_dl_estimate_port_mbsfn(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id, uint32_t rxant_id, uint16_t mbsfn_area_id) @@ -474,10 +503,6 @@ int srslte_chest_dl_estimate_port_mbsfn(srslte_chest_dl_t *q, cf_t *input, cf_t return 0; } - - - - int srslte_chest_dl_estimate_multi(srslte_chest_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS], cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], uint32_t sf_idx, uint32_t nof_rx_antennas) { for (uint32_t rxant_id=0;rxant_idcfo_estimate_enable = enable; + q->cfo_estimate_sf_mask = mask; +} +float srslte_chest_dl_get_cfo(srslte_chest_dl_t *q) { + return q->cfo; +} float srslte_chest_dl_get_noise_estimate(srslte_chest_dl_t *q) { float n = 0; From 2772471e41692f3893a3856b7205a035da3ff027 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 29 Nov 2017 11:58:18 +0100 Subject: [PATCH 172/242] Added filtering function to PSS --- lib/include/srslte/phy/sync/pss.h | 24 +++-- lib/src/phy/sync/pss.c | 168 ++++++++++++++++++------------ 2 files changed, 118 insertions(+), 74 deletions(-) diff --git a/lib/include/srslte/phy/sync/pss.h b/lib/include/srslte/phy/sync/pss.h index 9760a178c..f94b2deba 100644 --- a/lib/include/srslte/phy/sync/pss.h +++ b/lib/include/srslte/phy/sync/pss.h @@ -70,9 +70,7 @@ /* Low-level API */ typedef struct SRSLTE_API { - - srslte_dft_plan_t dftp_input; - + #ifdef CONVOLUTION_FFT srslte_conv_fft_cc_t conv_fft; srslte_filt_cc_t filter; @@ -87,16 +85,23 @@ typedef struct SRSLTE_API { uint32_t N_id_2; uint32_t fft_size; cf_t *pss_signal_freq_full[3]; - + cf_t *pss_signal_time[3]; - + cf_t pss_signal_freq[3][SRSLTE_PSS_LEN]; // One sequence for each N_id_2 cf_t *tmp_input; cf_t *conv_output; float *conv_output_abs; - float ema_alpha; + float ema_alpha; float *conv_output_avg; float peak_value; + + bool filter_pss_enable; + srslte_dft_plan_t dftp_input; + srslte_dft_plan_t idftp_input; + cf_t tmp_fft[SRSLTE_SYMBOL_SZ_MAX]; + cf_t tmp_fft2[SRSLTE_SYMBOL_SZ_MAX]; + }srslte_pss_synch_t; typedef enum { PSS_TX, PSS_RX } pss_direction_t; @@ -128,6 +133,13 @@ SRSLTE_API void srslte_pss_synch_free(srslte_pss_synch_t *q); SRSLTE_API void srslte_pss_synch_reset(srslte_pss_synch_t *q); +SRSLTE_API void srslte_pss_synch_filter_enable(srslte_pss_synch_t *q, + bool enable); + +SRSLTE_API void srslte_pss_synch_filter(srslte_pss_synch_t *q, + cf_t *input, + cf_t *output); + SRSLTE_API int srslte_pss_generate(cf_t *signal, uint32_t N_id_2); diff --git a/lib/src/phy/sync/pss.c b/lib/src/phy/sync/pss.c index f7b35071d..411579d7c 100644 --- a/lib/src/phy/sync/pss.c +++ b/lib/src/phy/sync/pss.c @@ -30,12 +30,8 @@ #include #include #include -#include #include "srslte/phy/sync/pss.h" -#include "srslte/phy/dft/dft.h" -#include "srslte/phy/utils/vector.h" -#include "srslte/phy/utils/convolution.h" #include "srslte/phy/utils/debug.h" @@ -69,7 +65,7 @@ int srslte_pss_synch_init_N_id_2(cf_t *pss_signal_freq, cf_t *pss_signal_time, srslte_vec_sc_prod_cfc(pss_signal_time, 1.0/SRSLTE_PSS_LEN, pss_signal_time, fft_size); srslte_dft_plan_free(&plan); - + ret = SRSLTE_SUCCESS; } return ret; @@ -123,6 +119,8 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, buffer_size = fft_size + frame_size + 1; + q->filter_pss_enable = true; + if(q->decimate > 1) { int filter_order = 3; srslte_filt_decim_cc_init(&q->filter,q->decimate,filter_order); @@ -137,9 +135,19 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, } srslte_dft_plan_set_mirror(&q->dftp_input, true); srslte_dft_plan_set_dc(&q->dftp_input, true); - srslte_dft_plan_set_norm(&q->dftp_input, true); + srslte_dft_plan_set_norm(&q->dftp_input, false); - q->tmp_input = srslte_vec_malloc((buffer_size + frame_size*(q->decimate - 1)) * sizeof(cf_t)); + if (srslte_dft_plan(&q->idftp_input, fft_size, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)) { + fprintf(stderr, "Error creating DFT plan \n"); + goto clean_and_exit; + } + srslte_dft_plan_set_mirror(&q->idftp_input, true); + srslte_dft_plan_set_dc(&q->idftp_input, true); + srslte_dft_plan_set_norm(&q->idftp_input, true); + + bzero(q->tmp_fft2, sizeof(cf_t)*SRSLTE_SYMBOL_SZ_MAX); + + q->tmp_input = srslte_vec_malloc((buffer_size + frame_size*(q->decimate - 1)) * sizeof(cf_t)); if (!q->tmp_input) { fprintf(stderr, "Error allocating memory\n"); goto clean_and_exit; @@ -167,7 +175,7 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, } bzero(q->conv_output_abs, sizeof(float) * buffer_size); #endif - + for (N_id_2=0;N_id_2<3;N_id_2++) { q->pss_signal_time[N_id_2] = srslte_vec_malloc(buffer_size * sizeof(cf_t)); if (!q->pss_signal_time[N_id_2]) { @@ -178,14 +186,14 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, if (srslte_pss_synch_init_N_id_2(q->pss_signal_freq[N_id_2], q->pss_signal_time[N_id_2], N_id_2, fft_size, offset)) { fprintf(stderr, "Error initiating PSS detector for N_id_2=%d fft_size=%d\n", N_id_2, fft_size); goto clean_and_exit; - } + } bzero(&q->pss_signal_time[N_id_2][q->fft_size], q->frame_size * sizeof(cf_t)); - } + } #ifdef CONVOLUTION_FFT for(N_id_2=0; N_id_2<3; N_id_2++) - q->pss_signal_freq_full[N_id_2] = srslte_vec_malloc(buffer_size * sizeof(cf_t)); + q->pss_signal_freq_full[N_id_2] = srslte_vec_malloc(buffer_size * sizeof(cf_t)); if (srslte_conv_fft_cc_init(&q->conv_fft, frame_size, fft_size)) { fprintf(stderr, "Error initiating convolution FFT\n"); @@ -194,15 +202,15 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, for(int i=0; i<3; i++) { srslte_dft_run_c(&q->conv_fft.filter_plan, q->pss_signal_time[i], q->pss_signal_freq_full[i]); } - + #endif - + srslte_pss_synch_reset(q); - + ret = SRSLTE_SUCCESS; } -clean_and_exit: +clean_and_exit: if (ret == SRSLTE_ERROR) { srslte_pss_synch_free(q); } @@ -248,6 +256,13 @@ int srslte_pss_synch_resize(srslte_pss_synch_t *q, uint32_t frame_size, uint32_t return SRSLTE_ERROR; } + if (srslte_dft_replan(&q->idftp_input, fft_size)) { + fprintf(stderr, "Error creating DFT plan \n"); + return SRSLTE_ERROR; + } + + bzero(q->tmp_fft2, sizeof(cf_t)*SRSLTE_SYMBOL_SZ_MAX); + bzero(&q->tmp_input[q->frame_size], q->fft_size * sizeof(cf_t)); bzero(q->conv_output, sizeof(cf_t) * buffer_size); bzero(q->conv_output_avg, sizeof(float) * buffer_size); @@ -298,7 +313,7 @@ void srslte_pss_synch_free(srslte_pss_synch_t *q) { } #ifdef CONVOLUTION_FFT srslte_conv_fft_cc_free(&q->conv_fft); - + #endif if (q->tmp_input) { free(q->tmp_input); @@ -312,9 +327,10 @@ void srslte_pss_synch_free(srslte_pss_synch_t *q) { if (q->conv_output_avg) { free(q->conv_output_avg); } - + srslte_dft_plan_free(&q->dftp_input); - + srslte_dft_plan_free(&q->idftp_input); + if(q->decimate > 1) { srslte_filt_decim_cc_free(&q->filter); @@ -323,7 +339,7 @@ void srslte_pss_synch_free(srslte_pss_synch_t *q) { } - bzero(q, sizeof(srslte_pss_synch_t)); + bzero(q, sizeof(srslte_pss_synch_t)); } } @@ -379,7 +395,7 @@ void srslte_pss_put_slot(cf_t *pss_signal, cf_t *slot, uint32_t nof_prb, srslte_ void srslte_pss_get_slot(cf_t *slot, cf_t *pss_signal, uint32_t nof_prb, srslte_cp_t cp) { int k; k = (SRSLTE_CP_NSYMB(cp) - 1) * nof_prb * SRSLTE_NRE + nof_prb * SRSLTE_NRE / 2 - 31; - memcpy(pss_signal, &slot[k], SRSLTE_PSS_LEN * sizeof(cf_t)); + memcpy(pss_signal, &slot[k], SRSLTE_PSS_LEN * sizeof(cf_t)); } @@ -398,34 +414,34 @@ int srslte_pss_synch_set_N_id_2(srslte_pss_synch_t *q, uint32_t N_id_2) { /* Sets the weight factor alpha for the exponential moving average of the PSS correlation output */ void srslte_pss_synch_set_ema_alpha(srslte_pss_synch_t *q, float alpha) { - q->ema_alpha = alpha; + q->ema_alpha = alpha; } -/** Performs time-domain PSS correlation. +/** Performs time-domain PSS correlation. * Returns the index of the PSS correlation peak in a subframe. * The frame starts at corr_peak_pos-subframe_size/2. * The value of the correlation is stored in corr_peak_value. * * Input buffer must be subframe_size long. */ -int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_peak_value) +int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_peak_value) { int ret = SRSLTE_ERROR_INVALID_INPUTS; - - if (q != NULL && + + if (q != NULL && input != NULL) { uint32_t corr_peak_pos; uint32_t conv_output_len; - + if (!srslte_N_id_2_isvalid(q->N_id_2)) { fprintf(stderr, "Error finding PSS peak, Must set N_id_2 first\n"); return SRSLTE_ERROR; } /* Correlate input with PSS sequence - * + * * We do not reverse time-domain PSS signal because it's conjugate is symmetric. * The conjugate operation on pss_signal_time has been done in srslte_pss_synch_init_N_id_2 * This is why we can use FFT-based convolution @@ -442,7 +458,7 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe { conv_output_len = srslte_conv_fft_cc_run_opt(&q->conv_fft, q->tmp_input, q->pss_signal_freq_full[q->N_id_2], q->conv_output); } - + #else conv_output_len = srslte_conv_cc(input, q->pss_signal_time[q->N_id_2], q->conv_output, q->frame_size, q->fft_size); #endif @@ -450,19 +466,19 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe for (int i=0;iframe_size;i++) { q->conv_output[i] = srslte_vec_dot_prod_ccc(q->pss_signal_time[q->N_id_2], &input[i], q->fft_size); } - conv_output_len = q->frame_size; + conv_output_len = q->frame_size; } - + #ifdef SRSLTE_PSS_ABS_SQUARE srslte_vec_abs_square_cf(q->conv_output, q->conv_output_abs, conv_output_len-1); #else srslte_vec_abs_cf(q->conv_output, q->conv_output_abs, conv_output_len-1); #endif - + if (q->ema_alpha < 1.0 && q->ema_alpha > 0.0) { - srslte_vec_sc_prod_fff(q->conv_output_abs, q->ema_alpha, q->conv_output_abs, conv_output_len-1); - srslte_vec_sc_prod_fff(q->conv_output_avg, 1-q->ema_alpha, q->conv_output_avg, conv_output_len-1); + srslte_vec_sc_prod_fff(q->conv_output_abs, q->ema_alpha, q->conv_output_abs, conv_output_len-1); + srslte_vec_sc_prod_fff(q->conv_output_avg, 1-q->ema_alpha, q->conv_output_avg, conv_output_len-1); srslte_vec_sum_fff(q->conv_output_abs, q->conv_output_avg, q->conv_output_avg, conv_output_len-1); } else { @@ -470,43 +486,43 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe } /* Find maximum of the absolute value of the correlation */ corr_peak_pos = srslte_vec_max_fi(q->conv_output_avg, conv_output_len-1); - - // save absolute value + + // save absolute value q->peak_value = q->conv_output_avg[corr_peak_pos]; - -#ifdef SRSLTE_PSS_RETURN_PSR + +#ifdef SRSLTE_PSS_RETURN_PSR // Find second side lobe - + // Find end of peak lobe to the right int pl_ub = corr_peak_pos+1; while(q->conv_output_avg[pl_ub+1] <= q->conv_output_avg[pl_ub] && pl_ub < conv_output_len) { - pl_ub ++; + pl_ub ++; } // Find end of peak lobe to the left - int pl_lb; + int pl_lb; if (corr_peak_pos > 2) { pl_lb = corr_peak_pos-1; while(q->conv_output_avg[pl_lb-1] <= q->conv_output_avg[pl_lb] && pl_lb > 1) { - pl_lb --; - } + pl_lb --; + } } else { - pl_lb = 0; + pl_lb = 0; } - int sl_distance_right = conv_output_len-1-pl_ub; + int sl_distance_right = conv_output_len-1-pl_ub; if (sl_distance_right < 0) { - sl_distance_right = 0; + sl_distance_right = 0; } - int sl_distance_left = pl_lb; - + int sl_distance_left = pl_lb; + int sl_right = pl_ub+srslte_vec_max_fi(&q->conv_output_avg[pl_ub], sl_distance_right); - int sl_left = srslte_vec_max_fi(q->conv_output_avg, sl_distance_left); - float side_lobe_value = SRSLTE_MAX(q->conv_output_avg[sl_right], q->conv_output_avg[sl_left]); + int sl_left = srslte_vec_max_fi(q->conv_output_avg, sl_distance_left); + float side_lobe_value = SRSLTE_MAX(q->conv_output_avg[sl_right], q->conv_output_avg[sl_left]); if (corr_peak_value) { *corr_peak_value = q->conv_output_avg[corr_peak_pos]/side_lobe_value; - + if (*corr_peak_value < 10) - DEBUG("peak_pos=%2d, pl_ub=%2d, pl_lb=%2d, sl_right: %2d, sl_left: %2d, PSR: %.2f/%.2f=%.2f\n", corr_peak_pos, pl_ub, pl_lb, + DEBUG("peak_pos=%2d, pl_ub=%2d, pl_lb=%2d, sl_right: %2d, sl_left: %2d, PSR: %.2f/%.2f=%.2f\n", corr_peak_pos, pl_ub, pl_lb, sl_right,sl_left, q->conv_output_avg[corr_peak_pos], side_lobe_value,*corr_peak_value); } #else @@ -514,7 +530,7 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe *corr_peak_value = q->conv_output_avg[corr_peak_pos]; } #endif - + if(q->decimate >1) { int decimation_correction = (q->filter.num_taps - 2); @@ -524,23 +540,23 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe if (q->frame_size >= q->fft_size) { - ret = (int) corr_peak_pos; + ret = (int) corr_peak_pos; } else { ret = (int) corr_peak_pos + q->fft_size; } - } + } return ret; } -/* Computes frequency-domain channel estimation of the PSS symbol - * input signal is in the time-domain. - * ce is the returned frequency-domain channel estimates. +/* Computes frequency-domain channel estimation of the PSS symbol + * input signal is in the time-domain. + * ce is the returned frequency-domain channel estimates. */ int srslte_pss_synch_chest(srslte_pss_synch_t *q, cf_t *input, cf_t ce[SRSLTE_PSS_LEN]) { int ret = SRSLTE_ERROR_INVALID_INPUTS; cf_t input_fft[SRSLTE_SYMBOL_SZ_MAX]; - if (q != NULL && + if (q != NULL && input != NULL) { @@ -548,16 +564,28 @@ int srslte_pss_synch_chest(srslte_pss_synch_t *q, cf_t *input, cf_t ce[SRSLTE_PS fprintf(stderr, "Error finding PSS peak, Must set N_id_2 first\n"); return SRSLTE_ERROR; } - + /* Transform to frequency-domain */ srslte_dft_run_c(&q->dftp_input, input, input_fft); - + /* Compute channel estimate taking the PSS sequence as reference */ srslte_vec_prod_conj_ccc(&input_fft[(q->fft_size-SRSLTE_PSS_LEN)/2], q->pss_signal_freq[q->N_id_2], ce, SRSLTE_PSS_LEN); - + ret = SRSLTE_SUCCESS; } - return ret; + return ret; +} + +// Frequency-domain filtering of the central 64 sub-carriers +void srslte_pss_synch_filter(srslte_pss_synch_t *q, cf_t *input, cf_t *output) +{ + srslte_dft_run_c(&q->dftp_input, input, q->tmp_fft); + + memcpy(&q->tmp_fft2[q->fft_size/2-SRSLTE_PSS_LEN/2], + &q->tmp_fft[q->fft_size/2-SRSLTE_PSS_LEN/2], + sizeof(cf_t)*SRSLTE_PSS_LEN); + + srslte_dft_run_c(&q->idftp_input, q->tmp_fft2, output); } /* Returns the CFO estimation given a PSS received sequence @@ -566,13 +594,17 @@ int srslte_pss_synch_chest(srslte_pss_synch_t *q, cf_t *input, cf_t ce[SRSLTE_PS * Feng Wang and Yu Zhu */ float srslte_pss_synch_cfo_compute(srslte_pss_synch_t* q, cf_t *pss_recv) { - cf_t y0, y1, yr; + cf_t y0, y1; - y0 = srslte_vec_dot_prod_ccc(q->pss_signal_time[q->N_id_2], pss_recv, q->fft_size/2); - y1 = srslte_vec_dot_prod_ccc(&q->pss_signal_time[q->N_id_2][q->fft_size/2], &pss_recv[q->fft_size/2], q->fft_size/2); - - yr = conjf(y0) * y1; + cf_t *pss_ptr = pss_recv; + + if (q->filter_pss_enable) { + srslte_pss_synch_filter(q, pss_recv, q->tmp_fft); + pss_ptr = q->tmp_fft; + } - return atan2f(__imag__ yr, __real__ yr) / M_PI; + y0 = srslte_vec_dot_prod_ccc(q->pss_signal_time[q->N_id_2], pss_ptr, q->fft_size/2); + y1 = srslte_vec_dot_prod_ccc(&q->pss_signal_time[q->N_id_2][q->fft_size/2], &pss_ptr[q->fft_size/2], q->fft_size/2); + return carg(conjf(y0) * y1)/M_PI; } From 5292137b3a5d863dc0e33edc49a213558bdac517 Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Wed, 29 Nov 2017 11:51:12 +0000 Subject: [PATCH 173/242] Adding APN info to log output --- srsue/src/upper/nas.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index 9c24cbf2e..62e23d852 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -360,13 +360,14 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { ip_addr |= act_def_eps_bearer_context_req.pdn_addr.addr[2] << 8; ip_addr |= act_def_eps_bearer_context_req.pdn_addr.addr[3]; - nas_log->info("IP allocated by network %u.%u.%u.%u\n", + nas_log->info("Network attach successful. APN: %s, IP: %u.%u.%u.%u\n", + act_def_eps_bearer_context_req.apn.apn.c_str(), act_def_eps_bearer_context_req.pdn_addr.addr[0], act_def_eps_bearer_context_req.pdn_addr.addr[1], act_def_eps_bearer_context_req.pdn_addr.addr[2], act_def_eps_bearer_context_req.pdn_addr.addr[3]); - nas_log->console("Network attach successful. IP: %u.%u.%u.%u\n", + nas_log->console("Network attach successful. IP: %u.%u.%u.%u\n", act_def_eps_bearer_context_req.pdn_addr.addr[0], act_def_eps_bearer_context_req.pdn_addr.addr[1], act_def_eps_bearer_context_req.pdn_addr.addr[2], From a3a1d268b7ac81446c364a5466a5220b41881fec Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 29 Nov 2017 18:30:21 +0100 Subject: [PATCH 174/242] Improved CFO estimation/correction by filtering central 6 PRB. Cleaned ue_sync/sync/pss objects. Used const attr in vector and other objects --- lib/examples/cell_measurement.c | 3 - lib/examples/pdsch_ue.c | 9 +- lib/include/srslte/phy/dft/dft.h | 14 +- lib/include/srslte/phy/sync/cfo.h | 2 +- lib/include/srslte/phy/sync/cp.h | 2 +- lib/include/srslte/phy/sync/pss.h | 12 +- lib/include/srslte/phy/sync/sss.h | 10 +- lib/include/srslte/phy/sync/sync.h | 84 ++-- lib/include/srslte/phy/ue/ue_sync.h | 37 +- lib/include/srslte/phy/utils/convolution.h | 16 +- lib/include/srslte/phy/utils/simd.h | 22 +- lib/include/srslte/phy/utils/vector.h | 98 ++-- lib/include/srslte/phy/utils/vector_simd.h | 65 +-- lib/src/phy/dft/dft_fftw.c | 10 +- lib/src/phy/modem/demod_soft.c | 4 +- .../phy/resampling/test/resample_arb_bench.c | 2 +- lib/src/phy/rf/rf_blade_imp.c | 4 +- lib/src/phy/rf/rf_utils.c | 7 +- lib/src/phy/sync/cfo.c | 2 +- lib/src/phy/sync/cp.c | 4 +- lib/src/phy/sync/find_sss.c | 8 +- lib/src/phy/sync/pss.c | 115 +++-- lib/src/phy/sync/sync.c | 431 ++++++++++-------- lib/src/phy/sync/test/pss_usrp.c | 18 +- lib/src/phy/sync/test/sync_test.c | 3 +- lib/src/phy/ue/ue_cell_search.c | 4 +- lib/src/phy/ue/ue_sync.c | 242 +++++----- lib/src/phy/utils/convolution.c | 6 +- lib/src/phy/utils/test/vector_test.c | 2 +- lib/src/phy/utils/vector.c | 107 +++-- lib/src/phy/utils/vector_simd.c | 67 +-- srsue/src/phy/phch_recv.cc | 6 +- 32 files changed, 749 insertions(+), 667 deletions(-) diff --git a/lib/examples/cell_measurement.c b/lib/examples/cell_measurement.c index 6415257f0..573cab255 100644 --- a/lib/examples/cell_measurement.c +++ b/lib/examples/cell_measurement.c @@ -299,9 +299,6 @@ int main(int argc, char **argv) { float rx_gain_offset = 0; - // Set initial CFO for ue_sync - srslte_ue_sync_set_cfo(&ue_sync, cfo); - /* Main loop */ while ((sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1) && !go_exit) { diff --git a/lib/examples/pdsch_ue.c b/lib/examples/pdsch_ue.c index e8d4b1d00..e15aa473f 100644 --- a/lib/examples/pdsch_ue.c +++ b/lib/examples/pdsch_ue.c @@ -579,11 +579,8 @@ int main(int argc, char **argv) { srslte_ra_dl_dci_t old_dl_dci; bzero(&old_dl_dci, sizeof(srslte_ra_dl_dci_t)); #endif - - ue_sync.correct_cfo = !prog_args.disable_cfo; - - // Set initial CFO for ue_sync - srslte_ue_sync_set_cfo(&ue_sync, cfo); + + ue_sync.cfo_correct_enable = !prog_args.disable_cfo; srslte_pbch_decode_reset(&ue_mib.pbch); @@ -776,7 +773,7 @@ int main(int argc, char **argv) { /* Print basic Parameters */ PRINT_LINE(" nof layers: %d", ue_dl.pdsch_cfg.nof_layers); PRINT_LINE("nof codewords: %d", SRSLTE_RA_DL_GRANT_NOF_TB(&ue_dl.pdsch_cfg.grant)); - PRINT_LINE(" CFO: %+5.2f kHz", srslte_ue_sync_get_cfo(&ue_sync) / 1000); + PRINT_LINE(" CFO: %+7.2f kHz", srslte_ue_sync_get_cfo(&ue_sync)); PRINT_LINE(" SNR: %+5.1f dB | %+5.1f dB", 10 * log10(rsrp0 / noise), 10 * log10(rsrp1 / noise)); PRINT_LINE(" Rb: %6.2f / %6.2f / %6.2f Mbps (net/maximum/processing)", uerate, enodebrate, procrate); PRINT_LINE(" PDCCH-Miss: %5.2f%%", 100 * (1 - (float) ue_dl.nof_detected / nof_trials)); diff --git a/lib/include/srslte/phy/dft/dft.h b/lib/include/srslte/phy/dft/dft.h index b3dd4378b..afe8024d2 100644 --- a/lib/include/srslte/phy/dft/dft.h +++ b/lib/include/srslte/phy/dft/dft.h @@ -139,22 +139,22 @@ SRSLTE_API void srslte_dft_plan_set_dc(srslte_dft_plan_t *plan, /* Compute DFT */ -SRSLTE_API void srslte_dft_run(srslte_dft_plan_t *plan, - void *in, +SRSLTE_API void srslte_dft_run(srslte_dft_plan_t *plan, + const void *in, void *out); -SRSLTE_API void srslte_dft_run_c_zerocopy(srslte_dft_plan_t *plan, - cf_t *in, +SRSLTE_API void srslte_dft_run_c_zerocopy(srslte_dft_plan_t *plan, + const cf_t *in, cf_t *out); -SRSLTE_API void srslte_dft_run_c(srslte_dft_plan_t *plan, - cf_t *in, +SRSLTE_API void srslte_dft_run_c(srslte_dft_plan_t *plan, + const 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, + const float *in, float *out); #endif // DFT_H_ diff --git a/lib/include/srslte/phy/sync/cfo.h b/lib/include/srslte/phy/sync/cfo.h index fd2ab4d83..5b9b3c0dd 100644 --- a/lib/include/srslte/phy/sync/cfo.h +++ b/lib/include/srslte/phy/sync/cfo.h @@ -66,7 +66,7 @@ SRSLTE_API void srslte_cfo_set_tol(srslte_cfo_t *h, float tol); SRSLTE_API void srslte_cfo_correct(srslte_cfo_t *h, - cf_t *input, + const cf_t *input, cf_t *output, float freq); diff --git a/lib/include/srslte/phy/sync/cp.h b/lib/include/srslte/phy/sync/cp.h index 9daf7d4f6..d9da03722 100644 --- a/lib/include/srslte/phy/sync/cp.h +++ b/lib/include/srslte/phy/sync/cp.h @@ -47,7 +47,7 @@ SRSLTE_API int srslte_cp_synch_resize(srslte_cp_synch_t *q, uint32_t symbol_sz); SRSLTE_API uint32_t srslte_cp_synch(srslte_cp_synch_t *q, - cf_t *input, + const cf_t *input, uint32_t max_offset, uint32_t nof_symbols, uint32_t cp_len); diff --git a/lib/include/srslte/phy/sync/pss.h b/lib/include/srslte/phy/sync/pss.h index f94b2deba..aba84f5cd 100644 --- a/lib/include/srslte/phy/sync/pss.h +++ b/lib/include/srslte/phy/sync/pss.h @@ -63,8 +63,6 @@ #define SRSLTE_PSS_ACCUMULATE_ABS // If enabled, accumulates the correlation absolute value on consecutive calls to srslte_pss_synch_find_pss -#define SRSLTE_PSS_ABS_SQUARE // If enabled, compute abs square, otherwise computes absolute value only - #define SRSLTE_PSS_RETURN_PSR // If enabled returns peak to side-lobe ratio, otherwise returns absolute peak value @@ -137,7 +135,7 @@ SRSLTE_API void srslte_pss_synch_filter_enable(srslte_pss_synch_t *q, bool enable); SRSLTE_API void srslte_pss_synch_filter(srslte_pss_synch_t *q, - cf_t *input, + const cf_t *input, cf_t *output); SRSLTE_API int srslte_pss_generate(cf_t *signal, @@ -160,14 +158,14 @@ SRSLTE_API int srslte_pss_synch_set_N_id_2(srslte_pss_synch_t *q, uint32_t N_id_2); SRSLTE_API int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, - cf_t *input, + const cf_t *input, float *corr_peak_value); SRSLTE_API int srslte_pss_synch_chest(srslte_pss_synch_t *q, - cf_t *input, + const cf_t *input, cf_t ce[SRSLTE_PSS_LEN]); -SRSLTE_API float srslte_pss_synch_cfo_compute(srslte_pss_synch_t* q, - cf_t *pss_recv); +SRSLTE_API float srslte_pss_synch_cfo_compute(srslte_pss_synch_t* q, + const cf_t *pss_recv); #endif // PSS_ diff --git a/lib/include/srslte/phy/sync/sss.h b/lib/include/srslte/phy/sync/sss.h index 35eedac8f..4a0942d61 100644 --- a/lib/include/srslte/phy/sync/sss.h +++ b/lib/include/srslte/phy/sync/sss.h @@ -107,8 +107,8 @@ SRSLTE_API void srslte_sss_put_slot(float *sss, SRSLTE_API int srslte_sss_synch_set_N_id_2(srslte_sss_synch_t *q, uint32_t N_id_2); -SRSLTE_API int srslte_sss_synch_m0m1_partial(srslte_sss_synch_t *q, - cf_t *input, +SRSLTE_API int srslte_sss_synch_m0m1_partial(srslte_sss_synch_t *q, + const cf_t *input, uint32_t M, cf_t ce[2*SRSLTE_SSS_N], uint32_t *m0, @@ -117,15 +117,15 @@ SRSLTE_API int srslte_sss_synch_m0m1_partial(srslte_sss_synch_t *q, float *m1_value); SRSLTE_API int srslte_sss_synch_m0m1_diff_coh(srslte_sss_synch_t *q, - cf_t *input, + const cf_t *input, cf_t ce[2*SRSLTE_SSS_N], uint32_t *m0, float *m0_value, uint32_t *m1, float *m1_value); -SRSLTE_API int srslte_sss_synch_m0m1_diff(srslte_sss_synch_t *q, - cf_t *input, +SRSLTE_API int srslte_sss_synch_m0m1_diff(srslte_sss_synch_t *q, + const cf_t *input, uint32_t *m0, float *m0_value, uint32_t *m1, diff --git a/lib/include/srslte/phy/sync/sync.h b/lib/include/srslte/phy/sync/sync.h index 1c70b2449..151c530b1 100644 --- a/lib/include/srslte/phy/sync/sync.h +++ b/lib/include/srslte/phy/sync/sync.h @@ -74,19 +74,8 @@ typedef struct SRSLTE_API { uint32_t fft_size; uint32_t frame_size; uint32_t max_offset; - bool enable_cfo_corr; - bool mean_cfo2_isunset; - bool mean_cfo_isunset; - float mean_cfo; - float mean_cfo2; - int cfo_i; - bool find_cfo_i; - bool find_cfo_i_initiated; - float cfo_ema_alpha; uint32_t nof_symbols; uint32_t cp_len; - srslte_cfo_t cfocorr; - srslte_cfo_t cfocorr2; float current_cfo_tol; sss_alg_t sss_alg; bool detect_cp; @@ -102,6 +91,30 @@ typedef struct SRSLTE_API { uint32_t max_frame_size; + + // variables for various CFO estimation methods + bool cfo_cp_enable; + bool cfo_pss_enable; + bool cfo_i_enable; + + bool cfo_cp_is_set; + bool cfo_pss_is_set; + bool cfo_i_initiated; + + float cfo_cp_mean; + float cfo_pss_mean; + int cfo_i_value; + + float cfo_ema_alpha; + + srslte_cfo_t cfo_corr_frame; + srslte_cfo_t cfo_corr_symbol; + + bool sss_filtering_enabled; + bool pss_filtering_enabled; + cf_t sss_filt[SRSLTE_SYMBOL_SZ_MAX]; + cf_t pss_filt[SRSLTE_SYMBOL_SZ_MAX]; + }srslte_sync_t; typedef enum { @@ -135,29 +148,23 @@ SRSLTE_API void srslte_sync_reset(srslte_sync_t *q); /* Finds a correlation peak in the input signal around position find_offset */ SRSLTE_API srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, - cf_t *input, + const cf_t *input, uint32_t find_offset, uint32_t *peak_position); /* Estimates the CP length */ SRSLTE_API srslte_cp_t srslte_sync_detect_cp(srslte_sync_t *q, - cf_t *input, + const cf_t *input, uint32_t peak_pos); /* Sets the threshold for peak comparison */ SRSLTE_API void srslte_sync_set_threshold(srslte_sync_t *q, float threshold); -SRSLTE_API void srslte_sync_set_cfo_tol(srslte_sync_t *q, - float tol); - /* Gets the subframe idx (0 or 5) */ SRSLTE_API uint32_t srslte_sync_get_sf_idx(srslte_sync_t *q); -/* Gets the last peak value */ -SRSLTE_API float srslte_sync_get_last_peak_value(srslte_sync_t *q); - -/* Gets the mean peak value */ +/* Gets the peak value */ SRSLTE_API float srslte_sync_get_peak_value(srslte_sync_t *q); /* Choose SSS detection algorithm */ @@ -175,23 +182,40 @@ SRSLTE_API int srslte_sync_set_N_id_2(srslte_sync_t *q, /* Gets the Physical CellId from the last call to synch_run() */ SRSLTE_API int srslte_sync_get_cell_id(srslte_sync_t *q); +/* Enables/disables filtering of the central PRBs before PSS CFO estimation or SSS correlation*/ +SRSLTE_API void srslte_sync_set_pss_filt_enable(srslte_sync_t *q, + bool enable); + +SRSLTE_API void srslte_sync_set_sss_filt_enable(srslte_sync_t *q, + bool enable); + /* Gets the CFO estimation from the last call to synch_run() */ SRSLTE_API float srslte_sync_get_cfo(srslte_sync_t *q); -/* Sets known CFO to avoid long transients due to average */ -SRSLTE_API void srslte_sync_set_cfo(srslte_sync_t *q, float cfo); +/* Resets internal CFO state */ +SRSLTE_API void srslte_sync_cfo_reset(srslte_sync_t *q); + +/* Copies CFO internal state from another object to avoid long transients */ +SRSLTE_API void srslte_sync_copy_cfo(srslte_sync_t *q, + srslte_sync_t *src_obj); -/* Set integer CFO */ -SRSLTE_API void srslte_sync_set_cfo_i(srslte_sync_t *q, - int cfo_i); +/* Enable different CFO estimation stages */ +SRSLTE_API void srslte_sync_set_cfo_i_enable(srslte_sync_t *q, + bool enable); +SRSLTE_API void srslte_sync_set_cfo_cp_enable(srslte_sync_t *q, + bool enable); +SRSLTE_API void srslte_sync_set_cfo_pss_enable(srslte_sync_t *q, + bool enable); -SRSLTE_API void srslte_sync_set_cfo_enable(srslte_sync_t *q, - bool enable); +/* Sets CFO correctors tolerance (in Hz) */ +SRSLTE_API void srslte_sync_set_cfo_tol(srslte_sync_t *q, + float tol); /* Sets the exponential moving average coefficient for CFO averaging */ SRSLTE_API void srslte_sync_set_cfo_ema_alpha(srslte_sync_t *q, float alpha); + /* Gets the CP length estimation from the last call to synch_run() */ SRSLTE_API srslte_cp_t srslte_sync_get_cp(srslte_sync_t *q); @@ -199,10 +223,6 @@ SRSLTE_API srslte_cp_t srslte_sync_get_cp(srslte_sync_t *q); SRSLTE_API void srslte_sync_set_cp(srslte_sync_t *q, srslte_cp_t cp); -/* Enable integer CFO detection */ -SRSLTE_API void srslte_sync_cfo_i_detec_en(srslte_sync_t *q, - bool enabled); - /* Enables/Disables SSS detection */ SRSLTE_API void srslte_sync_sss_en(srslte_sync_t *q, bool enabled); @@ -211,8 +231,6 @@ SRSLTE_API srslte_pss_synch_t* srslte_sync_get_cur_pss_obj(srslte_sync_t *q); SRSLTE_API bool srslte_sync_sss_detected(srslte_sync_t *q); -SRSLTE_API bool srslte_sync_sss_is_en(srslte_sync_t *q); - /* Enables/Disables CP detection */ SRSLTE_API void srslte_sync_cp_en(srslte_sync_t *q, bool enabled); diff --git a/lib/include/srslte/phy/ue/ue_sync.h b/lib/include/srslte/phy/ue/ue_sync.h index e5877dd23..11d7893c8 100644 --- a/lib/include/srslte/phy/ue/ue_sync.h +++ b/lib/include/srslte/phy/ue/ue_sync.h @@ -110,8 +110,12 @@ typedef struct SRSLTE_API { uint32_t sf_idx; bool decode_sss_on_track; - bool correct_cfo; - + + bool cfo_correct_enable; + float cfo_current_value; + float cfo_loop_bw; + float cfo_pss_tol; + uint32_t peak_idx; int next_rf_sample_offset; int last_sample_offset; @@ -165,6 +169,10 @@ SRSLTE_API void srslte_ue_sync_free(srslte_ue_sync_t *q); SRSLTE_API int srslte_ue_sync_set_cell(srslte_ue_sync_t *q, srslte_cell_t cell); +SRSLTE_API void srslte_ue_sync_cfo_reset(srslte_ue_sync_t *q); + +SRSLTE_API void srslte_ue_sync_reset(srslte_ue_sync_t *q); + SRSLTE_API int srslte_ue_sync_start_agc(srslte_ue_sync_t *q, double (set_gain_callback)(void*, double), float init_gain_value); @@ -175,34 +183,34 @@ SRSLTE_API void srslte_ue_sync_set_agc_period(srslte_ue_sync_t *q, uint32_t period); /* CAUTION: input_buffer MUST have space for 2 subframes */ -SRSLTE_API int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, +SRSLTE_API int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer); -SRSLTE_API int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, +SRSLTE_API int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE_MAX_PORTS]); 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); +SRSLTE_API void srslte_ue_sync_copy_cfo(srslte_ue_sync_t *q, + srslte_ue_sync_t *src_obj); + +SRSLTE_API void srslte_ue_sync_set_cfo_loop_bw(srslte_ue_sync_t *q, + float bw, + float pss_tol); 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); +SRSLTE_API void srslte_ue_sync_set_cfo_i_enable(srslte_ue_sync_t *q, + bool enable); -SRSLTE_API void srslte_ue_sync_reset(srslte_ue_sync_t *q); - -SRSLTE_API void srslte_ue_sync_set_N_id_2(srslte_ue_sync_t *q, +SRSLTE_API void srslte_ue_sync_set_N_id_2(srslte_ue_sync_t *q, uint32_t N_id_2); SRSLTE_API void srslte_ue_sync_decode_sss_on_track(srslte_ue_sync_t *q, bool enabled); -SRSLTE_API srslte_ue_sync_state_t srslte_ue_sync_get_state(srslte_ue_sync_t *q); - SRSLTE_API uint32_t srslte_ue_sync_get_sfidx(srslte_ue_sync_t *q); SRSLTE_API float srslte_ue_sync_get_cfo(srslte_ue_sync_t *q); @@ -218,8 +226,5 @@ SRSLTE_API void srslte_ue_sync_get_last_timestamp(srslte_ue_sync_t *q, srslte_timestamp_t *timestamp); - - - #endif // SYNC_FRAME_ diff --git a/lib/include/srslte/phy/utils/convolution.h b/lib/include/srslte/phy/utils/convolution.h index fcb321ce5..a93dfb955 100644 --- a/lib/include/srslte/phy/utils/convolution.h +++ b/lib/include/srslte/phy/utils/convolution.h @@ -66,18 +66,18 @@ SRSLTE_API int srslte_conv_fft_cc_replan(srslte_conv_fft_cc_t *q, SRSLTE_API void srslte_conv_fft_cc_free(srslte_conv_fft_cc_t *q); -SRSLTE_API uint32_t srslte_conv_fft_cc_run(srslte_conv_fft_cc_t *q, - cf_t *input, - cf_t *filter, +SRSLTE_API uint32_t srslte_conv_fft_cc_run(srslte_conv_fft_cc_t *q, + const cf_t *input, + const cf_t *filter, cf_t *output); -SRSLTE_API uint32_t srslte_conv_fft_cc_run_opt(srslte_conv_fft_cc_t *q, - cf_t *input, - cf_t *filter_freq, +SRSLTE_API uint32_t srslte_conv_fft_cc_run_opt(srslte_conv_fft_cc_t *q, + const cf_t *input, + const cf_t *filter_freq, cf_t *output); -SRSLTE_API uint32_t srslte_conv_cc(cf_t *input, - cf_t *filter, +SRSLTE_API uint32_t srslte_conv_cc(const cf_t *input, + const cf_t *filter, cf_t *output, uint32_t input_len, uint32_t filter_len); diff --git a/lib/include/srslte/phy/utils/simd.h b/lib/include/srslte/phy/utils/simd.h index cec003886..226e2ecae 100644 --- a/lib/include/srslte/phy/utils/simd.h +++ b/lib/include/srslte/phy/utils/simd.h @@ -172,7 +172,7 @@ typedef float32x4_t simd_f_t; #endif /* LV_HAVE_AVX512 */ /* Single precision Floating point functions */ -static inline simd_f_t srslte_simd_f_load(float *ptr) { +static inline simd_f_t srslte_simd_f_load(const float *ptr) { #ifdef LV_HAVE_AVX512 return _mm512_load_ps(ptr); #else /* LV_HAVE_AVX512 */ @@ -190,7 +190,7 @@ static inline simd_f_t srslte_simd_f_load(float *ptr) { #endif /* LV_HAVE_AVX512 */ } -static inline simd_f_t srslte_simd_f_loadu(float *ptr) { +static inline simd_f_t srslte_simd_f_loadu(const float *ptr) { #ifdef LV_HAVE_AVX512 return _mm512_loadu_ps(ptr); #else /* LV_HAVE_AVX512 */ @@ -477,7 +477,7 @@ typedef struct { #endif /* Complex Single precission Floating point functions */ -static inline simd_cf_t srslte_simd_cfi_load(cf_t *ptr) { +static inline simd_cf_t srslte_simd_cfi_load(const cf_t *ptr) { simd_cf_t ret; #ifdef LV_HAVE_AVX512 __m512 in1 = _mm512_load_ps((float*)(ptr)); @@ -513,7 +513,7 @@ static inline simd_cf_t srslte_simd_cfi_load(cf_t *ptr) { } /* Complex Single precission Floating point functions */ -static inline simd_cf_t srslte_simd_cfi_loadu(cf_t *ptr) { +static inline simd_cf_t srslte_simd_cfi_loadu(const cf_t *ptr) { simd_cf_t ret; #ifdef LV_HAVE_AVX512 __m512 in1 = _mm512_loadu_ps((float*)(ptr)); @@ -548,7 +548,7 @@ static inline simd_cf_t srslte_simd_cfi_loadu(cf_t *ptr) { return ret; } -static inline simd_cf_t srslte_simd_cf_load(float *re, float *im) { +static inline simd_cf_t srslte_simd_cf_load(const float *re, const float *im) { simd_cf_t ret; #ifdef LV_HAVE_AVX512 ret.re = _mm512_load_ps(re); @@ -572,7 +572,7 @@ static inline simd_cf_t srslte_simd_cf_load(float *re, float *im) { return ret; } -static inline simd_cf_t srslte_simd_cf_loadu(float *re, float *im) { +static inline simd_cf_t srslte_simd_cf_loadu(const float *re, const float *im) { simd_cf_t ret; #ifdef LV_HAVE_AVX512 ret.re = _mm512_loadu_ps(re); @@ -1074,7 +1074,7 @@ typedef int16x8_t simd_s_t; #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ -static inline simd_s_t srslte_simd_s_load(int16_t *ptr) { +static inline simd_s_t srslte_simd_s_load(const int16_t *ptr) { #ifdef LV_HAVE_AVX512 return _mm512_load_si512(ptr); #else /* LV_HAVE_AVX512 */ @@ -1092,7 +1092,7 @@ static inline simd_s_t srslte_simd_s_load(int16_t *ptr) { #endif /* LV_HAVE_AVX512 */ } -static inline simd_s_t srslte_simd_s_loadu(int16_t *ptr) { +static inline simd_s_t srslte_simd_s_loadu(const int16_t *ptr) { #ifdef LV_HAVE_AVX512 return _mm512_loadu_si512(ptr); #else /* LV_HAVE_AVX512 */ @@ -1267,7 +1267,7 @@ typedef } simd_c16_t; /* Fixed point precision (16-bit) functions */ -static inline simd_c16_t srslte_simd_c16i_load(c16_t *ptr) { +static inline simd_c16_t srslte_simd_c16i_load(const c16_t *ptr) { simd_c16_t ret; #ifdef LV_HAVE_AVX512 __m512i in1 = _mm512_load_si512((__m512i*)(ptr)); @@ -1296,7 +1296,7 @@ static inline simd_c16_t srslte_simd_c16i_load(c16_t *ptr) { return ret; } -static inline simd_c16_t srslte_simd_c16_load(int16_t *re, int16_t *im) { +static inline simd_c16_t srslte_simd_c16_load(const int16_t *re, const int16_t *im) { simd_c16_t ret; #ifdef LV_HAVE_AVX2 ret.re.m256 = _mm256_load_si256((__m256i*)(re)); @@ -1315,7 +1315,7 @@ static inline simd_c16_t srslte_simd_c16_load(int16_t *re, int16_t *im) { return ret; } -static inline simd_c16_t srslte_simd_c16_loadu(int16_t *re, int16_t *im) { +static inline simd_c16_t srslte_simd_c16_loadu(const int16_t *re, const int16_t *im) { simd_c16_t ret; #ifdef LV_HAVE_AVX2 ret.re.m256 = _mm256_loadu_si256((__m256i*)(re)); diff --git a/lib/include/srslte/phy/utils/vector.h b/lib/include/srslte/phy/utils/vector.h index 7dad585a0..a4028e495 100644 --- a/lib/include/srslte/phy/utils/vector.h +++ b/lib/include/srslte/phy/utils/vector.h @@ -55,100 +55,100 @@ extern "C" { /*logical operations */ -SRSLTE_API void srslte_vec_xor_bbb(int8_t *x,int8_t *y,int8_t *z, uint32_t len); +SRSLTE_API void srslte_vec_xor_bbb(int8_t *x,int8_t *y,int8_t *z, const uint32_t len); /** Return the sum of all the elements */ -SRSLTE_API float srslte_vec_acc_ff(float *x, uint32_t len); -SRSLTE_API cf_t srslte_vec_acc_cc(cf_t *x, uint32_t len); +SRSLTE_API float srslte_vec_acc_ff(const float *x, const uint32_t len); +SRSLTE_API cf_t srslte_vec_acc_cc(const cf_t *x, const uint32_t len); SRSLTE_API void *srslte_vec_malloc(uint32_t size); SRSLTE_API void *srslte_vec_realloc(void *ptr, uint32_t old_size, uint32_t new_size); /* print vectors */ -SRSLTE_API void srslte_vec_fprint_c(FILE *stream, cf_t *x, uint32_t len); -SRSLTE_API void srslte_vec_fprint_f(FILE *stream, float *x, uint32_t len); -SRSLTE_API void srslte_vec_fprint_b(FILE *stream, uint8_t *x, uint32_t len); -SRSLTE_API void srslte_vec_fprint_byte(FILE *stream, uint8_t *x, uint32_t len); -SRSLTE_API void srslte_vec_fprint_i(FILE *stream, int *x, uint32_t len); -SRSLTE_API void srslte_vec_fprint_s(FILE *stream, short *x, uint32_t len); -SRSLTE_API void srslte_vec_fprint_hex(FILE *stream, uint8_t *x, uint32_t len); -SRSLTE_API void srslte_vec_sprint_hex(char *str, uint8_t *x, uint32_t len); +SRSLTE_API void srslte_vec_fprint_c(FILE *stream, cf_t *x, const uint32_t len); +SRSLTE_API void srslte_vec_fprint_f(FILE *stream, float *x, const uint32_t len); +SRSLTE_API void srslte_vec_fprint_b(FILE *stream, uint8_t *x, const uint32_t len); +SRSLTE_API void srslte_vec_fprint_byte(FILE *stream, uint8_t *x, const uint32_t len); +SRSLTE_API void srslte_vec_fprint_i(FILE *stream, int *x, const uint32_t len); +SRSLTE_API void srslte_vec_fprint_s(FILE *stream, short *x, const uint32_t len); +SRSLTE_API void srslte_vec_fprint_hex(FILE *stream, uint8_t *x, const uint32_t len); +SRSLTE_API void srslte_vec_sprint_hex(char *str, uint8_t *x, const uint32_t len); /* Saves/loads a vector to a file */ -SRSLTE_API void srslte_vec_save_file(char *filename, void *buffer, uint32_t len); -SRSLTE_API void srslte_vec_load_file(char *filename, void *buffer, uint32_t len); +SRSLTE_API void srslte_vec_save_file(char *filename, const void *buffer, const uint32_t len); +SRSLTE_API void srslte_vec_load_file(char *filename, void *buffer, const uint32_t len); /* sum two vectors */ -SRSLTE_API void srslte_vec_sum_fff(float *x, float *y, float *z, uint32_t len); -SRSLTE_API void srslte_vec_sum_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len); -SRSLTE_API void srslte_vec_sub_sss(int16_t *x, int16_t *y, int16_t *z, uint32_t len); -SRSLTE_API void srslte_vec_sum_sss(int16_t *x, int16_t *y, int16_t *z, uint32_t len); +SRSLTE_API void srslte_vec_sum_fff(const float *x, const float *y, float *z, const uint32_t len); +SRSLTE_API void srslte_vec_sum_ccc(const cf_t *x, const cf_t *y, cf_t *z, const uint32_t len); +SRSLTE_API void srslte_vec_sub_sss(const int16_t *x, const int16_t *y, int16_t *z, const uint32_t len); +SRSLTE_API void srslte_vec_sum_sss(const int16_t *x, const int16_t *y, int16_t *z, const uint32_t len); /* substract two vectors z=x-y */ -SRSLTE_API void srslte_vec_sub_fff(float *x, float *y, float *z, uint32_t len); -SRSLTE_API void srslte_vec_sub_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len); +SRSLTE_API void srslte_vec_sub_fff(const float *x, const float *y, float *z, const uint32_t len); +SRSLTE_API void srslte_vec_sub_ccc(const cf_t *x, const cf_t *y, cf_t *z, const uint32_t len); /* scalar product */ -SRSLTE_API void srslte_vec_sc_prod_cfc(cf_t *x, float h, cf_t *z, uint32_t len); -SRSLTE_API void srslte_vec_sc_prod_ccc(cf_t *x, cf_t h, cf_t *z, uint32_t len); -SRSLTE_API void srslte_vec_sc_prod_fff(float *x, float h, float *z, uint32_t len); +SRSLTE_API void srslte_vec_sc_prod_cfc(const cf_t *x, const float h, cf_t *z, const uint32_t len); +SRSLTE_API void srslte_vec_sc_prod_ccc(const cf_t *x, const cf_t h, cf_t *z, const uint32_t len); +SRSLTE_API void srslte_vec_sc_prod_fff(const float *x, const float h, float *z, const uint32_t len); -SRSLTE_API void srslte_vec_convert_fi(float *x, int16_t *z, float scale, uint32_t len); -SRSLTE_API void srslte_vec_convert_if(int16_t *x, float *z, float scale, uint32_t len); +SRSLTE_API void srslte_vec_convert_fi(const float *x, const float scale, int16_t *z, const uint32_t len); +SRSLTE_API void srslte_vec_convert_if(const int16_t *x, const float scale, float *z, const uint32_t len); -SRSLTE_API void srslte_vec_lut_sss(short *x, unsigned short *lut, short *y, uint32_t len); +SRSLTE_API void srslte_vec_lut_sss(const short *x, const unsigned short *lut, short *y, const uint32_t len); /* vector product (element-wise) */ -SRSLTE_API void srslte_vec_prod_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len); -SRSLTE_API void srslte_vec_prod_ccc_split(float *x_re, float *x_im, float *y_re, float *y_im, float *z_re, float *z_im, uint32_t len); +SRSLTE_API void srslte_vec_prod_ccc(const cf_t *x, const cf_t *y, cf_t *z, const uint32_t len); +SRSLTE_API void srslte_vec_prod_ccc_split(const float *x_re, const float *x_im, const float *y_re, const float *y_im, float *z_re, float *z_im, const uint32_t len); /* vector product (element-wise) */ -SRSLTE_API void srslte_vec_prod_cfc(cf_t *x, float *y, cf_t *z, uint32_t len); +SRSLTE_API void srslte_vec_prod_cfc(const cf_t *x, const float *y, cf_t *z, const uint32_t len); /* conjugate vector product (element-wise) */ -SRSLTE_API void srslte_vec_prod_conj_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len); +SRSLTE_API void srslte_vec_prod_conj_ccc(const cf_t *x, const cf_t *y, cf_t *z, const uint32_t len); /* real vector product (element-wise) */ -SRSLTE_API void srslte_vec_prod_fff(float *x, float *y, float *z, uint32_t len); -SRSLTE_API void srslte_vec_prod_sss(int16_t *x, int16_t *y, int16_t *z, uint32_t len); +SRSLTE_API void srslte_vec_prod_fff(const float *x, const float *y, float *z, const uint32_t len); +SRSLTE_API void srslte_vec_prod_sss(const int16_t *x, const int16_t *y, int16_t *z, const uint32_t len); /* Dot-product */ -SRSLTE_API cf_t srslte_vec_dot_prod_cfc(cf_t *x, float *y, uint32_t len); -SRSLTE_API cf_t srslte_vec_dot_prod_ccc(cf_t *x, cf_t *y, uint32_t len); -SRSLTE_API cf_t srslte_vec_dot_prod_conj_ccc(cf_t *x, cf_t *y, uint32_t len); -SRSLTE_API float srslte_vec_dot_prod_fff(float *x, float *y, uint32_t len); -SRSLTE_API int32_t srslte_vec_dot_prod_sss(int16_t *x, int16_t *y, uint32_t len); +SRSLTE_API cf_t srslte_vec_dot_prod_cfc(const cf_t *x, const float *y, const uint32_t len); +SRSLTE_API cf_t srslte_vec_dot_prod_ccc(const cf_t *x, const cf_t *y, const uint32_t len); +SRSLTE_API cf_t srslte_vec_dot_prod_conj_ccc(const cf_t *x, const cf_t *y, const uint32_t len); +SRSLTE_API float srslte_vec_dot_prod_fff(const float *x, const float *y, const uint32_t len); +SRSLTE_API int32_t srslte_vec_dot_prod_sss(const int16_t *x, const int16_t *y, const uint32_t len); /* z=x/y vector division (element-wise) */ -SRSLTE_API void srslte_vec_div_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len); -SRSLTE_API void srslte_vec_div_cfc(cf_t *x, float *y, cf_t *z, uint32_t len); -SRSLTE_API void srslte_vec_div_fff(float *x, float *y, float *z, uint32_t len); +SRSLTE_API void srslte_vec_div_ccc(const cf_t *x, const cf_t *y, cf_t *z, const uint32_t len); +SRSLTE_API void srslte_vec_div_cfc(const cf_t *x, const float *y, cf_t *z, const uint32_t len); +SRSLTE_API void srslte_vec_div_fff(const float *x, const float *y, float *z, const uint32_t len); /* conjugate */ -SRSLTE_API void srslte_vec_conj_cc(cf_t *x, cf_t *y, uint32_t len); +SRSLTE_API void srslte_vec_conj_cc(const cf_t *x, cf_t *y, const uint32_t len); /* average vector power */ -SRSLTE_API float srslte_vec_avg_power_cf(cf_t *x, uint32_t len); +SRSLTE_API float srslte_vec_avg_power_cf(const cf_t *x, const uint32_t len); /* Correlation between complex vectors x and y */ -SRSLTE_API float srslte_vec_corr_ccc(cf_t *x, cf_t *y, uint32_t len); +SRSLTE_API float srslte_vec_corr_ccc(const cf_t *x, cf_t *y, const uint32_t len); /* return the index of the maximum value in the vector */ -SRSLTE_API uint32_t srslte_vec_max_fi(float *x, uint32_t len); -SRSLTE_API uint32_t srslte_vec_max_abs_ci(cf_t *x, uint32_t len); +SRSLTE_API uint32_t srslte_vec_max_fi(const float *x, const uint32_t len); +SRSLTE_API uint32_t srslte_vec_max_abs_ci(const cf_t *x, const uint32_t len); /* quantify vector of floats or int16 and convert to uint8_t */ -SRSLTE_API void srslte_vec_quant_fuc(float *in, uint8_t *out, float gain, float offset, float clip, uint32_t len); -SRSLTE_API void srslte_vec_quant_suc(int16_t *in, uint8_t *out, float gain, int16_t offset, int16_t clip, uint32_t len); +SRSLTE_API void srslte_vec_quant_fuc(const float *in, uint8_t *out, const float gain, const float offset, const float clip, const uint32_t len); +SRSLTE_API void srslte_vec_quant_suc(const int16_t *in, uint8_t *out, const float gain, const int16_t offset, const int16_t clip, const uint32_t len); /* magnitude of each vector element */ -SRSLTE_API void srslte_vec_abs_cf(cf_t *x, float *abs, uint32_t len); -SRSLTE_API void srslte_vec_abs_square_cf(cf_t *x, float *abs_square, uint32_t len); +SRSLTE_API void srslte_vec_abs_cf(const cf_t *x, float *abs, const uint32_t len); +SRSLTE_API void srslte_vec_abs_square_cf(const cf_t *x, float *abs_square, const uint32_t len); /* Copy 256 bit aligned vector */ -SRSLTE_API void srs_vec_cf_cpy(cf_t *src, cf_t *dst, int len); +SRSLTE_API void srs_vec_cf_cpy(const cf_t *src, cf_t *dst, const int len); #ifdef __cplusplus } diff --git a/lib/include/srslte/phy/utils/vector_simd.h b/lib/include/srslte/phy/utils/vector_simd.h index 468c5e11a..54ac55f98 100644 --- a/lib/include/srslte/phy/utils/vector_simd.h +++ b/lib/include/srslte/phy/utils/vector_simd.h @@ -55,77 +55,78 @@ extern "C" { /*SIMD Logical operations*/ -SRSLTE_API void srslte_vec_xor_bbb_simd(int8_t *x, int8_t *y, int8_t *z, int len); +SRSLTE_API void srslte_vec_xor_bbb_simd(const int8_t *x, const int8_t *y, int8_t *z, int len); /* SIMD Basic vector math */ -SRSLTE_API void srslte_vec_sum_sss_simd(int16_t *x, int16_t *y, int16_t *z, int len); +SRSLTE_API void srslte_vec_sum_sss_simd(const int16_t *x, const int16_t *y, int16_t *z, int len); -SRSLTE_API void srslte_vec_sub_sss_simd(int16_t *x, int16_t *y, int16_t *z, int len); +SRSLTE_API void srslte_vec_sub_sss_simd(const int16_t *x, const int16_t *y, int16_t *z, int len); -SRSLTE_API float srslte_vec_acc_ff_simd(float *x, int len); +SRSLTE_API float srslte_vec_acc_ff_simd(const float *x, int len); -SRSLTE_API cf_t srslte_vec_acc_cc_simd(cf_t *x, int len); +SRSLTE_API cf_t srslte_vec_acc_cc_simd(const cf_t *x, int len); -SRSLTE_API void srslte_vec_add_fff_simd(float *x, float *y, float *z, int len); +SRSLTE_API void srslte_vec_add_fff_simd(const float *x, const float *y, float *z, int len); -SRSLTE_API void srslte_vec_sub_fff_simd(float *x, float *y, float *z, int len); +SRSLTE_API void srslte_vec_sub_fff_simd(const float *x, const float *y, float *z, int len); /* SIMD Vector Scalar Product */ -SRSLTE_API void srslte_vec_sc_prod_cfc_simd(const cf_t *x,const float h,cf_t *y,const int len); +SRSLTE_API void srslte_vec_sc_prod_cfc_simd(const cf_t *x, const float h,cf_t *y, const int len); -SRSLTE_API void srslte_vec_sc_prod_fff_simd(float *x, float h, float *z, int len); +SRSLTE_API void srslte_vec_sc_prod_fff_simd(const float *x, const float h, float *z, const int len); -SRSLTE_API void srslte_vec_sc_prod_ccc_simd(cf_t *x, cf_t h, cf_t *z, int len); +SRSLTE_API void srslte_vec_sc_prod_ccc_simd(const cf_t *x, const cf_t h, cf_t *z, const int len); /* SIMD Vector Product */ -SRSLTE_API void srslte_vec_prod_ccc_split_simd(float *a_re, float *a_im, float *b_re, float *b_im, float *r_re, float *r_im, int len); +SRSLTE_API void srslte_vec_prod_ccc_split_simd(const float *a_re, const float *a_im, const float *b_re, const float *b_im, + float *r_re, float *r_im, const int len); -SRSLTE_API void srslte_vec_prod_ccc_c16_simd(int16_t *a_re, int16_t *a_im, int16_t *b_re, int16_t *b_im, int16_t *r_re, - int16_t *r_im, int len); +SRSLTE_API void srslte_vec_prod_ccc_c16_simd(const int16_t *a_re, const int16_t *a_im, const int16_t *b_re, const int16_t *b_im, + int16_t *r_re, int16_t *r_im, const int len); -SRSLTE_API void srslte_vec_prod_sss_simd(int16_t *x, int16_t *y, int16_t *z, int len); +SRSLTE_API void srslte_vec_prod_sss_simd(const int16_t *x, const int16_t *y, int16_t *z, const int len); -SRSLTE_API void srslte_vec_prod_cfc_simd(cf_t *x, float *y, cf_t *z, int len); +SRSLTE_API void srslte_vec_prod_cfc_simd(const cf_t *x, const float *y, cf_t *z, const int len); -SRSLTE_API void srslte_vec_prod_fff_simd(float *x, float *y, float *z, int len); +SRSLTE_API void srslte_vec_prod_fff_simd(const float *x, const float *y, float *z, const int len); -SRSLTE_API void srslte_vec_prod_ccc_simd(cf_t *x,cf_t *y, cf_t *z, int len); +SRSLTE_API void srslte_vec_prod_ccc_simd(const cf_t *x, const cf_t *y, cf_t *z, const int len); -SRSLTE_API void srslte_vec_prod_conj_ccc_simd(cf_t *x,cf_t *y, cf_t *z, int len); +SRSLTE_API void srslte_vec_prod_conj_ccc_simd(const cf_t *x, const cf_t *y, cf_t *z, const int len); /* SIMD Division */ -SRSLTE_API void srslte_vec_div_ccc_simd(cf_t *x,cf_t *y, cf_t *z, int len); +SRSLTE_API void srslte_vec_div_ccc_simd(const cf_t *x, const cf_t *y, cf_t *z, const int len); -SRSLTE_API void srslte_vec_div_cfc_simd(cf_t *x, float *y, cf_t *z, int len); +SRSLTE_API void srslte_vec_div_cfc_simd(const cf_t *x, const float *y, cf_t *z, const int len); -SRSLTE_API void srslte_vec_div_fff_simd(float *x, float *y, float *z, int len); +SRSLTE_API void srslte_vec_div_fff_simd(const float *x, const float *y, float *z, const int len); /* SIMD Dot product */ -SRSLTE_API cf_t srslte_vec_dot_prod_conj_ccc_simd(cf_t *x, cf_t *y, int len); +SRSLTE_API cf_t srslte_vec_dot_prod_conj_ccc_simd(const cf_t *x, const cf_t *y, const int len); -SRSLTE_API cf_t srslte_vec_dot_prod_ccc_simd(cf_t *x, cf_t *y, int len); +SRSLTE_API cf_t srslte_vec_dot_prod_ccc_simd(const cf_t *x, const cf_t *y, const int len); -SRSLTE_API c16_t srslte_vec_dot_prod_ccc_c16i_simd(c16_t *x, c16_t *y, int len); +SRSLTE_API c16_t srslte_vec_dot_prod_ccc_c16i_simd(const c16_t *x, const c16_t *y, const int len); -SRSLTE_API int srslte_vec_dot_prod_sss_simd(int16_t *x, int16_t *y, int len); +SRSLTE_API int srslte_vec_dot_prod_sss_simd(const int16_t *x, const int16_t *y, const int len); /* SIMD Modulus functions */ -SRSLTE_API void srslte_vec_abs_cf_simd(cf_t *x, float *z, int len); +SRSLTE_API void srslte_vec_abs_cf_simd(const cf_t *x, float *z, const int len); -SRSLTE_API void srslte_vec_abs_square_cf_simd(cf_t *x, float *z, int len); +SRSLTE_API void srslte_vec_abs_square_cf_simd(const cf_t *x, float *z, const int len); /* Other Functions */ -SRSLTE_API void srslte_vec_lut_sss_simd(short *x, unsigned short *lut, short *y, int len); +SRSLTE_API void srslte_vec_lut_sss_simd(const short *x, const unsigned short *lut, short *y, const int len); -SRSLTE_API void srslte_vec_convert_fi_simd(float *x, int16_t *z, float scale, int len); +SRSLTE_API void srslte_vec_convert_fi_simd(const float *x, int16_t *z, const float scale, const int len); -SRSLTE_API void srslte_vec_cp_simd(cf_t *src, cf_t *dst, int len); +SRSLTE_API void srslte_vec_cp_simd(const cf_t *src, cf_t *dst, int len); /* SIMD Find Max functions */ -SRSLTE_API uint32_t srslte_vec_max_fi_simd(float *x, int len); +SRSLTE_API uint32_t srslte_vec_max_fi_simd(const float *x, const int len); -SRSLTE_API uint32_t srslte_vec_max_ci_simd(cf_t *x, int len); +SRSLTE_API uint32_t srslte_vec_max_ci_simd(const cf_t *x, const int len); #ifdef __cplusplus } diff --git a/lib/src/phy/dft/dft_fftw.c b/lib/src/phy/dft/dft_fftw.c index 9d6898117..e6eb70ecf 100644 --- a/lib/src/phy/dft/dft_fftw.c +++ b/lib/src/phy/dft/dft_fftw.c @@ -245,7 +245,7 @@ static void copy_post(uint8_t *dst, uint8_t *src, int size_d, int len, } } -void srslte_dft_run(srslte_dft_plan_t *plan, void *in, void *out) { +void srslte_dft_run(srslte_dft_plan_t *plan, const void *in, void *out) { if(plan->mode == SRSLTE_DFT_COMPLEX) { srslte_dft_run_c(plan,in,out); } else { @@ -253,11 +253,11 @@ void srslte_dft_run(srslte_dft_plan_t *plan, void *in, void *out) { } } -void srslte_dft_run_c_zerocopy(srslte_dft_plan_t *plan, cf_t *in, cf_t *out) { - fftwf_execute_dft(plan->p, in, out); +void srslte_dft_run_c_zerocopy(srslte_dft_plan_t *plan, const cf_t *in, cf_t *out) { + fftwf_execute_dft(plan->p, (cf_t*) in, out); } -void srslte_dft_run_c(srslte_dft_plan_t *plan, cf_t *in, cf_t *out) { +void srslte_dft_run_c(srslte_dft_plan_t *plan, const cf_t *in, cf_t *out) { float norm; int i; fftwf_complex *f_out = plan->out; @@ -286,7 +286,7 @@ void srslte_dft_run_guru_c(srslte_dft_plan_t *plan) { } } -void srslte_dft_run_r(srslte_dft_plan_t *plan, float *in, float *out) { +void srslte_dft_run_r(srslte_dft_plan_t *plan, const float *in, float *out) { float norm; int i; int len = plan->size; diff --git a/lib/src/phy/modem/demod_soft.c b/lib/src/phy/modem/demod_soft.c index 259a12271..0ea3ce938 100644 --- a/lib/src/phy/modem/demod_soft.c +++ b/lib/src/phy/modem/demod_soft.c @@ -57,11 +57,11 @@ void demod_bpsk_lte(const cf_t *symbols, float *llr, int nsymbols) { } void demod_qpsk_lte_s(const cf_t *symbols, short *llr, int nsymbols) { - srslte_vec_convert_fi((float*) symbols, llr, -SCALE_SHORT_CONV_QPSK*sqrt(2), nsymbols*2); + srslte_vec_convert_fi((const float*) symbols, -SCALE_SHORT_CONV_QPSK*sqrt(2), llr, nsymbols*2); } void demod_qpsk_lte(const cf_t *symbols, float *llr, int nsymbols) { - srslte_vec_sc_prod_fff((float*) symbols, -sqrt(2), llr, nsymbols*2); + srslte_vec_sc_prod_fff((const float*) symbols, -sqrt(2), llr, nsymbols*2); } void demod_16qam_lte(const cf_t *symbols, float *llr, int nsymbols) { diff --git a/lib/src/phy/resampling/test/resample_arb_bench.c b/lib/src/phy/resampling/test/resample_arb_bench.c index 773291913..e9ef3c442 100644 --- a/lib/src/phy/resampling/test/resample_arb_bench.c +++ b/lib/src/phy/resampling/test/resample_arb_bench.c @@ -50,7 +50,7 @@ int main(int argc, char **argv) { clock_t start = clock(), diff; for(int xx = 0; xxrx_rate, meta.timestamp, secs, frac_secs); - srslte_vec_convert_if(handler->rx_buffer, data, 2048, 2*nsamples); + srslte_vec_convert_if(handler->rx_buffer, 2048, data, 2*nsamples); return nsamples; } @@ -506,7 +506,7 @@ int rf_blade_send_timed(void *h, return -1; } - srslte_vec_convert_fi(data, handler->tx_buffer, 2048, 2*nsamples); + srslte_vec_convert_fi(data, 2048, handler->tx_buffer, 2*nsamples); memset(&meta, 0, sizeof(meta)); if (is_start_of_burst) { diff --git a/lib/src/phy/rf/rf_utils.c b/lib/src/phy/rf/rf_utils.c index ce288b5c5..f97784305 100644 --- a/lib/src/phy/rf/rf_utils.c +++ b/lib/src/phy/rf/rf_utils.c @@ -123,12 +123,7 @@ int rf_mib_decoder(srslte_rf_t *rf, uint32_t nof_rx_antennas,cell_search_cfg_t * INFO("Starting receiver...\n", 0); srslte_rf_start_rx_stream(rf); - - // Set CFO if available - if (cfo) { - srslte_ue_sync_set_cfo(&ue_mib.ue_sync, *cfo); - } - + /* Find and decody MIB */ ret = srslte_ue_mib_sync_decode(&ue_mib, config->max_frames_pbch, bch_payload, &cell->nof_ports, NULL); if (ret < 0) { diff --git a/lib/src/phy/sync/cfo.c b/lib/src/phy/sync/cfo.c index 34498ce58..44c795c19 100644 --- a/lib/src/phy/sync/cfo.c +++ b/lib/src/phy/sync/cfo.c @@ -83,7 +83,7 @@ int srslte_cfo_resize(srslte_cfo_t *h, uint32_t samples) { return SRSLTE_SUCCESS; } -void srslte_cfo_correct(srslte_cfo_t *h, cf_t *input, cf_t *output, float freq) { +void srslte_cfo_correct(srslte_cfo_t *h, const cf_t *input, cf_t *output, float freq) { if (fabs(h->last_freq - freq) > h->tol) { h->last_freq = freq; srslte_cexptab_gen(&h->tab, h->cur_cexp, h->last_freq, h->nsamples); diff --git a/lib/src/phy/sync/cp.c b/lib/src/phy/sync/cp.c index a282f6dfd..80d0a2179 100644 --- a/lib/src/phy/sync/cp.c +++ b/lib/src/phy/sync/cp.c @@ -63,14 +63,14 @@ int srslte_cp_synch_resize(srslte_cp_synch_t *q, uint32_t symbol_sz) } -uint32_t srslte_cp_synch(srslte_cp_synch_t *q, cf_t *input, uint32_t max_offset, uint32_t nof_symbols, uint32_t cp_len) +uint32_t srslte_cp_synch(srslte_cp_synch_t *q, const cf_t *input, uint32_t max_offset, uint32_t nof_symbols, uint32_t cp_len) { if (max_offset > q->symbol_sz) { max_offset = q->symbol_sz; } for (int i=0;icorr[i] = 0; - cf_t *inputPtr = input; + const cf_t *inputPtr = input; for (int n=0;ncorr[i] += srslte_vec_dot_prod_conj_ccc(&inputPtr[i], &inputPtr[i+q->symbol_sz], cplen)/nof_symbols; diff --git a/lib/src/phy/sync/find_sss.c b/lib/src/phy/sync/find_sss.c index 082aee52a..70b300bd3 100644 --- a/lib/src/phy/sync/find_sss.c +++ b/lib/src/phy/sync/find_sss.c @@ -68,7 +68,7 @@ static void corr_all_sz_partial(cf_t z[SRSLTE_SSS_N], float s[SRSLTE_SSS_N][SRSL } } -static void extract_pair_sss(srslte_sss_synch_t *q, cf_t *input, cf_t *ce, cf_t y[2][SRSLTE_SSS_N]) { +static void extract_pair_sss(srslte_sss_synch_t *q, const cf_t *input, cf_t *ce, cf_t y[2][SRSLTE_SSS_N]) { cf_t input_fft[SRSLTE_SYMBOL_SZ_MAX]; srslte_dft_run_c(&q->dftp_input, input, input_fft); @@ -88,7 +88,7 @@ static void extract_pair_sss(srslte_sss_synch_t *q, cf_t *input, cf_t *ce, cf_t } -int srslte_sss_synch_m0m1_diff(srslte_sss_synch_t *q, cf_t *input, uint32_t *m0, float *m0_value, +int srslte_sss_synch_m0m1_diff(srslte_sss_synch_t *q, const cf_t *input, uint32_t *m0, float *m0_value, uint32_t *m1, float *m1_value) { return srslte_sss_synch_m0m1_diff_coh(q, input, NULL, m0, m0_value, m1, m1_value); @@ -102,7 +102,7 @@ int srslte_sss_synch_m0m1_diff(srslte_sss_synch_t *q, cf_t *input, uint32_t *m0, * */ -int srslte_sss_synch_m0m1_diff_coh(srslte_sss_synch_t *q, cf_t *input, cf_t ce[2*SRSLTE_SSS_N], uint32_t *m0, float *m0_value, +int srslte_sss_synch_m0m1_diff_coh(srslte_sss_synch_t *q, const cf_t *input, cf_t ce[2*SRSLTE_SSS_N], uint32_t *m0, float *m0_value, uint32_t *m1, float *m1_value) { @@ -145,7 +145,7 @@ int srslte_sss_synch_m0m1_diff_coh(srslte_sss_synch_t *q, cf_t *input, cf_t ce[2 * Jung-In Kim, Jung-Su Han, Hee-Jin Roh and Hyung-Jin Choi */ -int srslte_sss_synch_m0m1_partial(srslte_sss_synch_t *q, cf_t *input, uint32_t M, cf_t ce[2*SRSLTE_SSS_N], uint32_t *m0, float *m0_value, +int srslte_sss_synch_m0m1_partial(srslte_sss_synch_t *q, const cf_t *input, uint32_t M, cf_t ce[2*SRSLTE_SSS_N], uint32_t *m0, float *m0_value, uint32_t *m1, float *m1_value) { diff --git a/lib/src/phy/sync/pss.c b/lib/src/phy/sync/pss.c index 411579d7c..d93fe0896 100644 --- a/lib/src/phy/sync/pss.c +++ b/lib/src/phy/sync/pss.c @@ -119,7 +119,7 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, buffer_size = fft_size + frame_size + 1; - q->filter_pss_enable = true; + q->filter_pss_enable = false; if(q->decimate > 1) { int filter_order = 3; @@ -417,6 +417,37 @@ void srslte_pss_synch_set_ema_alpha(srslte_pss_synch_t *q, float alpha) { q->ema_alpha = alpha; } +float compute_peak_sidelobe(srslte_pss_synch_t *q, uint32_t corr_peak_pos, uint32_t conv_output_len) +{ + // Find end of peak lobe to the right + int pl_ub = corr_peak_pos+1; + while(q->conv_output_avg[pl_ub+1] <= q->conv_output_avg[pl_ub] && pl_ub < conv_output_len) { + pl_ub ++; + } + // Find end of peak lobe to the left + int pl_lb; + if (corr_peak_pos > 2) { + pl_lb = corr_peak_pos-1; + while(q->conv_output_avg[pl_lb-1] <= q->conv_output_avg[pl_lb] && pl_lb > 1) { + pl_lb --; + } + } else { + pl_lb = 0; + } + + int sl_distance_right = conv_output_len-1-pl_ub; + if (sl_distance_right < 0) { + sl_distance_right = 0; + } + int sl_distance_left = pl_lb; + + int sl_right = pl_ub+srslte_vec_max_fi(&q->conv_output_avg[pl_ub], sl_distance_right); + int sl_left = srslte_vec_max_fi(q->conv_output_avg, sl_distance_left); + float side_lobe_value = SRSLTE_MAX(q->conv_output_avg[sl_right], q->conv_output_avg[sl_left]); + + return q->conv_output_avg[corr_peak_pos]/side_lobe_value; +} + /** Performs time-domain PSS correlation. * Returns the index of the PSS correlation peak in a subframe. * The frame starts at corr_peak_pos-subframe_size/2. @@ -424,7 +455,7 @@ void srslte_pss_synch_set_ema_alpha(srslte_pss_synch_t *q, float alpha) { * * Input buffer must be subframe_size long. */ -int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_peak_value) +int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, const cf_t *input, float *corr_peak_value) { int ret = SRSLTE_ERROR_INVALID_INPUTS; @@ -448,16 +479,13 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe */ if (q->frame_size >= q->fft_size) { #ifdef CONVOLUTION_FFT - memcpy(q->tmp_input, input, (q->frame_size * q->decimate) * sizeof(cf_t)); - if(q->decimate > 1) - { - srslte_filt_decim_cc_execute(&(q->filter), q->tmp_input, q->filter.downsampled_input, q->filter.filter_output , (q->frame_size * q->decimate)); - conv_output_len = srslte_conv_fft_cc_run_opt(&q->conv_fft, q->filter.filter_output,q->pss_signal_freq_full[q->N_id_2], q->conv_output); - } - else - { - conv_output_len = srslte_conv_fft_cc_run_opt(&q->conv_fft, q->tmp_input, q->pss_signal_freq_full[q->N_id_2], q->conv_output); - } + memcpy(q->tmp_input, input, (q->frame_size * q->decimate) * sizeof(cf_t)); + if(q->decimate > 1) { + srslte_filt_decim_cc_execute(&(q->filter), q->tmp_input, q->filter.downsampled_input, q->filter.filter_output , (q->frame_size * q->decimate)); + conv_output_len = srslte_conv_fft_cc_run_opt(&q->conv_fft, q->filter.filter_output,q->pss_signal_freq_full[q->N_id_2], q->conv_output); + } else { + conv_output_len = srslte_conv_fft_cc_run_opt(&q->conv_fft, q->tmp_input, q->pss_signal_freq_full[q->N_id_2], q->conv_output); + } #else conv_output_len = srslte_conv_cc(input, q->pss_signal_time[q->N_id_2], q->conv_output, q->frame_size, q->fft_size); @@ -469,13 +497,10 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe conv_output_len = q->frame_size; } + // Compute modulus square + srslte_vec_abs_square_cf(q->conv_output, q->conv_output_abs, conv_output_len-1); - #ifdef SRSLTE_PSS_ABS_SQUARE - srslte_vec_abs_square_cf(q->conv_output, q->conv_output_abs, conv_output_len-1); - #else - srslte_vec_abs_cf(q->conv_output, q->conv_output_abs, conv_output_len-1); - #endif - + // If enabled, average the absolute value from previous calls if (q->ema_alpha < 1.0 && q->ema_alpha > 0.0) { srslte_vec_sc_prod_fff(q->conv_output_abs, q->ema_alpha, q->conv_output_abs, conv_output_len-1); srslte_vec_sc_prod_fff(q->conv_output_avg, 1-q->ema_alpha, q->conv_output_avg, conv_output_len-1); @@ -484,6 +509,7 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe } else { memcpy(q->conv_output_avg, q->conv_output_abs, sizeof(float)*(conv_output_len-1)); } + /* Find maximum of the absolute value of the correlation */ corr_peak_pos = srslte_vec_max_fi(q->conv_output_avg, conv_output_len-1); @@ -491,39 +517,8 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe q->peak_value = q->conv_output_avg[corr_peak_pos]; #ifdef SRSLTE_PSS_RETURN_PSR - // Find second side lobe - - // Find end of peak lobe to the right - int pl_ub = corr_peak_pos+1; - while(q->conv_output_avg[pl_ub+1] <= q->conv_output_avg[pl_ub] && pl_ub < conv_output_len) { - pl_ub ++; - } - // Find end of peak lobe to the left - int pl_lb; - if (corr_peak_pos > 2) { - pl_lb = corr_peak_pos-1; - while(q->conv_output_avg[pl_lb-1] <= q->conv_output_avg[pl_lb] && pl_lb > 1) { - pl_lb --; - } - } else { - pl_lb = 0; - } - - int sl_distance_right = conv_output_len-1-pl_ub; - if (sl_distance_right < 0) { - sl_distance_right = 0; - } - int sl_distance_left = pl_lb; - - int sl_right = pl_ub+srslte_vec_max_fi(&q->conv_output_avg[pl_ub], sl_distance_right); - int sl_left = srslte_vec_max_fi(q->conv_output_avg, sl_distance_left); - float side_lobe_value = SRSLTE_MAX(q->conv_output_avg[sl_right], q->conv_output_avg[sl_left]); if (corr_peak_value) { - *corr_peak_value = q->conv_output_avg[corr_peak_pos]/side_lobe_value; - - if (*corr_peak_value < 10) - DEBUG("peak_pos=%2d, pl_ub=%2d, pl_lb=%2d, sl_right: %2d, sl_left: %2d, PSR: %.2f/%.2f=%.2f\n", corr_peak_pos, pl_ub, pl_lb, - sl_right,sl_left, q->conv_output_avg[corr_peak_pos], side_lobe_value,*corr_peak_value); + *corr_peak_value = compute_peak_sidelobe(q, corr_peak_pos, conv_output_len); } #else if (corr_peak_value) { @@ -531,14 +526,12 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe } #endif - if(q->decimate >1) - { - int decimation_correction = (q->filter.num_taps - 2); - corr_peak_pos = corr_peak_pos - decimation_correction; - corr_peak_pos = corr_peak_pos*q->decimate; + if(q->decimate >1) { + int decimation_correction = (q->filter.num_taps - 2); + corr_peak_pos = corr_peak_pos - decimation_correction; + corr_peak_pos = corr_peak_pos*q->decimate; } - if (q->frame_size >= q->fft_size) { ret = (int) corr_peak_pos; } else { @@ -552,7 +545,7 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe * input signal is in the time-domain. * ce is the returned frequency-domain channel estimates. */ -int srslte_pss_synch_chest(srslte_pss_synch_t *q, cf_t *input, cf_t ce[SRSLTE_PSS_LEN]) { +int srslte_pss_synch_chest(srslte_pss_synch_t *q, const cf_t *input, cf_t ce[SRSLTE_PSS_LEN]) { int ret = SRSLTE_ERROR_INVALID_INPUTS; cf_t input_fft[SRSLTE_SYMBOL_SZ_MAX]; @@ -577,7 +570,7 @@ int srslte_pss_synch_chest(srslte_pss_synch_t *q, cf_t *input, cf_t ce[SRSLTE_PS } // Frequency-domain filtering of the central 64 sub-carriers -void srslte_pss_synch_filter(srslte_pss_synch_t *q, cf_t *input, cf_t *output) +void srslte_pss_synch_filter(srslte_pss_synch_t *q, const cf_t *input, cf_t *output) { srslte_dft_run_c(&q->dftp_input, input, q->tmp_fft); @@ -593,14 +586,14 @@ void srslte_pss_synch_filter(srslte_pss_synch_t *q, cf_t *input, cf_t *output) * Source: An Efficient CFO Estimation Algorithm for the Downlink of 3GPP-LTE * Feng Wang and Yu Zhu */ -float srslte_pss_synch_cfo_compute(srslte_pss_synch_t* q, cf_t *pss_recv) { +float srslte_pss_synch_cfo_compute(srslte_pss_synch_t* q, const cf_t *pss_recv) { cf_t y0, y1; - cf_t *pss_ptr = pss_recv; + const cf_t *pss_ptr = pss_recv; if (q->filter_pss_enable) { srslte_pss_synch_filter(q, pss_recv, q->tmp_fft); - pss_ptr = q->tmp_fft; + pss_ptr = (const cf_t*) q->tmp_fft; } y0 = srslte_vec_dot_prod_ccc(q->pss_signal_time[q->N_id_2], pss_ptr, q->fft_size/2); diff --git a/lib/src/phy/sync/sync.c b/lib/src/phy/sync/sync.c index d1a477046..d14419965 100644 --- a/lib/src/phy/sync/sync.c +++ b/lib/src/phy/sync/sync.c @@ -37,11 +37,10 @@ #include "srslte/phy/utils/vector.h" #include "srslte/phy/sync/cfo.h" -#define MEANPEAK_EMA_ALPHA 0.1 -#define CFO_EMA_ALPHA 0.1 -#define CP_EMA_ALPHA 0.1 +#define CFO_EMA_ALPHA 0.1 +#define CP_EMA_ALPHA 0.1 -#define DEFAULT_CFO_TOL 50.0 // Hz +#define DEFAULT_CFO_TOL 50.0 // Hz static bool fft_size_isvalid(uint32_t fft_size) { if (fft_size >= SRSLTE_SYNC_FFT_SZ_MIN && fft_size <= SRSLTE_SYNC_FFT_SZ_MAX && (fft_size%64) == 0) { @@ -51,13 +50,12 @@ static bool fft_size_isvalid(uint32_t fft_size) { } } - - int srslte_sync_init(srslte_sync_t *q, uint32_t frame_size, uint32_t max_offset, uint32_t fft_size) { return srslte_sync_init_decim(q, frame_size, max_offset, fft_size, 1); } -int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_offset, uint32_t fft_size, int decimate) { +int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_offset, uint32_t fft_size, int decimate) +{ int ret = SRSLTE_ERROR_INVALID_INPUTS; @@ -67,31 +65,34 @@ int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_o { ret = SRSLTE_ERROR; bzero(q, sizeof(srslte_sync_t)); - q->detect_cp = true; - q->sss_en = true; - q->mean_cfo = 0; - q->mean_cfo2 = 0; - q->N_id_2 = 1000; + + q->N_id_2 = 1000; q->N_id_1 = 1000; - q->cfo_i = 0; - q->find_cfo_i = false; - q->find_cfo_i_initiated = false; + q->cfo_ema_alpha = CFO_EMA_ALPHA; + q->sss_alg = SSS_FULL; + + q->detect_cp = true; + q->sss_en = true; + q->cfo_pss_enable = false; + q->cfo_cp_enable = false; + q->cfo_i_initiated = false; + q->pss_filtering_enabled = false; + q->sss_filtering_enabled = false; + q->fft_size = fft_size; q->frame_size = frame_size; q->max_offset = max_offset; - q->sss_alg = SSS_FULL; q->max_frame_size = frame_size; - q->mean_cfo_isunset = true; - q->mean_cfo2_isunset = true; - q->enable_cfo_corr = true; - if (srslte_cfo_init(&q->cfocorr, q->frame_size)) { + srslte_sync_cfo_reset(q); + + if (srslte_cfo_init(&q->cfo_corr_frame, q->frame_size)) { fprintf(stderr, "Error initiating CFO\n"); goto clean_exit; } - if (srslte_cfo_init(&q->cfocorr2, q->frame_size)) { + if (srslte_cfo_init(&q->cfo_corr_symbol, q->fft_size)) { fprintf(stderr, "Error initiating CFO\n"); goto clean_exit; } @@ -147,18 +148,23 @@ clean_exit: return ret; } -void srslte_sync_free(srslte_sync_t *q) { +void srslte_sync_free(srslte_sync_t *q) +{ if (q) { + srslte_pss_synch_free(&q->pss); srslte_sss_synch_free(&q->sss); - srslte_cfo_free(&q->cfocorr); - srslte_cfo_free(&q->cfocorr2); + srslte_cfo_free(&q->cfo_corr_frame); + srslte_cfo_free(&q->cfo_corr_symbol); srslte_cp_synch_free(&q->cp_synch); - for (int i=0;i<2;i++) { - if (q->cfo_i_corr[i]) { - free(q->cfo_i_corr[i]); + + if (q->cfo_i_initiated) { + for (int i=0;i<2;i++) { + if (q->cfo_i_corr[i]) { + free(q->cfo_i_corr[i]); + } + srslte_pss_synch_free(&q->pss_i[i]); } - srslte_pss_synch_free(&q->pss_i[i]); } if (q->temp) { free(q->temp); @@ -174,53 +180,51 @@ int srslte_sync_resize(srslte_sync_t *q, uint32_t frame_size, uint32_t max_offse frame_size <= 307200 && fft_size_isvalid(fft_size)) { - ret = SRSLTE_ERROR; - if (frame_size > q->max_frame_size) { fprintf(stderr, "Error in sync_resize(): frame_size must be lower than initialized\n"); return SRSLTE_ERROR; } - q->detect_cp = true; - q->sss_en = true; - q->mean_cfo = 0; - q->mean_cfo2 = 0; - q->N_id_2 = 1000; - q->N_id_1 = 1000; - q->cfo_i = 0; - q->find_cfo_i = false; - q->find_cfo_i_initiated = false; - q->cfo_ema_alpha = CFO_EMA_ALPHA; - q->fft_size = fft_size; + + q->fft_size = fft_size; q->frame_size = frame_size; q->max_offset = max_offset; - q->sss_alg = SSS_FULL; - q->enable_cfo_corr = true; - - if (srslte_pss_synch_resize(&q->pss, max_offset, fft_size, 0)) { + if (srslte_pss_synch_resize(&q->pss, q->max_offset, q->fft_size, 0)) { fprintf(stderr, "Error resizing PSS object\n"); return SRSLTE_ERROR; } - if (srslte_sss_synch_resize(&q->sss, fft_size)) { + if (srslte_sss_synch_resize(&q->sss, q->fft_size)) { fprintf(stderr, "Error resizing SSS object\n"); return SRSLTE_ERROR; } - if (srslte_cp_synch_resize(&q->cp_synch, fft_size)) { + if (srslte_cp_synch_resize(&q->cp_synch, q->fft_size)) { fprintf(stderr, "Error resizing CFO\n"); return SRSLTE_ERROR; } - if (srslte_cfo_resize(&q->cfocorr, q->frame_size)) { + if (srslte_cfo_resize(&q->cfo_corr_frame, q->frame_size)) { fprintf(stderr, "Error resizing CFO\n"); return SRSLTE_ERROR; } - if (srslte_cfo_resize(&q->cfocorr2, q->frame_size)) { + if (srslte_cfo_resize(&q->cfo_corr_symbol, q->fft_size)) { fprintf(stderr, "Error resizing CFO\n"); return SRSLTE_ERROR; } + if (q->cfo_i_initiated) { + for (int i=0;i<2;i++) { + int offset=(i==0)?-1:1; + if (srslte_pss_synch_resize(&q->pss_i[i], q->max_offset, q->fft_size, offset)) { + fprintf(stderr, "Error initializing PSS object\n"); + } + for (int t=0;tframe_size;t++) { + q->cfo_i_corr[i][t] = cexpf(-2*_Complex_I*M_PI*offset*(float) t/q->fft_size); + } + } + } + // Update CFO tolerance srslte_sync_set_cfo_tol(q, q->current_cfo_tol); @@ -236,30 +240,14 @@ int srslte_sync_resize(srslte_sync_t *q, uint32_t frame_size, uint32_t max_offse void srslte_sync_set_cfo_tol(srslte_sync_t *q, float tol) { q->current_cfo_tol = tol; - srslte_cfo_set_tol(&q->cfocorr, tol/(15000.0*q->fft_size)); - srslte_cfo_set_tol(&q->cfocorr2, tol/(15000.0*q->fft_size)); + srslte_cfo_set_tol(&q->cfo_corr_frame, tol/(15000.0*q->fft_size)); + srslte_cfo_set_tol(&q->cfo_corr_symbol, tol/(15000.0*q->fft_size)); } void srslte_sync_set_threshold(srslte_sync_t *q, float threshold) { q->threshold = threshold; } -void srslte_sync_cfo_i_detec_en(srslte_sync_t *q, bool enabled) { - q->find_cfo_i = enabled; - if (enabled && !q->find_cfo_i_initiated) { - for (int i=0;i<2;i++) { - int offset=(i==0)?-1:1; - if (srslte_pss_synch_init_fft_offset(&q->pss_i[i], q->max_offset, q->fft_size, offset)) { - fprintf(stderr, "Error initializing PSS object\n"); - } - for (int t=0;tframe_size;t++) { - q->cfo_i_corr[i][t] = cexpf(-2*_Complex_I*M_PI*offset*(float) t/q->fft_size); - } - } - q->find_cfo_i_initiated = true; - } -} - void srslte_sync_sss_en(srslte_sync_t *q, bool enabled) { q->sss_en = enabled; } @@ -291,30 +279,59 @@ uint32_t srslte_sync_get_sf_idx(srslte_sync_t *q) { } float srslte_sync_get_cfo(srslte_sync_t *q) { - return q->mean_cfo2 + q->cfo_i; + return q->cfo_cp_mean + q->cfo_pss_mean + q->cfo_i_value; } -void srslte_sync_set_cfo(srslte_sync_t *q, float cfo) { - q->mean_cfo = cfo; - q->mean_cfo2 = cfo; - q->mean_cfo2_isunset = false; - q->mean_cfo_isunset = false; +void srslte_sync_cfo_reset(srslte_sync_t *q) +{ + q->cfo_cp_mean = 0; + q->cfo_cp_is_set = false; + q->cfo_pss_mean = 0; + q->cfo_pss_is_set = false; } -void srslte_sync_set_cfo_i(srslte_sync_t *q, int cfo_i) { - q->cfo_i = cfo_i; +void srslte_sync_copy_cfo(srslte_sync_t *q, srslte_sync_t *src_obj) { + q->cfo_cp_mean = src_obj->cfo_cp_mean; + q->cfo_pss_mean = src_obj->cfo_pss_mean; + q->cfo_i_value = src_obj->cfo_i_value; + q->cfo_cp_is_set = false; + q->cfo_pss_is_set = false; } -void srslte_sync_set_cfo_enable(srslte_sync_t *q, bool enable) { - q->enable_cfo_corr = enable; +void srslte_sync_set_cfo_i_enable(srslte_sync_t *q, bool enable) { + q->cfo_i_enable = enable; + if (q->cfo_i_enable && !q->cfo_i_initiated) { + for (int i=0;i<2;i++) { + int offset=(i==0)?-1:1; + if (srslte_pss_synch_init_fft_offset(&q->pss_i[i], q->max_offset, q->fft_size, offset)) { + fprintf(stderr, "Error initializing PSS object\n"); + } + for (int t=0;tframe_size;t++) { + q->cfo_i_corr[i][t] = cexpf(-2*_Complex_I*M_PI*offset*(float) t/q->fft_size); + } + } + q->cfo_i_initiated = true; + } } -void srslte_sync_set_cfo_ema_alpha(srslte_sync_t *q, float alpha) { - q->cfo_ema_alpha = alpha; +void srslte_sync_set_sss_filt_enable(srslte_sync_t *q, bool enable) { + q->sss_filtering_enabled = enable; } -float srslte_sync_get_last_peak_value(srslte_sync_t *q) { - return q->peak_value; +void srslte_sync_set_pss_filt_enable(srslte_sync_t *q, bool enable) { + q->pss_filtering_enabled = enable; +} + +void srslte_sync_set_cfo_cp_enable(srslte_sync_t *q, bool enable) { + q->cfo_cp_enable = enable; +} + +void srslte_sync_set_cfo_pss_enable(srslte_sync_t *q, bool enable) { + q->cfo_pss_enable = enable; +} + +void srslte_sync_set_cfo_ema_alpha(srslte_sync_t *q, float alpha) { + q->cfo_ema_alpha = alpha; } float srslte_sync_get_peak_value(srslte_sync_t *q) { @@ -325,18 +342,17 @@ void srslte_sync_cp_en(srslte_sync_t *q, bool enabled) { q->detect_cp = enabled; } -bool srslte_sync_sss_is_en(srslte_sync_t *q) { - return q->sss_en; -} - -void srslte_sync_set_em_alpha(srslte_sync_t *q, float alpha) { +void srslte_sync_set_em_alpha(srslte_sync_t *q, float alpha) +{ srslte_pss_synch_set_ema_alpha(&q->pss, alpha); } -srslte_cp_t srslte_sync_get_cp(srslte_sync_t *q) { +srslte_cp_t srslte_sync_get_cp(srslte_sync_t *q) +{ return q->cp; } -void srslte_sync_set_cp(srslte_sync_t *q, srslte_cp_t cp) { +void srslte_sync_set_cp(srslte_sync_t *q, srslte_cp_t cp) +{ q->cp = cp; q->cp_len = SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_LEN_NORM(1,q->fft_size):SRSLTE_CP_LEN_EXT(q->fft_size); if (q->frame_size < q->fft_size) { @@ -346,7 +362,8 @@ void srslte_sync_set_cp(srslte_sync_t *q, srslte_cp_t cp) { } } -void srslte_sync_set_sss_algorithm(srslte_sync_t *q, sss_alg_t alg) { +void srslte_sync_set_sss_algorithm(srslte_sync_t *q, sss_alg_t alg) +{ q->sss_alg = alg; } @@ -354,7 +371,7 @@ void srslte_sync_set_sss_algorithm(srslte_sync_t *q, sss_alg_t alg) { * "SSS Detection Method for Initial Cell Search in 3GPP LTE FDD/TDD Dual Mode Receiver" * by Jung-In Kim et al. */ -srslte_cp_t srslte_sync_detect_cp(srslte_sync_t *q, cf_t *input, uint32_t peak_pos) +srslte_cp_t srslte_sync_detect_cp(srslte_sync_t *q, const cf_t *input, uint32_t peak_pos) { float R_norm=0, R_ext=0, C_norm=0, C_ext=0; float M_norm=0, M_ext=0; @@ -370,8 +387,8 @@ srslte_cp_t srslte_sync_detect_cp(srslte_sync_t *q, cf_t *input, uint32_t peak_p if (nof_symbols > 0) { - cf_t *input_cp_norm = &input[peak_pos-nof_symbols*(q->fft_size+cp_norm_len)]; - cf_t *input_cp_ext = &input[peak_pos-nof_symbols*(q->fft_size+cp_ext_len)]; + const cf_t *input_cp_norm = &input[peak_pos-nof_symbols*(q->fft_size+cp_norm_len)]; + const cf_t *input_cp_ext = &input[peak_pos-nof_symbols*(q->fft_size+cp_ext_len)]; for (int i=0;ifft_size], input_cp_norm, cp_norm_len)); @@ -414,28 +431,21 @@ srslte_cp_t srslte_sync_detect_cp(srslte_sync_t *q, cf_t *input, uint32_t peak_p /* Returns 1 if the SSS is found, 0 if not and -1 if there is not enough space * to correlate */ -int sync_sss(srslte_sync_t *q, cf_t *input, uint32_t peak_pos, srslte_cp_t cp) { - int sss_idx, ret; +int sync_sss_symbol(srslte_sync_t *q, const cf_t *input) +{ + int ret; srslte_sss_synch_set_N_id_2(&q->sss, q->N_id_2); - /* Make sure we have enough room to find SSS sequence */ - sss_idx = (int) peak_pos-2*q->fft_size-SRSLTE_CP_LEN(q->fft_size, (SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_NORM_LEN:SRSLTE_CP_EXT_LEN)); - if (sss_idx < 0) { - DEBUG("Not enough room to decode SSS (sss_idx=%d, peak_pos=%d)\n", sss_idx, peak_pos); - return SRSLTE_ERROR; - } - DEBUG("Searching SSS around sss_idx: %d, peak_pos: %d\n", sss_idx, peak_pos); - switch(q->sss_alg) { case SSS_DIFF: - srslte_sss_synch_m0m1_diff(&q->sss, &input[sss_idx], &q->m0, &q->m0_value, &q->m1, &q->m1_value); + srslte_sss_synch_m0m1_diff(&q->sss, input, &q->m0, &q->m0_value, &q->m1, &q->m1_value); break; case SSS_PARTIAL_3: - srslte_sss_synch_m0m1_partial(&q->sss, &input[sss_idx], 3, NULL, &q->m0, &q->m0_value, &q->m1, &q->m1_value); + srslte_sss_synch_m0m1_partial(&q->sss, input, 3, NULL, &q->m0, &q->m0_value, &q->m1, &q->m1_value); break; case SSS_FULL: - srslte_sss_synch_m0m1_partial(&q->sss, &input[sss_idx], 1, NULL, &q->m0, &q->m0_value, &q->m1, &q->m1_value); + srslte_sss_synch_m0m1_partial(&q->sss, input, 1, NULL, &q->m0, &q->m0_value, &q->m1, &q->m1_value); break; } @@ -452,20 +462,23 @@ int sync_sss(srslte_sync_t *q, cf_t *input, uint32_t peak_pos, srslte_cp_t cp) { } } -srslte_pss_synch_t* srslte_sync_get_cur_pss_obj(srslte_sync_t *q) { +srslte_pss_synch_t* srslte_sync_get_cur_pss_obj(srslte_sync_t *q) +{ srslte_pss_synch_t *pss_obj[3] = {&q->pss_i[0], &q->pss, &q->pss_i[1]}; - return pss_obj[q->cfo_i+1]; + return pss_obj[q->cfo_i_value+1]; } -static float cfo_estimate(srslte_sync_t *q, cf_t *input) { +static float cfo_cp_estimate(srslte_sync_t *q, const cf_t *input) +{ uint32_t cp_offset = 0; - cp_offset = srslte_cp_synch(&q->cp_synch, input, q->max_offset, 2, SRSLTE_CP_LEN_NORM(1,q->fft_size)); + cp_offset = srslte_cp_synch(&q->cp_synch, input, q->max_offset, 7, SRSLTE_CP_LEN_NORM(1,q->fft_size)); cf_t cp_corr_max = srslte_cp_synch_corr_output(&q->cp_synch, cp_offset); float cfo = -carg(cp_corr_max) / M_PI / 2; return cfo; } -static int cfo_i_estimate(srslte_sync_t *q, cf_t *input, int find_offset, int *peak_pos) { +static int cfo_i_estimate(srslte_sync_t *q, const cf_t *input, int find_offset, int *peak_pos, int *cfo_i) +{ float peak_value; float max_peak_value = -99; int max_cfo_i = 0; @@ -473,6 +486,9 @@ static int cfo_i_estimate(srslte_sync_t *q, cf_t *input, int find_offset, int *p for (int cfo_i=0;cfo_i<3;cfo_i++) { srslte_pss_synch_set_N_id_2(pss_obj[cfo_i], q->N_id_2); int p = srslte_pss_synch_find_pss(pss_obj[cfo_i], &input[find_offset], &peak_value); + if (p < 0) { + return -1; + } if (peak_value > max_peak_value) { max_peak_value = peak_value; if (peak_pos) { @@ -481,125 +497,172 @@ static int cfo_i_estimate(srslte_sync_t *q, cf_t *input, int find_offset, int *p q->peak_value = peak_value; max_cfo_i = cfo_i-1; } - } - return max_cfo_i; -} - -float srslte_sync_cfo_estimate(srslte_sync_t *q, cf_t *input, int find_offset) { - float cfo_f = cfo_estimate(q, input); - - int cfo_i = 0; - if (q->find_cfo_i) { - cfo_i = cfo_i_estimate(q, input, find_offset, NULL); } - return (float) cfo_i + cfo_f; + if (cfo_i) { + *cfo_i = max_cfo_i; + } + return 0; } /** Finds the PSS sequence previously defined by a call to srslte_sync_set_N_id_2() - * around the position find_offset in the buffer input. + * around the position find_offset in the buffer input. + * * Returns 1 if the correlation peak exceeds the threshold set by srslte_sync_set_threshold() * or 0 otherwise. Returns a negative number on error (if N_id_2 has not been set) - * + * + * The input signal is not modified. Any CFO correction is done in internal buffers + * * The maximum of the correlation peak is always stored in *peak_position */ -srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32_t *peak_position) +srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, const cf_t *input, uint32_t find_offset, uint32_t *peak_position) { - - srslte_sync_find_ret_t ret = SRSLTE_SYNC_ERROR; - + srslte_sync_find_ret_t ret = SRSLTE_SYNC_ERROR; + int peak_pos = 0; + if (!q) { return SRSLTE_ERROR_INVALID_INPUTS; } - if (input != NULL && + if (input != NULL && srslte_N_id_2_isvalid(q->N_id_2) && fft_size_isvalid(q->fft_size)) { - int peak_pos = 0; - - ret = SRSLTE_SUCCESS; - + if (peak_position) { *peak_position = 0; } - cf_t *input_cfo = input; + const cf_t *input_ptr = input; + + /* First CFO estimation stage is integer. + * Finds max PSS correlation for shifted +1/0/-1 integer versions. + * This should only used once N_id_2 is set + */ + if (q->cfo_i_enable) { + if (cfo_i_estimate(q, input_ptr, find_offset, &peak_pos, &q->cfo_i_value) < 0) { + fprintf(stderr, "Error calling finding PSS sequence at : %d \n", peak_pos); + return SRSLTE_ERROR; + } + // Correct it using precomputed signal and store in buffer (don't modify input signal) + if (q->cfo_i_value != 0) { + srslte_vec_prod_ccc((cf_t*) input_ptr, q->cfo_i_corr[q->cfo_i_value<0?0:1], q->temp, q->frame_size); + INFO("Compensating cfo_i=%d\n", q->cfo_i_value); + input_ptr = q->temp; + } + } - if (q->enable_cfo_corr) { - float cfo = cfo_estimate(q, input); + /* Second stage is coarse fractional CFO estimation using CP. + * In case of multi-cell, this can lead to incorrect estimations if CFO from different cells is different + */ + if (q->cfo_cp_enable) { + float cfo_cp = cfo_cp_estimate(q, input_ptr); - if (q->mean_cfo_isunset) { - q->mean_cfo = cfo; - q->mean_cfo_isunset = false; + if (!q->cfo_cp_is_set) { + q->cfo_cp_mean = cfo_cp; + q->cfo_cp_is_set = true; } else { /* compute exponential moving average CFO */ - q->mean_cfo = SRSLTE_VEC_EMA(cfo, q->mean_cfo, q->cfo_ema_alpha); + q->cfo_cp_mean = SRSLTE_VEC_EMA(cfo_cp, q->cfo_cp_mean, q->cfo_ema_alpha); } + INFO("CP-CFO: estimated=%f, mean=%f\n", cfo_cp, q->cfo_cp_mean); + /* Correct CFO with the averaged CFO estimation */ - srslte_cfo_correct(&q->cfocorr2, input, q->temp, -q->mean_cfo / q->fft_size); - - input_cfo = q->temp; + srslte_cfo_correct(&q->cfo_corr_frame, input_ptr, q->temp, -q->cfo_cp_mean / q->fft_size); + input_ptr = q->temp; } - - /* If integer CFO is enabled, find max PSS correlation for shifted +1/0/-1 integer versions */ - if (q->find_cfo_i && q->enable_cfo_corr) { - q->cfo_i = cfo_i_estimate(q, input_cfo, find_offset, &peak_pos); - if (q->cfo_i != 0) { - srslte_vec_prod_ccc(input_cfo, q->cfo_i_corr[q->cfo_i<0?0:1], input_cfo, q->frame_size); - INFO("Compensating cfo_i=%d\n", q->cfo_i); + + /* Find maximum of PSS correlation. If Integer CFO is enabled, correlation is already done + */ + if (!q->cfo_i_enable) { + srslte_pss_synch_set_N_id_2(&q->pss, q->N_id_2); + peak_pos = srslte_pss_synch_find_pss(&q->pss, &input_ptr[find_offset], q->threshold>0?&q->peak_value:NULL); + if (peak_pos < 0) { + fprintf(stderr, "Error calling finding PSS sequence at : %d \n", peak_pos); + return SRSLTE_ERROR; } } - srslte_pss_synch_set_N_id_2(&q->pss, q->N_id_2); - peak_pos = srslte_pss_synch_find_pss(&q->pss, &input_cfo[find_offset], &q->peak_value); - - // this compensates for the constant time shift caused by the low pass filter - if(q->decimate && peak_pos < 0) - { - peak_pos = 0 ;//peak_pos + q->decimate*(2);// replace 2 with q->filter_size -2; - } - if (peak_pos < 0) { - fprintf(stderr, "Error calling finding PSS sequence at : %d \n", peak_pos); - return SRSLTE_ERROR; - } + INFO("PSS: id=%d, peak_pos=%d, peak_value=%f\n", q->N_id_2, peak_pos, q->peak_value); + // Save peak position if (peak_position) { *peak_position = (uint32_t) peak_pos; } - - // Try to detect SSS - if (q->sss_en) { - // Set an invalid N_id_1 indicating SSS is yet to be detected - q->N_id_1 = 1000; - - if (sync_sss(q, input_cfo, find_offset + peak_pos, q->cp) < 0) { - DEBUG("No space for SSS processing. Frame starts at %d\n", peak_pos); - } + + // In case of decimation, this compensates for the constant time shift caused by the low pass filter + if(q->decimate && peak_pos < 0) { + peak_pos = 0 ;//peak_pos + q->decimate*(2);// replace 2 with q->filter_size -2; } - + /* If peak is over threshold, compute CFO and SSS */ - if (q->peak_value >= q->threshold) { + if (q->peak_value >= q->threshold || q->threshold == 0) { + + if (q->cfo_pss_enable && peak_pos >= q->fft_size) { + + // Filter central bands before PSS-based CFO estimation + const cf_t *pss_ptr = &input_ptr[find_offset + peak_pos - q->fft_size]; + if (q->pss_filtering_enabled) { + srslte_pss_synch_filter(&q->pss, pss_ptr, q->pss_filt); + pss_ptr = q->pss_filt; + } - if (q->detect_cp) { - if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) { - srslte_sync_set_cp(q, srslte_sync_detect_cp(q, input_cfo, peak_pos + find_offset)); + // PSS-based CFO estimation + float cfo_pss = srslte_pss_synch_cfo_compute(&q->pss, pss_ptr); + if (!q->cfo_pss_is_set) { + q->cfo_pss_mean = cfo_pss; + q->cfo_pss_is_set = true; } else { - DEBUG("Not enough room to detect CP length. Peak position: %d\n", peak_pos); + q->cfo_pss_mean = SRSLTE_VEC_EMA(cfo_pss, q->cfo_pss_mean, q->cfo_ema_alpha); } + + INFO("PSS-CFO: filter=%s, estimated=%f, mean=%f\n", + q->pss_filtering_enabled?"yes":"no", cfo_pss, q->cfo_pss_mean); + } - if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) { - float cfo2 = srslte_pss_synch_cfo_compute(&q->pss, &input[find_offset + peak_pos - q->fft_size]); - if (q->mean_cfo2_isunset) { - q->mean_cfo2 = cfo2; - q->mean_cfo2_isunset = true; + + // If there is enough space for CP and PSS-based CFO estimation + if (peak_pos + find_offset >= 2 * (q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) { + + // If SSS search is enabled, correlate SSS sequence + if (q->sss_en) { + + // Set an invalid N_id_1 indicating SSS is yet to be detected + q->N_id_1 = 1000; + + int sss_idx = find_offset + peak_pos - 2 * q->fft_size - + SRSLTE_CP_LEN(q->fft_size, (SRSLTE_CP_ISNORM(q->cp) ? SRSLTE_CP_NORM_LEN : SRSLTE_CP_EXT_LEN)); + + const cf_t *sss_ptr = &input_ptr[sss_idx]; + + // Correct CFO if detected in PSS + if (q->cfo_pss_enable) { + srslte_cfo_correct(&q->cfo_corr_symbol, sss_ptr, q->sss_filt, -q->cfo_pss_mean / q->fft_size); + sss_ptr = q->sss_filt; + } + + // Filter central bands before SSS estimation + if (q->sss_filtering_enabled) { + srslte_pss_synch_filter(&q->pss, sss_ptr, q->sss_filt); + sss_ptr = q->sss_filt; + } + + if (sync_sss_symbol(q, sss_ptr) < 0) { + fprintf(stderr, "Error correlating SSS\n"); + return -1; + } + } + + // Detect CP length + if (q->detect_cp) { + srslte_sync_set_cp(q, srslte_sync_detect_cp(q, input_ptr, peak_pos + find_offset)); } else { - q->mean_cfo2 = SRSLTE_VEC_EMA(cfo2, q->mean_cfo2, q->cfo_ema_alpha); + DEBUG("Not enough room to detect CP length. Peak position: %d\n", peak_pos); } ret = SRSLTE_SYNC_FOUND; } else { - ret = SRSLTE_SYNC_FOUND_NOSPACE; + ret = SRSLTE_SYNC_FOUND_NOSPACE; } } else { ret = SRSLTE_SYNC_NOFOUND; @@ -607,7 +670,7 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t DEBUG("SYNC ret=%d N_id_2=%d find_offset=%d frame_len=%d, pos=%d peak=%.2f threshold=%.2f sf_idx=%d, CFO=%.3f kHz\n", ret, q->N_id_2, find_offset, q->frame_size, peak_pos, q->peak_value, - q->threshold, q->sf_idx, 15*(q->cfo_i+q->mean_cfo)); + q->threshold, q->sf_idx, 15*(srslte_sync_get_cfo(q))); } else if (srslte_N_id_2_isvalid(q->N_id_2)) { fprintf(stderr, "Must call srslte_sync_set_N_id_2() first!\n"); diff --git a/lib/src/phy/sync/test/pss_usrp.c b/lib/src/phy/sync/test/pss_usrp.c index 8e8377b83..7c22652f7 100644 --- a/lib/src/phy/sync/test/pss_usrp.c +++ b/lib/src/phy/sync/test/pss_usrp.c @@ -221,7 +221,9 @@ int main(int argc, char **argv) { uint32_t max_peak = 0; uint32_t max_peak_ = 0; uint32_t min_peak = fft_size; - uint32_t min_peak_ = fft_size; + uint32_t min_peak_ = fft_size; + + pss.filter_pss_enable = true; while(frame_cnt < nof_frames || nof_frames == -1) { n = srslte_rf_recv(&rf, buffer, flen - peak_offset, 1); @@ -243,7 +245,7 @@ int main(int argc, char **argv) { if (peak_idx >= fft_size) { - // Estimate CFO + // Estimate CFO cfo = srslte_pss_synch_cfo_compute(&pss, &buffer[peak_idx-fft_size]); mean_cfo = SRSLTE_VEC_CMA(cfo, mean_cfo, frame_cnt); @@ -255,10 +257,14 @@ int main(int argc, char **argv) { fprintf(stderr, "Error computing channel estimation\n"); exit(-1); } - - // Find SSS + + // Find SSS int sss_idx = peak_idx-2*fft_size-(SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN(fft_size, SRSLTE_CP_NORM_LEN):SRSLTE_CP_LEN(fft_size, SRSLTE_CP_EXT_LEN)); if (sss_idx >= 0 && sss_idx < flen-fft_size) { + + // Filter SSS + srslte_pss_synch_filter(&pss, &buffer[sss_idx], &buffer[sss_idx]); + INFO("Full N_id_1: %d\n", srslte_sss_synch_N_id_1(&sss, m0, m1)); srslte_sss_synch_m0m1_partial(&sss, &buffer[sss_idx], 1, ce, &m0, &m0_value, &m1, &m1_value); if (srslte_sss_synch_N_id_1(&sss, m0, m1) != N_id_1) { @@ -301,12 +307,12 @@ int main(int argc, char **argv) { } printf("[%5d]: Pos: %5d (%d-%d), PSR: %4.1f (~%4.1f) Pdet: %4.2f, " - "FA: %4.2f, CFO: %+4.1f kHz, SFO: %+.2f Hz SSSmiss: %4.2f/%4.2f/%4.2f CPNorm: %.0f%%\r", + "FA: %4.2f, CFO: %+7.1f Hz, SFO: %+.2f Hz SSSmiss: %4.2f/%4.2f/%4.2f CPNorm: %.0f%%\r", frame_cnt, peak_idx, min_peak_, max_peak_, peak_value, mean_peak, (float) nof_det/frame_cnt, - (float) nof_nopeakdet/frame_cnt, mean_cfo*15, sfo, + (float) nof_nopeakdet/frame_cnt, mean_cfo*15000, sfo, (float) sss_error1/nof_det,(float) sss_error2/nof_det,(float) sss_error3/nof_det, (float) cp_is_norm/nof_det * 100); diff --git a/lib/src/phy/sync/test/sync_test.c b/lib/src/phy/sync/test/sync_test.c index 1e3951884..9016c1baa 100644 --- a/lib/src/phy/sync/test/sync_test.c +++ b/lib/src/phy/sync/test/sync_test.c @@ -124,8 +124,7 @@ int main(int argc, char **argv) { /* Set a very high threshold to make sure the correlation is ok */ srslte_sync_set_threshold(&syncobj, 5.0); srslte_sync_set_sss_algorithm(&syncobj, SSS_PARTIAL_3); - srslte_sync_set_cfo_enable(&syncobj, false); - + if (cell_id == -1) { cid = 0; max_cid = 49; diff --git a/lib/src/phy/ue/ue_cell_search.c b/lib/src/phy/ue/ue_cell_search.c index dc35fb48c..133aad144 100644 --- a/lib/src/phy/ue/ue_cell_search.c +++ b/lib/src/phy/ue/ue_cell_search.c @@ -116,7 +116,7 @@ int srslte_ue_cellsearch_init_multi(srslte_ue_cellsearch_t * q, uint32_t max_fra goto clean_exit; } if (srslte_ue_sync_set_cell(&q->ue_sync, cell)) { - fprintf(stderr, "Error initiating ue_sync\n"); + fprintf(stderr, "Error setting cell in ue_sync\n"); goto clean_exit; } @@ -292,6 +292,8 @@ int srslte_ue_cellsearch_scan_N_id_2(srslte_ue_cellsearch_t * q, srslte_ue_sync_set_N_id_2(&q->ue_sync, N_id_2); srslte_ue_sync_reset(&q->ue_sync); + srslte_ue_sync_cfo_reset(&q->ue_sync); + do { ret = srslte_ue_sync_zerocopy_multi(&q->ue_sync, q->sf_buffer); diff --git a/lib/src/phy/ue/ue_sync.c b/lib/src/phy/ue/ue_sync.c index 960d1de66..b6e0bd589 100644 --- a/lib/src/phy/ue/ue_sync.c +++ b/lib/src/phy/ue/ue_sync.c @@ -47,6 +47,9 @@ #define DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD 0 #define DEFAULT_SFO_EMA_COEFF 0.1 +#define DEFAULT_CFO_BW 0.2 +#define DEFAULT_CFO_PSS_TOL 100 // typical accuracy of PSS estimation + cf_t dummy_buffer0[15*2048/2]; cf_t dummy_buffer1[15*2048/2]; @@ -70,9 +73,10 @@ int srslte_ue_sync_init_file_multi(srslte_ue_sync_t *q, uint32_t nof_prb, char * q->file_mode = true; q->sf_len = SRSLTE_SF_LEN(srslte_symbol_sz(nof_prb)); q->file_cfo = -offset_freq; - q->correct_cfo = true; q->fft_size = srslte_symbol_sz(nof_prb); q->nof_rx_antennas = nof_rx_ant; + + q->cfo_correct_enable = true; if (srslte_cfo_init(&q->file_cfo_correct, 2*q->sf_len)) { fprintf(stderr, "Error initiating CFO\n"); @@ -96,6 +100,7 @@ int srslte_ue_sync_init_file_multi(srslte_ue_sync_t *q, uint32_t nof_prb, char * free(file_offset_buffer); } + srslte_ue_sync_cfo_reset(q); srslte_ue_sync_reset(q); ret = SRSLTE_SUCCESS; @@ -107,6 +112,31 @@ clean_exit: return ret; } +void srslte_ue_sync_cfo_reset(srslte_ue_sync_t *q) +{ + q->cfo_current_value = 0; + srslte_sync_cfo_reset(&q->strack); + srslte_sync_cfo_reset(&q->sfind); +} + +void srslte_ue_sync_reset(srslte_ue_sync_t *q) { + + if (!q->file_mode) { + srslte_sync_reset(&q->sfind); + srslte_sync_reset(&q->strack); + } else { + q->sf_idx = 9; + } + q->state = SF_FIND; + q->frame_ok_cnt = 0; + q->frame_no_cnt = 0; + q->frame_total_cnt = 0; + q->mean_sample_offset = 0.0; + q->next_rf_sample_offset = 0; + q->frame_find_cnt = 0; +} + + int srslte_ue_sync_start_agc(srslte_ue_sync_t *q, double (set_gain_callback)(void*, double), float init_gain_value) { uint32_t nframes; if (q->nof_recv_sf == 1) { @@ -179,13 +209,16 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q, q->fft_size = srslte_symbol_sz(max_prb); q->sf_len = SRSLTE_SF_LEN(q->fft_size); q->file_mode = false; - q->correct_cfo = true; - q->agc_period = 0; + q->agc_period = 0; q->sample_offset_correct_period = DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD; q->sfo_ema = DEFAULT_SFO_EMA_COEFF; q->max_prb = max_prb; + q->cfo_pss_tol = DEFAULT_CFO_PSS_TOL; + q->cfo_loop_bw = DEFAULT_CFO_BW; + q->cfo_correct_enable = true; + if (search_cell) { /* If the cell is unkown, we search PSS/SSS in 5 ms */ @@ -220,6 +253,29 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q, } } + // Configure FIND and TRACK sync objects behaviour (this configuration is always the same) + srslte_sync_set_cfo_i_enable(&q->sfind, false); + srslte_sync_set_cfo_cp_enable(&q->sfind, true); + srslte_sync_set_cfo_pss_enable(&q->sfind, true); + srslte_sync_set_pss_filt_enable(&q->sfind, true); + srslte_sync_set_sss_filt_enable(&q->sfind, true); + + // During track, we do CFO correction outside the sync object + srslte_sync_set_cfo_i_enable(&q->strack, false); + srslte_sync_set_cfo_cp_enable(&q->strack, false); + srslte_sync_set_cfo_pss_enable(&q->strack, true); + srslte_sync_set_pss_filt_enable(&q->strack, true); + srslte_sync_set_sss_filt_enable(&q->strack, true); + + // FIXME: CP detection not working very well. Not supporting Extended CP right now + srslte_sync_cp_en(&q->strack, false); + srslte_sync_cp_en(&q->sfind, false); + + + srslte_sync_sss_en(&q->strack, true); + q->decode_sss_on_track = true; + + ret = SRSLTE_SUCCESS; } @@ -255,8 +311,6 @@ int srslte_ue_sync_set_cell(srslte_ue_sync_t *q, srslte_cell_t cell) if (q != NULL && srslte_nofprb_isvalid(cell.nof_prb)) { - ret = SRSLTE_ERROR; - if (cell.nof_prb > q->max_prb) { fprintf(stderr, "Error in ue_sync_set_cell(): cell.nof_prb must be lower than initialized\n"); return SRSLTE_ERROR; @@ -271,15 +325,10 @@ int srslte_ue_sync_set_cell(srslte_ue_sync_t *q, srslte_cell_t cell) /* If the cell is unkown, we search PSS/SSS in 5 ms */ q->nof_recv_sf = 5; - - q->decode_sss_on_track = true; - } else { /* If the cell is known, we work on a 1ms basis */ q->nof_recv_sf = 1; - - q->decode_sss_on_track = true; } q->frame_len = q->nof_recv_sf*q->sf_len; @@ -289,59 +338,51 @@ int srslte_ue_sync_set_cell(srslte_ue_sync_t *q, srslte_cell_t cell) } if(srslte_sync_resize(&q->sfind, q->frame_len, q->frame_len, q->fft_size)) { - fprintf(stderr, "Error initiating sync find\n"); + fprintf(stderr, "Error setting cell sync find\n"); return SRSLTE_ERROR; } if (cell.id == 1000) { if(srslte_sync_resize(&q->strack, q->frame_len, TRACK_FRAME_SIZE, q->fft_size)) { - fprintf(stderr, "Error initiating sync track\n"); + fprintf(stderr, "Error setting cell sync track\n"); return SRSLTE_ERROR; } } else { if(srslte_sync_resize(&q->strack, q->frame_len, SRSLTE_CP_LEN_NORM(1,q->fft_size), q->fft_size)) { - fprintf(stderr, "Error initiating sync track\n"); + fprintf(stderr, "Error setting cell sync track\n"); return SRSLTE_ERROR; } } if (cell.id == 1000) { - /* If the cell id is unknown, enable CP detection on find */ - // FIXME: CP detection not working very well. Not supporting Extended CP right now - srslte_sync_cp_en(&q->sfind, false); - srslte_sync_cp_en(&q->strack, false); + q->nof_avg_find_frames = FIND_NOF_AVG_FRAMES; - srslte_sync_set_cfo_ema_alpha(&q->sfind, 0.8); + srslte_sync_set_cfo_ema_alpha(&q->sfind, 0.8); srslte_sync_set_cfo_ema_alpha(&q->strack, 0.1); - srslte_sync_cfo_i_detec_en(&q->sfind, false); + srslte_sync_set_em_alpha(&q->sfind, 1); - q->nof_avg_find_frames = FIND_NOF_AVG_FRAMES; - srslte_sync_set_threshold(&q->sfind, 2.0); + srslte_sync_set_threshold(&q->sfind, 2.0); srslte_sync_set_threshold(&q->strack, 1.2); } else { - srslte_sync_set_N_id_2(&q->sfind, cell.id%3); - srslte_sync_set_N_id_2(&q->strack, cell.id%3); - q->sfind.cp = cell.cp; + q->sfind.cp = cell.cp; q->strack.cp = cell.cp; - srslte_sync_cp_en(&q->sfind, false); - srslte_sync_cp_en(&q->strack, false); - srslte_sync_cfo_i_detec_en(&q->sfind, false); + srslte_sync_set_N_id_2(&q->sfind, cell.id%3); + srslte_sync_set_N_id_2(&q->strack, cell.id%3); - srslte_sync_set_cfo_ema_alpha(&q->sfind, 0.1); + srslte_sync_set_cfo_ema_alpha(&q->sfind, 0.1); srslte_sync_set_cfo_ema_alpha(&q->strack, 0.1); /* In find phase and if the cell is known, do not average pss correlation * because we only capture 1 subframe and do not know where the peak is. */ q->nof_avg_find_frames = 1; - srslte_sync_set_em_alpha(&q->sfind, 1); - srslte_sync_set_threshold(&q->sfind, 3.0); + srslte_sync_set_em_alpha(&q->sfind, 1); + srslte_sync_set_threshold(&q->sfind, 3.0); - srslte_sync_set_em_alpha(&q->strack, 0.2); + srslte_sync_set_em_alpha(&q->strack, 0.2); srslte_sync_set_threshold(&q->strack, 1.2); - } srslte_ue_sync_reset(q); @@ -357,34 +398,35 @@ void srslte_ue_sync_get_last_timestamp(srslte_ue_sync_t *q, srslte_timestamp_t * memcpy(timestamp, &q->last_timestamp, sizeof(srslte_timestamp_t)); } -uint32_t srslte_ue_sync_peak_idx(srslte_ue_sync_t *q) { - return q->peak_idx; +void srslte_ue_sync_set_cfo_loop_bw(srslte_ue_sync_t *q, float bw, float pss_tol) { + q->cfo_loop_bw = bw; + q->cfo_pss_tol = pss_tol; } 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->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; -} uint32_t srslte_ue_sync_get_sfidx(srslte_ue_sync_t *q) { return q->sf_idx; } -void srslte_ue_sync_cfo_i_detec_en(srslte_ue_sync_t *q, bool enable) { - srslte_sync_cfo_i_detec_en(&q->strack, enable); - srslte_sync_cfo_i_detec_en(&q->sfind, enable); +void srslte_ue_sync_set_cfo_i_enable(srslte_ue_sync_t *q, bool enable) { + printf("Warning: Setting integer CFO detection/correction. This is experimental!\n"); + srslte_sync_set_cfo_i_enable(&q->strack, enable); + srslte_sync_set_cfo_i_enable(&q->sfind, enable); } float srslte_ue_sync_get_cfo(srslte_ue_sync_t *q) { - return 15000 * srslte_sync_get_cfo(&q->strack); + return 15000 * q->cfo_current_value; } -void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q, float cfo) { - srslte_sync_set_cfo(&q->sfind, cfo/15000); - srslte_sync_set_cfo(&q->strack, cfo/15000); +void srslte_ue_sync_copy_cfo(srslte_ue_sync_t *q, srslte_ue_sync_t *src_obj) { + // Copy find object internal CFO averages + srslte_sync_copy_cfo(&q->sfind, &src_obj->sfind); + // Current CFO is tracking-phase CFO of previous object + q->cfo_current_value = srslte_ue_sync_get_cfo(src_obj); } void srslte_ue_sync_set_cfo_tol(srslte_ue_sync_t *q, float cfo_tol) {} @@ -406,7 +448,8 @@ void srslte_ue_sync_set_sfo_ema(srslte_ue_sync_t *q, float ema_coefficient) { } void srslte_ue_sync_decode_sss_on_track(srslte_ue_sync_t *q, bool enabled) { - q->decode_sss_on_track = enabled; + q->decode_sss_on_track = enabled; + srslte_sync_sss_en(&q->strack, q->decode_sss_on_track); } void srslte_ue_sync_set_N_id_2(srslte_ue_sync_t *q, uint32_t N_id_2) { @@ -434,7 +477,7 @@ static int find_peak_ok(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE_MAX_PORTS q->frame_find_cnt++; DEBUG("Found peak %d at %d, value %.3f, Cell_id: %d CP: %s\n", q->frame_find_cnt, q->peak_idx, - srslte_sync_get_last_peak_value(&q->sfind), q->cell.id, srslte_cp_string(q->cell.cp)); + srslte_sync_get_peak_value(&q->sfind), q->cell.id, srslte_cp_string(q->cell.cp)); if (q->frame_find_cnt >= q->nof_avg_find_frames || q->peak_idx < 2*q->fft_size) { INFO("Realigning frame, reading %d samples\n", q->peak_idx+q->sf_len/2); @@ -453,9 +496,9 @@ static int find_peak_ok(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE_MAX_PORTS /* Goto Tracking state */ q->state = SF_TRACK; - /* Initialize track state CFO */ - q->strack.mean_cfo = q->sfind.mean_cfo; - q->strack.cfo_i = q->sfind.cfo_i; + /* Set CFO values. Since we correct before track, the initial track state is CFO=0 Hz */ + q->cfo_current_value = srslte_sync_get_cfo(&q->sfind); + srslte_sync_cfo_reset(&q->strack); } return 0; @@ -491,6 +534,14 @@ static int track_peak_ok(srslte_ue_sync_t *q, uint32_t track_idx) { q->mean_sample_offset = q->last_sample_offset; } + /* Adjust current CFO estimation with PSS + * Since sync track has enabled only PSS-based correlation, get_cfo() returns that value only, already filtered. + */ + INFO("TRACK: cfo_current: %f, cfo_strack=%f\n", 15000*q->cfo_current_value, 15000*srslte_sync_get_cfo(&q->strack)); + if (abs(srslte_sync_get_cfo(&q->strack)*q->cfo_loop_bw) > q->cfo_pss_tol) { + q->cfo_current_value += srslte_sync_get_cfo(&q->strack)*q->cfo_loop_bw; + } + // Compute cumulative moving average time offset */ if (!frame_idx) { // Adjust RF sampling time based on the mean sampling offset @@ -543,13 +594,7 @@ static int track_peak_no(srslte_ue_sync_t *q) { return 0; } else { INFO("Tracking peak not found. Peak %.3f, %d lost\n", - srslte_sync_get_last_peak_value(&q->strack), (int) q->frame_no_cnt); - /* - printf("Saving files: pss_corr (%d), input (%d)\n", q->strack.pss.frame_size, SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); - srslte_vec_save_file("pss_corr", q->strack.pss.conv_output_avg, q->strack.pss.frame_size*sizeof(float)); - srslte_vec_save_file("input", q->input_buffer, SRSLTE_SF_LEN_PRB(q->cell.nof_prb)*sizeof(cf_t)); - exit(-1); - */ + srslte_sync_get_peak_value(&q->strack), (int) q->frame_no_cnt); return 1; } @@ -578,12 +623,10 @@ static int receive_samples(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE_MAX_PO return SRSLTE_SUCCESS; } -bool first_track = true; - int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer) { - cf_t *_input_buffer[SRSLTE_MAX_PORTS]; - _input_buffer[0] = input_buffer; - return srslte_ue_sync_zerocopy_multi(q, _input_buffer); + cf_t *_input_buffer[SRSLTE_MAX_PORTS]; + _input_buffer[0] = input_buffer; + return srslte_ue_sync_zerocopy_multi(q, _input_buffer); } /* Returns 1 if the subframe is synchronized in time, 0 otherwise */ @@ -610,7 +653,7 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE return SRSLTE_ERROR; } } - if (q->correct_cfo) { + if (q->cfo_correct_enable) { for (int i = 0; i < q->nof_rx_antennas; i++) { srslte_cfo_correct(&q->file_cfo_correct, input_buffer[i], @@ -625,13 +668,14 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE INFO("Reading %d samples. sf_idx = %d\n", q->sf_len, q->sf_idx); ret = 1; } else { + if (receive_samples(q, input_buffer)) { fprintf(stderr, "Error receiving samples\n"); return SRSLTE_ERROR; } switch (q->state) { - case SF_FIND: + case SF_FIND: switch(srslte_sync_find(&q->sfind, input_buffer[0], 0, &q->peak_idx)) { case SRSLTE_SYNC_ERROR: ret = SRSLTE_ERROR; @@ -659,37 +703,39 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE case SF_TRACK: ret = 1; - - srslte_sync_sss_en(&q->strack, q->decode_sss_on_track); - + + // Increase subframe counter q->sf_idx = (q->sf_idx + q->nof_recv_sf) % 10; - /* Every SF idx 0 and 5, find peak around known position q->peak_idx */ - if (q->sf_idx == 0 || q->sf_idx == 5) { + // Correct CFO before PSS/SSS tracking using the sync object corrector (initialized for 1 ms) + if (q->cfo_correct_enable) { + for (int i=0;inof_rx_antennas;i++) { + srslte_cfo_correct(&q->strack.cfo_corr_frame, + input_buffer[i], + input_buffer[i], + -q->cfo_current_value/q->fft_size); + } + } + /* Every SF idx 0 and 5, find peak around known position q->peak_idx */ + if (q->sf_idx == 0 || q->sf_idx == 5) + { + // Process AGC every period if (q->do_agc && (q->agc_period == 0 || (q->agc_period && (q->frame_total_cnt%q->agc_period) == 0))) { srslte_agc_process(&q->agc, input_buffer[0], q->sf_len); } - #ifdef MEASURE_EXEC_TIME - struct timeval t[3]; - gettimeofday(&t[1], NULL); - #endif - - track_idx = 0; - - /* Track PSS/SSS around the expected PSS position + /* Track PSS/SSS around the expected PSS position * In tracking phase, the subframe carrying the PSS is always the last one of the frame */ - + track_idx = 0; switch(srslte_sync_find(&q->strack, input_buffer[0], q->frame_len - q->sf_len/2 - q->fft_size - q->strack.max_offset/2, &track_idx)) { case SRSLTE_SYNC_ERROR: - ret = SRSLTE_ERROR; fprintf(stderr, "Error tracking correlation peak\n"); return SRSLTE_ERROR; case SRSLTE_SYNC_FOUND: @@ -699,19 +745,13 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE // It's very very unlikely that we fall here because this event should happen at FIND phase only ret = 0; q->state = SF_FIND; - printf("Warning: No space for SSS/CP while in tracking phase\n"); + INFO("Warning: No space for SSS/CP while in tracking phase\n"); break; case SRSLTE_SYNC_NOFOUND: ret = track_peak_no(q); break; } - #ifdef MEASURE_EXEC_TIME - gettimeofday(&t[2], NULL); - get_time_interval(t); - q->mean_exec_time = (float) SRSLTE_VEC_CMA((float) t[0].tv_usec, q->mean_exec_time, q->frame_total_cnt); - #endif - if (ret == SRSLTE_ERROR) { fprintf(stderr, "Error processing tracking peak\n"); q->state = SF_FIND; @@ -719,40 +759,12 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE } q->frame_total_cnt++; - } - if (q->correct_cfo) { - for (int i=0;inof_rx_antennas;i++) { - srslte_cfo_correct(&q->strack.cfocorr, - input_buffer[i], - input_buffer[i], - -srslte_sync_get_cfo(&q->strack) / q->fft_size); - } - } + } break; } - } } return ret; } -void srslte_ue_sync_reset(srslte_ue_sync_t *q) { - - if (!q->file_mode) { - srslte_sync_reset(&q->sfind); - srslte_sync_reset(&q->strack); - } else { - q->sf_idx = 9; - } - q->state = SF_FIND; - q->frame_ok_cnt = 0; - q->frame_no_cnt = 0; - q->frame_total_cnt = 0; - q->mean_sample_offset = 0.0; - q->next_rf_sample_offset = 0; - q->frame_find_cnt = 0; - #ifdef MEASURE_EXEC_TIME - q->mean_exec_time = 0; - #endif -} diff --git a/lib/src/phy/utils/convolution.c b/lib/src/phy/utils/convolution.c index f96bdd4a2..59807ad5b 100644 --- a/lib/src/phy/utils/convolution.c +++ b/lib/src/phy/utils/convolution.c @@ -115,7 +115,7 @@ void srslte_conv_fft_cc_free(srslte_conv_fft_cc_t *q) { } -uint32_t srslte_conv_fft_cc_run_opt(srslte_conv_fft_cc_t *q, cf_t *input, cf_t *filter_freq, cf_t *output) +uint32_t srslte_conv_fft_cc_run_opt(srslte_conv_fft_cc_t *q, const cf_t *input, const cf_t *filter_freq, cf_t *output) { srslte_dft_run_c(&q->input_plan, input, q->input_fft); srslte_vec_prod_ccc(q->input_fft, filter_freq, q->output_fft, q->output_len); @@ -125,7 +125,7 @@ uint32_t srslte_conv_fft_cc_run_opt(srslte_conv_fft_cc_t *q, cf_t *input, cf_t * } -uint32_t srslte_conv_fft_cc_run(srslte_conv_fft_cc_t *q, cf_t *input, cf_t *filter, cf_t *output) { +uint32_t srslte_conv_fft_cc_run(srslte_conv_fft_cc_t *q, const cf_t *input, const cf_t *filter, cf_t *output) { srslte_dft_run_c(&q->filter_plan, filter, q->filter_fft); @@ -133,7 +133,7 @@ uint32_t srslte_conv_fft_cc_run(srslte_conv_fft_cc_t *q, cf_t *input, cf_t *filt } -uint32_t srslte_conv_cc(cf_t *input, cf_t *filter, cf_t *output, uint32_t input_len, uint32_t filter_len) { +uint32_t srslte_conv_cc(const cf_t *input, const cf_t *filter, cf_t *output, uint32_t input_len, uint32_t filter_len) { uint32_t i; uint32_t M = filter_len; uint32_t N = input_len; diff --git a/lib/src/phy/utils/test/vector_test.c b/lib/src/phy/utils/test/vector_test.c index a717a7537..cb7eff480 100644 --- a/lib/src/phy/utils/test/vector_test.c +++ b/lib/src/phy/utils/test/vector_test.c @@ -441,7 +441,7 @@ TEST(srslte_vec_convert_fi, x[i] = (float) RANDOM_F(); } - TEST_CALL(srslte_vec_convert_fi(x, z, scale, block_size)) + TEST_CALL(srslte_vec_convert_fi(x, scale, z, block_size)) for (int i = 0; i < block_size; i++) { gold = (short) ((x[i] * scale)); diff --git a/lib/src/phy/utils/vector.c b/lib/src/phy/utils/vector.c index 5d5b6747a..35457fcb5 100644 --- a/lib/src/phy/utils/vector.c +++ b/lib/src/phy/utils/vector.c @@ -37,79 +37,73 @@ -void srslte_vec_xor_bbb(int8_t *x,int8_t *y,int8_t *z, uint32_t len) { +void srslte_vec_xor_bbb(int8_t *x,int8_t *y,int8_t *z, const uint32_t len) { srslte_vec_xor_bbb_simd(x, y, z, len); } // Used in PRACH detector, AGC and chest_dl for noise averaging -float srslte_vec_acc_ff(float *x, uint32_t len) { +float srslte_vec_acc_ff(const float *x, const uint32_t len) { return srslte_vec_acc_ff_simd(x, len); } -void srslte_vec_ema_filter(cf_t *new_data, cf_t *average, cf_t *output, float coeff, uint32_t len) { - srslte_vec_sc_prod_cfc(new_data, coeff, new_data, len); - srslte_vec_sc_prod_cfc(average, 1-coeff, output, len); - srslte_vec_sum_ccc(output, new_data, output, len); -} - -cf_t srslte_vec_acc_cc(cf_t *x, uint32_t len) { +cf_t srslte_vec_acc_cc(const cf_t *x, const uint32_t len) { return srslte_vec_acc_cc_simd(x, len); } -void srslte_vec_sub_fff(float *x, float *y, float *z, uint32_t len) { +void srslte_vec_sub_fff(const float *x, const float *y, float *z, const uint32_t len) { srslte_vec_sub_fff_simd(x, y, z, len); } -void srslte_vec_sub_sss(int16_t *x, int16_t *y, int16_t *z, uint32_t len) { +void srslte_vec_sub_sss(const int16_t *x, const int16_t *y, int16_t *z, const uint32_t len) { srslte_vec_sub_sss_simd(x, y, z, len); } // Noise estimation in chest_dl, interpolation -void srslte_vec_sub_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len) { - return srslte_vec_sub_fff((float*) x,(float*) y,(float*) z, 2*len); +void srslte_vec_sub_ccc(const cf_t *x, const cf_t *y, cf_t *z, const uint32_t len) { + return srslte_vec_sub_fff((const float*) x,(const float*) y,(float*) z, 2*len); } // Used in PSS/SSS and sum_ccc -void srslte_vec_sum_fff(float *x, float *y, float *z, uint32_t len) { +void srslte_vec_sum_fff(const float *x, const float *y, float *z, const uint32_t len) { srslte_vec_add_fff_simd(x, y, z, len); } -void srslte_vec_sum_sss(int16_t *x, int16_t *y, int16_t *z, uint32_t len) { +void srslte_vec_sum_sss(const int16_t *x, const int16_t *y, int16_t *z, const uint32_t len) { srslte_vec_sum_sss_simd(x, y, z, len); } -void srslte_vec_sum_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len) { +void srslte_vec_sum_ccc(const cf_t *x, const cf_t *y, cf_t *z, const uint32_t len) { srslte_vec_sum_fff((float*) x,(float*) y,(float*) z,2*len); } // PSS, PBCH, DEMOD, FFTW, etc. -void srslte_vec_sc_prod_fff(float *x, float h, float *z, uint32_t len) { +void srslte_vec_sc_prod_fff(const float *x, const float h, float *z, const uint32_t len) { srslte_vec_sc_prod_fff_simd(x, h, z, len); } // Used throughout -void srslte_vec_sc_prod_cfc(cf_t *x, float h, cf_t *z, uint32_t len) { +void srslte_vec_sc_prod_cfc(const const cf_t *x, const float h, cf_t *z, const uint32_t len) { srslte_vec_sc_prod_cfc_simd(x,h,z,len); } // Chest UL -void srslte_vec_sc_prod_ccc(cf_t *x, cf_t h, cf_t *z, uint32_t len) { +void srslte_vec_sc_prod_ccc(const cf_t *x, const cf_t h, cf_t *z, const uint32_t len) { srslte_vec_sc_prod_ccc_simd(x,h,z,len); } // Used in turbo decoder -void srslte_vec_convert_if(int16_t *x, float *z, float scale, uint32_t len) { +void srslte_vec_convert_if(const int16_t *x, const float scale, float *z, const uint32_t len) { int i; for (i=0;iargs->cfo_integer_enabled) { - srslte_ue_sync_cfo_i_detec_en(q, true); + srslte_ue_sync_set_cfo_i_enable(q, true); } srslte_ue_sync_set_cfo_ema(q, worker_com->args->cfo_ema); @@ -328,7 +328,7 @@ int phch_recv::cell_search(int force_N_id_2) { } srslte_ue_sync_reset(&ue_mib_sync.ue_sync); - srslte_ue_sync_set_cfo(&ue_mib_sync.ue_sync, cellsearch_cfo); + srslte_ue_sync_copy_cfo(&ue_mib_sync.ue_sync, &cs.ue_sync); /* Find and decode MIB */ int sfn_offset; @@ -340,7 +340,7 @@ int phch_recv::cell_search(int force_N_id_2) { cellsearch_cfo = srslte_ue_sync_get_cfo(&ue_mib_sync.ue_sync); srslte_ue_sync_reset(&ue_sync); - srslte_ue_sync_set_cfo(&ue_sync, cellsearch_cfo); + srslte_ue_sync_copy_cfo(&ue_sync, &ue_mib_sync.ue_sync); if (ret == 1) { srslte_pbch_mib_unpack(bch_payload, &cell, NULL); From 6e0c24c7eed9c8ccfc24aecdf329c0e5aebf8367 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 29 Nov 2017 18:54:45 +0100 Subject: [PATCH 175/242] Fixed feedback loop in CFO correction --- lib/src/phy/ue/ue_sync.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/phy/ue/ue_sync.c b/lib/src/phy/ue/ue_sync.c index b6e0bd589..dfd609e8f 100644 --- a/lib/src/phy/ue/ue_sync.c +++ b/lib/src/phy/ue/ue_sync.c @@ -47,8 +47,8 @@ #define DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD 0 #define DEFAULT_SFO_EMA_COEFF 0.1 -#define DEFAULT_CFO_BW 0.2 -#define DEFAULT_CFO_PSS_TOL 100 // typical accuracy of PSS estimation +#define DEFAULT_CFO_BW 0.7 +#define DEFAULT_CFO_PSS_TOL 80 // typical accuracy of PSS estimation cf_t dummy_buffer0[15*2048/2]; cf_t dummy_buffer1[15*2048/2]; @@ -538,7 +538,7 @@ static int track_peak_ok(srslte_ue_sync_t *q, uint32_t track_idx) { * Since sync track has enabled only PSS-based correlation, get_cfo() returns that value only, already filtered. */ INFO("TRACK: cfo_current: %f, cfo_strack=%f\n", 15000*q->cfo_current_value, 15000*srslte_sync_get_cfo(&q->strack)); - if (abs(srslte_sync_get_cfo(&q->strack)*q->cfo_loop_bw) > q->cfo_pss_tol) { + if (15000*fabsf(srslte_sync_get_cfo(&q->strack)) > q->cfo_pss_tol) { q->cfo_current_value += srslte_sync_get_cfo(&q->strack)*q->cfo_loop_bw; } From 46f15c19e62c5458c5eddd01307b79f50f4207b5 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 29 Nov 2017 20:28:04 +0100 Subject: [PATCH 176/242] Added subframe averaging option in chest_dl. Optional in pdsch_ue --- lib/examples/pdsch_ue.c | 34 +++++- .../srslte/phy/ch_estimation/chest_dl.h | 15 ++- lib/include/srslte/phy/ue/ue_sync.h | 8 +- lib/src/phy/ch_estimation/chest_dl.c | 112 ++++++++++++------ lib/src/phy/ue/ue_sync.c | 17 ++- 5 files changed, 137 insertions(+), 49 deletions(-) diff --git a/lib/examples/pdsch_ue.c b/lib/examples/pdsch_ue.c index e15aa473f..acc598296 100644 --- a/lib/examples/pdsch_ue.c +++ b/lib/examples/pdsch_ue.c @@ -90,6 +90,8 @@ typedef struct { uint32_t file_nof_prb; uint32_t file_nof_ports; uint32_t file_cell_id; + bool enable_cfo_ref; + bool average_subframe; char *rf_args; uint32_t rf_nof_rx_ant; double rf_freq; @@ -120,7 +122,9 @@ void args_default(prog_args_t *args) { args->file_offset_freq = 0; args->rf_args = ""; args->rf_freq = -1.0; - args->rf_nof_rx_ant = 1; + args->rf_nof_rx_ant = 1; + args->enable_cfo_ref = false; + args->average_subframe = false; #ifdef ENABLE_AGC_DEFAULT args->rf_gain = -1.0; #else @@ -137,7 +141,7 @@ void args_default(prog_args_t *args) { } void usage(prog_args_t *args, char *prog) { - printf("Usage: %s [agpPoOcildDnruMNv] -f rx_frequency (in Hz) | -i input_file\n", prog); + printf("Usage: %s [agpPoOcildFRDnruMNv] -f rx_frequency (in Hz) | -i input_file\n", prog); #ifndef DISABLE_RF printf("\t-a RF args [Default %s]\n", args->rf_args); printf("\t-A Number of RX antennas [Default %d]\n", args->rf_nof_rx_ant); @@ -158,6 +162,8 @@ void usage(prog_args_t *args, char *prog) { printf("\t-r RNTI in Hex [Default 0x%x]\n",args->rnti); printf("\t-l Force N_id_2 [Default best]\n"); printf("\t-C Disable CFO correction [Default %s]\n", args->disable_cfo?"Disabled":"Enabled"); + printf("\t-F Enable RS-based CFO correction [Default %s]\n", args->enable_cfo_ref?"Disabled":"Enabled"); + printf("\t-R Average channel estimates on 1 ms [Default %s]\n", args->average_subframe?"Disabled":"Enabled"); printf("\t-t Add time offset [Default %d]\n", args->time_offset); #ifndef DISABLE_GRAPHICS printf("\t-d disable plots [Default enabled]\n"); @@ -179,7 +185,7 @@ void usage(prog_args_t *args, char *prog) { void parse_args(prog_args_t *args, int argc, char **argv) { int opt; args_default(args); - while ((opt = getopt(argc, argv, "aAoglipPcOCtdDnvrfuUsSZyWMN")) != -1) { + while ((opt = getopt(argc, argv, "aAoglipPcOCtdDFRnvrfuUsSZyWMN")) != -1) { switch (opt) { case 'i': args->input_file_name = argv[optind]; @@ -211,6 +217,12 @@ void parse_args(prog_args_t *args, int argc, char **argv) { case 'C': args->disable_cfo = true; break; + case 'F': + args->enable_cfo_ref = true; + break; + case 'R': + args->average_subframe = true; + break; case 't': args->time_offset = atoi(argv[optind]); break; @@ -533,7 +545,10 @@ int main(int argc, char **argv) { fprintf(stderr, "Error initiating UE downlink processing module\n"); exit(-1); } - + + srslte_chest_dl_cfo_estimate_enable(&ue_dl.chest, prog_args.enable_cfo_ref, 0xff, 0.1); + srslte_chest_dl_average_subframe(&ue_dl.chest, prog_args.average_subframe); + /* Configure downlink receiver for the SI-RNTI since will be the only one we'll use */ srslte_ue_dl_set_rnti(&ue_dl, prog_args.rnti); @@ -655,6 +670,7 @@ int main(int argc, char **argv) { decode_pdsch = false; } } + gettimeofday(&t[1], NULL); if (decode_pdsch) { if(sfidx != 1 || prog_args.mbsfn_area_id < 0){ // Not an MBSFN subframe @@ -677,6 +693,12 @@ int main(int argc, char **argv) { } } } + + // Feed-back ue_sync with chest_dl CFO estimation + if (sfidx == 5 && prog_args.enable_cfo_ref) { + srslte_ue_sync_set_cfo_ref(&ue_sync, srslte_chest_dl_get_cfo(&ue_dl.chest)); + } + }else{ // MBSFN subframe n = srslte_ue_dl_decode_mbsfn(&ue_dl, sf_buffer, @@ -773,7 +795,7 @@ int main(int argc, char **argv) { /* Print basic Parameters */ PRINT_LINE(" nof layers: %d", ue_dl.pdsch_cfg.nof_layers); PRINT_LINE("nof codewords: %d", SRSLTE_RA_DL_GRANT_NOF_TB(&ue_dl.pdsch_cfg.grant)); - PRINT_LINE(" CFO: %+7.2f kHz", srslte_ue_sync_get_cfo(&ue_sync)); + PRINT_LINE(" CFO: %+7.2f Hz", srslte_ue_sync_get_cfo(&ue_sync)); PRINT_LINE(" SNR: %+5.1f dB | %+5.1f dB", 10 * log10(rsrp0 / noise), 10 * log10(rsrp1 / noise)); PRINT_LINE(" Rb: %6.2f / %6.2f / %6.2f Mbps (net/maximum/processing)", uerate, enodebrate, procrate); PRINT_LINE(" PDCCH-Miss: %5.2f%%", 100 * (1 - (float) ue_dl.nof_detected / nof_trials)); @@ -973,7 +995,7 @@ void *plot_thread_run(void *arg) { tmp_plot2[g+i] = -80; } } - plot_real_setNewData(&pce, tmp_plot2, sz); + plot_real_setNewData(&pce, tmp_plot2, sz); if (!prog_args.input_file_name) { if (plot_track) { diff --git a/lib/include/srslte/phy/ch_estimation/chest_dl.h b/lib/include/srslte/phy/ch_estimation/chest_dl.h index 229495a9b..91fda41e4 100644 --- a/lib/include/srslte/phy/ch_estimation/chest_dl.h +++ b/lib/include/srslte/phy/ch_estimation/chest_dl.h @@ -68,7 +68,8 @@ typedef struct { cf_t *pilot_estimates_average; cf_t *pilot_recv_signal; cf_t *tmp_noise; - + cf_t *tmp_cfo_estimate; + #ifdef FREQ_SEL_SNR float snr_vector[12000]; float pilot_power[12000]; @@ -84,8 +85,9 @@ typedef struct { float noise_estimate[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; float cfo; - bool cfo_estimate_enable; + bool cfo_estimate_enable; uint32_t cfo_estimate_sf_mask; + float cfo_ema; /* Use PSS for noise estimation in LS linear interpolation mode */ cf_t pss_signal[SRSLTE_PSS_LEN]; @@ -95,6 +97,7 @@ typedef struct { srslte_chest_dl_noise_alg_t noise_alg; int last_nof_antennas; + bool average_subframe; } srslte_chest_dl_t; @@ -148,7 +151,13 @@ SRSLTE_API int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, uint32_t port_id, uint32_t rxant_id); -SRSLTE_API void srslte_chest_dl_cfo_estimate_enable(srslte_chest_dl_t *q, bool enable, uint32_t mask); +SRSLTE_API void srslte_chest_dl_cfo_estimate_enable(srslte_chest_dl_t *q, + bool enable, + uint32_t mask, + float ema); + +SRSLTE_API void srslte_chest_dl_average_subframe(srslte_chest_dl_t *q, + bool enable); SRSLTE_API float srslte_chest_dl_get_noise_estimate(srslte_chest_dl_t *q); diff --git a/lib/include/srslte/phy/ue/ue_sync.h b/lib/include/srslte/phy/ue/ue_sync.h index 11d7893c8..3619156f7 100644 --- a/lib/include/srslte/phy/ue/ue_sync.h +++ b/lib/include/srslte/phy/ue/ue_sync.h @@ -115,6 +115,8 @@ typedef struct SRSLTE_API { float cfo_current_value; float cfo_loop_bw; float cfo_pss_tol; + float cfo_ref_tol; + float cfo_ref_max; uint32_t peak_idx; int next_rf_sample_offset; @@ -197,11 +199,15 @@ SRSLTE_API void srslte_ue_sync_copy_cfo(srslte_ue_sync_t *q, SRSLTE_API void srslte_ue_sync_set_cfo_loop_bw(srslte_ue_sync_t *q, float bw, - float pss_tol); + float pss_tol, + float ref_tol, + float ref_max); SRSLTE_API void srslte_ue_sync_set_cfo_ema(srslte_ue_sync_t *q, float ema); +SRSLTE_API void srslte_ue_sync_set_cfo_ref(srslte_ue_sync_t *q, float res_cfo); + SRSLTE_API void srslte_ue_sync_set_cfo_i_enable(srslte_ue_sync_t *q, bool enable); diff --git a/lib/src/phy/ch_estimation/chest_dl.c b/lib/src/phy/ch_estimation/chest_dl.c index 60d62a004..e04d30e69 100644 --- a/lib/src/phy/ch_estimation/chest_dl.c +++ b/lib/src/phy/ch_estimation/chest_dl.c @@ -102,25 +102,30 @@ int srslte_chest_dl_init(srslte_chest_dl_t *q, uint32_t max_prb) } q->tmp_noise = srslte_vec_malloc(sizeof(cf_t) * pilot_vec_size); - - if (!q->tmp_noise) { perror("malloc"); goto clean_exit; } - q->pilot_estimates = srslte_vec_malloc(sizeof(cf_t) * pilot_vec_size); + q->tmp_cfo_estimate = srslte_vec_malloc(sizeof(cf_t) * pilot_vec_size); + if (!q->tmp_cfo_estimate) { + perror("malloc"); + goto clean_exit; + } + + q->pilot_estimates = srslte_vec_malloc(sizeof(cf_t) * pilot_vec_size); if (!q->pilot_estimates) { perror("malloc"); goto clean_exit; } + q->pilot_estimates_average = srslte_vec_malloc(sizeof(cf_t) * pilot_vec_size); if (!q->pilot_estimates_average) { perror("malloc"); goto clean_exit; - } - q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * pilot_vec_size); + } + q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * pilot_vec_size); if (!q->pilot_recv_signal) { perror("malloc"); goto clean_exit; @@ -175,6 +180,9 @@ void srslte_chest_dl_free(srslte_chest_dl_t *q) if (q->tmp_noise) { free(q->tmp_noise); } + if (q->tmp_cfo_estimate) { + free(q->tmp_cfo_estimate); + } srslte_interp_linear_vector_free(&q->srslte_interp_linvec); srslte_interp_linear_free(&q->srslte_interp_lin); srslte_interp_linear_free(&q->srslte_interp_lin_mbsfn); @@ -241,6 +249,10 @@ static float estimate_noise_pilots(srslte_chest_dl_t *q, uint32_t port_id) { int nref=SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id); + if (q->average_subframe) { + nref /= 4; + } + /* Substract noisy pilot estimates */ srslte_vec_sub_ccc(q->pilot_estimates_average, q->pilot_estimates, q->tmp_noise, nref); @@ -305,9 +317,13 @@ static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t uint32_t nsymbols = (ch_mode == SRSLTE_SF_MBSFN ) ? srslte_refsignal_mbsfn_nof_symbols() + 1 : srslte_refsignal_cs_nof_symbols(port_id); uint32_t fidx_offset = 0; /* Interpolate in the frequency domain */ - + + if (q->average_subframe) { + nsymbols = 1; + } + // we add one to nsymbols to allow for inclusion of the non-mbms references in the channel estimation - for (l=0;l<(nsymbols);l++) { + for (l=0;lcell, l, port_id, 0); @@ -329,34 +345,41 @@ static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t } /* Now interpolate in the time domain between symbols */ - if (ch_mode == SRSLTE_SF_MBSFN) { - srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(2), &cesymb(1), 2, 1); - srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(2), &cesymb(6), &cesymb(3), 4, 3); - srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(6), &cesymb(10), &cesymb(7), 4, 3); - srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(6), &cesymb(10), &cesymb(10), &cesymb(11), 4, 1); - } else { - if (SRSLTE_CP_ISNORM(q->cell.cp)) { - if (nsymbols == 4) { - srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(4), &cesymb(1), 4, 3); - srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(4), &cesymb(7), &cesymb(5), 3, 2); - srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(7), &cesymb(11), &cesymb(8), 4, 3); - srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(7), &cesymb(11), &cesymb(11), &cesymb(12), 4, 2); - } else { - srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(8), &cesymb(1), &cesymb(1), &cesymb(0), 7, 1); - srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(8), &cesymb(2), 7, 6); - srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(8), &cesymb(9), 7, 5); - } + if (q->average_subframe) { + // If we average per subframe, just copy the estimates in the time domain + for (l=0;l<2*SRSLTE_CP_NSYMB(q->cell.cp);l++) { + memcpy(&ce[l*SRSLTE_NRE*q->cell.nof_prb], ce, sizeof(cf_t)*SRSLTE_NRE*q->cell.nof_prb); + } + } else { + if (ch_mode == SRSLTE_SF_MBSFN) { + srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(2), &cesymb(1), 2, 1); + srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(2), &cesymb(6), &cesymb(3), 4, 3); + srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(6), &cesymb(10), &cesymb(7), 4, 3); + srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(6), &cesymb(10), &cesymb(10), &cesymb(11), 4, 1); } else { - if (nsymbols == 4) { - srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(3), &cesymb(1), 3, 2); - srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(3), &cesymb(6), &cesymb(4), 3, 2); - srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(6), &cesymb(9), &cesymb(7), 3, 2); - srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(6), &cesymb(9), &cesymb(9), &cesymb(10), 3, 2); + if (SRSLTE_CP_ISNORM(q->cell.cp)) { + if (nsymbols == 4) { + srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(4), &cesymb(1), 4, 3); + srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(4), &cesymb(7), &cesymb(5), 3, 2); + srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(7), &cesymb(11), &cesymb(8), 4, 3); + srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(7), &cesymb(11), &cesymb(11), &cesymb(12), 4, 2); + } else { + srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(8), &cesymb(1), &cesymb(1), &cesymb(0), 7, 1); + srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(8), &cesymb(2), 7, 6); + srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(8), &cesymb(9), 7, 5); + } } else { - srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(7), &cesymb(1), &cesymb(1), &cesymb(0), 6, 1); - srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(7), &cesymb(2), 6, 5); - srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(7), &cesymb(8), 6, 4); - } + if (nsymbols == 4) { + srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(3), &cesymb(1), 3, 2); + srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(3), &cesymb(6), &cesymb(4), 3, 2); + srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(6), &cesymb(9), &cesymb(7), 3, 2); + srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(6), &cesymb(9), &cesymb(9), &cesymb(10), 3, 2); + } else { + srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(7), &cesymb(1), &cesymb(1), &cesymb(0), 6, 1); + srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(7), &cesymb(2), 6, 5); + srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(7), &cesymb(8), 6, 4); + } + } } } } @@ -392,6 +415,15 @@ static void average_pilots(srslte_chest_dl_t *q, cf_t *input, cf_t *output, uint uint32_t nsymbols = (ch_mode == SRSLTE_SF_MBSFN)?srslte_refsignal_mbsfn_nof_symbols(port_id):srslte_refsignal_cs_nof_symbols(port_id); uint32_t nref = (ch_mode == SRSLTE_SF_MBSFN)?6*q->cell.nof_prb:2*q->cell.nof_prb; + // Average in the time domain if enabled + if (q->average_subframe) { + for (int l=1;lsmooth_filter, &output[l*nref], nref, q->smooth_filter_len); @@ -424,11 +456,11 @@ float chest_estimate_cfo(srslte_chest_dl_t *q) for (int i=0;i<2;i++) { srslte_vec_prod_conj_ccc(&q->pilot_estimates[i*npilots/4], &q->pilot_estimates[(i+2)*npilots/4], - &q->tmp_noise[i*npilots/4], + &q->tmp_cfo_estimate[i*npilots/4], npilots/4); } // Average all angles - cf_t sum = srslte_vec_acc_cc(q->tmp_noise, npilots/2); + cf_t sum = srslte_vec_acc_cc(q->tmp_cfo_estimate, npilots/2); // Compute CFO return -cargf(sum)*n/(ns*(n+ng))/2/M_PI; @@ -459,7 +491,7 @@ void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, ui } if (q->cfo_estimate_enable && ((1<cfo_estimate_sf_mask)) { - q->cfo = chest_estimate_cfo(q); + q->cfo = SRSLTE_VEC_EMA(chest_estimate_cfo(q), q->cfo, q->cfo_ema); } /* Compute RSRP for the channel estimates in this port */ @@ -542,8 +574,14 @@ int srslte_chest_dl_estimate_multi_mbsfn(srslte_chest_dl_t *q, cf_t *input[SRSLT return SRSLTE_SUCCESS; } -void srslte_chest_dl_cfo_estimate_enable(srslte_chest_dl_t *q, bool enable, uint32_t mask) +void srslte_chest_dl_average_subframe(srslte_chest_dl_t *q, bool enable) +{ + q->average_subframe = enable; +} + +void srslte_chest_dl_cfo_estimate_enable(srslte_chest_dl_t *q, bool enable, uint32_t mask, float ema) { + q->cfo_ema = ema; q->cfo_estimate_enable = enable; q->cfo_estimate_sf_mask = mask; } diff --git a/lib/src/phy/ue/ue_sync.c b/lib/src/phy/ue/ue_sync.c index dfd609e8f..58489b92b 100644 --- a/lib/src/phy/ue/ue_sync.c +++ b/lib/src/phy/ue/ue_sync.c @@ -48,7 +48,9 @@ #define DEFAULT_SFO_EMA_COEFF 0.1 #define DEFAULT_CFO_BW 0.7 -#define DEFAULT_CFO_PSS_TOL 80 // typical accuracy of PSS estimation +#define DEFAULT_CFO_PSS_TOL 80 // typical accuracy of PSS estimation. Avoids ping-pong effect +#define DEFAULT_CFO_REF_TOL 5 // typical accuracy of REF estimation +#define DEFAULT_CFO_REF_MAX 300 // Maximum detection offset of REF based estimation cf_t dummy_buffer0[15*2048/2]; cf_t dummy_buffer1[15*2048/2]; @@ -215,6 +217,8 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q, q->max_prb = max_prb; + q->cfo_ref_max = DEFAULT_CFO_REF_MAX; + q->cfo_ref_tol = DEFAULT_CFO_REF_TOL; q->cfo_pss_tol = DEFAULT_CFO_PSS_TOL; q->cfo_loop_bw = DEFAULT_CFO_BW; q->cfo_correct_enable = true; @@ -398,9 +402,11 @@ void srslte_ue_sync_get_last_timestamp(srslte_ue_sync_t *q, srslte_timestamp_t * memcpy(timestamp, &q->last_timestamp, sizeof(srslte_timestamp_t)); } -void srslte_ue_sync_set_cfo_loop_bw(srslte_ue_sync_t *q, float bw, float pss_tol) { +void srslte_ue_sync_set_cfo_loop_bw(srslte_ue_sync_t *q, float bw, float pss_tol, float ref_tol, float ref_max) { q->cfo_loop_bw = bw; q->cfo_pss_tol = pss_tol; + q->cfo_ref_tol = ref_tol; + q->cfo_ref_max = ref_max; } void srslte_ue_sync_set_cfo_ema(srslte_ue_sync_t *q, float ema) { @@ -408,6 +414,13 @@ void srslte_ue_sync_set_cfo_ema(srslte_ue_sync_t *q, float ema) { srslte_sync_set_cfo_ema_alpha(&q->strack, ema); } +void srslte_ue_sync_set_cfo_ref(srslte_ue_sync_t *q, float ref_cfo) +{ + if (fabsf(ref_cfo)*15000 > q->cfo_ref_tol && fabsf(ref_cfo)*15000 < q->cfo_ref_max) { + q->cfo_current_value += ref_cfo*q->cfo_loop_bw; + } +} + uint32_t srslte_ue_sync_get_sfidx(srslte_ue_sync_t *q) { return q->sf_idx; } From 84724d2ab122d1d249b50145a1bc746e5be1a327 Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Thu, 30 Nov 2017 17:09:12 +0000 Subject: [PATCH 177/242] NAS-plane encryption working (thanks to David Rupprecht) --- lib/include/srslte/asn1/liblte_mme.h | 3 + lib/include/srslte/common/common.h | 29 + lib/include/srslte/common/interfaces_common.h | 10 +- lib/include/srslte/common/liblte_security.h | 67 ++ lib/include/srslte/common/liblte_ssl.h | 12 + lib/include/srslte/common/nas_pcap.h | 25 + lib/include/srslte/common/pcap.h | 72 +- lib/include/srslte/common/security.h | 20 + lib/include/srslte/interfaces/ue_interfaces.h | 10 +- lib/include/srslte/upper/pdcp.h | 1 + lib/include/srslte/upper/pdcp_entity.h | 33 +- lib/include/srslte/upper/rlc.h | 1 - lib/src/asn1/liblte_mme.cc | 26 + lib/src/common/liblte_security.cc | 632 ++++++++++++++++++ lib/src/common/mac_pcap.cc | 2 +- lib/src/common/nas_pcap.cc | 35 + lib/src/common/security.cc | 40 ++ lib/src/upper/pdcp.cc | 16 +- lib/src/upper/pdcp_entity.cc | 297 ++++++-- lib/src/upper/rlc.cc | 14 +- lib/src/upper/rlc_am.cc | 76 +-- lib/src/upper/rlc_tm.cc | 8 +- lib/src/upper/rlc_um.cc | 40 +- srsue/hdr/ue.h | 1 + srsue/hdr/ue_base.h | 2 + srsue/hdr/upper/nas.h | 21 +- srsue/hdr/upper/rrc.h | 29 - srsue/src/main.cc | 6 +- srsue/src/ue.cc | 22 +- srsue/src/upper/nas.cc | 223 ++++-- srsue/src/upper/rrc.cc | 11 +- srsue/src/upper/usim.cc | 8 +- srsue/ue.conf.example | 2 + 33 files changed, 1536 insertions(+), 258 deletions(-) create mode 100644 lib/include/srslte/common/nas_pcap.h create mode 100644 lib/src/common/nas_pcap.cc diff --git a/lib/include/srslte/asn1/liblte_mme.h b/lib/include/srslte/asn1/liblte_mme.h index 977f309ce..842fd2e17 100644 --- a/lib/include/srslte/asn1/liblte_mme.h +++ b/lib/include/srslte/asn1/liblte_mme.h @@ -2545,6 +2545,9 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_transaction_identifier_ie(uint8 // Enums // Structs // Functions +LIBLTE_ERROR_ENUM liblte_mme_parse_msg_sec_header(LIBLTE_BYTE_MSG_STRUCT *msg, + uint8 *pd, + uint8 *sec_hdr_type); LIBLTE_ERROR_ENUM liblte_mme_parse_msg_header(LIBLTE_BYTE_MSG_STRUCT *msg, uint8 *pd, uint8 *msg_type); diff --git a/lib/include/srslte/common/common.h b/lib/include/srslte/common/common.h index 41a89fb36..3fd71422b 100644 --- a/lib/include/srslte/common/common.h +++ b/lib/include/srslte/common/common.h @@ -96,6 +96,35 @@ static const char error_text[ERROR_N_ITEMS][20] = { "None", "Can't start", "Already started"}; +// Radio bearers +typedef enum{ + RB_ID_SRB0 = 0, + RB_ID_SRB1, + RB_ID_SRB2, + RB_ID_DRB1, + RB_ID_DRB2, + RB_ID_DRB3, + RB_ID_DRB4, + RB_ID_DRB5, + RB_ID_DRB6, + RB_ID_DRB7, + RB_ID_DRB8, + RB_ID_MAX +} rb_id_t; + +static const char rb_id_str[RB_ID_MAX][8] = {"SRB0", "SRB1", "SRB2", + "DRB1", "DRB2", "DRB3", + "DRB4", "DRB5", "DRB6", + "DRB7", "DRB8"}; + +inline const char* get_rb_name(uint32_t lcid) { + if (lcid < RB_ID_MAX) { + return rb_id_str[lcid]; + } else { + return "INVALID_RB"; + } +} + /****************************************************************************** * Byte and Bit buffers * diff --git a/lib/include/srslte/common/interfaces_common.h b/lib/include/srslte/common/interfaces_common.h index a027b6230..5fe26bc13 100644 --- a/lib/include/srslte/common/interfaces_common.h +++ b/lib/include/srslte/common/interfaces_common.h @@ -52,14 +52,12 @@ public: :direction(direction_) ,is_control(is_control_) ,is_data(is_data_) - ,do_security(false) ,sn_len(12) {} - uint8_t direction; - bool is_control; - bool is_data; - bool do_security; - uint8_t sn_len; + uint8_t direction; + bool is_control; + bool is_data; + uint8_t sn_len; // TODO: Support the following configurations // bool do_rohc; diff --git a/lib/include/srslte/common/liblte_security.h b/lib/include/srslte/common/liblte_security.h index b49f7211b..ebdbddd2f 100644 --- a/lib/include/srslte/common/liblte_security.h +++ b/lib/include/srslte/common/liblte_security.h @@ -185,6 +185,73 @@ LIBLTE_ERROR_ENUM liblte_security_128_eia2(uint8 *key, LIBLTE_BIT_MSG_STRUCT *msg, uint8 *mac); +/********************************************************************* + Name: liblte_security_encryption_eea1 + + Description: 128-bit encryption algorithm EEA1. + + Document Reference: 33.401 v13.1.0 Annex B.1.2 + 35.215 v13.0.0 References + Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D1 v2.1 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_security_encryption_eea1(uint8 *key, + uint32 count, + uint8 bearer, + uint8 direction, + uint8 *msg, + uint32 msg_len, + uint8 *out); + +/********************************************************************* + Name: liblte_security_decryption_eea1 + + Description: 128-bit decryption algorithm EEA1. + + Document Reference: 33.401 v13.1.0 Annex B.1.2 + 35.215 v13.0.0 References + Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D1 v2.1 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_security_decryption_eea1(uint8 *key, + uint32 count, + uint8 bearer, + uint8 direction, + uint8 *ct, + uint32 ct_len, + uint8 *out); + +/********************************************************************* + Name: liblte_security_encryption_eea2 + + Description: 128-bit encryption algorithm EEA2. + + Document Reference: 33.401 v13.1.0 Annex B.1.3 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_security_encryption_eea2(uint8 *key, + uint32 count, + uint8 bearer, + uint8 direction, + uint8 *msg, + uint32 msg_len, + uint8 *out); + +/********************************************************************* + Name: liblte_security_decryption_eea2 + + Description: 128-bit decryption algorithm EEA2. + + Document Reference: 33.401 v13.1.0 Annex B.1.3 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_security_decryption_eea2(uint8 *key, + uint32 count, + uint8 bearer, + uint8 direction, + uint8 *ct, + uint32 ct_len, + uint8 *out); + + /********************************************************************* Name: liblte_security_milenage_f1 diff --git a/lib/include/srslte/common/liblte_ssl.h b/lib/include/srslte/common/liblte_ssl.h index 886d557b1..d96c728ab 100644 --- a/lib/include/srslte/common/liblte_ssl.h +++ b/lib/include/srslte/common/liblte_ssl.h @@ -38,6 +38,18 @@ int aes_crypt_ecb( aes_context *ctx, return mbedtls_aes_crypt_ecb(ctx, mode, input, output); } +int aes_crypt_ctr(aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ) +{ + return mbedtls_aes_crypt_ctr(ctx, length, nc_off, nonce_counter, + stream_block, input, output); +} + void sha256(const unsigned char *key, size_t keylen, const unsigned char *input, size_t ilen, unsigned char output[32], int is224 ) diff --git a/lib/include/srslte/common/nas_pcap.h b/lib/include/srslte/common/nas_pcap.h new file mode 100644 index 000000000..68fcabb73 --- /dev/null +++ b/lib/include/srslte/common/nas_pcap.h @@ -0,0 +1,25 @@ +#ifndef NAS_PCAP_H +#define NAS_PCAP_H + +#include "srslte/common/pcap.h" + +namespace srslte { + +class nas_pcap +{ +public: + nas_pcap() {enable_write=false; ue_id=0; pcap_file = NULL; } + void enable(); + void open(const char *filename, uint32_t ue_id=0); + void close(); + void write_nas(uint8_t *pdu, uint32_t pdu_len_bytes); +private: + bool enable_write; + FILE *pcap_file; + uint32_t ue_id; + void pack_and_write(uint8_t* pdu, uint32_t pdu_len_bytes); +}; + +} //namespace srsue + +#endif // NAS_PCAP_H diff --git a/lib/include/srslte/common/pcap.h b/lib/include/srslte/common/pcap.h index db1dc17d0..611aea72d 100644 --- a/lib/include/srslte/common/pcap.h +++ b/lib/include/srslte/common/pcap.h @@ -33,6 +33,8 @@ #include #define MAC_LTE_DLT 147 +#define RRC_LTE_DLT 148 +#define NAS_LTE_DLT 149 /* This structure gets written to the start of the file */ @@ -113,7 +115,10 @@ typedef struct MAC_Context_Info_t { } MAC_Context_Info_t; - +/* Context information for every NAS PDU that will be logged */ +typedef struct NAS_Context_Info_s { + // No Context yet +} NAS_Context_Info_t; /**************************************************************************/ @@ -218,4 +223,69 @@ inline void MAC_LTE_PCAP_Close(FILE *fd) fclose(fd); } + +/**************************************************************************/ +/* API functions for opening/writing/closing NAS-LTE PCAP files */ + +/* Open the file and write file header */ +inline FILE *NAS_LTE_PCAP_Open(const char *fileName) +{ + pcap_hdr_t file_header = + { + 0xa1b2c3d4, /* magic number */ + 2, 4, /* version number is 2.4 */ + 0, /* timezone */ + 0, /* sigfigs - apparently all tools do this */ + 65535, /* snaplen - this should be long enough */ + NAS_LTE_DLT /* Data Link Type (DLT). Set as unused value 149 for now */ + }; + + FILE *fd = fopen(fileName, "w"); + if (fd == NULL) { + printf("Failed to open file \"%s\" for writing\n", fileName); + return NULL; + } + + /* Write the file header */ + fwrite(&file_header, sizeof(pcap_hdr_t), 1, fd); + + return fd; +} + +/* Write an individual PDU (PCAP packet header + mac-context + mac-pdu) */ +inline int NAS_LTE_PCAP_WritePDU(FILE *fd, NAS_Context_Info_t *context, + const unsigned char *PDU, unsigned int length) +{ + pcaprec_hdr_t packet_header; + + /* Can't write if file wasn't successfully opened */ + if (fd == NULL) { + printf("Error: Can't write to empty file handle\n"); + return 0; + } + + /****************************************************************/ + /* PCAP Header */ + struct timeval t; + gettimeofday(&t, NULL); + packet_header.ts_sec = t.tv_sec; + packet_header.ts_usec = t.tv_usec; + packet_header.incl_len = length; + packet_header.orig_len = length; + + /***************************************************************/ + /* Now write everything to the file */ + fwrite(&packet_header, sizeof(pcaprec_hdr_t), 1, fd); + fwrite(PDU, 1, length, fd); + + return 1; +} + +/* Close the PCAP file */ +inline void NAS_LTE_PCAP_Close(FILE *fd) +{ + if(fd) + fclose(fd); +} + #endif /* UEPCAP_H */ diff --git a/lib/include/srslte/common/security.h b/lib/include/srslte/common/security.h index 080f1848f..6ef23bafe 100644 --- a/lib/include/srslte/common/security.h +++ b/lib/include/srslte/common/security.h @@ -114,6 +114,26 @@ uint8_t security_128_eia2( uint8_t *key, uint32_t msg_len, uint8_t *mac); +/****************************************************************************** + * Encryption / Decryption + *****************************************************************************/ + +uint8_t security_128_eea1( uint8_t *key, + uint32_t count, + uint8_t bearer, + uint8_t direction, + uint8_t *msg, + uint32_t msg_len, + uint8_t *msg_out); + +uint8_t security_128_eea2(uint8_t *key, + uint32_t count, + uint8_t bearer, + uint8_t direction, + uint8_t *msg, + uint32_t msg_len, + uint8_t *msg_out); + /****************************************************************************** * Authentication *****************************************************************************/ diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index f083c89e2..37d73b910 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -118,15 +118,15 @@ public: class nas_interface_ue { public: - virtual void attach_request() = 0; - virtual void deattach_request() = 0; + virtual void attach_request() = 0; + virtual void deattach_request() = 0; }; // NAS interface for UE class nas_interface_gw { public: - virtual void attach_request() = 0; + virtual void attach_request() = 0; }; // RRC interface for MAC @@ -162,7 +162,6 @@ public: virtual void enable_capabilities() = 0; virtual void plmn_search() = 0; virtual void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) = 0; - virtual std::string get_rb_name(uint32_t lcid) = 0; }; // RRC interface for PDCP @@ -173,7 +172,6 @@ public: virtual void write_pdu_bcch_bch(srslte::byte_buffer_t *pdu) = 0; virtual void write_pdu_bcch_dlsch(srslte::byte_buffer_t *pdu) = 0; virtual void write_pdu_pcch(srslte::byte_buffer_t *pdu) = 0; - virtual std::string get_rb_name(uint32_t lcid) = 0; }; // RRC interface for RLC @@ -181,7 +179,6 @@ class rrc_interface_rlc { public: virtual void max_retx_attempted() = 0; - virtual std::string get_rb_name(uint32_t lcid) = 0; }; // PDCP interface for GW @@ -204,6 +201,7 @@ public: uint8_t *k_rrc_int_, srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0; + virtual void enable_encryption(uint32_t lcid) = 0; }; // PDCP interface for RLC diff --git a/lib/include/srslte/upper/pdcp.h b/lib/include/srslte/upper/pdcp.h index ce6ece151..f52fdbe05 100644 --- a/lib/include/srslte/upper/pdcp.h +++ b/lib/include/srslte/upper/pdcp.h @@ -62,6 +62,7 @@ public: uint8_t *k_rrc_int, CIPHERING_ALGORITHM_ID_ENUM cipher_algo, INTEGRITY_ALGORITHM_ID_ENUM integ_algo); + void enable_encryption(uint32_t lcid); // RLC interface void write_pdu(uint32_t lcid, byte_buffer_t *sdu); diff --git a/lib/include/srslte/upper/pdcp_entity.h b/lib/include/srslte/upper/pdcp_entity.h index 0ff005d07..bf1e8b5b2 100644 --- a/lib/include/srslte/upper/pdcp_entity.h +++ b/lib/include/srslte/upper/pdcp_entity.h @@ -32,6 +32,8 @@ #include "srslte/common/common.h" #include "srslte/interfaces/ue_interfaces.h" #include "srslte/common/security.h" +#include "srslte/common/msg_queue.h" +#include "srslte/common/threads.h" namespace srslte { @@ -59,6 +61,7 @@ static const char pdcp_d_c_text[PDCP_D_C_N_ITEMS][20] = {"Control PDU", * Common interface for all PDCP entities ***************************************************************************/ class pdcp_entity + :public thread { public: pdcp_entity(); @@ -68,6 +71,7 @@ public: srslte::log *log_, uint32_t lcid_, srslte_pdcp_config_t cfg_); + void stop(); void reset(); bool is_active(); @@ -78,6 +82,7 @@ public: uint8_t *k_rrc_int_, CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, INTEGRITY_ALGORITHM_ID_ENUM integ_algo_); + void enable_encryption(); // RLC interface void write_pdu(byte_buffer_t *pdu); @@ -90,9 +95,15 @@ private: srsue::rrc_interface_pdcp *rrc; srsue::gw_interface_pdcp *gw; + static const int PDCP_THREAD_PRIO = 7; + srslte::msg_queue rx_pdu_queue; + bool running; + bool active; uint32_t lcid; srslte_pdcp_config_t cfg; + bool do_integrity; + bool do_encryption; uint32_t rx_count; uint32_t tx_count; @@ -102,14 +113,26 @@ private: CIPHERING_ALGORITHM_ID_ENUM cipher_algo; INTEGRITY_ALGORITHM_ID_ENUM integ_algo; - void integrity_generate(uint8_t *key_128, - uint32_t count, - uint8_t rb_id, - uint8_t direction, - uint8_t *msg, + void integrity_generate(uint8_t *msg, uint32_t msg_len, uint8_t *mac); + bool integrity_verify(uint8_t *msg, + uint32_t count, + uint32_t msg_len, + uint8_t *mac); + + void cipher_encrypt(uint8_t *msg, + uint32_t msg_len, + uint8_t *ct); + + void cipher_decrypt(uint8_t *ct, + uint32_t count, + uint32_t ct_len, + uint8_t *msg); + + void run_thread(); + }; /**************************************************************************** diff --git a/lib/include/srslte/upper/rlc.h b/lib/include/srslte/upper/rlc.h index 349a7952d..fb0a82587 100644 --- a/lib/include/srslte/upper/rlc.h +++ b/lib/include/srslte/upper/rlc.h @@ -64,7 +64,6 @@ public: // PDCP interface void write_sdu(uint32_t lcid, byte_buffer_t *sdu); - std::string get_rb_name(uint32_t lcid); // MAC interface uint32_t get_buffer_state(uint32_t lcid); diff --git a/lib/src/asn1/liblte_mme.cc b/lib/src/asn1/liblte_mme.cc index 215ffd838..ce3c08987 100644 --- a/lib/src/asn1/liblte_mme.cc +++ b/lib/src/asn1/liblte_mme.cc @@ -4922,6 +4922,32 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_transaction_identifier_ie(uint8 MESSAGE FUNCTIONS *******************************************************************************/ +/********************************************************************* + Message Name: Security Message Header (Plain NAS Message) + + Description: Security header for NAS messages. + + Document Reference: 24.301 v10.2.0 Section 9.1 +*********************************************************************/ + +LIBLTE_ERROR_ENUM liblte_mme_parse_msg_sec_header(LIBLTE_BYTE_MSG_STRUCT *msg, + uint8 *pd, + uint8 *sec_hdr_type) +{ + + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if (msg != NULL && + pd != NULL && + sec_hdr_type != NULL) + { + *sec_hdr_type = (uint8) ((msg->msg[0] & 0xF0) >> 4); + err = LIBLTE_SUCCESS; + } + return(err); +} + + /********************************************************************* Message Name: Message Header (Plain NAS Message) diff --git a/lib/src/common/liblte_security.cc b/lib/src/common/liblte_security.cc index 95f9617cd..4ff35b5e4 100644 --- a/lib/src/common/liblte_security.cc +++ b/lib/src/common/liblte_security.cc @@ -55,6 +55,11 @@ typedef struct{ uint8 state[4][4]; }STATE_STRUCT; +typedef struct{ + uint32 * lfsr; + uint32 * fsm; +}S3G_STATE; + /******************************************************************************* GLOBAL VARIABLES *******************************************************************************/ @@ -76,6 +81,35 @@ static const uint8 S[256] = { 99,124,119,123,242,107,111,197, 48, 1,103, 43,254 225,248,152, 17,105,217,142,148,155, 30,135,233,206, 85, 40,223, 140,161,137, 13,191,230, 66,104, 65,153, 45, 15,176, 84,187, 22}; +/* S-box SQ */ +static const uint8 SQ[256] = { 0x25, 0x24, 0x73, 0x67, 0xD7, 0xAE, + 0x5C, 0x30, 0xA4, 0xEE, 0x6E, 0xCB, 0x7D, 0xB5, 0x82, 0xDB, + 0xE4, 0x8E, 0x48, 0x49, 0x4F, 0x5D, 0x6A, 0x78, 0x70, 0x88, + 0xE8, 0x5F, 0x5E, 0x84, 0x65, 0xE2, 0xD8, 0xE9, 0xCC, 0xED, + 0x40, 0x2F, 0x11, 0x28, 0x57, 0xD2, 0xAC, 0xE3, 0x4A, 0x15, + 0x1B, 0xB9, 0xB2, 0x80, 0x85, 0xA6, 0x2E, 0x02, 0x47, 0x29, + 0x07, 0x4B, 0x0E, 0xC1, 0x51, 0xAA, 0x89, 0xD4, 0xCA, 0x01, + 0x46, 0xB3, 0xEF, 0xDD, 0x44, 0x7B, 0xC2, 0x7F, 0xBE, 0xC3, + 0x9F, 0x20, 0x4C, 0x64, 0x83, 0xA2, 0x68, 0x42, 0x13, 0xB4, + 0x41, 0xCD, 0xBA, 0xC6, 0xBB, 0x6D, 0x4D, 0x71, 0x21, 0xF4, + 0x8D, 0xB0, 0xE5, 0x93, 0xFE, 0x8F, 0xE6, 0xCF, 0x43, 0x45, + 0x31, 0x22, 0x37, 0x36, 0x96, 0xFA, 0xBC, 0x0F, 0x08, 0x52, + 0x1D, 0x55, 0x1A, 0xC5, 0x4E, 0x23, 0x69, 0x7A, 0x92, 0xFF, + 0x5B, 0x5A, 0xEB, 0x9A, 0x1C, 0xA9, 0xD1, 0x7E, 0x0D, 0xFC, + 0x50, 0x8A, 0xB6, 0x62, 0xF5, 0x0A, 0xF8, 0xDC, 0x03, 0x3C, + 0x0C, 0x39, 0xF1, 0xB8, 0xF3, 0x3D, 0xF2, 0xD5, 0x97, 0x66, + 0x81, 0x32, 0xA0, 0x00, 0x06, 0xCE, 0xF6, 0xEA, 0xB7, 0x17, + 0xF7, 0x8C, 0x79, 0xD6, 0xA7, 0xBF, 0x8B, 0x3F, 0x1F, 0x53, + 0x63, 0x75, 0x35, 0x2C, 0x60, 0xFD, 0x27, 0xD3, 0x94, 0xA5, + 0x7C, 0xA1, 0x05, 0x58, 0x2D, 0xBD, 0xD9, 0xC7, 0xAF, 0x6B, + 0x54, 0x0B, 0xE0, 0x38, 0x04, 0xC8, 0x9D, 0xE7, 0x14, 0xB1, + 0x87, 0x9C, 0xDF, 0x6F, 0xF9, 0xDA, 0x2A, 0xC4, 0x59, 0x16, + 0x74, 0x91, 0xAB, 0x26, 0x61, 0x76, 0x34, 0x2B, 0xAD, 0x99, + 0xFB, 0x72, 0xEC, 0x33, 0x12, 0xDE, 0x98, 0x3B, 0xC0, 0x9B, + 0x3E, 0x18, 0x10, 0x3A, 0x56, 0xE1, 0x77, 0xC9, 0x1E, 0x9E, + 0x95, 0xA3, 0x90, 0x19, 0xA8, 0x6C, 0x09, 0xD0, 0xF0, 0x86 }; + + static const uint8 X_TIME[256] = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, @@ -195,6 +229,136 @@ void shift_row(STATE_STRUCT *state); // Functions void mix_column(STATE_STRUCT *state); +/********************************************************************* + Name: zero_tailing_bits + + Description: Fill tailing bits with zeros. + + Document Reference: - +*********************************************************************/ +void zero_tailing_bits(uint8 * data, uint32 length_bits); + +/********************************************************************* + Name: s3g_mul_x + + Description: Multiplication with reduction. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.1.1 +*********************************************************************/ +uint8 s3g_mul_x(uint8 v, uint8 c); + +/********************************************************************* + Name: s3g_mul_x_pow + + Description: Recursive multiplication with reduction. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.1.2 +*********************************************************************/ +uint8 s3g_mul_x_pow(uint8 v, uint8 i, uint8 c); + +/********************************************************************* + Name: s3g_mul_alpha + + Description: Multiplication with alpha. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.4.2 +*********************************************************************/ +uint32 s3g_mul_alpha(uint8 c); + +/********************************************************************* + Name: s3g_div_alpha + + Description: Division by alpha. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.4.3 +*********************************************************************/ +uint32 s3g_div_alpha(uint8 c); + +/********************************************************************* + Name: s3g_s1 + + Description: S-Box S1. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.3.1 +*********************************************************************/ +uint32 s3g_s1(uint32 w); + +/********************************************************************* + Name: s3g_s2 + + Description: S-Box S2. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.3.2 +*********************************************************************/ +uint32 s3g_s2(uint32 w); + +/********************************************************************* + Name: s3g_clock_lfsr + + Description: Clocking LFSR. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.4.4 and Section 3.4.5 +*********************************************************************/ +void s3g_clock_lfsr(S3G_STATE * state, uint32 f); + +/********************************************************************* + Name: s3g_clock_fsm + + Description: Clocking FSM. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.4.6 +*********************************************************************/ +uint32 s3g_clock_fsm(S3G_STATE * state); + +/********************************************************************* + Name: s3g_initialize + + Description: Initialization. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 4.1 +*********************************************************************/ +void s3g_initialize(S3G_STATE * state, uint32 k[4], uint32 iv[4]); + +/********************************************************************* + Name: s3g_deinitialize + + Description: Deinitialization. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 +*********************************************************************/ +void s3g_deinitialize(S3G_STATE * state); + +/********************************************************************* + Name: s3g_generate_keystream + + Description: Generation of Keystream. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 4.2 +*********************************************************************/ +void s3g_generate_keystream(S3G_STATE * state, uint32 n, uint32 *ks); + + /******************************************************************************* FUNCTIONS *******************************************************************************/ @@ -682,6 +846,184 @@ LIBLTE_ERROR_ENUM liblte_security_128_eia2(uint8 *key, return(err); } +/********************************************************************* + Name: liblte_security_encryption_eea1 + + Description: 128-bit encryption algorithm EEA1. + + Document Reference: 33.401 v13.1.0 Annex B.1.2 + 35.215 v13.0.0 References + Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D1 v2.1 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_security_encryption_eea1(uint8 *key, + uint32 count, + uint8 bearer, + uint8 direction, + uint8 *msg, + uint32 msg_len, + uint8 *out) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + S3G_STATE state, *state_ptr; + uint32 k[] = {0,0,0,0}; + uint32 iv[] = {0,0,0,0}; + uint32 *ks; + int32 i; + uint32 msg_len_block_8, msg_len_block_32, m; + + if (key != NULL && + msg != NULL && + out != NULL) + { + state_ptr = &state; + msg_len_block_8 = (msg_len + 7) / 8; + msg_len_block_32 = (msg_len + 31) / 32; + + // Transform key + for (i = 3; i >= 0; i--) { + k[i] = (key[4 * (3 - i) + 0] << 24) | + (key[4 * (3 - i) + 1] << 16) | + (key[4 * (3 - i) + 2] << 8) | + (key[4 * (3 - i) + 3]); + } + + // Construct iv + iv[3] = count; + iv[2] = ((bearer & 0x1F) << 27) | ((direction & 0x01) << 26); + iv[1] = iv[3]; + iv[0] = iv[2]; + + // Initialize keystream + s3g_initialize(state_ptr, k, iv); + + // Generate keystream + + ks = (uint32 *) calloc(msg_len_block_32, sizeof(uint32)); + s3g_generate_keystream(state_ptr, msg_len_block_32, ks); + + // Generate output except last block + for (i = 0; i < msg_len_block_32 - 1; i++) { + out[4 * i + 0] = msg[4 * i + 0] ^ ((ks[i] >> 24) & 0xFF); + out[4 * i + 1] = msg[4 * i + 1] ^ ((ks[i] >> 16) & 0xFF); + out[4 * i + 2] = msg[4 * i + 2] ^ ((ks[i] >> 8) & 0xFF); + out[4 * i + 3] = msg[4 * i + 3] ^ ((ks[i] & 0xFF)); + } + + // Process last bytes + for (i = (msg_len_block_32 - 1) * 4; i < msg_len_block_8; + i++) { + out[i] = msg[i] ^ ((ks[i / 4] >> ((3 - (i % 4)) * 8)) & 0xFF); + } + + // Zero tailing bits + zero_tailing_bits(out, msg_len); + + // Clean up + free(ks); + s3g_deinitialize(state_ptr); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +/********************************************************************* + Name: liblte_security_decryption_eea1 + + Description: 128-bit decryption algorithm EEA1. + + Document Reference: 33.401 v13.1.0 Annex B.1.2 + 35.215 v13.0.0 References + Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D1 v2.1 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_security_decryption_eea1(uint8 *key, + uint32 count, + uint8 bearer, + uint8 direction, + uint8 *ct, + uint32 ct_len, + uint8 *out) { + return liblte_security_encryption_eea1(key, count, bearer, + direction, ct, ct_len, out); +} + +/********************************************************************* + Name: liblte_security_encryption_eea2 + + Description: 128-bit encryption algorithm EEA2. + + Document Reference: 33.401 v13.1.0 Annex B.1.3 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_security_encryption_eea2(uint8 *key, + uint32 count, + uint8 bearer, + uint8 direction, + uint8 *msg, + uint32 msg_len, + uint8 *out) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + aes_context ctx; + unsigned char stream_blk[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + unsigned char nonce_cnt[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + int32 i; + int ret; + size_t nc_off = 0; + + if(key != NULL && + msg != NULL && + out != NULL) + { + ret = aes_setkey_enc(&ctx, key, 128); + + if (ret == 0) { + // Construct nonce + nonce_cnt[0] = (count >> 24) & 0xFF; + nonce_cnt[1] = (count >> 16) & 0xFF; + nonce_cnt[2] = (count >> 8) & 0xFF; + nonce_cnt[3] = (count) & 0xFF; + nonce_cnt[4] = ((bearer & 0x1F) << 3) | + ((direction & 0x01) << 2); + + // Encryption + ret = aes_crypt_ctr(&ctx, (msg_len + 7) / 8, &nc_off, nonce_cnt, + stream_blk, msg, out); + } + + if (ret == 0) { + // Zero tailing bits + zero_tailing_bits(out, msg_len); + err = LIBLTE_SUCCESS; + } + } + + return(err); +} + +/********************************************************************* + Name: liblte_security_decryption_eea2 + + Description: 128-bit decryption algorithm EEA2. + + Document Reference: 33.401 v13.1.0 Annex B.1.3 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_security_decryption_eea2(uint8 *key, + uint32 count, + uint8 bearer, + uint8 direction, + uint8 *ct, + uint32 ct_len, + uint8 *out) +{ + return liblte_security_encryption_eea2(key, count, bearer, + direction, ct, ct_len, out); +} + + + /********************************************************************* Name: liblte_security_milenage_f1 @@ -1243,3 +1585,293 @@ void mix_column(STATE_STRUCT *state) state->state[3][i] ^= temp ^ tmp; } } + +/********************************************************************* + Name: zero_tailing_bits + + Description: Fill tailing bits with zeros. + + Document Reference: - +*********************************************************************/ +void zero_tailing_bits(uint8 * data, uint32 length_bits) { + uint8 bits = (8 - (length_bits & 0x07)) & 0x07; + data[(length_bits + 7) / 8 - 1] &= (uint8) (0xFF << bits); +} + +/********************************************************************* + Name: s3g_mul_x + + Description: Multiplication with reduction. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.1.1 +*********************************************************************/ +uint8 s3g_mul_x(uint8 v, uint8 c) { + if (v & 0x80) + return ((v << 1) ^ c); + else + return (v << 1); +} + +/********************************************************************* + Name: s3g_mul_x_pow + + Description: Recursive multiplication with reduction. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.1.2 +*********************************************************************/ +uint8 s3g_mul_x_pow(uint8 v, uint8 i, uint8 c) { + if (i == 0) + return v; + else + return s3g_mul_x(s3g_mul_x_pow(v, i - 1, c), c); +} + +/********************************************************************* + Name: s3g_mul_alpha + + Description: Multiplication with alpha. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.4.2 +*********************************************************************/ +uint32 s3g_mul_alpha(uint8 c) { + return ((((uint32) s3g_mul_x_pow(c, 23, 0xa9)) << 24) | + (((uint32) s3g_mul_x_pow(c, 245, 0xa9)) << 16) | + (((uint32) s3g_mul_x_pow(c, 48, 0xa9)) << 8) | + (((uint32) s3g_mul_x_pow(c, 239, 0xa9)))); +} + +/********************************************************************* + Name: s3g_div_alpha + + Description: Division by alpha. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.4.3 +*********************************************************************/ +uint32 s3g_div_alpha(uint8 c) { + return ((((uint32) s3g_mul_x_pow(c, 16, 0xa9)) << 24) | + (((uint32) s3g_mul_x_pow(c, 39, 0xa9)) << 16) | + (((uint32) s3g_mul_x_pow(c, 6, 0xa9)) << 8) | + (((uint32) s3g_mul_x_pow(c, 64, 0xa9)))); +} + +/********************************************************************* + Name: s3g_s1 + + Description: S-Box S1. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.3.1 +*********************************************************************/ +uint32 s3g_s1(uint32 w) { + uint8 r0 = 0, r1 = 0, r2 = 0, r3 = 0; + uint8 srw0 = S[(uint8) ((w >> 24) & 0xff)]; + uint8 srw1 = S[(uint8) ((w >> 16) & 0xff)]; + uint8 srw2 = S[(uint8) ((w >> 8) & 0xff)]; + uint8 srw3 = S[(uint8) ((w) & 0xff)]; + + r0 = ((s3g_mul_x(srw0, 0x1b)) ^ + (srw1) ^ + (srw2) ^ + ((s3g_mul_x(srw3, 0x1b)) ^ srw3)); + + r1 = (((s3g_mul_x(srw0, 0x1b)) ^ srw0) ^ + (s3g_mul_x(srw1, 0x1b)) ^ + (srw2) ^ + (srw3)); + + r2 = ((srw0) ^ + ((s3g_mul_x(srw1, 0x1b)) ^ srw1) ^ + (s3g_mul_x(srw2, 0x1b)) ^ + (srw3)); + + r3 = ((srw0) ^ + (srw1) ^ + ((s3g_mul_x(srw2, 0x1b)) ^ srw2) ^ + (s3g_mul_x(srw3, 0x1b))); + + return ((((uint32) r0) << 24) | + (((uint32) r1) << 16) | + (((uint32) r2) << 8) | + (((uint32) r3))); +} + +/********************************************************************* + Name: s3g_s2 + + Description: S-Box S2. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.3.2 +*********************************************************************/ +uint32 s3g_s2(uint32 w) { + uint8 r0 = 0, r1 = 0, r2 = 0, r3 = 0; + uint8 sqw0 = SQ[(uint8) ((w >> 24) & 0xff)]; + uint8 sqw1 = SQ[(uint8) ((w >> 16) & 0xff)]; + uint8 sqw2 = SQ[(uint8) ((w >> 8) & 0xff)]; + uint8 sqw3 = SQ[(uint8) ((w) & 0xff)]; + + r0 = ((s3g_mul_x(sqw0, 0x69)) ^ + (sqw1) ^ + (sqw2) ^ + ((s3g_mul_x(sqw3, 0x69)) ^ sqw3)); + + r1 = (((s3g_mul_x(sqw0, 0x69)) ^ sqw0) ^ + (s3g_mul_x(sqw1, 0x69)) ^ + (sqw2) ^ + (sqw3)); + + r2 = ((sqw0) ^ + ((s3g_mul_x(sqw1, 0x69)) ^ sqw1) ^ + (s3g_mul_x(sqw2, 0x69)) ^ + (sqw3)); + + r3 = ((sqw0) ^ + (sqw1) ^ + ((s3g_mul_x(sqw2, 0x69)) ^ sqw2) ^ + (s3g_mul_x(sqw3, 0x69))); + + return ((((uint32) r0) << 24) | + (((uint32) r1) << 16) | + (((uint32) r2) << 8) | + (((uint32) r3))); +} + +/********************************************************************* + Name: s3g_clock_lfsr + + Description: Clocking LFSR. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.4.4 and Section 3.4.5 +*********************************************************************/ +void s3g_clock_lfsr(S3G_STATE * state, uint32 f) { + uint32 v = ( + ((state->lfsr[0] << 8) & 0xffffff00) ^ + (s3g_mul_alpha((uint8) ((state->lfsr[0] >> 24) & 0xff))) ^ + (state->lfsr[2]) ^ + ((state->lfsr[11] >> 8) & 0x00ffffff) ^ + (s3g_div_alpha((uint8) ((state->lfsr[11]) & 0xff))) ^ + (f) + ); + uint8 i; + + for (i = 0; i < 15; i++) { + state->lfsr[i] = state->lfsr[i + 1]; + } + state->lfsr[15] = v; +} + +/********************************************************************* + Name: s3g_clock_fsm + + Description: Clocking FSM. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.4.6 +*********************************************************************/ +uint32 s3g_clock_fsm(S3G_STATE * state) { + uint32 f = ((state->lfsr[15] + state->fsm[0]) & 0xffffffff) ^ + state->fsm[1]; + uint32 r = (state->fsm[1] + (state->fsm[2] ^ state->lfsr[5])) & + 0xffffffff; + + state->fsm[2] = s3g_s2(state->fsm[1]); + state->fsm[1] = s3g_s1(state->fsm[0]); + state->fsm[0] = r; + + return f; +} + +/********************************************************************* + Name: s3g_initialize + + Description: Initialization. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 4.1 +*********************************************************************/ +void s3g_initialize(S3G_STATE * state, uint32 k[4], uint32 iv[4]) { + uint8 i = 0; + uint32 f = 0x0; + + state->lfsr = (uint32 *) calloc(16, sizeof(uint32)); + state->fsm = (uint32 *) calloc( 3, sizeof(uint32)); + + state->lfsr[15] = k[3] ^ iv[0]; + state->lfsr[14] = k[2]; + state->lfsr[13] = k[1]; + state->lfsr[12] = k[0] ^ iv[1]; + + state->lfsr[11] = k[3] ^ 0xffffffff; + state->lfsr[10] = k[2] ^ 0xffffffff ^ iv[2]; + state->lfsr[ 9] = k[1] ^ 0xffffffff ^ iv[3]; + state->lfsr[ 8] = k[0] ^ 0xffffffff; + state->lfsr[ 7] = k[3]; + state->lfsr[ 6] = k[2]; + state->lfsr[ 5] = k[1]; + state->lfsr[ 4] = k[0]; + state->lfsr[ 3] = k[3] ^ 0xffffffff; + state->lfsr[ 2] = k[2] ^ 0xffffffff; + state->lfsr[ 1] = k[1] ^ 0xffffffff; + state->lfsr[ 0] = k[0] ^ 0xffffffff; + + state->fsm[0] = 0x0; + state->fsm[1] = 0x0; + state->fsm[2] = 0x0; + for (i = 0; i < 32; i++) { + f = s3g_clock_fsm(state); + s3g_clock_lfsr(state, f); + } +} + +/********************************************************************* + Name: s3g_deinitialize + + Description: Deinitialization. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 +*********************************************************************/ +void s3g_deinitialize(S3G_STATE * state) { + free(state->lfsr); + free(state->fsm); +} + +/********************************************************************* + Name: s3g_generate_keystream + + Description: Generation of Keystream. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 4.2 +*********************************************************************/ +void s3g_generate_keystream(S3G_STATE * state, uint32 n, uint32 *ks) { + uint32 t = 0; + uint32 f = 0x0; + + // Clock FSM once. Discard the output. + s3g_clock_fsm(state); + // Clock LFSR in keystream mode once. + s3g_clock_lfsr(state, 0x0); + + for (t = 0; t < n; t++) { + f = s3g_clock_fsm(state); + // Note that ks[t] corresponds to z_{t+1} in section 4.2 + ks[t] = f ^ state->lfsr[0]; + s3g_clock_lfsr(state, 0x0); + } +} diff --git a/lib/src/common/mac_pcap.cc b/lib/src/common/mac_pcap.cc index ff30670ed..b73181e73 100644 --- a/lib/src/common/mac_pcap.cc +++ b/lib/src/common/mac_pcap.cc @@ -46,7 +46,7 @@ void mac_pcap::open(const char* filename, uint32_t ue_id) } void mac_pcap::close() { - fprintf(stdout, "Saving PCAP file\n"); + fprintf(stdout, "Saving MAC PCAP file\n"); MAC_LTE_PCAP_Close(pcap_file); } diff --git a/lib/src/common/nas_pcap.cc b/lib/src/common/nas_pcap.cc new file mode 100644 index 000000000..80603f8d5 --- /dev/null +++ b/lib/src/common/nas_pcap.cc @@ -0,0 +1,35 @@ +#include +#include "srslte/srslte.h" +#include "srslte/common/pcap.h" +#include "srslte/common/nas_pcap.h" + + +namespace srslte { + +void nas_pcap::enable() +{ + enable_write = true; +} +void nas_pcap::open(const char* filename, uint32_t ue_id) +{ + pcap_file = NAS_LTE_PCAP_Open(filename); + ue_id = ue_id; + enable_write = true; +} +void nas_pcap::close() +{ + fprintf(stdout, "Saving NAS PCAP file\n"); + MAC_LTE_PCAP_Close(pcap_file); +} + +void nas_pcap::write_nas(uint8_t *pdu, uint32_t pdu_len_bytes) +{ + if (enable_write) { + NAS_Context_Info_t context; + if (pdu) { + NAS_LTE_PCAP_WritePDU(pcap_file, &context, pdu, pdu_len_bytes); + } + } +} + +} diff --git a/lib/src/common/security.cc b/lib/src/common/security.cc index f0ad1ce7e..3f2dcff03 100644 --- a/lib/src/common/security.cc +++ b/lib/src/common/security.cc @@ -146,6 +146,46 @@ uint8_t security_128_eia2( uint8_t *key, mac); } +/****************************************************************************** + * Encryption / Decryption + *****************************************************************************/ + +uint8_t security_128_eea1(uint8_t *key, + uint32_t count, + uint8_t bearer, + uint8_t direction, + uint8_t *msg, + uint32_t msg_len, + uint8_t *msg_out){ + + return liblte_security_encryption_eea1(key, + count, + bearer, + direction, + msg, + msg_len * 8, + msg_out); + +} + + +uint8_t security_128_eea2(uint8_t *key, + uint32_t count, + uint8_t bearer, + uint8_t direction, + uint8_t *msg, + uint32_t msg_len, + uint8_t *msg_out){ + + return liblte_security_encryption_eea2(key, + count, + bearer, + direction, + msg, + msg_len * 8, + msg_out); +} + /****************************************************************************** * Authentication *****************************************************************************/ diff --git a/lib/src/upper/pdcp.cc b/lib/src/upper/pdcp.cc index 0acc7f6bd..ed7e13684 100644 --- a/lib/src/upper/pdcp.cc +++ b/lib/src/upper/pdcp.cc @@ -51,7 +51,11 @@ void pdcp::init(srsue::rlc_interface_pdcp *rlc_, srsue::rrc_interface_pdcp *rrc_ } void pdcp::stop() -{} +{ + for(uint32_t i=0;iinfo("Added bearer %s\n", rrc->get_rb_name(lcid).c_str()); + pdcp_log->info("Added bearer %s\n", get_rb_name(lcid)); } else { - pdcp_log->warning("Bearer %s already configured. Reconfiguration not supported\n", rrc->get_rb_name(lcid).c_str()); + pdcp_log->warning("Bearer %s already configured. Reconfiguration not supported\n", get_rb_name(lcid)); } } @@ -104,6 +108,12 @@ void pdcp::config_security(uint32_t lcid, pdcp_array[lcid].config_security(k_rrc_enc, k_rrc_int, cipher_algo, integ_algo); } +void pdcp::enable_encryption(uint32_t lcid) +{ + if(valid_lcid(lcid)) + pdcp_array[lcid].enable_encryption(); +} + /******************************************************************************* RLC interface *******************************************************************************/ diff --git a/lib/src/upper/pdcp_entity.cc b/lib/src/upper/pdcp_entity.cc index 9f658a577..066bb127f 100644 --- a/lib/src/upper/pdcp_entity.cc +++ b/lib/src/upper/pdcp_entity.cc @@ -45,25 +45,37 @@ void pdcp_entity::init(srsue::rlc_interface_pdcp *rlc_, uint32_t lcid_, srslte_pdcp_config_t cfg_) { - rlc = rlc_; - rrc = rrc_; - gw = gw_; - log = log_; - lcid = lcid_; - cfg = cfg_; - active = true; - - tx_count = 0; - rx_count = 0; + rlc = rlc_; + rrc = rrc_; + gw = gw_; + log = log_; + lcid = lcid_; + cfg = cfg_; + active = true; + tx_count = 0; + rx_count = 0; + do_integrity = false; + do_encryption = false; + + start(PDCP_THREAD_PRIO); + + log->debug("Init %s\n", get_rb_name(lcid)); +} - log->debug("Init %s\n", rrc->get_rb_name(lcid).c_str()); +void pdcp_entity::stop() +{ + if(running) { + running = false; + thread_cancel(); + wait_thread_finish(); + } } void pdcp_entity::reset() { active = false; if(log) - log->debug("Reset %s\n", rrc->get_rb_name(lcid).c_str()); + log->debug("Reset %s\n", get_rb_name(lcid)); } bool pdcp_entity::is_active() @@ -74,17 +86,15 @@ bool pdcp_entity::is_active() // RRC interface void pdcp_entity::write_sdu(byte_buffer_t *sdu) { - log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU, do_security = %s", rrc->get_rb_name(lcid).c_str(), (cfg.do_security)?"true":"false"); + log->info_hex(sdu->msg, sdu->N_bytes, + "TX %s SDU, do_integrity = %s, do_encryption = %s", get_rb_name(lcid), + (do_integrity) ? "true" : "false", (do_encryption) ? "true" : "false"); if (cfg.is_control) { pdcp_pack_control_pdu(tx_count, sdu); - if(cfg.do_security) + if(do_integrity) { - integrity_generate(&k_rrc_int[16], - tx_count, - lcid-1, - cfg.direction, - sdu->msg, + integrity_generate(sdu->msg, sdu->N_bytes-4, &sdu->msg[sdu->N_bytes-4]); } @@ -107,7 +117,7 @@ void pdcp_entity::config_security(uint8_t *k_rrc_enc_, CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) { - cfg.do_security = true; + do_integrity = true; for(int i=0; i<32; i++) { k_rrc_enc[i] = k_rrc_enc_[i]; @@ -117,43 +127,18 @@ void pdcp_entity::config_security(uint8_t *k_rrc_enc_, integ_algo = integ_algo_; } +void pdcp_entity::enable_encryption() +{ + do_encryption = true; +} + // RLC interface void pdcp_entity::write_pdu(byte_buffer_t *pdu) { - - - - - - if (cfg.is_data) { - uint32_t sn; - if(12 == cfg.sn_len) - { - pdcp_unpack_data_pdu_long_sn(pdu, &sn); - } else { - pdcp_unpack_data_pdu_short_sn(pdu, &sn); - } - log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU: %d", rrc->get_rb_name(lcid).c_str(), sn); - gw->write_pdu(lcid, pdu); - } else { - if (cfg.is_control) { - uint32_t sn; - pdcp_unpack_control_pdu(pdu, &sn); - log->info_hex(pdu->msg, pdu->N_bytes, "RX %s SDU SN: %d", - rrc->get_rb_name(lcid).c_str(), sn); - } else { - log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU", rrc->get_rb_name(lcid).c_str()); - } - // pass to RRC - rrc->write_pdu(lcid, pdu); - } + rx_pdu_queue.write(pdu); } -void pdcp_entity::integrity_generate( uint8_t *key_128, - uint32_t count, - uint8_t rb_id, - uint8_t direction, - uint8_t *msg, +void pdcp_entity::integrity_generate( uint8_t *msg, uint32_t msg_len, uint8_t *mac) { @@ -162,19 +147,19 @@ void pdcp_entity::integrity_generate( uint8_t *key_128, case INTEGRITY_ALGORITHM_ID_EIA0: break; case INTEGRITY_ALGORITHM_ID_128_EIA1: - security_128_eia1(key_128, - count, - rb_id, - direction, + security_128_eia1(&k_rrc_int[16], + tx_count, + lcid-1, + cfg.direction, msg, msg_len, mac); break; case INTEGRITY_ALGORITHM_ID_128_EIA2: - security_128_eia2(key_128, - count, - rb_id, - direction, + security_128_eia2(&k_rrc_int[16], + tx_count, + lcid-1, + cfg.direction, msg, msg_len, mac); @@ -184,6 +169,198 @@ void pdcp_entity::integrity_generate( uint8_t *key_128, } } +bool pdcp_entity::integrity_verify(uint8_t *msg, + uint32_t count, + uint32_t msg_len, + uint8_t *mac) +{ + uint8_t mac_exp[4] = {0x00}; + uint8_t i = 0; + bool isValid = true; + + switch(integ_algo) + { + case INTEGRITY_ALGORITHM_ID_EIA0: + break; + case INTEGRITY_ALGORITHM_ID_128_EIA1: + security_128_eia1(&k_rrc_int[16], + count, + lcid-1, + ( cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK), + msg, + msg_len, + mac_exp); + break; + case INTEGRITY_ALGORITHM_ID_128_EIA2: + security_128_eia2(&k_rrc_int[16], + count, + lcid-1, + ( cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK), + msg, + msg_len, + mac_exp); + break; + default: + break; + } + + switch(integ_algo) + { + case INTEGRITY_ALGORITHM_ID_EIA0: + break; + case INTEGRITY_ALGORITHM_ID_128_EIA1: // Intentional fall-through + case INTEGRITY_ALGORITHM_ID_128_EIA2: + for(i=0; i<4; i++){ + if(mac[i] != mac_exp[i]){ + log->error_hex(mac_exp, 4, "MAC mismatch (expected)"); + log->error_hex(mac, 4, "MAC mismatch (found)"); + isValid = false; + break; + } + } + if (isValid){ + log->info_hex(mac_exp, 4, "MAC match (expected)"); + log->info_hex(mac, 4, "MAC match (found)"); + } + break; + default: + break; + } + + return isValid; +} + +void pdcp_entity::cipher_encrypt(uint8_t *msg, + uint32_t msg_len, + uint8_t *ct) +{ + byte_buffer_t ct_tmp; + switch(cipher_algo) + { + case CIPHERING_ALGORITHM_ID_EEA0: + break; + case CIPHERING_ALGORITHM_ID_128_EEA1: + security_128_eea1(&(k_rrc_enc[16]), + tx_count, + lcid - 1, + cfg.direction, + msg, + msg_len, + ct_tmp.msg); + memcpy(ct, ct_tmp.msg, msg_len); + break; + case CIPHERING_ALGORITHM_ID_128_EEA2: + security_128_eea2(&(k_rrc_enc[16]), + tx_count, + lcid - 1, + cfg.direction, + msg, + msg_len, + ct_tmp.msg); + memcpy(ct, ct_tmp.msg, msg_len); + break; + default: + break; + } +} + +void pdcp_entity::cipher_decrypt(uint8_t *ct, + uint32_t count, + uint32_t ct_len, + uint8_t *msg) +{ + byte_buffer_t msg_tmp; + switch(cipher_algo) + { + case CIPHERING_ALGORITHM_ID_EEA0: + break; + case CIPHERING_ALGORITHM_ID_128_EEA1: + security_128_eea1(&(k_rrc_enc[16]), + count, + lcid - 1, + ( cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK), + ct, + ct_len, + msg_tmp.msg); + break; + case CIPHERING_ALGORITHM_ID_128_EEA2: + security_128_eea2(&(k_rrc_enc[16]), + count, + lcid - 1, + ( cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK), + ct, + ct_len, + msg_tmp.msg); + memcpy(msg, msg_tmp.msg, ct_len); + break; + default: + break; + } +} + + +void pdcp_entity::run_thread() +{ + byte_buffer_t *pdu; + running = true; + + while(running) { + rx_pdu_queue.read(&pdu); + + // Handle SRB messages + switch(lcid) + { + case RB_ID_SRB0: + // Simply pass on to RRC + log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU", get_rb_name(lcid)); + rrc->write_pdu(RB_ID_SRB0, pdu); + break; + case RB_ID_SRB1: // Intentional fall-through + case RB_ID_SRB2: + uint32_t sn; + + log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU", get_rb_name(lcid)); + + if (do_encryption) { + cipher_decrypt(&(pdu->msg[1]), + pdu->msg[0], + pdu->N_bytes - 1, + &(pdu->msg[1])); + log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU (decrypted)", get_rb_name(lcid)); + } + + if (do_integrity) { + integrity_verify(pdu->msg, + pdu->msg[0], + pdu->N_bytes - 4, + &(pdu->msg[pdu->N_bytes - 4])); + } + + pdcp_unpack_control_pdu(pdu, &sn); + log->info_hex(pdu->msg, pdu->N_bytes, "RX %s SDU SN: %d", + get_rb_name(lcid), sn); + rrc->write_pdu(lcid, pdu); + break; + } + + // Handle DRB messages + if(lcid >= RB_ID_DRB1) + { + uint32_t sn; + if(12 == cfg.sn_len) + { + pdcp_unpack_data_pdu_long_sn(pdu, &sn); + } else { + pdcp_unpack_data_pdu_short_sn(pdu, &sn); + } + log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU: %d", get_rb_name(lcid), sn); + gw->write_pdu(lcid, pdu); + } + } +} + + + /**************************************************************************** * Pack/Unpack helper functions * Ref: 3GPP TS 36.323 v10.1.0 diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index f506ebc63..c16a09cab 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -123,11 +123,6 @@ void rlc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) } } -std::string rlc::get_rb_name(uint32_t lcid) -{ - return rrc->get_rb_name(lcid); -} - /******************************************************************************* MAC interface *******************************************************************************/ @@ -217,11 +212,10 @@ void rlc::add_bearer(uint32_t lcid) cnfg.dl_am_rlc.t_status_prohibit = LIBLTE_RRC_T_STATUS_PROHIBIT_MS0; add_bearer(lcid, srslte_rlc_config_t(&cnfg)); } else { - rlc_log->warning("Bearer %s already configured. Reconfiguration not supported\n", get_rb_name(lcid).c_str()); + rlc_log->warning("Bearer %s already configured. Reconfiguration not supported\n", get_rb_name(lcid)); } }else{ - rlc_log->error("Radio bearer %s does not support default RLC configuration.\n", - get_rb_name(lcid).c_str()); + rlc_log->error("Radio bearer %s does not support default RLC configuration.\n", get_rb_name(lcid)); } } @@ -234,7 +228,7 @@ void rlc::add_bearer(uint32_t lcid, srslte_rlc_config_t cnfg) if (!rlc_array[lcid].active()) { rlc_log->info("Adding radio bearer %s with mode %s\n", - get_rb_name(lcid).c_str(), liblte_rrc_rlc_mode_text[cnfg.rlc_mode]); + get_rb_name(lcid), liblte_rrc_rlc_mode_text[cnfg.rlc_mode]); switch(cnfg.rlc_mode) { case LIBLTE_RRC_RLC_MODE_AM: @@ -254,7 +248,7 @@ void rlc::add_bearer(uint32_t lcid, srslte_rlc_config_t cnfg) return; } } else { - rlc_log->warning("Bearer %s already created.\n", get_rb_name(lcid).c_str()); + rlc_log->warning("Bearer %s already created.\n", get_rb_name(lcid)); } rlc_array[lcid].configure(cnfg); diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index f8abc0aef..c048133d6 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -79,7 +79,7 @@ void rlc_am::configure(srslte_rlc_config_t cfg_) cfg = cfg_.am; log->info("%s configured: t_poll_retx=%d, poll_pdu=%d, poll_byte=%d, max_retx_thresh=%d, " "t_reordering=%d, t_status_prohibit=%d\n", - rrc->get_rb_name(lcid).c_str(), cfg.t_poll_retx, cfg.poll_pdu, cfg.poll_byte, cfg.max_retx_thresh, + get_rb_name(lcid), cfg.t_poll_retx, cfg.poll_pdu, cfg.poll_byte, cfg.max_retx_thresh, cfg.t_reordering, cfg.t_status_prohibit); } @@ -175,7 +175,7 @@ uint32_t rlc_am::get_bearer() void rlc_am::write_sdu(byte_buffer_t *sdu) { - log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU", rrc->get_rb_name(lcid).c_str()); + log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU", get_rb_name(lcid)); tx_sdu_queue.write(sdu); } @@ -359,7 +359,7 @@ void rlc_am::check_reordering_timeout() if(reordering_timeout.is_running() && reordering_timeout.expired()) { reordering_timeout.reset(); - log->debug("%s reordering timeout expiry - updating vr_ms\n", rrc->get_rb_name(lcid).c_str()); + log->debug("%s reordering timeout expiry - updating vr_ms\n", get_rb_name(lcid)); // 36.322 v10 Section 5.1.3.2.4 vr_ms = vr_x; @@ -433,7 +433,7 @@ int rlc_am::build_status_pdu(uint8_t *payload, uint32_t nof_bytes) if(pdu_len > 0 && nof_bytes >= (uint32_t)pdu_len) { log->info("%s Tx status PDU - %s\n", - rrc->get_rb_name(lcid).c_str(), rlc_am_to_string(&status).c_str()); + get_rb_name(lcid), rlc_am_to_string(&status).c_str()); do_status = false; poll_received = false; @@ -444,7 +444,7 @@ int rlc_am::build_status_pdu(uint8_t *payload, uint32_t nof_bytes) return rlc_am_write_status_pdu(&status, payload); }else{ log->warning("%s Cannot tx status PDU - %d bytes available, %d bytes required\n", - rrc->get_rb_name(lcid).c_str(), nof_bytes, pdu_len); + get_rb_name(lcid), nof_bytes, pdu_len); return 0; } } @@ -478,7 +478,7 @@ int rlc_am::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes) return -1; } if(retx.is_segment || req_size > (int)nof_bytes) { - log->debug("%s build_retx_pdu - resegmentation required\n", rrc->get_rb_name(lcid).c_str()); + log->debug("%s build_retx_pdu - resegmentation required\n", get_rb_name(lcid)); return build_segment(payload, nof_bytes, retx); } @@ -503,7 +503,7 @@ int rlc_am::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes) if(tx_window[retx.sn].retx_count >= cfg.max_retx_thresh) rrc->max_retx_attempted(); log->info("%s Retx PDU scheduled for tx. SN: %d, retx count: %d\n", - rrc->get_rb_name(lcid).c_str(), retx.sn, tx_window[retx.sn].retx_count); + get_rb_name(lcid), retx.sn, tx_window[retx.sn].retx_count); debug_state(); return (ptr-payload) + tx_window[retx.sn].buf->N_bytes; @@ -540,7 +540,7 @@ int rlc_am::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_amd_retx_t r if(nof_bytes <= head_len) { log->warning("%s Cannot build a PDU segment - %d bytes available, %d bytes required for header\n", - rrc->get_rb_name(lcid).c_str(), nof_bytes, head_len); + get_rb_name(lcid), nof_bytes, head_len); return 0; } pdu_space = nof_bytes-head_len; @@ -606,15 +606,15 @@ int rlc_am::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_amd_retx_t r memcpy(ptr, data, len); log->info("%s Retx PDU segment scheduled for tx. SN: %d, SO: %d\n", - rrc->get_rb_name(lcid).c_str(), retx.sn, retx.so_start); + get_rb_name(lcid), retx.sn, retx.so_start); debug_state(); int pdu_len = (ptr-payload) + len; if(pdu_len > (int)nof_bytes) { log->error("%s Retx PDU segment length error. Available: %d, Used: %d\n", - rrc->get_rb_name(lcid).c_str(), nof_bytes, pdu_len); + get_rb_name(lcid), nof_bytes, pdu_len); log->debug("%s Retx PDU segment length error. Header len: %d, Payload len: %d, N_li: %d\n", - rrc->get_rb_name(lcid).c_str(), (ptr-payload), len, new_header.N_li); + get_rb_name(lcid), (ptr-payload), len, new_header.N_li); } return pdu_len; @@ -662,13 +662,13 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) 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); + get_rb_name(lcid), nof_bytes, head_len); pool->deallocate(pdu); return 0; } log->debug("%s Building PDU - pdu_space: %d, head_len: %d \n", - rrc->get_rb_name(lcid).c_str(), pdu_space, head_len); + get_rb_name(lcid), pdu_space, head_len); // Check for SDU segment if(tx_sdu) @@ -683,7 +683,7 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) if(tx_sdu->N_bytes == 0) { log->info("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", - rrc->get_rb_name(lcid).c_str(), tx_sdu->get_latency_us()); + get_rb_name(lcid), tx_sdu->get_latency_us()); pool->deallocate(tx_sdu); tx_sdu = NULL; } @@ -694,7 +694,7 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) header.fi |= RLC_FI_FIELD_NOT_START_ALIGNED; // First byte does not correspond to first byte of SDU log->debug("%s Building PDU - added SDU segment (len:%d) - pdu_space: %d, head_len: %d \n", - rrc->get_rb_name(lcid).c_str(), to_move, pdu_space, head_len); + get_rb_name(lcid), to_move, pdu_space, head_len); } // Pull SDUs from queue @@ -718,7 +718,7 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) if(tx_sdu->N_bytes == 0) { log->info("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", - rrc->get_rb_name(lcid).c_str(), tx_sdu->get_latency_us()); + get_rb_name(lcid), tx_sdu->get_latency_us()); pool->deallocate(tx_sdu); tx_sdu = NULL; } @@ -728,7 +728,7 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) pdu_space = 0; log->debug("%s Building PDU - added SDU segment (len:%d) - pdu_space: %d, head_len: %d \n", - rrc->get_rb_name(lcid).c_str(), to_move, pdu_space, head_len); + get_rb_name(lcid), to_move, pdu_space, head_len); } if(tx_sdu) @@ -737,11 +737,11 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) // Set Poll bit pdu_without_poll++; byte_without_poll += (pdu->N_bytes + head_len); - log->debug("%s pdu_without_poll: %d\n", rrc->get_rb_name(lcid).c_str(), pdu_without_poll); - log->debug("%s byte_without_poll: %d\n", rrc->get_rb_name(lcid).c_str(), byte_without_poll); + log->debug("%s pdu_without_poll: %d\n", get_rb_name(lcid), pdu_without_poll); + log->debug("%s byte_without_poll: %d\n", get_rb_name(lcid), byte_without_poll); if(poll_required()) { - log->debug("%s setting poll bit to request status\n", rrc->get_rb_name(lcid).c_str()); + log->debug("%s setting poll bit to request status\n", get_rb_name(lcid)); header.p = 1; poll_sn = vt_s; pdu_without_poll = 0; @@ -752,7 +752,7 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) // Set SN header.sn = vt_s; vt_s = (vt_s + 1)%MOD; - log->info("%s PDU scheduled for tx. SN: %d\n", rrc->get_rb_name(lcid).c_str(), header.sn); + log->info("%s PDU scheduled for tx. SN: %d\n", get_rb_name(lcid), header.sn); // Place PDU in tx_window, write header and TX tx_window[header.sn].buf = pdu; @@ -773,26 +773,26 @@ void rlc_am::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes, rlc_amd_pdu_h std::map::iterator it; log->info_hex(payload, nof_bytes, "%s Rx data PDU SN: %d", - rrc->get_rb_name(lcid).c_str(), header.sn); + get_rb_name(lcid), header.sn); if(!inside_rx_window(header.sn)) { if(header.p) { - log->info("%s Status packet requested through polling bit\n", rrc->get_rb_name(lcid).c_str()); + log->info("%s Status packet requested through polling bit\n", get_rb_name(lcid)); do_status = true; } log->info("%s SN: %d outside rx window [%d:%d] - discarding\n", - rrc->get_rb_name(lcid).c_str(), header.sn, vr_r, vr_mr); + get_rb_name(lcid), header.sn, vr_r, vr_mr); return; } it = rx_window.find(header.sn); if(rx_window.end() != it) { if(header.p) { - log->info("%s Status packet requested through polling bit\n", rrc->get_rb_name(lcid).c_str()); + log->info("%s Status packet requested through polling bit\n", get_rb_name(lcid)); do_status = true; } log->info("%s Discarding duplicate SN: %d\n", - rrc->get_rb_name(lcid).c_str(), header.sn); + get_rb_name(lcid), header.sn); return; } @@ -825,7 +825,7 @@ void rlc_am::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes, rlc_amd_pdu_h // Check poll bit if(header.p) { - log->info("%s Status packet requested through polling bit\n", rrc->get_rb_name(lcid).c_str()); + log->info("%s Status packet requested through polling bit\n", get_rb_name(lcid)); poll_received = true; // 36.322 v10 Section 5.2.3 @@ -870,16 +870,16 @@ void rlc_am::handle_data_pdu_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a std::map::iterator it; log->info_hex(payload, nof_bytes, "%s Rx data PDU segment. SN: %d, SO: %d", - rrc->get_rb_name(lcid).c_str(), header.sn, header.so); + get_rb_name(lcid), header.sn, header.so); // Check inside rx window if(!inside_rx_window(header.sn)) { if(header.p) { - log->info("%s Status packet requested through polling bit\n", rrc->get_rb_name(lcid).c_str()); + log->info("%s Status packet requested through polling bit\n", get_rb_name(lcid)); do_status = true; } log->info("%s SN: %d outside rx window [%d:%d] - discarding\n", - rrc->get_rb_name(lcid).c_str(), header.sn, vr_r, vr_mr); + get_rb_name(lcid), header.sn, vr_r, vr_mr); return; } @@ -898,7 +898,7 @@ void rlc_am::handle_data_pdu_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a if(rx_segments.end() != it) { if(header.p) { - log->info("%s Status packet requested through polling bit\n", rrc->get_rb_name(lcid).c_str()); + log->info("%s Status packet requested through polling bit\n", get_rb_name(lcid)); do_status = true; } @@ -928,7 +928,7 @@ void rlc_am::handle_data_pdu_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a // Check poll bit if(header.p) { - log->info("%s Status packet requested through polling bit\n", rrc->get_rb_name(lcid).c_str()); + log->info("%s Status packet requested through polling bit\n", get_rb_name(lcid)); poll_received = true; // 36.322 v10 Section 5.2.3 @@ -946,12 +946,12 @@ void rlc_am::handle_data_pdu_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a void rlc_am::handle_control_pdu(uint8_t *payload, uint32_t nof_bytes) { - log->info_hex(payload, nof_bytes, "%s Rx control PDU", rrc->get_rb_name(lcid).c_str()); + log->info_hex(payload, nof_bytes, "%s Rx control PDU", get_rb_name(lcid)); rlc_status_pdu_t status; rlc_am_read_status_pdu(payload, nof_bytes, &status); - log->info("%s Rx Status PDU: %s\n", rrc->get_rb_name(lcid).c_str(), rlc_am_to_string(&status).c_str()); + log->info("%s Rx Status PDU: %s\n", get_rb_name(lcid), rlc_am_to_string(&status).c_str()); poll_retx_timeout.reset(); @@ -989,7 +989,7 @@ void rlc_am::handle_control_pdu(uint8_t *payload, uint32_t nof_bytes) } } else { log->warning("%s invalid segment NACK received for SN %d. so_start: %d, so_end: %d, N_bytes: %d\n", - rrc->get_rb_name(lcid).c_str(), i, status.nacks[j].so_start, status.nacks[j].so_end, it->second.buf->N_bytes); + get_rb_name(lcid), i, status.nacks[j].so_start, status.nacks[j].so_end, it->second.buf->N_bytes); } } @@ -1043,7 +1043,7 @@ void rlc_am::reassemble_rx_sdus() rx_sdu->N_bytes += len; rx_window[vr_r].buf->msg += len; rx_window[vr_r].buf->N_bytes -= len; - log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU", rrc->get_rb_name(lcid).c_str()); + log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU", get_rb_name(lcid)); rx_sdu->set_timestamp(); pdcp->write_pdu(lcid, rx_sdu); rx_sdu = pool_allocate; @@ -1059,7 +1059,7 @@ void rlc_am::reassemble_rx_sdus() rx_sdu->N_bytes += rx_window[vr_r].buf->N_bytes; if(rlc_am_end_aligned(rx_window[vr_r].header.fi)) { - log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU", rrc->get_rb_name(lcid).c_str()); + log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU", get_rb_name(lcid)); rx_sdu->set_timestamp(); pdcp->write_pdu(lcid, rx_sdu); rx_sdu = pool_allocate; @@ -1103,7 +1103,7 @@ void rlc_am::debug_state() { log->debug("%s vt_a = %d, vt_ms = %d, vt_s = %d, poll_sn = %d " "vr_r = %d, vr_mr = %d, vr_x = %d, vr_ms = %d, vr_h = %d\n", - rrc->get_rb_name(lcid).c_str(), vt_a, vt_ms, vt_s, poll_sn, + get_rb_name(lcid), vt_a, vt_ms, vt_s, poll_sn, vr_r, vr_mr, vr_x, vr_ms, vr_h); } diff --git a/lib/src/upper/rlc_tm.cc b/lib/src/upper/rlc_tm.cc index 627752494..4559dd07b 100644 --- a/lib/src/upper/rlc_tm.cc +++ b/lib/src/upper/rlc_tm.cc @@ -84,7 +84,7 @@ uint32_t rlc_tm::get_bearer() // PDCP interface void rlc_tm::write_sdu(byte_buffer_t *sdu) { - log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU", rrc->get_rb_name(lcid).c_str()); + log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU", get_rb_name(lcid)); ul_queue.write(sdu); } @@ -104,7 +104,7 @@ int rlc_tm::read_pdu(uint8_t *payload, uint32_t nof_bytes) uint32_t pdu_size = ul_queue.size_tail_bytes(); if(pdu_size > nof_bytes) { - log->error("TX %s PDU size larger than MAC opportunity\n", rrc->get_rb_name(lcid).c_str()); + log->error("TX %s PDU size larger than MAC opportunity\n", get_rb_name(lcid)); return 0; } byte_buffer_t *buf; @@ -112,9 +112,9 @@ int rlc_tm::read_pdu(uint8_t *payload, uint32_t nof_bytes) pdu_size = buf->N_bytes; memcpy(payload, buf->msg, buf->N_bytes); log->info("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", - rrc->get_rb_name(lcid).c_str(), buf->get_latency_us()); + get_rb_name(lcid), buf->get_latency_us()); pool->deallocate(buf); - log->info_hex(payload, pdu_size, "TX %s, %s PDU", rrc->get_rb_name(lcid).c_str(), rlc_mode_text[RLC_MODE_TM]); + log->info_hex(payload, pdu_size, "TX %s, %s PDU", get_rb_name(lcid), rlc_mode_text[RLC_MODE_TM]); return pdu_size; } diff --git a/lib/src/upper/rlc_um.cc b/lib/src/upper/rlc_um.cc index 4756e2f7c..5b395228f 100644 --- a/lib/src/upper/rlc_um.cc +++ b/lib/src/upper/rlc_um.cc @@ -75,18 +75,18 @@ void rlc_um::configure(srslte_rlc_config_t cnfg_) case LIBLTE_RRC_RLC_MODE_UM_BI: log->info("%s configured in %s mode: " "t_reordering=%d ms, rx_sn_field_length=%u bits, tx_sn_field_length=%u bits\n", - rrc->get_rb_name(lcid).c_str(), liblte_rrc_rlc_mode_text[cnfg_.rlc_mode], + get_rb_name(lcid), liblte_rrc_rlc_mode_text[cnfg_.rlc_mode], cfg.t_reordering, rlc_umd_sn_size_num[cfg.rx_sn_field_length], rlc_umd_sn_size_num[cfg.rx_sn_field_length]); break; case LIBLTE_RRC_RLC_MODE_UM_UNI_UL: log->info("%s configured in %s mode: tx_sn_field_length=%u bits\n", - rrc->get_rb_name(lcid).c_str(), liblte_rrc_rlc_mode_text[cnfg_.rlc_mode], + get_rb_name(lcid), liblte_rrc_rlc_mode_text[cnfg_.rlc_mode], rlc_umd_sn_size_num[cfg.rx_sn_field_length]); break; case LIBLTE_RRC_RLC_MODE_UM_UNI_DL: log->info("%s configured in %s mode: " "t_reordering=%d ms, rx_sn_field_length=%u bits\n", - rrc->get_rb_name(lcid).c_str(), liblte_rrc_rlc_mode_text[cnfg_.rlc_mode], + get_rb_name(lcid), liblte_rrc_rlc_mode_text[cnfg_.rlc_mode], cfg.t_reordering, rlc_umd_sn_size_num[cfg.rx_sn_field_length]); break; default: @@ -153,7 +153,7 @@ uint32_t rlc_um::get_bearer() void rlc_um::write_sdu(byte_buffer_t *sdu) { - log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU", rrc->get_rb_name(lcid).c_str()); + log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU", get_rb_name(lcid)); tx_sdu_queue.write(sdu); } @@ -216,7 +216,7 @@ void rlc_um::timer_expired(uint32_t timeout_id) // 36.322 v10 Section 5.1.2.2.4 log->info("%s reordering timeout expiry - updating vr_ur and reassembling\n", - rrc->get_rb_name(lcid).c_str()); + get_rb_name(lcid)); log->warning("Lost PDU SN: %d\n", vr_ur); pdu_lost = true; @@ -281,7 +281,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) { 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); + get_rb_name(lcid), nof_bytes, head_len); return 0; } @@ -291,7 +291,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) uint32_t space = pdu_space-head_len; to_move = space >= tx_sdu->N_bytes ? tx_sdu->N_bytes : space; log->debug("%s adding remainder of SDU segment - %d bytes of %d remaining\n", - rrc->get_rb_name(lcid).c_str(), to_move, tx_sdu->N_bytes); + get_rb_name(lcid), to_move, tx_sdu->N_bytes); memcpy(pdu_ptr, tx_sdu->msg, to_move); last_li = to_move; pdu_ptr += to_move; @@ -301,7 +301,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) if(tx_sdu->N_bytes == 0) { log->info("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", - rrc->get_rb_name(lcid).c_str(), tx_sdu->get_latency_us()); + get_rb_name(lcid), tx_sdu->get_latency_us()); pool->deallocate(tx_sdu); tx_sdu = NULL; } @@ -320,7 +320,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) uint32_t space = pdu_space-head_len; to_move = space >= tx_sdu->N_bytes ? tx_sdu->N_bytes : space; log->debug("%s adding new SDU segment - %d bytes of %d remaining\n", - rrc->get_rb_name(lcid).c_str(), to_move, tx_sdu->N_bytes); + get_rb_name(lcid), to_move, tx_sdu->N_bytes); memcpy(pdu_ptr, tx_sdu->msg, to_move); last_li = to_move; pdu_ptr += to_move; @@ -330,7 +330,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) if(tx_sdu->N_bytes == 0) { log->info("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", - rrc->get_rb_name(lcid).c_str(), tx_sdu->get_latency_us()); + get_rb_name(lcid), tx_sdu->get_latency_us()); pool->deallocate(tx_sdu); tx_sdu = NULL; } @@ -345,11 +345,11 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) vt_us = (vt_us + 1)%cfg.tx_mod; // Add header and TX - log->debug("%s packing PDU with length %d\n", rrc->get_rb_name(lcid).c_str(), pdu->N_bytes); + log->debug("%s packing PDU with length %d\n", get_rb_name(lcid), pdu->N_bytes); rlc_um_write_data_pdu_header(&header, pdu); memcpy(payload, pdu->msg, pdu->N_bytes); uint32_t ret = pdu->N_bytes; - log->debug("%s returning length %d\n", rrc->get_rb_name(lcid).c_str(), pdu->N_bytes); + log->debug("%s returning length %d\n", get_rb_name(lcid), pdu->N_bytes); pool->deallocate(pdu); debug_state(); @@ -363,20 +363,20 @@ void rlc_um::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes) rlc_um_read_data_pdu_header(payload, nof_bytes, cfg.rx_sn_field_length, &header); log->info_hex(payload, nof_bytes, "RX %s Rx data PDU SN: %d", - rrc->get_rb_name(lcid).c_str(), header.sn); + get_rb_name(lcid), header.sn); if(RX_MOD_BASE(header.sn) >= RX_MOD_BASE(vr_uh-cfg.rx_window_size) && RX_MOD_BASE(header.sn) < RX_MOD_BASE(vr_ur)) { log->info("%s SN: %d outside rx window [%d:%d] - discarding\n", - rrc->get_rb_name(lcid).c_str(), header.sn, vr_ur, vr_uh); + get_rb_name(lcid), header.sn, vr_ur, vr_uh); return; } it = rx_window.find(header.sn); if(rx_window.end() != it) { log->info("%s Discarding duplicate SN: %d\n", - rrc->get_rb_name(lcid).c_str(), header.sn); + get_rb_name(lcid), header.sn); return; } @@ -451,7 +451,7 @@ void rlc_um::reassemble_rx_sdus() log->warning("Dropping remainder of lost PDU (lower edge middle segments, vr_ur=%d, vr_ur_in_rx_sdu=%d)\n", vr_ur, vr_ur_in_rx_sdu); rx_sdu->reset(); } else { - log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d, i=%d (lower edge middle segments)", rrc->get_rb_name(lcid).c_str(), vr_ur, i); + log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d, i=%d (lower edge middle segments)", get_rb_name(lcid), vr_ur, i); rx_sdu->set_timestamp(); pdcp->write_pdu(lcid, rx_sdu); rx_sdu = pool_allocate; @@ -471,7 +471,7 @@ void rlc_um::reassemble_rx_sdus() log->warning("Dropping remainder of lost PDU (lower edge last segments)\n"); rx_sdu->reset(); } else { - log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d (lower edge last segments)", rrc->get_rb_name(lcid).c_str(), vr_ur); + log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d (lower edge last segments)", get_rb_name(lcid), vr_ur); rx_sdu->set_timestamp(); pdcp->write_pdu(lcid, rx_sdu); rx_sdu = pool_allocate; @@ -505,7 +505,7 @@ void rlc_um::reassemble_rx_sdus() log->warning("Dropping remainder of lost PDU (update vr_ur middle segments, vr_ur=%d, vr_ur_in_rx_sdu=%d)\n", vr_ur, vr_ur_in_rx_sdu); rx_sdu->reset(); } else { - log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d, i=%d, (update vr_ur middle segments)", rrc->get_rb_name(lcid).c_str(), vr_ur, i); + log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d, i=%d, (update vr_ur middle segments)", get_rb_name(lcid), vr_ur, i); rx_sdu->set_timestamp(); pdcp->write_pdu(lcid, rx_sdu); rx_sdu = pool_allocate; @@ -534,7 +534,7 @@ void rlc_um::reassemble_rx_sdus() log->warning("Dropping remainder of lost PDU (update vr_ur last segments)\n"); rx_sdu->reset(); } else { - log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d (update vr_ur last segments)", rrc->get_rb_name(lcid).c_str(), vr_ur); + log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d (update vr_ur last segments)", get_rb_name(lcid), vr_ur); rx_sdu->set_timestamp(); pdcp->write_pdu(lcid, rx_sdu); rx_sdu = pool_allocate; @@ -564,7 +564,7 @@ bool rlc_um::inside_reordering_window(uint16_t sn) void rlc_um::debug_state() { log->debug("%s vt_us = %d, vr_ur = %d, vr_ux = %d, vr_uh = %d \n", - rrc->get_rb_name(lcid).c_str(), vt_us, vr_ur, vr_ux, vr_uh); + get_rb_name(lcid), vt_us, vr_ur, vr_ux, vr_uh); } diff --git a/srsue/hdr/ue.h b/srsue/hdr/ue.h index 4e48f6b6d..b559396be 100644 --- a/srsue/hdr/ue.h +++ b/srsue/hdr/ue.h @@ -88,6 +88,7 @@ private: srsue::phy phy; srsue::mac mac; srslte::mac_pcap mac_pcap; + srslte::nas_pcap nas_pcap; srslte::rlc rlc; srslte::pdcp pdcp; srsue::rrc rrc; diff --git a/srsue/hdr/ue_base.h b/srsue/hdr/ue_base.h index e23adf3d2..8e5ce22a9 100644 --- a/srsue/hdr/ue_base.h +++ b/srsue/hdr/ue_base.h @@ -69,6 +69,8 @@ typedef struct { typedef struct { bool enable; std::string filename; + bool nas_enable; + std::string nas_filename; }pcap_args_t; typedef struct { diff --git a/srsue/hdr/upper/nas.h b/srsue/hdr/upper/nas.h index 2e795098e..5ab77f28c 100644 --- a/srsue/hdr/upper/nas.h +++ b/srsue/hdr/upper/nas.h @@ -33,6 +33,7 @@ #include "srslte/interfaces/ue_interfaces.h" #include "srslte/common/security.h" #include "srslte/asn1/liblte_mme.h" +#include "srslte/common/nas_pcap.h" using srslte::byte_buffer_t; @@ -57,8 +58,8 @@ static const char emm_state_text[EMM_STATE_N_ITEMS][100] = {"NULL", "DEREGISTERED INITIATED", "TRACKING AREA UPDATE INITIATED"}; -static const bool eia_caps[8] = {false, true, true, false, false, false, false, false}; -static const bool eea_caps[8] = {true, false, false, false, false, false, false, false}; +static const bool eia_caps[8] = {false, true, true, false, false, false, false, false}; +static const bool eea_caps[8] = {true, true, true, false, false, false, false, false}; typedef enum { PLMN_NOT_SELECTED = 0, @@ -96,6 +97,9 @@ public: void attach_request(); void deattach_request(); + // PCAP + void start_pcap(srslte::nas_pcap *pcap_); + private: srslte::byte_buffer_pool *pool; srslte::log *nas_log; @@ -140,17 +144,20 @@ private: uint8_t k_nas_enc[32]; uint8_t k_nas_int[32]; - void integrity_generate(uint8_t integ_algo, - uint8_t *key_128, + // PCAP + srslte::nas_pcap *pcap = NULL; + + void integrity_generate(uint8_t *key_128, uint32_t count, uint8_t rb_id, uint8_t direction, uint8_t *msg, uint32_t msg_len, uint8_t *mac); - void integrity_check(); - void cipher_encrypt(); - void cipher_decrypt(); + bool integrity_check(uint32 lcid, byte_buffer_t *pdu); + void cipher_encrypt(uint32 lcid, byte_buffer_t *pdu); + void cipher_decrypt(uint32 lcid, byte_buffer_t *pdu); + bool check_cap_replay(LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT *caps); // Parsers diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index d561b0f1c..489e33314 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -50,11 +50,6 @@ using srslte::byte_buffer_t; namespace srsue { -static std::string rb_id_str[] = {"SRB0", "SRB1", "SRB2", - "DRB1","DRB2","DRB3", - "DRB4","DRB5","DRB6", - "DRB7","DRB8"}; - class rrc :public rrc_interface_nas ,public rrc_interface_phy @@ -208,30 +203,6 @@ private: void write_pdu_bcch_dlsch(byte_buffer_t *pdu); void write_pdu_pcch(byte_buffer_t *pdu); - // Radio bearers - typedef enum{ - RB_ID_SRB0 = 0, - RB_ID_SRB1, - RB_ID_SRB2, - RB_ID_DRB1, - RB_ID_DRB2, - RB_ID_DRB3, - RB_ID_DRB4, - RB_ID_DRB5, - RB_ID_DRB6, - RB_ID_DRB7, - RB_ID_DRB8, - RB_ID_MAX - } rb_id_t; - - std::string get_rb_name(uint32_t lcid) { - if (lcid < RB_ID_MAX) { - return rb_id_str[lcid]; - } else { - return std::string("INVALID_RB"); - } - } - // RLC interface void max_retx_attempted(); diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 1c9b6edc6..0f1ffa61c 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -82,9 +82,11 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { ("rrc.ue_category", bpo::value(&args->ue_category_str)->default_value("4"), "UE Category (1 to 5)") - ("pcap.enable", bpo::value(&args->pcap.enable)->default_value(false), - "Enable MAC packet captures for wireshark") + ("pcap.enable", bpo::value(&args->pcap.enable)->default_value(false), "Enable MAC packet captures for wireshark") ("pcap.filename", bpo::value(&args->pcap.filename)->default_value("ue.pcap"), "MAC layer capture filename") + ("pcap.nas_enable", bpo::value(&args->pcap.nas_enable)->default_value(false), "Enable NAS packet captures for wireshark") + ("pcap.nas_filename", bpo::value(&args->pcap.nas_filename)->default_value("ue_nas.pcap"), "NAS layer capture filename (useful when NAS encryption is enabled)") + ("trace.enable", bpo::value(&args->trace.enable)->default_value(false), "Enable PHY and radio timing traces") ("trace.phy_filename", bpo::value(&args->trace.phy_filename)->default_value("ue.phy_trace"), diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index b7e744bd8..2edf0fed5 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -104,13 +104,15 @@ bool ue::init(all_args_t *args_) usim_log.set_hex_limit(args->log.usim_hex_limit); // Set up pcap and trace - if(args->pcap.enable) - { + if(args->pcap.enable) { mac_pcap.open(args->pcap.filename.c_str()); mac.start_pcap(&mac_pcap); } - if(args->trace.enable) - { + if(args->pcap.nas_enable) { + nas_pcap.open(args->pcap.nas_filename.c_str()); + nas.start_pcap(&nas_pcap); + } + if(args->trace.enable) { phy.start_trace(); radio.start_trace(); } @@ -137,8 +139,7 @@ bool ue::init(all_args_t *args_) } printf("Opening RF device with %d RX antennas...\n", args->rf.nof_rx_ant); - if(!radio.init_multi(args->rf.nof_rx_ant, dev_args, dev_name)) - { + if(!radio.init_multi(args->rf.nof_rx_ant, dev_args, dev_name)) { printf("Failed to find device %s with args %s\n", args->rf.device_name.c_str(), args->rf.device_args.c_str()); return false; @@ -244,12 +245,13 @@ void ue::stop() radio.stop(); usleep(1e5); - if(args->pcap.enable) - { + if(args->pcap.enable) { mac_pcap.close(); } - if(args->trace.enable) - { + if(args->pcap.nas_enable) { + nas_pcap.close(); + } + if(args->trace.enable) { phy.write_trace(args->trace.phy_filename); radio.write_trace(args->trace.radio_filename); } diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index 62e23d852..99e237ba2 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -32,6 +32,7 @@ #include #include "srslte/asn1/liblte_rrc.h" #include "upper/nas.h" +#include "srslte/common/security.h" #include "srslte/common/bcd_helpers.h" using namespace srslte; @@ -190,11 +191,42 @@ void nas::notify_connection_setup() { void nas::write_pdu(uint32_t lcid, byte_buffer_t *pdu) { uint8 pd; uint8 msg_type; + uint8 sec_hdr_type; + bool mac_valid = false; - nas_log->info_hex(pdu->msg, pdu->N_bytes, "DL %s PDU", rrc->get_rb_name(lcid).c_str()); + nas_log->info_hex(pdu->msg, pdu->N_bytes, "DL %s PDU", get_rb_name(lcid)); - // Parse the message + // Parse the message security header + liblte_mme_parse_msg_sec_header((LIBLTE_BYTE_MSG_STRUCT*)pdu, &pd, &sec_hdr_type); + switch(sec_hdr_type) + { + case LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS: + case LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_WITH_NEW_EPS_SECURITY_CONTEXT: + case LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST: + case LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY: + break; + case LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED: + mac_valid = integrity_check(lcid, pdu); + cipher_decrypt(lcid, pdu); + break; + case LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT: + break; + default: + nas_log->error("Not handling NAS message with SEC_HDR_TYPE=%02X\n",msg_type); + pool->deallocate(pdu); + break; + } + + // Write NAS pcap + if(pcap != NULL) { + pcap->write_nas(pdu->msg, pdu->N_bytes); + } + + // Parse the message header liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) pdu, &pd, &msg_type); + nas_log->info_hex(pdu->msg, pdu->N_bytes, "DL %s Decrypted PDU", get_rb_name(lcid)); + // TODO: Check if message type requieres specical security header type and if it isvalid + switch (msg_type) { case LIBLTE_MME_MSG_TYPE_ATTACH_ACCEPT: parse_attach_accept(lcid, pdu); @@ -258,19 +290,27 @@ bool nas::get_k_asme(uint8_t *k_asme_, uint32_t n) { return true; } +/******************************************************************************* + PCAP +*******************************************************************************/ + +void nas::start_pcap(srslte::nas_pcap *pcap_) +{ + pcap = pcap_; +} + /******************************************************************************* * Security ******************************************************************************/ -void nas::integrity_generate(uint8_t integ_algo, - uint8_t *key_128, +void nas::integrity_generate(uint8_t *key_128, uint32_t count, uint8_t rb_id, uint8_t direction, uint8_t *msg, uint32_t msg_len, uint8_t *mac) { - switch (integ_algo) { + switch (ctxt.integ_algo) { case INTEGRITY_ALGORITHM_ID_EIA0: break; case INTEGRITY_ALGORITHM_ID_128_EIA1: @@ -296,16 +336,102 @@ void nas::integrity_generate(uint8_t integ_algo, } } -void nas::integrity_check() { - -} +// This function depends to a valid k_nas_int. +// This key is generated in the security mode command. -void nas::cipher_encrypt() { +bool nas::integrity_check(uint32 lcid, + byte_buffer_t *pdu) +{ + uint8_t exp_mac[4]; + uint8_t *mac = &pdu->msg[1]; + int i; + integrity_generate(&k_nas_int[16], + ctxt.rx_count, + lcid-1, + SECURITY_DIRECTION_DOWNLINK, + &pdu->msg[5], + pdu->N_bytes-5, + &exp_mac[0]); + + // Check if expected mac equals the sent mac + for(i=0; i<4; i++){ + if(exp_mac[i] != mac[i]){ + nas_log->warning("Expected MAC [%02x %02x %02x %02x] does not match sent MAC [%02x %02x %02x %02x]\n", exp_mac[0], exp_mac[1], exp_mac[2], exp_mac[3], mac[0], mac[1], mac[2], mac[3]); + return false; + } + } + nas_log->info("Expected MAC [%02x %02x %02x %02x] equals sent MAC [%02x %02x %02x %02x]\n", exp_mac[0], exp_mac[1], exp_mac[2], exp_mac[3], mac[0], mac[1], mac[2], mac[3]); + return true; } -void nas::cipher_decrypt() { +void nas::cipher_encrypt(uint32 lcid, + byte_buffer_t *pdu) +{ + byte_buffer_t pdu_tmp; + switch(ctxt.cipher_algo) + { + case CIPHERING_ALGORITHM_ID_EEA0: + break; + case CIPHERING_ALGORITHM_ID_128_EEA1: + security_128_eea1(&k_nas_enc[16], + pdu->msg[5], + lcid-1, + SECURITY_DIRECTION_UPLINK, + &pdu->msg[6], + pdu->N_bytes-6, + &pdu_tmp.msg[6]); + memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes-6); + break; + case CIPHERING_ALGORITHM_ID_128_EEA2: + security_128_eea2(&k_nas_enc[16], + pdu->msg[5], + lcid-1, + SECURITY_DIRECTION_UPLINK, + &pdu->msg[6], + pdu->N_bytes-6, + &pdu_tmp.msg[6]); + memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes-6); + break; + default: + nas_log->error("Ciphering algorithmus not known"); + break; + } +} +void nas::cipher_decrypt(uint32 lcid, + byte_buffer_t *pdu) +{ + byte_buffer_t tmp_pdu; + switch(ctxt.cipher_algo) + { + case CIPHERING_ALGORITHM_ID_EEA0: + break; + case CIPHERING_ALGORITHM_ID_128_EEA1: + security_128_eea1(&k_nas_enc[16], + pdu->msg[5], + lcid-1, + SECURITY_DIRECTION_DOWNLINK, + &pdu->msg[6], + pdu->N_bytes-6, + &tmp_pdu.msg[6]); + memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes-6); + break; + case CIPHERING_ALGORITHM_ID_128_EEA2: + security_128_eea2(&k_nas_enc[16], + pdu->msg[5], + lcid-1, + SECURITY_DIRECTION_DOWNLINK, + &pdu->msg[6], + pdu->N_bytes-6, + &tmp_pdu.msg[6]); + nas_log->debug_hex(tmp_pdu.msg, pdu->N_bytes, "Decrypted"); + memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes-6); + break; + default: + nas_log->error("Ciphering algorithmus not known"); + break; + } } bool nas::check_cap_replay(LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT *caps) @@ -418,8 +544,13 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED, ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT *) pdu); - integrity_generate(ctxt.integ_algo, - &k_nas_int[16], + // Write NAS pcap + if (pcap != NULL) { + pcap->write_nas(pdu->msg, pdu->N_bytes); + } + + cipher_encrypt(lcid, pdu); + integrity_generate(&k_nas_int[16], ctxt.tx_count, lcid - 1, SECURITY_DIRECTION_UPLINK, @@ -489,6 +620,10 @@ void nas::parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu) { liblte_mme_pack_authentication_response_msg(&auth_res, (LIBLTE_BYTE_MSG_STRUCT *) pdu); nas_log->info("Sending Authentication Response\n"); + // Write NAS pcap + if (pcap != NULL) { + pcap->write_nas(pdu->msg, pdu->N_bytes); + } rrc->write_sdu(lcid, pdu); } else { nas_log->warning("Network authentication failure\n"); @@ -567,7 +702,7 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu) return; } - // Reset counterd (as per 24.301 5.4.3.2) + // Reset counters (as per 24.301 5.4.3.2) ctxt.rx_count = 0; ctxt.tx_count = 0; @@ -583,43 +718,23 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu) } // Generate NAS keys - usim->generate_nas_keys(ctxt.k_asme, k_nas_enc, k_nas_int, ctxt.cipher_algo, ctxt.integ_algo); + usim->generate_nas_keys(ctxt.k_asme, k_nas_enc, k_nas_int, + ctxt.cipher_algo, ctxt.integ_algo); nas_log->debug_hex(k_nas_enc, 32, "NAS encryption key - k_nas_enc"); nas_log->debug_hex(k_nas_int, 32, "NAS integrity key - k_nas_int"); nas_log->debug("Generating integrity check. integ_algo:%d, count_dl:%d, lcid:%d\n", ctxt.integ_algo, ctxt.rx_count, lcid); - // Check incoming MAC - uint8_t *inMAC = &pdu->msg[1]; - uint8_t genMAC[4]; - integrity_generate(ctxt.integ_algo, - &k_nas_int[16], - ctxt.rx_count, - lcid - 1, - SECURITY_DIRECTION_DOWNLINK, - &pdu->msg[5], - pdu->N_bytes - 5, - genMAC); - - nas_log->info_hex(inMAC, 4, "Incoming PDU MAC:"); - nas_log->info_hex(genMAC, 4, "Generated PDU MAC:"); - - ctxt.rx_count++; - - bool match = true; - for (int i = 0; i < 4; i++) { - if (inMAC[i] != genMAC[i]) { - match = false; - } - } - if(!match) { + if (integrity_check(lcid, pdu) != true) { nas_log->warning("Sending Security Mode Reject due to integrity check failure\n"); - send_security_mode_reject(LIBLTE_MME_EMM_CAUSE_SECURITY_MODE_REJECTED_UNSPECIFIED); + send_security_mode_reject(LIBLTE_MME_EMM_CAUSE_MAC_FAILURE); pool->deallocate(pdu); return; } + ctxt.rx_count++; + // Take security context into use have_ctxt = true; @@ -636,11 +751,14 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu) // Send response byte_buffer_t *sdu = pool_allocate; liblte_mme_pack_security_mode_complete_msg(&sec_mode_comp, - LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED, + LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT, ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT *) sdu); - integrity_generate(ctxt.integ_algo, - &k_nas_int[16], + if(pcap != NULL) { + pcap->write_nas(sdu->msg, sdu->N_bytes); + } + cipher_encrypt(lcid, sdu); + integrity_generate(&k_nas_int[16], ctxt.tx_count, lcid - 1, SECURITY_DIRECTION_UPLINK, @@ -649,7 +767,7 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu) &sdu->msg[1]); nas_log->info("Sending Security Mode Complete nas_current_ctxt.tx_count=%d, RB=%s\n", ctxt.tx_count, - rrc->get_rb_name(lcid).c_str()); + get_rb_name(lcid)); rrc->write_sdu(lcid, sdu); ctxt.tx_count++; pool->deallocate(pdu); @@ -726,8 +844,7 @@ void nas::send_attach_request() { (LIBLTE_BYTE_MSG_STRUCT *) msg); // Add MAC - integrity_generate(ctxt.integ_algo, - &k_nas_int[16], + integrity_generate(&k_nas_int[16], ctxt.tx_count, cfg.lcid-1, SECURITY_DIRECTION_UPLINK, @@ -741,6 +858,10 @@ void nas::send_attach_request() { liblte_mme_pack_attach_request_msg(&attach_req, (LIBLTE_BYTE_MSG_STRUCT *) msg); } + if(pcap != NULL) { + pcap->write_nas(msg->msg, msg->N_bytes); + } + nas_log->info("Sending attach request\n"); rrc->write_sdu(cfg.lcid, msg); @@ -776,6 +897,10 @@ void nas::send_security_mode_reject(uint8_t cause) { LIBLTE_MME_SECURITY_MODE_REJECT_MSG_STRUCT sec_mode_rej; sec_mode_rej.emm_cause = cause; liblte_mme_pack_security_mode_reject_msg(&sec_mode_rej, (LIBLTE_BYTE_MSG_STRUCT *) msg); + if(pcap != NULL) { + pcap->write_nas(msg->msg, msg->N_bytes); + } + nas_log->info("Sending security mode reject\n"); rrc->write_sdu(cfg.lcid, msg); } @@ -792,8 +917,7 @@ void nas::send_service_request() { msg->N_bytes++; uint8_t mac[4]; - integrity_generate(ctxt.integ_algo, - &k_nas_int[16], + integrity_generate(&k_nas_int[16], ctxt.tx_count, cfg.lcid-1, SECURITY_DIRECTION_UPLINK, @@ -805,6 +929,11 @@ void nas::send_service_request() { msg->N_bytes++; msg->msg[3] = mac[3]; msg->N_bytes++; + + if(pcap != NULL) { + pcap->write_nas(msg->msg, msg->N_bytes); + } + nas_log->info("Sending service request\n"); rrc->write_sdu(cfg.lcid, msg); ctxt.tx_count++; diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 665761a04..273a2d84d 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -1067,7 +1067,7 @@ void rrc::write_pdu_pcch(byte_buffer_t *pdu) { * *******************************************************************************/ void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) { - rrc_log->info_hex(sdu->msg, sdu->N_bytes, "RX %s SDU", get_rb_name(lcid).c_str()); + rrc_log->info_hex(sdu->msg, sdu->N_bytes, "RX %s SDU", get_rb_name(lcid)); switch (state) { case RRC_STATE_CONNECTING: send_con_setup_complete(sdu); @@ -1082,7 +1082,7 @@ void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) { } void rrc::write_pdu(uint32_t lcid, byte_buffer_t *pdu) { - rrc_log->info_hex(pdu->msg, pdu->N_bytes, "TX %s PDU", get_rb_name(lcid).c_str()); + rrc_log->info_hex(pdu->msg, pdu->N_bytes, "TX %s PDU", get_rb_name(lcid)); rrc_log->info("TX PDU Stack latency: %ld us\n", pdu->get_latency_us()); switch (lcid) { @@ -1145,7 +1145,7 @@ void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu) { liblte_rrc_unpack_dl_dcch_msg((LIBLTE_BIT_MSG_STRUCT *) &bit_buf, &dl_dcch_msg); rrc_log->info("%s - Received %s\n", - get_rb_name(lcid).c_str(), + get_rb_name(lcid), liblte_rrc_dl_dcch_msg_type_text[dl_dcch_msg.msg_type]); // Reset and reuse pdu buffer if possible @@ -1170,6 +1170,7 @@ void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu) { usim->generate_as_keys(k_asme, nas->get_ul_count()-1, k_rrc_enc, k_rrc_int, k_up_enc, k_up_int, cipher_algo, integ_algo); pdcp->config_security(lcid, k_rrc_enc, k_rrc_int, cipher_algo, integ_algo); send_security_mode_complete(lcid, pdu); + pdcp->enable_encryption(lcid); break; case LIBLTE_RRC_DL_DCCH_MSG_TYPE_RRC_CON_RECONFIG: transaction_id = dl_dcch_msg.msg.rrc_con_reconfig.rrc_transaction_id; @@ -1663,7 +1664,7 @@ void rrc::add_srb(LIBLTE_RRC_SRB_TO_ADD_MOD_STRUCT *srb_cnfg) { } srbs[srb_cnfg->srb_id] = *srb_cnfg; - rrc_log->info("Added radio bearer %s\n", get_rb_name(srb_cnfg->srb_id).c_str()); + rrc_log->info("Added radio bearer %s\n", get_rb_name(srb_cnfg->srb_id)); } void rrc::add_drb(LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT *drb_cnfg) { @@ -1721,7 +1722,7 @@ void rrc::add_drb(LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT *drb_cnfg) { drbs[lcid] = *drb_cnfg; drb_up = true; - rrc_log->info("Added radio bearer %s\n", get_rb_name(lcid).c_str()); + rrc_log->info("Added radio bearer %s\n", get_rb_name(lcid)); } void rrc::release_drb(uint8_t lcid) { diff --git a/srsue/src/upper/usim.cc b/srsue/src/upper/usim.cc index 7ae53988b..7a524f17a 100644 --- a/srsue/src/upper/usim.cc +++ b/srsue/src/upper/usim.cc @@ -223,6 +223,8 @@ void usim::generate_nas_keys(uint8_t *k_asme, integ_algo, k_nas_enc, k_nas_int); + + } /******************************************************************************* @@ -239,9 +241,9 @@ void usim::generate_as_keys(uint8_t *k_asme, INTEGRITY_ALGORITHM_ID_ENUM integ_algo) { // Generate K_enb - security_generate_k_enb( k_asme, - count_ul, - k_enb); + security_generate_k_enb( k_asme, + count_ul, + k_enb); // Generate K_rrc_enc and K_rrc_int security_generate_k_rrc( k_enb, diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index 867221e87..dedd392c1 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -50,6 +50,8 @@ rx_gain = 40 [pcap] enable = false filename = /tmp/ue.pcap +nas_enable = false +nas_filename = /tmp/nas.pcap ##################################################################### # Log configuration From dd8bacf46683e853830fac5d2e0692a0cd5e243d Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 30 Nov 2017 20:01:35 +0100 Subject: [PATCH 178/242] Calibrated CFO loop default values --- lib/examples/pdsch_ue.c | 10 +- lib/include/srslte/interfaces/ue_interfaces.h | 10 +- lib/include/srslte/phy/ue/ue_sync.h | 18 +- lib/src/phy/sync/sync.c | 2 +- lib/src/phy/ue/ue_sync.c | 97 ++++--- lib/src/phy/ue/ue_ul.c | 2 +- srsue/hdr/phy/phch_common.h | 255 +++++++++--------- srsue/hdr/phy/phch_recv.h | 5 +- srsue/hdr/phy/phch_worker.h | 5 +- srsue/src/main.cc | 45 +++- srsue/src/phy/phch_recv.cc | 23 +- srsue/src/phy/phch_worker.cc | 39 ++- srsue/src/phy/phy.cc | 3 +- srsue/ue.conf.example | 42 ++- 14 files changed, 353 insertions(+), 203 deletions(-) diff --git a/lib/examples/pdsch_ue.c b/lib/examples/pdsch_ue.c index acc598296..b62ae263e 100644 --- a/lib/examples/pdsch_ue.c +++ b/lib/examples/pdsch_ue.c @@ -546,7 +546,7 @@ int main(int argc, char **argv) { exit(-1); } - srslte_chest_dl_cfo_estimate_enable(&ue_dl.chest, prog_args.enable_cfo_ref, 0xff, 0.1); + srslte_chest_dl_cfo_estimate_enable(&ue_dl.chest, prog_args.enable_cfo_ref, 0xff, 0.005); srslte_chest_dl_average_subframe(&ue_dl.chest, prog_args.average_subframe); /* Configure downlink receiver for the SI-RNTI since will be the only one we'll use */ @@ -959,7 +959,7 @@ void *plot_thread_run(void *arg) { plot_real_init(&pce); plot_real_setTitle(&pce, "Channel Response - Magnitude"); plot_real_setLabels(&pce, "Index", "dB"); - plot_real_setYAxisScale(&pce, -40, 40); + plot_real_setYAxisScale(&pce, -M_PI, M_PI); plot_real_init(&p_sync); plot_real_setTitle(&p_sync, "PSS Cross-Corr abs value"); @@ -995,7 +995,11 @@ void *plot_thread_run(void *arg) { tmp_plot2[g+i] = -80; } } - plot_real_setNewData(&pce, tmp_plot2, sz); + uint32_t nrefs = 2*ue_dl.cell.nof_prb; + for (i=0;i= SRSLTE_SYNC_FFT_SZ_MIN && fft_size <= SRSLTE_SYNC_FFT_SZ_MAX && (fft_size%64) == 0) { diff --git a/lib/src/phy/ue/ue_sync.c b/lib/src/phy/ue/ue_sync.c index 58489b92b..b5d89743f 100644 --- a/lib/src/phy/ue/ue_sync.c +++ b/lib/src/phy/ue/ue_sync.c @@ -47,10 +47,14 @@ #define DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD 0 #define DEFAULT_SFO_EMA_COEFF 0.1 -#define DEFAULT_CFO_BW 0.7 -#define DEFAULT_CFO_PSS_TOL 80 // typical accuracy of PSS estimation. Avoids ping-pong effect -#define DEFAULT_CFO_REF_TOL 5 // typical accuracy of REF estimation -#define DEFAULT_CFO_REF_MAX 300 // Maximum detection offset of REF based estimation +#define DEFAULT_CFO_BW 0.2 +#define DEFAULT_CFO_PSS_MIN 500 // typical bias of PSS estimation. +#define DEFAULT_CFO_REF_MIN 0 // typical bias of REF estimation +#define DEFAULT_CFO_REF_MAX 500 // Maximum detection offset of REF based estimation + +#define DEFAULT_PSS_STABLE_TIMEOUT 100 // Time after which the PSS is considered to be stable and we accept REF-CFO + +#define DEFAULT_CFO_EMA_TRACK 0.1 cf_t dummy_buffer0[15*2048/2]; cf_t dummy_buffer1[15*2048/2]; @@ -116,6 +120,7 @@ clean_exit: void srslte_ue_sync_cfo_reset(srslte_ue_sync_t *q) { + q->cfo_is_copied = false; q->cfo_current_value = 0; srslte_sync_cfo_reset(&q->strack); srslte_sync_cfo_reset(&q->sfind); @@ -129,6 +134,7 @@ void srslte_ue_sync_reset(srslte_ue_sync_t *q) { } else { q->sf_idx = 9; } + q->pss_stable_timeout = false; q->state = SF_FIND; q->frame_ok_cnt = 0; q->frame_no_cnt = 0; @@ -218,11 +224,15 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q, q->max_prb = max_prb; q->cfo_ref_max = DEFAULT_CFO_REF_MAX; - q->cfo_ref_tol = DEFAULT_CFO_REF_TOL; - q->cfo_pss_tol = DEFAULT_CFO_PSS_TOL; - q->cfo_loop_bw = DEFAULT_CFO_BW; + q->cfo_ref_min = DEFAULT_CFO_REF_MIN; + q->cfo_pss_min = DEFAULT_CFO_PSS_MIN; + q->cfo_loop_bw_pss = DEFAULT_CFO_BW; + q->cfo_loop_bw_ref = DEFAULT_CFO_BW; q->cfo_correct_enable = true; + q->pss_stable_cnt = 0; + q->pss_stable_timeout = DEFAULT_PSS_STABLE_TIMEOUT; + if (search_cell) { /* If the cell is unkown, we search PSS/SSS in 5 ms */ @@ -269,11 +279,11 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q, srslte_sync_set_cfo_cp_enable(&q->strack, false); srslte_sync_set_cfo_pss_enable(&q->strack, true); srslte_sync_set_pss_filt_enable(&q->strack, true); - srslte_sync_set_sss_filt_enable(&q->strack, true); + srslte_sync_set_sss_filt_enable(&q->strack, false); // FIXME: CP detection not working very well. Not supporting Extended CP right now srslte_sync_cp_en(&q->strack, false); - srslte_sync_cp_en(&q->sfind, false); + srslte_sync_cp_en(&q->sfind, false); srslte_sync_sss_en(&q->strack, true); @@ -368,6 +378,9 @@ int srslte_ue_sync_set_cell(srslte_ue_sync_t *q, srslte_cell_t cell) srslte_sync_set_threshold(&q->sfind, 2.0); srslte_sync_set_threshold(&q->strack, 1.2); + srslte_sync_set_cfo_ema_alpha(&q->sfind, 0.1); + srslte_sync_set_cfo_ema_alpha(&q->strack, 0.1); + } else { q->sfind.cp = cell.cp; q->strack.cp = cell.cp; @@ -376,7 +389,7 @@ int srslte_ue_sync_set_cell(srslte_ue_sync_t *q, srslte_cell_t cell) srslte_sync_set_N_id_2(&q->strack, cell.id%3); srslte_sync_set_cfo_ema_alpha(&q->sfind, 0.1); - srslte_sync_set_cfo_ema_alpha(&q->strack, 0.1); + srslte_sync_set_cfo_ema_alpha(&q->strack, DEFAULT_CFO_EMA_TRACK); /* In find phase and if the cell is known, do not average pss correlation * because we only capture 1 subframe and do not know where the peak is. @@ -402,22 +415,31 @@ void srslte_ue_sync_get_last_timestamp(srslte_ue_sync_t *q, srslte_timestamp_t * memcpy(timestamp, &q->last_timestamp, sizeof(srslte_timestamp_t)); } -void srslte_ue_sync_set_cfo_loop_bw(srslte_ue_sync_t *q, float bw, float pss_tol, float ref_tol, float ref_max) { - q->cfo_loop_bw = bw; - q->cfo_pss_tol = pss_tol; - q->cfo_ref_tol = ref_tol; +void srslte_ue_sync_set_cfo_loop_bw(srslte_ue_sync_t *q, float bw_pss, float bw_ref, + float pss_tol, float ref_tol, float ref_max, + uint32_t pss_stable_conv_time) { + q->cfo_loop_bw_pss = bw_pss; + q->cfo_loop_bw_ref = bw_ref; + q->cfo_pss_min = pss_tol; + q->cfo_ref_min = ref_tol; q->cfo_ref_max = ref_max; + q->pss_stable_timeout = pss_stable_conv_time; } 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); } void srslte_ue_sync_set_cfo_ref(srslte_ue_sync_t *q, float ref_cfo) { - if (fabsf(ref_cfo)*15000 > q->cfo_ref_tol && fabsf(ref_cfo)*15000 < q->cfo_ref_max) { - q->cfo_current_value += ref_cfo*q->cfo_loop_bw; + // Accept REF-based CFO adjustments only after PSS CFO is stable + if (q->pss_is_stable) { + if (fabsf(ref_cfo)*15000 > q->cfo_ref_min) { + if (fabsf(ref_cfo)*15000 > q->cfo_ref_max) { + ref_cfo = (ref_cfo>0?q->cfo_ref_max:-q->cfo_ref_max)/15000; + } + q->cfo_current_value += ref_cfo*q->cfo_loop_bw_ref; + } } } @@ -437,12 +459,16 @@ float srslte_ue_sync_get_cfo(srslte_ue_sync_t *q) { void srslte_ue_sync_copy_cfo(srslte_ue_sync_t *q, srslte_ue_sync_t *src_obj) { // Copy find object internal CFO averages - srslte_sync_copy_cfo(&q->sfind, &src_obj->sfind); + srslte_sync_copy_cfo(&q->sfind, &src_obj->sfind); // Current CFO is tracking-phase CFO of previous object - q->cfo_current_value = srslte_ue_sync_get_cfo(src_obj); + q->cfo_current_value = src_obj->cfo_current_value; + q->cfo_is_copied = true; } -void srslte_ue_sync_set_cfo_tol(srslte_ue_sync_t *q, float cfo_tol) {} +void srslte_ue_sync_set_cfo_tol(srslte_ue_sync_t *q, float cfo_tol) { + srslte_sync_set_cfo_tol(&q->strack, cfo_tol); + srslte_sync_set_cfo_tol(&q->sfind, cfo_tol); +} float srslte_ue_sync_get_sfo(srslte_ue_sync_t *q) { return q->mean_sfo/5e-3; @@ -507,10 +533,12 @@ static int find_peak_ok(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE_MAX_PORTS q->mean_sample_offset = 0; /* Goto Tracking state */ - q->state = SF_TRACK; - + q->state = SF_TRACK; + /* Set CFO values. Since we correct before track, the initial track state is CFO=0 Hz */ - q->cfo_current_value = srslte_sync_get_cfo(&q->sfind); + if (!q->cfo_is_copied) { + q->cfo_current_value = srslte_sync_get_cfo(&q->sfind); + } srslte_sync_cfo_reset(&q->strack); } @@ -550,9 +578,18 @@ static int track_peak_ok(srslte_ue_sync_t *q, uint32_t track_idx) { /* Adjust current CFO estimation with PSS * Since sync track has enabled only PSS-based correlation, get_cfo() returns that value only, already filtered. */ - INFO("TRACK: cfo_current: %f, cfo_strack=%f\n", 15000*q->cfo_current_value, 15000*srslte_sync_get_cfo(&q->strack)); - if (15000*fabsf(srslte_sync_get_cfo(&q->strack)) > q->cfo_pss_tol) { - q->cfo_current_value += srslte_sync_get_cfo(&q->strack)*q->cfo_loop_bw; + INFO("TRACK: cfo_current=%f, cfo_strack=%f\n", 15000*q->cfo_current_value, 15000*srslte_sync_get_cfo(&q->strack)); + if (15000*fabsf(srslte_sync_get_cfo(&q->strack)) > q->cfo_pss_min) { + q->cfo_current_value += srslte_sync_get_cfo(&q->strack)*q->cfo_loop_bw_pss; + q->pss_stable_cnt = 0; + q->pss_is_stable = false; + } else { + if (!q->pss_is_stable) { + q->pss_stable_cnt++; + if (q->pss_stable_cnt >= q->pss_stable_timeout) { + q->pss_is_stable = true; + } + } } // Compute cumulative moving average time offset */ @@ -694,7 +731,7 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE ret = SRSLTE_ERROR; fprintf(stderr, "Error finding correlation peak (%d)\n", ret); return SRSLTE_ERROR; - case SRSLTE_SYNC_FOUND: + case SRSLTE_SYNC_FOUND: ret = find_peak_ok(q, input_buffer); break; case SRSLTE_SYNC_FOUND_NOSPACE: @@ -769,9 +806,9 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE fprintf(stderr, "Error processing tracking peak\n"); q->state = SF_FIND; return SRSLTE_SUCCESS; - } - - q->frame_total_cnt++; + } + + q->frame_total_cnt++; } break; } diff --git a/lib/src/phy/ue/ue_ul.c b/lib/src/phy/ue/ue_ul.c index ec2809dfe..e50be05a6 100644 --- a/lib/src/phy/ue/ue_ul.c +++ b/lib/src/phy/ue/ue_ul.c @@ -38,7 +38,7 @@ #define MAX_SFLEN SRSLTE_SF_LEN(srslte_symbol_sz(max_prb)) -#define DEFAULT_CFO_TOL 50.0 // Hz +#define DEFAULT_CFO_TOL 0.0 // Hz int srslte_ue_ul_init(srslte_ue_ul_t *q, cf_t *out_buffer, diff --git a/srsue/hdr/phy/phch_common.h b/srsue/hdr/phy/phch_common.h index 0fe8529da..963f146dc 100644 --- a/srsue/hdr/phy/phch_common.h +++ b/srsue/hdr/phy/phch_common.h @@ -42,131 +42,138 @@ namespace srsue { + +class chest_feedback_itf +{ +public: + virtual void set_cfo(float cfo) = 0; +}; + /* Subclass that manages variables common to all workers */ - class phch_common { - public: - - /* Common variables used by all phy workers */ - phy_interface_rrc::phy_cfg_t *config; - phy_args_t *args; - rrc_interface_phy *rrc; - mac_interface_phy *mac; - srslte_ue_ul_t ue_ul; - - /* Power control variables */ - float pathloss; - float cur_pathloss; - float p0_preamble; - float cur_radio_power; - float cur_pusch_power; - float avg_rsrp_db; - float avg_rsrq_db; - float rx_gain_offset; - float avg_snr_db; - float avg_noise; - float avg_rsrp; - - // Save last TBS for mcs>28 cases - int last_dl_tbs[2*HARQ_DELAY_MS][SRSLTE_MAX_CODEWORDS]; - uint32_t last_dl_tti[2*HARQ_DELAY_MS]; - - int last_ul_tbs[2*HARQ_DELAY_MS]; - uint32_t last_ul_tti[2*HARQ_DELAY_MS]; - srslte_mod_t last_ul_mod[2*HARQ_DELAY_MS]; - - phch_common(uint32_t max_mutex = 3); - void init(phy_interface_rrc::phy_cfg_t *config, - phy_args_t *args, - srslte::log *_log, - srslte::radio *_radio, - rrc_interface_phy *rrc, - mac_interface_phy *_mac); - - /* For RNTI searches, -1 means now or forever */ - void set_ul_rnti(srslte_rnti_type_t type, uint16_t rnti_value, int tti_start = -1, int tti_end = -1); - uint16_t get_ul_rnti(uint32_t tti); - srslte_rnti_type_t get_ul_rnti_type(); - - void set_dl_rnti(srslte_rnti_type_t type, uint16_t rnti_value, int tti_start = -1, int tti_end = -1); - uint16_t get_dl_rnti(uint32_t tti); - srslte_rnti_type_t get_dl_rnti_type(); - - void set_rar_grant(uint32_t tti, uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN]); - bool get_pending_rar(uint32_t tti, srslte_dci_rar_grant_t *rar_grant = NULL); - - void reset_pending_ack(uint32_t tti); - void set_pending_ack(uint32_t tti, uint32_t I_lowest, uint32_t n_dmrs); - bool get_pending_ack(uint32_t tti); - bool get_pending_ack(uint32_t tti, uint32_t *I_lowest, uint32_t *n_dmrs); - - void worker_end(uint32_t tti, bool tx_enable, cf_t *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time); - - void set_nof_mutex(uint32_t nof_mutex); - - bool sr_enabled; - int sr_last_tx_tti; - - srslte::radio* get_radio(); - - void set_cell(const srslte_cell_t &c); - uint32_t get_nof_prb(); - void set_dl_metrics(const dl_metrics_t &m); - void get_dl_metrics(dl_metrics_t &m); - void set_ul_metrics(const ul_metrics_t &m); - void get_ul_metrics(ul_metrics_t &m); - void set_sync_metrics(const sync_metrics_t &m); - void get_sync_metrics(sync_metrics_t &m); - - void reset_ul(); - - private: - - std::vector tx_mutex; - - bool is_first_of_burst; - srslte::radio *radio_h; - float cfo; - srslte::log *log_h; - - - bool ul_rnti_active(uint32_t tti); - bool dl_rnti_active(uint32_t tti); - uint16_t ul_rnti, dl_rnti; - srslte_rnti_type_t ul_rnti_type, dl_rnti_type; - int ul_rnti_start, ul_rnti_end, dl_rnti_start, dl_rnti_end; - - float time_adv_sec; - - srslte_dci_rar_grant_t rar_grant; - bool rar_grant_pending; - uint32_t rar_grant_tti; - - typedef struct { - bool enabled; - uint32_t I_lowest; - uint32_t n_dmrs; - } pending_ack_t; - pending_ack_t pending_ack[TTIMOD_SZ]; - - bool is_first_tx; - - uint32_t nof_workers; - uint32_t nof_mutex; - uint32_t max_mutex; - - srslte_cell_t cell; - - dl_metrics_t dl_metrics; - uint32_t dl_metrics_count; - bool dl_metrics_read; - ul_metrics_t ul_metrics; - uint32_t ul_metrics_count; - bool ul_metrics_read; - sync_metrics_t sync_metrics; - uint32_t sync_metrics_count; - bool sync_metrics_read; - }; - +class phch_common { +public: + + /* Common variables used by all phy workers */ + phy_interface_rrc::phy_cfg_t *config; + phy_args_t *args; + rrc_interface_phy *rrc; + mac_interface_phy *mac; + srslte_ue_ul_t ue_ul; + + /* Power control variables */ + float pathloss; + float cur_pathloss; + float p0_preamble; + float cur_radio_power; + float cur_pusch_power; + float avg_rsrp_db; + float avg_rsrq_db; + float rx_gain_offset; + float avg_snr_db; + float avg_noise; + float avg_rsrp; + + // Save last TBS for mcs>28 cases + int last_dl_tbs[2*HARQ_DELAY_MS][SRSLTE_MAX_CODEWORDS]; + uint32_t last_dl_tti[2*HARQ_DELAY_MS]; + + int last_ul_tbs[2*HARQ_DELAY_MS]; + uint32_t last_ul_tti[2*HARQ_DELAY_MS]; + srslte_mod_t last_ul_mod[2*HARQ_DELAY_MS]; + + phch_common(uint32_t max_mutex = 3); + void init(phy_interface_rrc::phy_cfg_t *config, + phy_args_t *args, + srslte::log *_log, + srslte::radio *_radio, + rrc_interface_phy *rrc, + mac_interface_phy *_mac); + + /* For RNTI searches, -1 means now or forever */ + void set_ul_rnti(srslte_rnti_type_t type, uint16_t rnti_value, int tti_start = -1, int tti_end = -1); + uint16_t get_ul_rnti(uint32_t tti); + srslte_rnti_type_t get_ul_rnti_type(); + + void set_dl_rnti(srslte_rnti_type_t type, uint16_t rnti_value, int tti_start = -1, int tti_end = -1); + uint16_t get_dl_rnti(uint32_t tti); + srslte_rnti_type_t get_dl_rnti_type(); + + void set_rar_grant(uint32_t tti, uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN]); + bool get_pending_rar(uint32_t tti, srslte_dci_rar_grant_t *rar_grant = NULL); + + void reset_pending_ack(uint32_t tti); + void set_pending_ack(uint32_t tti, uint32_t I_lowest, uint32_t n_dmrs); + bool get_pending_ack(uint32_t tti); + bool get_pending_ack(uint32_t tti, uint32_t *I_lowest, uint32_t *n_dmrs); + + void worker_end(uint32_t tti, bool tx_enable, cf_t *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time); + + void set_nof_mutex(uint32_t nof_mutex); + + bool sr_enabled; + int sr_last_tx_tti; + + srslte::radio* get_radio(); + + void set_cell(const srslte_cell_t &c); + uint32_t get_nof_prb(); + void set_dl_metrics(const dl_metrics_t &m); + void get_dl_metrics(dl_metrics_t &m); + void set_ul_metrics(const ul_metrics_t &m); + void get_ul_metrics(ul_metrics_t &m); + void set_sync_metrics(const sync_metrics_t &m); + void get_sync_metrics(sync_metrics_t &m); + + void reset_ul(); + +private: + + std::vector tx_mutex; + + bool is_first_of_burst; + srslte::radio *radio_h; + float cfo; + srslte::log *log_h; + + + bool ul_rnti_active(uint32_t tti); + bool dl_rnti_active(uint32_t tti); + uint16_t ul_rnti, dl_rnti; + srslte_rnti_type_t ul_rnti_type, dl_rnti_type; + int ul_rnti_start, ul_rnti_end, dl_rnti_start, dl_rnti_end; + + float time_adv_sec; + + srslte_dci_rar_grant_t rar_grant; + bool rar_grant_pending; + uint32_t rar_grant_tti; + + typedef struct { + bool enabled; + uint32_t I_lowest; + uint32_t n_dmrs; + } pending_ack_t; + pending_ack_t pending_ack[TTIMOD_SZ]; + + bool is_first_tx; + + uint32_t nof_workers; + uint32_t nof_mutex; + uint32_t max_mutex; + + srslte_cell_t cell; + + dl_metrics_t dl_metrics; + uint32_t dl_metrics_count; + bool dl_metrics_read; + ul_metrics_t ul_metrics; + uint32_t ul_metrics_count; + bool ul_metrics_read; + sync_metrics_t sync_metrics; + uint32_t sync_metrics_count; + bool sync_metrics_read; +}; + } // namespace srsue #endif // UEPHYWORKERCOMMON_H diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index 01a296094..a5f290887 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -41,7 +41,7 @@ namespace srsue { typedef _Complex float cf_t; -class phch_recv : public thread +class phch_recv : public thread, public chest_feedback_itf { public: phch_recv(); @@ -65,6 +65,9 @@ public: bool status_is_sync(); + // from chest_feedback_itf + void set_cfo(float cfo); + void set_time_adv_sec(float time_adv_sec); void get_current_cell(srslte_cell_t *cell); diff --git a/srsue/hdr/phy/phch_worker.h b/srsue/hdr/phy/phch_worker.h index e7030d777..570d3d0c2 100644 --- a/srsue/hdr/phy/phch_worker.h +++ b/srsue/hdr/phy/phch_worker.h @@ -45,7 +45,7 @@ public: ~phch_worker(); void reset(); void set_common(phch_common *phy); - bool init(uint32_t max_prb, srslte::log *log); + bool init(uint32_t max_prb, srslte::log *log, chest_feedback_itf *chest_loop); bool set_cell(srslte_cell_t cell); @@ -66,6 +66,8 @@ public: int read_ce_abs(float *ce_abs); int read_pdsch_d(cf_t *pdsch_d); void start_plot(); + + float get_ref_cfo(); private: /* Inherited from thread_pool::worker. Function called every subframe to run the DL/UL processing */ @@ -114,6 +116,7 @@ private: /* Common objects */ phch_common *phy; srslte::log *log_h; + chest_feedback_itf *chest_loop; srslte_cell_t cell; bool mem_initiated; bool cell_initiated; diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 1c9b6edc6..201af1b14 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -199,13 +199,46 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { "Enables integer CFO estimation and correction.") ("expert.cfo_correct_tol_hz", - bpo::value(&args->expert.phy.cfo_correct_tol_hz)->default_value(50.0), - "Tolerance (in Hz) for digial CFO compensation.") + bpo::value(&args->expert.phy.cfo_correct_tol_hz)->default_value(0.0), + "Tolerance (in Hz) for digital CFO compensation (needs to be low if average_subframe_enabled=true.") - ("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.cfo_pss_ema", + bpo::value(&args->expert.phy.cfo_pss_ema)->default_value(0.1), + "CFO Exponential Moving Average coefficient for PSS estimation during TRACK.") + + ("expert.cfo_ref_ema", + bpo::value(&args->expert.phy.cfo_ref_ema)->default_value(0.01), + "CFO Exponential Moving Average coefficient for RS estimation after PSS acquisition") + + ("expert.cfo_ref_mask", + bpo::value(&args->expert.phy.cfo_ref_mask)->default_value(1023), + "Bitmask for subframes on which to run RS estimation (set to 0 to disable, default all sf)") + + ("expert.cfo_loop_bw_pss", + bpo::value(&args->expert.phy.cfo_loop_bw_pss)->default_value(0.05), + "CFO feedback loop bandwidth for samples from PSS") + + ("expert.cfo_loop_bw_ref", + bpo::value(&args->expert.phy.cfo_loop_bw_ref)->default_value(0.01), + "CFO feedback loop bandwidth for samples from RS") + + ("expert.cfo_loop_pss_tol", + bpo::value(&args->expert.phy.cfo_loop_pss_tol)->default_value(300), + "Tolerance (in Hz) of the PSS estimation method. Below this value, PSS estimation does not feeds back the loop" + "and RS estimations are used instead (when available)") + + ("expert.cfo_loop_ref_min", + bpo::value(&args->expert.phy.cfo_loop_ref_min)->default_value(0), + "Tolerance (in Hz) of the RS estimation method. Below this value, RS estimation does not feeds back the loop") + + + ("expert.cfo_loop_pss_conv", + bpo::value(&args->expert.phy.cfo_loop_pss_conv)->default_value(50), + "After the PSS estimation is below cfo_loop_pss_tol for cfo_loop_pss_timeout times consecutively, RS adjustments are allowed.") + + ("expert.average_subframe_enabled", + bpo::value(&args->expert.phy.average_subframe_enabled)->default_value(true), + "Averages in the time domain the channel estimates within 1 subframe. Needs accurate CFO correction.") ("expert.time_correct_period", bpo::value(&args->expert.phy.time_correct_period)->default_value(5), diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 37f7970ee..652a848bd 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -98,9 +98,6 @@ void phch_recv:: init(srslte::radio_multi *_radio_handler, mac_interface_phy *_ srslte_ue_cellsearch_set_nof_valid_frames(&cs, 2); - // Set options defined in expert section - set_ue_sync_opts(&cs.ue_sync); - last_gain = 40; if (do_agc) { srslte_ue_sync_start_agc(&cs.ue_sync, callback_set_rx_gain, last_gain); @@ -184,6 +181,11 @@ void phch_recv::radio_error() { radio_is_resetting=false; } +void phch_recv::set_cfo(float cfo) { + Debug("set_ref_cfo=%f\n",cfo*15000); + srslte_ue_sync_set_cfo_ref(&ue_sync, cfo); +} + bool phch_recv::wait_radio_reset() { int cnt=0; while(cnt < 20 && radio_is_resetting) { @@ -211,8 +213,13 @@ void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q) { srslte_ue_sync_set_cfo_i_enable(q, true); } - srslte_ue_sync_set_cfo_ema(q, worker_com->args->cfo_ema); + srslte_ue_sync_set_cfo_ema(q, worker_com->args->cfo_pss_ema); srslte_ue_sync_set_cfo_tol(q, worker_com->args->cfo_correct_tol_hz); + srslte_ue_sync_set_cfo_loop_bw(q, worker_com->args->cfo_loop_bw_pss, worker_com->args->cfo_loop_bw_ref, + worker_com->args->cfo_loop_pss_tol, + worker_com->args->cfo_loop_ref_min, + worker_com->args->cfo_loop_pss_tol, + worker_com->args->cfo_loop_pss_conv); int time_correct_period = worker_com->args->time_correct_period; if (time_correct_period > 0) { @@ -320,15 +327,13 @@ int phch_recv::cell_search(int force_N_id_2) { return false; } - // Set options defined in expert section - set_ue_sync_opts(&ue_mib_sync.ue_sync); - if (do_agc) { srslte_ue_sync_start_agc(&ue_mib_sync.ue_sync, callback_set_rx_gain, last_gain); } srslte_ue_sync_reset(&ue_mib_sync.ue_sync); srslte_ue_sync_copy_cfo(&ue_mib_sync.ue_sync, &cs.ue_sync); + Info("Copied cfo=%f Hz from cs_sync to ue_mib\n", srslte_ue_sync_get_cfo(&ue_mib_sync.ue_sync)); /* Find and decode MIB */ int sfn_offset; @@ -341,6 +346,7 @@ int phch_recv::cell_search(int force_N_id_2) { srslte_ue_sync_reset(&ue_sync); srslte_ue_sync_copy_cfo(&ue_sync, &ue_mib_sync.ue_sync); + Info("Copied cfo=%f Hz from ue_mib_sync to ue_sync\n", srslte_ue_sync_get_cfo(&ue_sync)); if (ret == 1) { srslte_pbch_mib_unpack(bch_payload, &cell, NULL); @@ -731,6 +737,9 @@ void phch_recv::run_thread() { worker->set_cfo(ul_dl_factor * metrics.cfo / 15000); worker_com->set_sync_metrics(metrics); + Debug("current_cfo=%f, pss_stable_cnt=%d, cfo_pss=%f Hz\n", + metrics.cfo, ue_sync.pss_stable_cnt, srslte_sync_get_cfo(&ue_sync.strack)*15000); + worker->set_sample_offset(srslte_ue_sync_get_sfo(&ue_sync)/1000); /* Compute TX time: Any transmission happens in TTI+4 thus advance 4 ms the reception time */ diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 7b4ec48bd..fefa7d250 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -57,7 +57,9 @@ namespace srsue { phch_worker::phch_worker() : tr_exec(10240) { - phy = NULL; + phy = NULL; + chest_loop = NULL; + bzero(signal_buffer, sizeof(cf_t*)*SRSLTE_MAX_PORTS); mem_initiated = false; @@ -104,9 +106,11 @@ void phch_worker::set_common(phch_common* phy_) phy = phy_; } -bool phch_worker::init(uint32_t max_prb, srslte::log *log_h) +bool phch_worker::init(uint32_t max_prb, srslte::log *log_h, chest_feedback_itf *chest_loop) { this->log_h = log_h; + this->chest_loop = chest_loop; + // ue_sync in phy.cc requires a buffer for 3 subframes for (uint32_t i=0;iargs->nof_rx_ant;i++) { signal_buffer[i] = (cf_t*) srslte_vec_malloc(3 * sizeof(cf_t) * SRSLTE_SF_LEN_PRB(max_prb)); @@ -126,6 +130,8 @@ bool phch_worker::init(uint32_t max_prb, srslte::log *log_h) return false; } + srslte_chest_dl_average_subframe(&ue_dl.chest, phy->args->average_subframe_enabled); + srslte_chest_dl_cfo_estimate_enable(&ue_dl.chest, phy->args->cfo_ref_mask!=0, phy->args->cfo_ref_mask, phy->args->cfo_ref_ema); srslte_ue_ul_set_normalization(&ue_ul, true); srslte_ue_ul_set_cfo_enable(&ue_ul, true); @@ -134,6 +140,10 @@ bool phch_worker::init(uint32_t max_prb, srslte::log *log_h) return true; } +float phch_worker::get_ref_cfo() { + return srslte_chest_dl_get_cfo(&ue_dl.chest); +} + bool phch_worker::set_cell(srslte_cell_t cell_) { if (cell.id != cell_.id || !cell_initiated) { @@ -221,6 +231,11 @@ void phch_worker::work_imp() bool snr_th_ok = 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest))>1.0; + // Call feedback loop for chest + if (chest_loop && ((1<<(tti%10)) & phy->args->cfo_ref_mask)) { + chest_loop->set_cfo(srslte_chest_dl_get_cfo(&ue_dl.chest)); + } + if (chest_ok && snr_th_ok) { /***** Downlink Processing *******/ @@ -394,11 +409,8 @@ void phch_worker::work_imp() bool phch_worker::extract_fft_and_pdcch_llr() { - bool decode_pdcch = false; - if (phy->get_ul_rnti(tti) || phy->get_dl_rnti(tti) || phy->get_pending_rar(tti)) { - decode_pdcch = true; - } - + bool decode_pdcch = true; + /* Without a grant, we might need to do fft processing if need to decode PHICH */ if (phy->get_pending_ack(tti) || decode_pdcch) { @@ -1213,13 +1225,18 @@ int phch_worker::read_ce_abs(float *ce_abs) { int sz = srslte_symbol_sz(cell.nof_prb); bzero(ce_abs, sizeof(float)*sz); int g = (sz - 12*cell.nof_prb)/2; - for (i = 0; i < 12*cell.nof_prb; i++) { +/* for (i = 0; i < 12*cell.nof_prb; i++) { ce_abs[g+i] = 20 * log10f(cabsf(ue_dl.ce_m[0][0][i])); if (isinf(ce_abs[g+i])) { ce_abs[g+i] = -80; } } - return sz; +*/ + uint32_t nrefs = 2*ue_dl.cell.nof_prb; + for (i=0;iavg_snr_db = 10*log10(phy->avg_rsrp/phy->avg_noise); + phy->avg_snr_db = 10*log10(phy->avg_rsrp/phy->avg_noise); // Store metrics dl_metrics.n = phy->avg_noise; @@ -1371,7 +1388,7 @@ void *plot_thread_run(void *arg) { plot_real_init(&pce); plot_real_setTitle(&pce, (char*) "Channel Response - Magnitude"); plot_real_setLabels(&pce, (char*) "Index", (char*) "dB"); - plot_real_setYAxisScale(&pce, -40, 40); + plot_real_setYAxisScale(&pce, -1000, 1000); plot_scatter_init(&pconst); plot_scatter_setTitle(&pconst, (char*) "PDSCH - Equalized Symbols"); diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 6dfb2c6d7..0daecf0de 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -37,7 +37,6 @@ #include "srslte/common/threads.h" #include "srslte/common/log.h" #include "phy/phy.h" -#include "phy/phch_worker.h" #define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) #define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) @@ -134,7 +133,7 @@ void phy::run_thread() { // Add workers to workers pool and start threads for (uint32_t i=0;iworker_cpu_mask); } diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index 867221e87..7bd6fae18 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -137,13 +137,7 @@ enable = false # 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. -# 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 -# a new table will be generated more often. -# time_correct_period: Period for sampling time offset correction. Default is 10 (ue_sync.c), +# time_correct_period: Period for sampling time offset correction. Default is 10 (ue_sync.c), # good for long channels. For best performance at highest SNR reduce it to 1. # sfo_correct_disable: Disables phase correction before channel estimation to compensate for # sampling frequency offset. Default is enabled. @@ -155,10 +149,28 @@ enable = false # # pregenerate_signals: Pregenerate uplink signals after attach. Improves CPU performance. # +# average_subframe_enabled: Averages in the time domain the channel estimates within 1 subframe. +# Needs accurate CFO correction. +# # metrics_csv_enable: Write UE metrics to CSV file. # # metrics_csv_filename: File path to use for CSV metrics. # +# 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 +# a new table will be generated more often. +# +# cfo_pss_ema: CFO Exponential Moving Average coefficient for PSS estimation during TRACK. +# cfo_ref_ema: CFO Exponential Moving Average coefficient for RS estimation after PSS acquisition +# cfo_ref_mask: Bitmask for subframes on which to run RS estimation (set to 0 to disable, default sf=[1, 5]) +# cfo_loop_bw: CFO feedback loop bandwidth for samples from PSS or RS +# cfo_loop_pss_tol: Tolerance (in Hz) of the PSS estimation method. Below this value, PSS estimation does not feeds back the loop +# and RS estimations are used instead (when available) +# cfo_loop_ref_min: Tolerance (in Hz) of the RS estimation method. Below this value, RS estimation does not feeds back the loop +# cfo_loop_pss_timeout: After the PSS estimation is below cfo_loop_pss_tol for cfo_loop_pss_timeout times consecutively, +# RS adjustments are allowed. +# ##################################################################### [expert] #ip_netmask = 255.255.255.0 @@ -172,17 +184,27 @@ 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 #sfo_correct_disable = false #sss_algorithm = full #estimator_fil_w = 0.1 +#average_subframe_enabled = true #pregenerate_signals = false #metrics_csv_enable = false #metrics_csv_filename = /tmp/ue_metrics.csv +# CFO related values +#cfo_integer_enabled = false +#cfo_correct_tol_hz = 0 +#cfo_pss_ema = 0.1 +#cfo_ref_ema = 0.01 +#cfo_ref_mask = 1023 +#cfo_loop_bw_pss = 0.05 +#cfo_loop_bw_ref = 0.01 +#cfo_loop_pss_tol = 300 +#cfo_loop_ref_min = 0 +#cfo_loop_pss_conv = 50 + ##################################################################### # Manual RF calibration # From 6b264732d2621353d9c26e9d8ce88430d9edf433 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 1 Dec 2017 11:25:27 +0100 Subject: [PATCH 179/242] Disabled subframe average --- lib/examples/pdsch_ue.c | 8 +-- lib/src/phy/ue/ue_dl.c | 2 +- lib/src/phy/ue/ue_ul.c | 2 +- srsue/hdr/phy/phch_recv.h | 2 + srsue/hdr/upper/rrc.h | 6 +- srsue/src/main.cc | 2 +- srsue/src/phy/phch_recv.cc | 85 ++++++++++++----------- srsue/src/phy/phch_worker.cc | 15 ++-- srsue/src/upper/rrc.cc | 129 ++++++++++++++++++++++++++++------- srsue/ue.conf.example | 2 +- 10 files changed, 171 insertions(+), 82 deletions(-) diff --git a/lib/examples/pdsch_ue.c b/lib/examples/pdsch_ue.c index 6608f0817..ae43a5260 100644 --- a/lib/examples/pdsch_ue.c +++ b/lib/examples/pdsch_ue.c @@ -958,7 +958,7 @@ void *plot_thread_run(void *arg) { plot_real_init(&pce); plot_real_setTitle(&pce, "Channel Response - Magnitude"); plot_real_setLabels(&pce, "Index", "dB"); - plot_real_setYAxisScale(&pce, -M_PI, M_PI); + plot_real_setYAxisScale(&pce, -40, 40); plot_real_init(&p_sync); plot_real_setTitle(&p_sync, "PSS Cross-Corr abs value"); @@ -994,11 +994,7 @@ void *plot_thread_run(void *arg) { tmp_plot2[g+i] = -80; } } - uint32_t nrefs = 2*ue_dl.cell.nof_prb; - for (i=0;i(&args->expert.phy.average_subframe_enabled)->default_value(true), + bpo::value(&args->expert.phy.average_subframe_enabled)->default_value(false), "Averages in the time domain the channel estimates within 1 subframe. Needs accurate CFO correction.") ("expert.time_correct_period", diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index e3ab21c0e..dc056f9c0 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -399,22 +399,24 @@ bool phch_recv::cell_select(uint32_t earfcn, srslte_cell_t cell) { log_h->warning("Still not in idle\n"); } - current_earfcn = earfcn; + if (earfcn != current_earfcn) { + if (set_frequency()) { + log_h->error("Cell Select: Configuring cell in EARFCN=%d, PCI=%d\n", earfcn, cell.id); + return false; + } + current_earfcn = earfcn; + } - if (set_frequency()) { - this->cell = cell; - log_h->info("Cell Select: Configuring cell...\n"); + this->cell = cell; + log_h->info("Cell Select: Configuring cell...\n"); - if (set_cell()) { - log_h->info("Cell Select: Synchronizing on cell...\n"); + if (set_cell()) { + log_h->info("Cell Select: Synchronizing on cell...\n"); - resync_sfn(); + resync_sfn(); - usleep(500000); // Time offset we set start_rx to start receiving samples - return true; - } else { - log_h->error("Cell Select: Configuring cell in EARFCN=%d, PCI=%d\n", earfcn, cell.id); - } + usleep(500000); // Time offset we set start_rx to start receiving samples + return true; } return false; } @@ -669,13 +671,21 @@ void phch_recv::run_thread() workers_pool->start_worker(worker); intra_freq_meas.write(tti, buffer[0], SRSLTE_SF_LEN_PRB(cell.nof_prb)); + out_of_sync_cnt = 0; break; case 0: - log_h->error("SYNC: Sync error. Sending out-of-sync to RRC\n"); - // Notify RRC of out-of-sync frame - rrc->out_of_sync(); + // Signal every 5 errors only (PSS is every 5) + if (out_of_sync_cnt == 0) { + // Notify RRC of out-of-sync frame + log_h->error("SYNC: Sync error. Sending out-of-sync to RRC\n"); + rrc->out_of_sync(); + } worker->release(); worker_com->reset_ul(); + out_of_sync_cnt++; + if (out_of_sync_cnt >= 5) { + out_of_sync_cnt = 0; + } break; default: radio_error(); @@ -1203,7 +1213,7 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, int nof_cells = 0; uint32_t peak_idx = 0; uint32_t sf_idx = 0; - uint32_t cell_id = 0; + int cell_id = 0; srslte_cell_t found_cell; memcpy(&found_cell, &cell, sizeof(srslte_cell_t)); @@ -1226,29 +1236,28 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, sf_idx = srslte_sync_get_sf_idx(&sync_find); cell_id = srslte_sync_get_cell_id(&sync_find); - Info("INTRA: found peak_idx=%d, n_id_2=%d, cell_id=%d, sf=%d\n", + if (cell_id != -1) { + Info("INTRA: found peak_idx=%d, n_id_2=%d, cell_id=%d, sf=%d\n", peak_idx, n_id_2, cell_id, sf_idx); - found_cell.id = cell_id; - found_cell.nof_ports = 1; // Use port 0 only for measurement - measure_p.set_cell(found_cell); - - //printf("cell_id=%d, correcting cfo=%f Hz\n", cell_id, 15000*sync_find.mean_cfo2); - //srslte_cfo_correct(&sync_find.cfocorr, input_buffer, input_buffer, -sync_find.mean_cfo2 / sync_find.fft_size); - - switch(measure_p.run_multiple_subframes(input_buffer, peak_idx, sf_idx, nof_sf)) { - case measure::MEASURE_OK: - cells[nof_cells].pci = found_cell.id; - cells[nof_cells].rsrp = measure_p.rsrp(); - cells[nof_cells].rsrq = measure_p.rsrq(); - cells[nof_cells].offset = peak_idx; - nof_cells++; - break; - case measure::ERROR: - Error("Measuring neighbour cell\n"); - return SRSLTE_ERROR; - default: - break; + found_cell.id = cell_id; + found_cell.nof_ports = 1; // Use port 0 only for measurement + measure_p.set_cell(found_cell); + + switch(measure_p.run_multiple_subframes(input_buffer, peak_idx, sf_idx, nof_sf)) { + case measure::MEASURE_OK: + cells[nof_cells].pci = found_cell.id; + cells[nof_cells].rsrp = measure_p.rsrp(); + cells[nof_cells].rsrq = measure_p.rsrq(); + cells[nof_cells].offset = peak_idx; + nof_cells++; + break; + case measure::ERROR: + Error("Measuring neighbour cell\n"); + return SRSLTE_ERROR; + default: + break; + } } break; case SRSLTE_SYNC_FOUND_NOSPACE: @@ -1347,7 +1356,7 @@ void phch_recv::intra_measure::add_cell(int pci) { receive_enabled = true; Info("INTRA: Starting intra-frequency measurement for pci=%d\n", pci); } else { - Warning("INTRA: Requested to start already existing intra-frequency measurement for PCI=%d\n", pci); + Debug("INTRA: Requested to start already existing intra-frequency measurement for PCI=%d\n", pci); } } diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index c56ce9eb8..bf5000ecf 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -230,7 +230,7 @@ void phch_worker::work_imp() /* Do FFT and extract PDCCH LLR, or quit if no actions are required in this subframe */ bool chest_ok = extract_fft_and_pdcch_llr(); - bool snr_th_ok = 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest))>-10.0; + bool snr_th_ok = 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest))>-20.0; // Call feedback loop for chest if (chest_loop && ((1<<(tti%10)) & phy->args->cfo_ref_mask)) { @@ -1227,18 +1227,13 @@ int phch_worker::read_ce_abs(float *ce_abs) { int sz = srslte_symbol_sz(cell.nof_prb); bzero(ce_abs, sizeof(float)*sz); int g = (sz - 12*cell.nof_prb)/2; -/* for (i = 0; i < 12*cell.nof_prb; i++) { + for (i = 0; i < 12*cell.nof_prb; i++) { ce_abs[g+i] = 20 * log10f(cabsf(ue_dl.ce_m[0][0][i])); if (isinf(ce_abs[g+i])) { ce_abs[g+i] = -80; } } -*/ - uint32_t nrefs = 2*ue_dl.cell.nof_prb; - for (i=0;iavg_rsrp_dbm= rsrp_dbm; } else { phy->avg_rsrp_dbm = SRSLTE_VEC_EMA(rsrp_dbm, phy->avg_rsrp_dbm, snr_ema_coeff); - } + } if ((tti%phy->pcell_report_period) == 0 && phy->pcell_meas_enabled) { phy->rrc->new_phy_meas(phy->avg_rsrp_dbm, phy->avg_rsrq_db, tti); } @@ -1388,7 +1383,7 @@ void *plot_thread_run(void *arg) { plot_real_init(&pce); plot_real_setTitle(&pce, (char*) "Channel Response - Magnitude"); plot_real_setLabels(&pce, (char*) "Index", (char*) "dB"); - plot_real_setYAxisScale(&pce, -1000, 1000); + plot_real_setYAxisScale(&pce, -40, 40); plot_scatter_init(&pconst); plot_scatter_setTitle(&pconst, (char*) "PDSCH - Equalized Symbols"); diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 31ed25384..6e73670f7 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -225,14 +225,22 @@ void rrc::run_thread() { } break; case RRC_STATE_CELL_SELECTED: - rrc_log->info("RRC Cell Selected: Sending connection request...\n"); - if (reestablishment_in_progress) { + if (!nas->is_attached() || paging_received) { + paging_received = false; + rrc_log->info("RRC Cell Selected: Sending connection request...\n"); + send_con_request(); + state = RRC_STATE_CONNECTING; + connecting_timeout = 0; + } else if (reestablishment_in_progress) { + rrc_log->info("RRC Cell Selected: Sending connection reestablishment...\n"); con_restablish_cell_reselected(); + state = RRC_STATE_CONNECTING; + connecting_timeout = 0; } else { - send_con_request(); + rrc_log->console("RRC Cell Selected: New PCI=%d\n", current_cell->phy_cell.id); + mac->pcch_start_rx(); + state = RRC_STATE_IDLE; } - state = RRC_STATE_CONNECTING; - connecting_timeout = 0; break; case RRC_STATE_CONNECTING: connecting_timeout++; @@ -471,7 +479,34 @@ void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, uint32_t earfcn, ui if (state == RRC_STATE_CONNECTED) { measurements.new_phy_meas(earfcn, pci, rsrp, rsrq, tti); } else { - cell_reselection_eval(rsrp, rsrq); + // If measurement is of the serving cell, evaluate cell reselection criteria + if ((earfcn == phy->get_current_earfcn() && pci == phy->get_current_pci()) || (earfcn == 0 && pci == 0)) { + cell_reselection_eval(rsrp, rsrq); + current_cell->rsrp = rsrp; + rrc_log->info("MEAS: New measurement serving cell, rsrp=%f, rsrq=%f, tti=%d\n", rsrp, rsrq, tti); + } else { + // Add/update cell measurement + srslte_cell_t cell; + phy->get_current_cell(&cell, NULL); + cell.id = pci; + add_new_cell(earfcn, cell, rsrp); + + rrc_log->info("MEAS: New measurement PCI=%d, RSRP=%.1f dBm.\n", pci, rsrp); + } + + srslte_cell_t best_cell; + uint32_t best_cell_idx = find_best_cell(phy->get_current_earfcn(), &best_cell); + + // Verify cell selection criteria + if (cell_selection_eval(known_cells[best_cell_idx].rsrp) && + known_cells[best_cell_idx].rsrp > current_cell->rsrp + 5 && + best_cell.id != phy->get_current_pci()) + { + rrc_log->info("Selecting best neighbour cell PCI=%d, rsrp=%.1f dBm\n", best_cell.id, known_cells[best_cell_idx].rsrp); + state = RRC_STATE_CELL_SELECTING; + current_cell = &known_cells[best_cell_idx]; + phy->cell_select(phy->get_current_earfcn(), best_cell); + } } } @@ -498,8 +533,13 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { return; } } - // add to list of known cells - add_new_cell(earfcn, phy_cell, rsrp); + // add to list of known cells and set current_cell + current_cell = add_new_cell(earfcn, phy_cell, rsrp); + if(!current_cell) { + current_cell = &known_cells[0]; + rrc_log->error("Couldn't add new cell\n"); + return; + } si_acquire_state = SI_ACQUIRE_SIB1; @@ -508,22 +548,52 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { current_cell->earfcn, current_cell->rsrp, current_cell); } -void rrc::add_new_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { +uint32_t rrc::find_best_cell(uint32_t earfcn, srslte_cell_t *cell) { + float best_rsrp = -INFINITY; + uint32_t best_cell_idx = 0; + for (int i=0;i best_rsrp) { + best_rsrp = known_cells[i].rsrp; + best_cell_idx = i; + } + } + } + if (cell) { + memcpy(cell, &known_cells[best_cell_idx].phy_cell, sizeof(srslte_cell_t)); + } + return best_cell_idx; +} + +rrc::cell_t* rrc::add_new_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { + if (earfcn == 0) { + return NULL; + } + // First check it does not exist already + int j=0; + while(jerror("Can't add more cells\n"); - return; + return NULL; } - current_cell = &known_cells[i]; - current_cell->phy_cell = phy_cell; - current_cell->rsrp = rsrp; - current_cell->earfcn = earfcn; - current_cell->has_valid_sib1 = false; - current_cell->has_valid_sib2 = false; - current_cell->has_valid_sib3 = false; + + known_cells[i].phy_cell = phy_cell; + known_cells[i].rsrp = rsrp; + known_cells[i].earfcn = earfcn; + known_cells[i].has_valid_sib1 = false; + known_cells[i].has_valid_sib2 = false; + known_cells[i].has_valid_sib3 = false; + return &known_cells[i]; } // PHY indicates that has gone through all known EARFCN @@ -551,14 +621,16 @@ void rrc::add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp) { add_new_cell(earfcn, cell, rsrp); } -// Cell reselection in IDLE Section 5.2.4 of 36.304 +// Cell reselction in IDLE Section 5.2.4 of 36.304 void rrc::cell_reselection_eval(float rsrp, float rsrq) { // Intra-frequency cell-reselection criteria - if (get_srxlev(rsrp) > cell_resel_cfg.s_intrasearchP) { - // UE may not perform intra-frequency measurements + if (get_srxlev(rsrp) > cell_resel_cfg.s_intrasearchP && rsrp > -80.0) { + // UE may not perform intra-frequency measurements. phy->meas_reset(); + // keep measuring serving cell + phy->meas_start(phy->get_current_earfcn(), phy->get_current_pci()); } else { // UE must start intra-frequency measurements phy->meas_start(phy->get_current_earfcn(), -1); @@ -567,6 +639,16 @@ void rrc::cell_reselection_eval(float rsrp, float rsrq) // TODO: Inter-frequency cell reselection } +// Cell selection in IDLE Section 5.2.3.2 of 36.304 +bool rrc::cell_selection_eval(float rsrp, float rsrq) +{ + if (get_srxlev(rsrp) > 0) { + return true; + } else { + return false; + } +} + float rrc::get_srxlev(float Qrxlevmeas) { // TODO: Do max power limitation float Pcompensation = 0; @@ -1144,12 +1226,12 @@ void rrc::handle_sib3() cell_resel_cfg.q_hyst = liblte_rrc_q_hyst_num[sib3->q_hyst]; // cellReselectionServingFreqInfo - cell_resel_cfg.threshservinglow = 2*sib3->thresh_serving_low; + cell_resel_cfg.threshservinglow = sib3->thresh_serving_low; // intraFreqCellReselectionInfo - cell_resel_cfg.Qrxlevmin = 2*sib3->q_rx_lev_min; + cell_resel_cfg.Qrxlevmin = sib3->q_rx_lev_min; if (sib3->s_intra_search_present) { - cell_resel_cfg.s_intrasearchP = 2*sib3->s_intra_search; + cell_resel_cfg.s_intrasearchP = sib3->s_intra_search; } else { cell_resel_cfg.s_intrasearchP = INFINITY; } @@ -1214,6 +1296,7 @@ void rrc::write_pdu_pcch(byte_buffer_t *pdu) { mac->pcch_stop_rx(); if (RRC_STATE_IDLE == state) { rrc_log->info("RRC in IDLE state - sending connection request.\n"); + paging_received = true; state = RRC_STATE_CELL_SELECTING; } } diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index 7bd6fae18..0b3314e7a 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -188,7 +188,7 @@ enable = false #sfo_correct_disable = false #sss_algorithm = full #estimator_fil_w = 0.1 -#average_subframe_enabled = true +#average_subframe_enabled = false #pregenerate_signals = false #metrics_csv_enable = false #metrics_csv_filename = /tmp/ue_metrics.csv From 516fdc27f19dc4156118021251626ff4f397b71c Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Fri, 1 Dec 2017 12:38:18 +0000 Subject: [PATCH 180/242] Fix for NAS security bearer id, added encryption test sets, fix for compile warning --- lib/src/common/liblte_security.cc | 5 +- lib/test/common/CMakeLists.txt | 8 + lib/test/common/test_eea1.cc | 569 ++++++++++++++++++++++++++++++ lib/test/common/test_eea2.cc | 567 +++++++++++++++++++++++++++++ srsue/hdr/upper/nas.h | 7 +- srsue/src/upper/nas.cc | 47 ++- 6 files changed, 1170 insertions(+), 33 deletions(-) create mode 100644 lib/test/common/test_eea1.cc create mode 100644 lib/test/common/test_eea2.cc diff --git a/lib/src/common/liblte_security.cc b/lib/src/common/liblte_security.cc index 4ff35b5e4..37df6c7df 100644 --- a/lib/src/common/liblte_security.cc +++ b/lib/src/common/liblte_security.cc @@ -903,7 +903,7 @@ LIBLTE_ERROR_ENUM liblte_security_encryption_eea1(uint8 *key, s3g_generate_keystream(state_ptr, msg_len_block_32, ks); // Generate output except last block - for (i = 0; i < msg_len_block_32 - 1; i++) { + for (i = 0; i < (int32_t)msg_len_block_32 - 1; i++) { out[4 * i + 0] = msg[4 * i + 0] ^ ((ks[i] >> 24) & 0xFF); out[4 * i + 1] = msg[4 * i + 1] ^ ((ks[i] >> 16) & 0xFF); out[4 * i + 2] = msg[4 * i + 2] ^ ((ks[i] >> 8) & 0xFF); @@ -911,8 +911,7 @@ LIBLTE_ERROR_ENUM liblte_security_encryption_eea1(uint8 *key, } // Process last bytes - for (i = (msg_len_block_32 - 1) * 4; i < msg_len_block_8; - i++) { + for (i = (msg_len_block_32 - 1) * 4; i < (int32_t)msg_len_block_8; i++) { out[i] = msg[i] ^ ((ks[i / 4] >> ((3 - (i % 4)) * 8)) & 0xFF); } diff --git a/lib/test/common/CMakeLists.txt b/lib/test/common/CMakeLists.txt index 3faa2ff59..bbdc74613 100644 --- a/lib/test/common/CMakeLists.txt +++ b/lib/test/common/CMakeLists.txt @@ -29,6 +29,14 @@ add_executable(msg_queue_test msg_queue_test.cc) target_link_libraries(msg_queue_test srslte_phy srslte_common ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) add_test(msg_queue_test msg_queue_test) +add_executable(test_eea1 test_eea1.cc) +target_link_libraries(test_eea1 srslte_common ${CMAKE_THREAD_LIBS_INIT}) +add_test(test_eea1 test_eea1) + +add_executable(test_eea2 test_eea2.cc) +target_link_libraries(test_eea2 srslte_common ${CMAKE_THREAD_LIBS_INIT}) +add_test(test_eea2 test_eea2) + add_executable(log_filter_test log_filter_test.cc) target_link_libraries(log_filter_test srslte_phy srslte_common srslte_phy ${SEC_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) diff --git a/lib/test/common/test_eea1.cc b/lib/test/common/test_eea1.cc new file mode 100644 index 000000000..b3c57caa6 --- /dev/null +++ b/lib/test/common/test_eea1.cc @@ -0,0 +1,569 @@ +/* + * Includes + */ + +#include +#include +#include + +#include "srslte/common/liblte_security.h" + +/* + * Prototypes + */ + +int32 arrcmp(uint8_t const * const a, uint8_t const * const b, uint32 len) { + uint32 i = 0; + + for (i = 0; i < len; i++) { + if (a[i] != b[i]) { + return a[i] - b[i]; + } + } + return 0; +} + +/* + * Tests + * + * Document Reference: 33.401 V13.1.0 Annex C.3 + * Specification of the 3GPP Confidentiality and + * Integrity Algorithms UEA2 & UIA2 D4 v1.0 + */ + +void test_set_1() +{ + LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS; + int32 err_cmp = 0; + + uint8_t key[] = { 0xd3, 0xc5, 0xd5, 0x92, 0x32, 0x7f, 0xb1, + 0x1c, 0x40, 0x35, 0xc6, 0x68, 0x0a, 0xf8, 0xc6, 0xd1 }; + uint32_t count = 0x398a59b4; + uint8_t bearer = 0x15; + uint8_t direction = 1; + uint32_t len_bits = 253, len_bytes = (len_bits + 7) / 8; + uint8_t msg[] = { 0x98, 0x1b, 0xa6, 0x82, 0x4c, 0x1b, 0xfb, + 0x1a, 0xb4, 0x85, 0x47, 0x20, 0x29, 0xb7, 0x1d, 0x80, + 0x8c, 0xe3, 0x3e, 0x2c, 0xc3, 0xc0, 0xb5, 0xfc, 0x1f, + 0x3d, 0xe8, 0xa6, 0xdc, 0x66, 0xb1, 0xf0 }; + uint8_t ct[] = { 0x5d, 0x5b, 0xfe, 0x75, 0xeb, 0x04, 0xf6, + 0x8c, 0xe0, 0xa1, 0x23, 0x77, 0xea, 0x00, 0xb3, 0x7d, + 0x47, 0xc6, 0xa0, 0xba, 0x06, 0x30, 0x91, 0x55, 0x08, + 0x6a, 0x85, 0x9c, 0x43, 0x41, 0xb3, 0x78 }; + + uint8_t * out = (uint8_t *) calloc(len_bytes, + sizeof(uint8_t)); + + // encryption + err_lte = liblte_security_encryption_eea1(key, count, bearer, + direction, msg, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(ct, out, len_bytes); + assert(err_cmp == 0); + + // decryption + err_lte = liblte_security_decryption_eea1(key, count, bearer, + direction, ct, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(msg, out, len_bytes); + assert(err_cmp == 0); + + free(out); +} + +void test_set_2() +{ + LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS; + int32 err_cmp = 0; + + uint8_t key[] = { 0x2b, 0xd6, 0x45, 0x9f, 0x82, 0xc4, 0x40, + 0xe0, 0x95, 0x2c, 0x49, 0x10, 0x48, 0x05, 0xff, 0x48 }; + uint32_t count = 0xc675a64b; + uint8_t bearer = 0x0c; + uint8_t direction = 1; + uint32_t len_bits = 798, len_bytes = (len_bits + 7) / 8; + uint8_t msg[] = { 0x7e, 0xc6, 0x12, 0x72, 0x74, 0x3b, 0xf1, + 0x61, 0x47, 0x26, 0x44, 0x6a, 0x6c, 0x38, 0xce, 0xd1, + 0x66, 0xf6, 0xca, 0x76, 0xeb, 0x54, 0x30, 0x04, 0x42, + 0x86, 0x34, 0x6c, 0xef, 0x13, 0x0f, 0x92, 0x92, 0x2b, + 0x03, 0x45, 0x0d, 0x3a, 0x99, 0x75, 0xe5, 0xbd, 0x2e, + 0xa0, 0xeb, 0x55, 0xad, 0x8e, 0x1b, 0x19, 0x9e, 0x3e, + 0xc4, 0x31, 0x60, 0x20, 0xe9, 0xa1, 0xb2, 0x85, 0xe7, + 0x62, 0x79, 0x53, 0x59, 0xb7, 0xbd, 0xfd, 0x39, 0xbe, + 0xf4, 0xb2, 0x48, 0x45, 0x83, 0xd5, 0xaf, 0xe0, 0x82, + 0xae, 0xe6, 0x38, 0xbf, 0x5f, 0xd5, 0xa6, 0x06, 0x19, + 0x39, 0x01, 0xa0, 0x8f, 0x4a, 0xb4, 0x1a, 0xab, 0x9b, + 0x13, 0x48, 0x80 }; + uint8_t ct[] = { 0x3f, 0x67, 0x85, 0x07, 0x14, 0xb8, 0xda, + 0x69, 0xef, 0xb7, 0x27, 0xed, 0x7a, 0x6c, 0x0c, 0x50, + 0x71, 0x4a, 0xd7, 0x36, 0xc4, 0xf5, 0x60, 0x00, 0x06, + 0xe3, 0x52, 0x5b, 0xe8, 0x07, 0xc4, 0x67, 0xc6, 0x77, + 0xff, 0x86, 0x4a, 0xf4, 0x5f, 0xba, 0x09, 0xc2, 0x7c, + 0xde, 0x38, 0xf8, 0x7a, 0x1f, 0x84, 0xd5, 0x9a, 0xb2, + 0x55, 0x40, 0x8f, 0x2c, 0x7b, 0x82, 0xf9, 0xea, 0xd4, + 0x1a, 0x1f, 0xe6, 0x5e, 0xab, 0xeb, 0xfb, 0xc1, 0xf3, + 0xa4, 0xc5, 0x6c, 0x9a, 0x26, 0xfc, 0xf7, 0xb3, 0xd6, + 0x6d, 0x02, 0x20, 0xee, 0x47, 0x75, 0xbc, 0x58, 0x17, + 0x0a, 0x2b, 0x12, 0xf3, 0x43, 0x1d, 0x11, 0xb3, 0x44, + 0xd6, 0xe3, 0x6c }; + + uint8_t * out = (uint8_t *) calloc(len_bytes, + sizeof(uint8_t)); + + // encryption + err_lte = liblte_security_encryption_eea1(key, count, bearer, + direction, msg, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(ct, out, len_bytes); + assert(err_cmp == 0); + + // decryption + err_lte = liblte_security_decryption_eea1(key, count, bearer, + direction, ct, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(msg, out, len_bytes); + assert(err_cmp == 0); + + free(out); +} + +void test_set_3() +{ + LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS; + int32 err_cmp = 0; + + uint8_t key[] = { 0x0a, 0x8b, 0x6b, 0xd8, 0xd9, 0xb0, 0x8b, + 0x08, 0xd6, 0x4e, 0x32, 0xd1, 0x81, 0x77, 0x77, 0xfb }; + uint32_t count = 0x544d49cd; + uint8_t bearer = 0x04; + uint8_t direction = 0; + uint32_t len_bits = 310, len_bytes = (len_bits + 7) / 8; + uint8_t msg[] = { 0xfd, 0x40, 0xa4, 0x1d, 0x37, 0x0a, 0x1f, + 0x65, 0x74, 0x50, 0x95, 0x68, 0x7d, 0x47, 0xba, 0x1d, + 0x36, 0xd2, 0x34, 0x9e, 0x23, 0xf6, 0x44, 0x39, 0x2c, + 0x8e, 0xa9, 0xc4, 0x9d, 0x40, 0xc1, 0x32, 0x71, 0xaf, + 0xf2, 0x64, 0xd0, 0xf2, 0x48, 0x00 }; + uint8_t ct[] = { 0x48, 0x14, 0x8e, 0x54, 0x52, 0xa2, 0x10, + 0xc0, 0x5f, 0x46, 0xbc, 0x80, 0xdc, 0x6f, 0x73, 0x49, + 0x5b, 0x02, 0x04, 0x8c, 0x1b, 0x95, 0x8b, 0x02, 0x61, + 0x02, 0xca, 0x97, 0x28, 0x02, 0x79, 0xa4, 0xc1, 0x8d, + 0x2e, 0xe3, 0x08, 0x92, 0x1c }; + + uint8_t * out = (uint8_t *) calloc(len_bytes, + sizeof(uint8_t)); + + // encryption + err_lte = liblte_security_encryption_eea1(key, count, bearer, + direction, msg, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(ct, out, len_bytes); + assert(err_cmp == 0); + + // decryption + err_lte = liblte_security_decryption_eea1(key, count, bearer, + direction, ct, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(msg, out, len_bytes); + assert(err_cmp == 0); + + free(out); +} + +void test_set_4() +{ + LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS; + int32 err_cmp = 0; + + uint8_t key[] = { 0xaa, 0x1f, 0x95, 0xae, 0xa5, 0x33, 0xbc, + 0xb3, 0x2e, 0xb6, 0x3b, 0xf5, 0x2d, 0x8f, 0x83, 0x1a }; + uint32_t count = 0x72d8c671; + uint8_t bearer = 0x10; + uint8_t direction = 1; + uint32_t len_bits = 1022, len_bytes = (len_bits + 7) / 8; + uint8_t msg[] = { 0xfb, 0x1b, 0x96, 0xc5, 0xc8, 0xba, 0xdf, + 0xb2, 0xe8, 0xe8, 0xed, 0xfd, 0xe7, 0x8e, 0x57, 0xf2, + 0xad, 0x81, 0xe7, 0x41, 0x03, 0xfc, 0x43, 0x0a, 0x53, + 0x4d, 0xcc, 0x37, 0xaf, 0xce, 0xc7, 0x0e, 0x15, 0x17, + 0xbb, 0x06, 0xf2, 0x72, 0x19, 0xda, 0xe4, 0x90, 0x22, + 0xdd, 0xc4, 0x7a, 0x06, 0x8d, 0xe4, 0xc9, 0x49, 0x6a, + 0x95, 0x1a, 0x6b, 0x09, 0xed, 0xbd, 0xc8, 0x64, 0xc7, + 0xad, 0xbd, 0x74, 0x0a, 0xc5, 0x0c, 0x02, 0x2f, 0x30, + 0x82, 0xba, 0xfd, 0x22, 0xd7, 0x81, 0x97, 0xc5, 0xd5, + 0x08, 0xb9, 0x77, 0xbc, 0xa1, 0x3f, 0x32, 0xe6, 0x52, + 0xe7, 0x4b, 0xa7, 0x28, 0x57, 0x60, 0x77, 0xce, 0x62, + 0x8c, 0x53, 0x5e, 0x87, 0xdc, 0x60, 0x77, 0xba, 0x07, + 0xd2, 0x90, 0x68, 0x59, 0x0c, 0x8c, 0xb5, 0xf1, 0x08, + 0x8e, 0x08, 0x2c, 0xfa, 0x0e, 0xc9, 0x61, 0x30, 0x2d, + 0x69, 0xcf, 0x3d, 0x44 }; + uint8_t ct[] = { 0xff, 0xcf, 0xc2, 0xfe, 0xad, 0x6c, 0x09, + 0x4e, 0x96, 0xc5, 0x89, 0xd0, 0xf6, 0x77, 0x9b, 0x67, + 0x84, 0x24, 0x6c, 0x3c, 0x4d, 0x1c, 0xea, 0x20, 0x3d, + 0xb3, 0x90, 0x1f, 0x40, 0xad, 0x4f, 0xd7, 0x13, 0x8b, + 0xc6, 0xd7, 0x7e, 0x83, 0x20, 0xcb, 0x10, 0x2f, 0x49, + 0x7f, 0xdd, 0x44, 0xa2, 0x69, 0xa9, 0x6e, 0xcb, 0x28, + 0x61, 0x77, 0x00, 0xe3, 0x32, 0xeb, 0x2f, 0x73, 0x6b, + 0x34, 0xf4, 0xf2, 0x69, 0x30, 0x94, 0xe2, 0x2f, 0xf9, + 0x4f, 0x9b, 0xe4, 0x72, 0x3d, 0xa4, 0x0c, 0x40, 0xdf, + 0xd3, 0x93, 0x1c, 0xc1, 0xac, 0x97, 0x23, 0xf6, 0xb4, + 0xa9, 0x91, 0x3e, 0x96, 0xb6, 0xdb, 0x7a, 0xbc, 0xac, + 0xe4, 0x15, 0x17, 0x7c, 0x1d, 0x01, 0x15, 0xc5, 0xf0, + 0x9b, 0x5f, 0xde, 0xa0, 0xb3, 0xad, 0xb8, 0xf9, 0xda, + 0x6e, 0x9f, 0x9a, 0x04, 0xc5, 0x43, 0x39, 0x7b, 0x9d, + 0x43, 0xf8, 0x73, 0x30 }; + + uint8_t * out = (uint8_t *) calloc(len_bytes, + sizeof(uint8_t)); + + // encryption + err_lte = liblte_security_encryption_eea1(key, count, bearer, + direction, msg, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(ct, out, len_bytes); + assert(err_cmp == 0); + + // decryption + err_lte = liblte_security_decryption_eea1(key, count, bearer, + direction, ct, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(msg, out, len_bytes); + assert(err_cmp == 0); + + free(out); +} + +void test_set_5() +{ + LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS; + int32 err_cmp = 0; + + uint8_t key[] = { 0x96, 0x18, 0xae, 0x46, 0x89, 0x1f, 0x86, + 0x57, 0x8e, 0xeb, 0xe9, 0x0e, 0xf7, 0xa1, 0x20, 0x2e }; + uint32_t count = 0xc675a64b; + uint8_t bearer = 0x0c; + uint8_t direction = 1; + uint32_t len_bits = 1245, len_bytes = (len_bits + 7) / 8; + uint8_t msg[] = { 0x8d, 0xaa, 0x17, 0xb1, 0xae, 0x05, 0x05, + 0x29, 0xc6, 0x82, 0x7f, 0x28, 0xc0, 0xef, 0x6a, 0x12, + 0x42, 0xe9, 0x3f, 0x8b, 0x31, 0x4f, 0xb1, 0x8a, 0x77, + 0xf7, 0x90, 0xae, 0x04, 0x9f, 0xed, 0xd6, 0x12, 0x26, + 0x7f, 0xec, 0xae, 0xfc, 0x45, 0x01, 0x74, 0xd7, 0x6d, + 0x9f, 0x9a, 0xa7, 0x75, 0x5a, 0x30, 0xcd, 0x90, 0xa9, + 0xa5, 0x87, 0x4b, 0xf4, 0x8e, 0xaf, 0x70, 0xee, 0xa3, + 0xa6, 0x2a, 0x25, 0x0a, 0x8b, 0x6b, 0xd8, 0xd9, 0xb0, + 0x8b, 0x08, 0xd6, 0x4e, 0x32, 0xd1, 0x81, 0x77, 0x77, + 0xfb, 0x54, 0x4d, 0x49, 0xcd, 0x49, 0x72, 0x0e, 0x21, + 0x9d, 0xbf, 0x8b, 0xbe, 0xd3, 0x39, 0x04, 0xe1, 0xfd, + 0x40, 0xa4, 0x1d, 0x37, 0x0a, 0x1f, 0x65, 0x74, 0x50, + 0x95, 0x68, 0x7d, 0x47, 0xba, 0x1d, 0x36, 0xd2, 0x34, + 0x9e, 0x23, 0xf6, 0x44, 0x39, 0x2c, 0x8e, 0xa9, 0xc4, + 0x9d, 0x40, 0xc1, 0x32, 0x71, 0xaf, 0xf2, 0x64, 0xd0, + 0xf2, 0x48, 0x41, 0xd6, 0x46, 0x5f, 0x09, 0x96, 0xff, + 0x84, 0xe6, 0x5f, 0xc5, 0x17, 0xc5, 0x3e, 0xfc, 0x33, + 0x63, 0xc3, 0x84, 0x92, 0xa8 }; + uint8_t ct[] = { 0x6c, 0xdb, 0x18, 0xa7, 0xca, 0x82, 0x18, + 0xe8, 0x6e, 0x4b, 0x4b, 0x71, 0x6a, 0x4d, 0x04, 0x37, + 0x1f, 0xbe, 0xc2, 0x62, 0xfc, 0x5a, 0xd0, 0xb3, 0x81, + 0x9b, 0x18, 0x7b, 0x97, 0xe5, 0x5b, 0x1a, 0x4d, 0x7c, + 0x19, 0xee, 0x24, 0xc8, 0xb4, 0xd7, 0x72, 0x3c, 0xfe, + 0xdf, 0x04, 0x5b, 0x8a, 0xca, 0xe4, 0x86, 0x95, 0x17, + 0xd8, 0x0e, 0x50, 0x61, 0x5d, 0x90, 0x35, 0xd5, 0xd9, + 0xc5, 0xa4, 0x0a, 0xf6, 0x02, 0x28, 0x0b, 0x54, 0x25, + 0x97, 0xb0, 0xcb, 0x18, 0x61, 0x9e, 0xeb, 0x35, 0x92, + 0x57, 0x59, 0xd1, 0x95, 0xe1, 0x00, 0xe8, 0xe4, 0xaa, + 0x0c, 0x38, 0xa3, 0xc2, 0xab, 0xe0, 0xf3, 0xd8, 0xff, + 0x04, 0xf3, 0xc3, 0x3c, 0x29, 0x50, 0x69, 0xc2, 0x36, + 0x94, 0xb5, 0xbb, 0xea, 0xcd, 0xd5, 0x42, 0xe2, 0x8e, + 0x8a, 0x94, 0xed, 0xb9, 0x11, 0x9f, 0x41, 0x2d, 0x05, + 0x4b, 0xe1, 0xfa, 0x72, 0x72, 0xb5, 0xff, 0xb2, 0xb2, + 0x57, 0x0f, 0x4f, 0x7c, 0xea, 0xf3, 0x83, 0xa8, 0xa9, + 0xd9, 0x35, 0x72, 0xf0, 0x4d, 0x6e, 0x3a, 0x6e, 0x29, + 0x37, 0x26, 0xec, 0x62, 0xc8 }; + + uint8_t * out = (uint8_t *) calloc(len_bytes, + sizeof(uint8_t)); + + // encryption + err_lte = liblte_security_encryption_eea1(key, count, bearer, + direction, msg, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(ct, out, len_bytes); + assert(err_cmp == 0); + + // decryption + err_lte = liblte_security_decryption_eea1(key, count, bearer, + direction, ct, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(msg, out, len_bytes); + assert(err_cmp == 0); + + free(out); +} + +void test_set_6() +{ + LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS; + int32 err_cmp = 0; + + uint8_t key[] = { 0x54, 0xf4, 0xe2, 0xe0, 0x4c, 0x83, 0x78, + 0x6e, 0xec, 0x8f, 0xb5, 0xab, 0xe8, 0xe3, 0x65, 0x66 }; + uint32_t count = 0xaca4f50f; + uint8_t bearer = 0x0b; + uint8_t direction = 0; + uint32_t len_bits = 3861, len_bytes = (len_bits + 7) / 8; + uint8_t msg[] = { 0x40, 0x98, 0x1b, 0xa6, 0x82, 0x4c, 0x1b, + 0xfb, 0x42, 0x86, 0xb2, 0x99, 0x78, 0x3d, 0xaf, 0x44, + 0x2c, 0x09, 0x9f, 0x7a, 0xb0, 0xf5, 0x8d, 0x5c, 0x8e, + 0x46, 0xb1, 0x04, 0xf0, 0x8f, 0x01, 0xb4, 0x1a, 0xb4, + 0x85, 0x47, 0x20, 0x29, 0xb7, 0x1d, 0x36, 0xbd, 0x1a, + 0x3d, 0x90, 0xdc, 0x3a, 0x41, 0xb4, 0x6d, 0x51, 0x67, + 0x2a, 0xc4, 0xc9, 0x66, 0x3a, 0x2b, 0xe0, 0x63, 0xda, + 0x4b, 0xc8, 0xd2, 0x80, 0x8c, 0xe3, 0x3e, 0x2c, 0xcc, + 0xbf, 0xc6, 0x34, 0xe1, 0xb2, 0x59, 0x06, 0x08, 0x76, + 0xa0, 0xfb, 0xb5, 0xa4, 0x37, 0xeb, 0xcc, 0x8d, 0x31, + 0xc1, 0x9e, 0x44, 0x54, 0x31, 0x87, 0x45, 0xe3, 0xfa, + 0x16, 0xbb, 0x11, 0xad, 0xae, 0x24, 0x88, 0x79, 0xfe, + 0x52, 0xdb, 0x25, 0x43, 0xe5, 0x3c, 0xf4, 0x45, 0xd3, + 0xd8, 0x28, 0xce, 0x0b, 0xf5, 0xc5, 0x60, 0x59, 0x3d, + 0x97, 0x27, 0x8a, 0x59, 0x76, 0x2d, 0xd0, 0xc2, 0xc9, + 0xcd, 0x68, 0xd4, 0x49, 0x6a, 0x79, 0x25, 0x08, 0x61, + 0x40, 0x14, 0xb1, 0x3b, 0x6a, 0xa5, 0x11, 0x28, 0xc1, + 0x8c, 0xd6, 0xa9, 0x0b, 0x87, 0x97, 0x8c, 0x2f, 0xf1, + 0xca, 0xbe, 0x7d, 0x9f, 0x89, 0x8a, 0x41, 0x1b, 0xfd, + 0xb8, 0x4f, 0x68, 0xf6, 0x72, 0x7b, 0x14, 0x99, 0xcd, + 0xd3, 0x0d, 0xf0, 0x44, 0x3a, 0xb4, 0xa6, 0x66, 0x53, + 0x33, 0x0b, 0xcb, 0xa1, 0x10, 0x5e, 0x4c, 0xec, 0x03, + 0x4c, 0x73, 0xe6, 0x05, 0xb4, 0x31, 0x0e, 0xaa, 0xad, + 0xcf, 0xd5, 0xb0, 0xca, 0x27, 0xff, 0xd8, 0x9d, 0x14, + 0x4d, 0xf4, 0x79, 0x27, 0x59, 0x42, 0x7c, 0x9c, 0xc1, + 0xf8, 0xcd, 0x8c, 0x87, 0x20, 0x23, 0x64, 0xb8, 0xa6, + 0x87, 0x95, 0x4c, 0xb0, 0x5a, 0x8d, 0x4e, 0x2d, 0x99, + 0xe7, 0x3d, 0xb1, 0x60, 0xde, 0xb1, 0x80, 0xad, 0x08, + 0x41, 0xe9, 0x67, 0x41, 0xa5, 0xd5, 0x9f, 0xe4, 0x18, + 0x9f, 0x15, 0x42, 0x00, 0x26, 0xfe, 0x4c, 0xd1, 0x21, + 0x04, 0x93, 0x2f, 0xb3, 0x8f, 0x73, 0x53, 0x40, 0x43, + 0x8a, 0xaf, 0x7e, 0xca, 0x6f, 0xd5, 0xcf, 0xd3, 0xa1, + 0x95, 0xce, 0x5a, 0xbe, 0x65, 0x27, 0x2a, 0xf6, 0x07, + 0xad, 0xa1, 0xbe, 0x65, 0xa6, 0xb4, 0xc9, 0xc0, 0x69, + 0x32, 0x34, 0x09, 0x2c, 0x4d, 0x01, 0x8f, 0x17, 0x56, + 0xc6, 0xdb, 0x9d, 0xc8, 0xa6, 0xd8, 0x0b, 0x88, 0x81, + 0x38, 0x61, 0x6b, 0x68, 0x12, 0x62, 0xf9, 0x54, 0xd0, + 0xe7, 0x71, 0x17, 0x48, 0x78, 0x0d, 0x92, 0x29, 0x1d, + 0x86, 0x29, 0x99, 0x72, 0xdb, 0x74, 0x1c, 0xfa, 0x4f, + 0x37, 0xb8, 0xb5, 0x6c, 0xdb, 0x18, 0xa7, 0xca, 0x82, + 0x18, 0xe8, 0x6e, 0x4b, 0x4b, 0x71, 0x6a, 0x4d, 0x04, + 0x37, 0x1f, 0xbe, 0xc2, 0x62, 0xfc, 0x5a, 0xd0, 0xb3, + 0x81, 0x9b, 0x18, 0x7b, 0x97, 0xe5, 0x5b, 0x1a, 0x4d, + 0x7c, 0x19, 0xee, 0x24, 0xc8, 0xb4, 0xd7, 0x72, 0x3c, + 0xfe, 0xdf, 0x04, 0x5b, 0x8a, 0xca, 0xe4, 0x86, 0x95, + 0x17, 0xd8, 0x0e, 0x50, 0x61, 0x5d, 0x90, 0x35, 0xd5, + 0xd9, 0xc5, 0xa4, 0x0a, 0xf6, 0x02, 0x28, 0x0b, 0x54, + 0x25, 0x97, 0xb0, 0xcb, 0x18, 0x61, 0x9e, 0xeb, 0x35, + 0x92, 0x57, 0x59, 0xd1, 0x95, 0xe1, 0x00, 0xe8, 0xe4, + 0xaa, 0x0c, 0x38, 0xa3, 0xc2, 0xab, 0xe0, 0xf3, 0xd8, + 0xff, 0x04, 0xf3, 0xc3, 0x3c, 0x29, 0x50, 0x69, 0xc2, + 0x36, 0x94, 0xb5, 0xbb, 0xea, 0xcd, 0xd5, 0x42, 0xe2, + 0x8e, 0x8a, 0x94, 0xed, 0xb9, 0x11, 0x9f, 0x41, 0x2d, + 0x05, 0x4b, 0xe1, 0xfa, 0x72, 0xb0, 0x95, 0x50 }; + uint8_t ct[] = { 0x35, 0x1e, 0x30, 0xd4, 0xd9, 0x10, 0xc5, + 0xdd, 0x5a, 0xd7, 0x83, 0x4c, 0x42, 0x6e, 0x6c, 0x0c, + 0xab, 0x64, 0x86, 0xda, 0x7b, 0x0f, 0xda, 0x4c, 0xd8, + 0x3a, 0xf1, 0xb9, 0x64, 0x71, 0x37, 0xf1, 0xac, 0x43, + 0xb4, 0x34, 0x22, 0x3b, 0x19, 0xbe, 0x07, 0xbd, 0x89, + 0xd1, 0xcc, 0x30, 0x69, 0x44, 0xd3, 0x36, 0x1e, 0xa1, + 0xa2, 0xf8, 0xcd, 0xbd, 0x32, 0x16, 0x55, 0x97, 0x63, + 0x50, 0xd0, 0x0b, 0x80, 0xdd, 0x83, 0x81, 0x20, 0xa7, + 0x75, 0x5c, 0x6d, 0xea, 0x2a, 0xb2, 0xb0, 0xc9, 0x9a, + 0x91, 0x3f, 0x47, 0xda, 0xe2, 0xb8, 0xde, 0xb9, 0xa8, + 0x29, 0xe5, 0x46, 0x9f, 0xf2, 0xe1, 0x87, 0x77, 0x6f, + 0x6f, 0xd0, 0x81, 0xe3, 0x87, 0x1d, 0x11, 0x9a, 0x76, + 0xe2, 0x4c, 0x91, 0x7e, 0xa6, 0x26, 0x48, 0xe0, 0x2e, + 0x90, 0x36, 0x75, 0x64, 0xde, 0x72, 0xae, 0x7e, 0x4f, + 0x0a, 0x42, 0x49, 0xa9, 0xa5, 0xb0, 0xe4, 0x65, 0xa2, + 0xd6, 0xd9, 0xdc, 0x87, 0x84, 0x3b, 0x1b, 0x87, 0x5c, + 0xc9, 0xa3, 0xbe, 0x93, 0xd8, 0xda, 0x8f, 0x56, 0xec, + 0xaf, 0x59, 0x81, 0xfe, 0x93, 0xc2, 0x84, 0x31, 0x8b, + 0x0d, 0xec, 0x7a, 0x3b, 0xa1, 0x08, 0xe2, 0xcb, 0x1a, + 0x61, 0xe9, 0x66, 0xfa, 0x7a, 0xfa, 0x7a, 0xc7, 0xf6, + 0x7f, 0x65, 0xbc, 0x4a, 0x2d, 0xf0, 0x70, 0xd4, 0xe4, + 0x34, 0x84, 0x5f, 0x10, 0x9a, 0xb2, 0xb6, 0x8a, 0xde, + 0x3d, 0xc3, 0x16, 0xca, 0x63, 0x32, 0xa6, 0x28, 0x93, + 0xe0, 0xa7, 0xec, 0x0b, 0x4f, 0xc2, 0x51, 0x91, 0xbf, + 0x2f, 0xf1, 0xb9, 0xf9, 0x81, 0x5e, 0x4b, 0xa8, 0xa9, + 0x9c, 0x64, 0x3b, 0x52, 0x18, 0x04, 0xf7, 0xd5, 0x85, + 0x0d, 0xde, 0x39, 0x52, 0x20, 0x6e, 0xc6, 0xcc, 0xf3, + 0x40, 0xf9, 0xb3, 0x22, 0x0b, 0x30, 0x23, 0xbd, 0xd0, + 0x63, 0x95, 0x6e, 0xa8, 0x33, 0x39, 0x20, 0xfd, 0xe9, + 0x9e, 0x06, 0x75, 0x41, 0x0e, 0x49, 0xef, 0x3b, 0x4d, + 0x3f, 0xb3, 0xdf, 0x51, 0x92, 0xf9, 0x9c, 0xa8, 0x3d, + 0x3b, 0x00, 0x32, 0xde, 0x08, 0xc2, 0x20, 0x77, 0x6a, + 0x58, 0x65, 0xb0, 0xe4, 0xb3, 0xb0, 0xc7, 0x5d, 0xef, + 0xe7, 0x76, 0x2d, 0xff, 0x01, 0x8e, 0xa7, 0xf5, 0xbe, + 0x2b, 0x2f, 0x97, 0x2b, 0x2a, 0x8b, 0xa5, 0x97, 0x0e, + 0x43, 0xbd, 0x6f, 0xdd, 0x63, 0xda, 0xe6, 0x29, 0x78, + 0x4e, 0xc4, 0x8d, 0x61, 0x00, 0x54, 0xee, 0x4e, 0x4b, + 0x5d, 0xbb, 0xf1, 0xfc, 0x2f, 0xa0, 0xb8, 0x30, 0xe9, + 0x4d, 0xcb, 0xb7, 0x01, 0x4e, 0x8a, 0xb4, 0x29, 0xab, + 0x10, 0x0f, 0xc4, 0x8f, 0x83, 0x17, 0x1d, 0x99, 0xfc, + 0x25, 0x8b, 0x7c, 0x2b, 0xa7, 0xc1, 0x76, 0xea, 0xea, + 0xad, 0x37, 0xf8, 0x60, 0xd5, 0x97, 0xa3, 0x1c, 0xe7, + 0x9b, 0x59, 0x47, 0x33, 0xc7, 0x14, 0x1d, 0xf7, 0x91, + 0x51, 0xfc, 0xa9, 0x0c, 0x08, 0x47, 0x8a, 0x5c, 0x6c, + 0x2c, 0xc4, 0x81, 0xd5, 0x1f, 0xfe, 0xce, 0x3c, 0xd7, + 0xd2, 0x58, 0x13, 0x48, 0x82, 0x7a, 0x71, 0xf0, 0x91, + 0x42, 0x8e, 0xbe, 0x38, 0xc9, 0x5a, 0x3f, 0x5c, 0x63, + 0xe0, 0x56, 0xdf, 0xb7, 0xcc, 0x45, 0xa9, 0xb7, 0xc0, + 0x7d, 0x83, 0x4e, 0x7b, 0x20, 0xb9, 0x9e, 0xd2, 0x02, + 0x42, 0x9c, 0x14, 0xbb, 0x85, 0xff, 0xa4, 0x3b, 0x7c, + 0xb6, 0x84, 0x95, 0xcd, 0x75, 0xab, 0x66, 0xd9, 0x64, + 0xd4, 0xca, 0xfe, 0x64, 0xdd, 0x94, 0x04, 0xda, 0xe2, + 0xdc, 0x51, 0x10, 0x61, 0x7f, 0x19, 0x4f, 0xc3, 0xc1, + 0x84, 0xf5, 0x83, 0xcd, 0x0d, 0xef, 0x6d, 0x00 }; + + uint8_t * out = (uint8_t *) calloc(len_bytes, + sizeof(uint8_t)); + + // encryption + err_lte = liblte_security_encryption_eea1(key, count, bearer, + direction, msg, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(ct, out, len_bytes); + assert(err_cmp == 0); + + // decryption + err_lte = liblte_security_decryption_eea1(key, count, bearer, + direction, ct, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(msg, out, len_bytes); + assert(err_cmp == 0); + + free(out); +} + +// set len_bitsgth to multiple of 8 respectively 128 +void test_set_1_block_size() +{ + LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS; + int32 err_cmp = 0; + + uint8_t key[] = { 0xd3, 0xc5, 0xd5, 0x92, 0x32, 0x7f, 0xb1, + 0x1c, 0x40, 0x35, 0xc6, 0x68, 0x0a, 0xf8, 0xc6, 0xd1 }; + uint32_t count = 0x398a59b4; + uint8_t bearer = 0x15; + uint8_t direction = 1; + uint32_t len_bits = 256, len_bytes = (len_bits + 7) / 8; + uint8_t msg[] = { 0x98, 0x1b, 0xa6, 0x82, 0x4c, 0x1b, 0xfb, + 0x1a, 0xb4, 0x85, 0x47, 0x20, 0x29, 0xb7, 0x1d, 0x80, + 0x8c, 0xe3, 0x3e, 0x2c, 0xc3, 0xc0, 0xb5, 0xfc, 0x1f, + 0x3d, 0xe8, 0xa6, 0xdc, 0x66, 0xb1, 0xf0 }; + uint8_t ct[] = { 0x5d, 0x5b, 0xfe, 0x75, 0xeb, 0x04, 0xf6, + 0x8c, 0xe0, 0xa1, 0x23, 0x77, 0xea, 0x00, 0xb3, 0x7d, + 0x47, 0xc6, 0xa0, 0xba, 0x06, 0x30, 0x91, 0x55, 0x08, + 0x6a, 0x85, 0x9c, 0x43, 0x41, 0xb3, 0x7c }; + + uint8_t * out = (uint8_t *) calloc(len_bytes, + sizeof(uint8_t)); + + // encryption + err_lte = liblte_security_encryption_eea1(key, count, bearer, + direction, msg, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(ct, out, len_bytes); + assert(err_cmp == 0); + + // decryption + err_lte = liblte_security_decryption_eea1(key, count, bearer, + direction, ct, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(msg, out, len_bytes); + assert(err_cmp == 0); + + free(out); +} + +// inserted bit flip in msg[0] +void test_set_1_invalid() +{ + LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS; + int32 err_cmp = 0; + + uint8_t key[] = { 0xd3, 0xc5, 0xd5, 0x92, 0x32, 0x7f, 0xb1, + 0x1c, 0x40, 0x35, 0xc6, 0x68, 0x0a, 0xf8, 0xc6, 0xd1 }; + uint32_t count = 0x398a59b4; + uint8_t bearer = 0x15; + uint8_t direction = 1; + uint32_t len_bits = 253, len_bytes = (len_bits + 7) / 8; + uint8_t msg[] = { 0x99, 0x1b, 0xa6, 0x82, 0x4c, 0x1b, 0xfb, + 0x1a, 0xb4, 0x85, 0x47, 0x20, 0x29, 0xb7, 0x1d, 0x80, + 0x8c, 0xe3, 0x3e, 0x2c, 0xc3, 0xc0, 0xb5, 0xfc, 0x1f, + 0x3d, 0xe8, 0xa6, 0xdc, 0x66, 0xb1, 0xf0 }; + uint8_t ct[] = { 0x5d, 0x5b, 0xfe, 0x75, 0xeb, 0x04, 0xf6, + 0x8c, 0xe0, 0xa1, 0x23, 0x77, 0xea, 0x00, 0xb3, 0x7d, + 0x47, 0xc6, 0xa0, 0xba, 0x06, 0x30, 0x91, 0x55, 0x08, + 0x6a, 0x85, 0x9c, 0x43, 0x41, 0xb3, 0x78 }; + + uint8_t * out = (uint8_t *) calloc(len_bytes, + sizeof(uint8_t)); + + // encryption + err_lte = liblte_security_encryption_eea1(key, count, bearer, + direction, msg, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(ct, out, len_bytes); + assert(err_cmp != 0); + + // decryption + err_lte = liblte_security_decryption_eea1(key, count, bearer, + direction, ct, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(msg, out, len_bytes); + assert(err_cmp != 0); + + free(out); +} + +/* + * Functions + */ + +int main(int argc, char * argv[]) { + test_set_1(); + test_set_2(); + test_set_3(); + test_set_4(); + test_set_5(); + test_set_6(); + test_set_1_block_size(); + test_set_1_invalid(); +} diff --git a/lib/test/common/test_eea2.cc b/lib/test/common/test_eea2.cc new file mode 100644 index 000000000..fccaefe70 --- /dev/null +++ b/lib/test/common/test_eea2.cc @@ -0,0 +1,567 @@ +/* + * Includes + */ + +#include +#include +#include + +#include "srslte/common/liblte_security.h" + +/* + * Prototypes + */ + +int32 arrcmp(uint8_t const * const a, uint8_t const * const b, uint32 len) { + uint32 i = 0; + + for (i = 0; i < len; i++) { + if (a[i] != b[i]) { + return a[i] - b[i]; + } + } + return 0; +} + +/* + * Tests + * + * Document Reference: 33.401 V13.1.0 Annex C.1 + */ + +void test_set_1() +{ + LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS; + int32 err_cmp = 0; + + uint8_t key[] = { 0xd3, 0xc5, 0xd5, 0x92, 0x32, 0x7f, 0xb1, + 0x1c, 0x40, 0x35, 0xc6, 0x68, 0x0a, 0xf8, 0xc6, 0xd1 }; + uint32_t count = 0x398a59b4; + uint8_t bearer = 0x15; + uint8_t direction = 1; + uint32_t len_bits = 253, len_bytes = (len_bits + 7) / 8; + uint8_t msg[] = { 0x98, 0x1b, 0xa6, 0x82, 0x4c, 0x1b, 0xfb, + 0x1a, 0xb4, 0x85, 0x47, 0x20, 0x29, 0xb7, 0x1d, 0x80, + 0x8c, 0xe3, 0x3e, 0x2c, 0xc3, 0xc0, 0xb5, 0xfc, 0x1f, + 0x3d, 0xe8, 0xa6, 0xdc, 0x66, 0xb1, 0xf0 }; + uint8_t ct[] = { 0xe9, 0xfe, 0xd8, 0xa6, 0x3d, 0x15, 0x53, + 0x04, 0xd7, 0x1d, 0xf2, 0x0b, 0xf3, 0xe8, 0x22, 0x14, + 0xb2, 0x0e, 0xd7, 0xda, 0xd2, 0xf2, 0x33, 0xdc, 0x3c, + 0x22, 0xd7, 0xbd, 0xee, 0xed, 0x8e, 0x78 }; + + uint8_t * out = (uint8_t *) calloc(len_bytes, + sizeof(uint8_t)); + + // encryption + err_lte = liblte_security_encryption_eea2(key, count, bearer, + direction, msg, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(ct, out, len_bytes); + assert(err_cmp == 0); + + // decryption + err_lte = liblte_security_decryption_eea2(key, count, bearer, + direction, ct, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(msg, out, len_bytes); + assert(err_cmp == 0); + + free(out); +} + +void test_set_2() +{ + LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS; + int32 err_cmp = 0; + + uint8_t key[] = { 0x2b, 0xd6, 0x45, 0x9f, 0x82, 0xc4, 0x40, + 0xe0, 0x95, 0x2c, 0x49, 0x10, 0x48, 0x05, 0xff, 0x48 }; + uint32_t count = 0xc675a64b; + uint8_t bearer = 0x0c; + uint8_t direction = 1; + uint32_t len_bits = 798, len_bytes = (len_bits + 7) / 8; + uint8_t msg[] = { 0x7e, 0xc6, 0x12, 0x72, 0x74, 0x3b, 0xf1, + 0x61, 0x47, 0x26, 0x44, 0x6a, 0x6c, 0x38, 0xce, 0xd1, + 0x66, 0xf6, 0xca, 0x76, 0xeb, 0x54, 0x30, 0x04, 0x42, + 0x86, 0x34, 0x6c, 0xef, 0x13, 0x0f, 0x92, 0x92, 0x2b, + 0x03, 0x45, 0x0d, 0x3a, 0x99, 0x75, 0xe5, 0xbd, 0x2e, + 0xa0, 0xeb, 0x55, 0xad, 0x8e, 0x1b, 0x19, 0x9e, 0x3e, + 0xc4, 0x31, 0x60, 0x20, 0xe9, 0xa1, 0xb2, 0x85, 0xe7, + 0x62, 0x79, 0x53, 0x59, 0xb7, 0xbd, 0xfd, 0x39, 0xbe, + 0xf4, 0xb2, 0x48, 0x45, 0x83, 0xd5, 0xaf, 0xe0, 0x82, + 0xae, 0xe6, 0x38, 0xbf, 0x5f, 0xd5, 0xa6, 0x06, 0x19, + 0x39, 0x01, 0xa0, 0x8f, 0x4a, 0xb4, 0x1a, 0xab, 0x9b, + 0x13, 0x48, 0x80 }; + uint8_t ct[] = { 0x59, 0x61, 0x60, 0x53, 0x53, 0xc6, 0x4b, + 0xdc, 0xa1, 0x5b, 0x19, 0x5e, 0x28, 0x85, 0x53, 0xa9, + 0x10, 0x63, 0x25, 0x06, 0xd6, 0x20, 0x0a, 0xa7, 0x90, + 0xc4, 0xc8, 0x06, 0xc9, 0x99, 0x04, 0xcf, 0x24, 0x45, + 0xcc, 0x50, 0xbb, 0x1c, 0xf1, 0x68, 0xa4, 0x96, 0x73, + 0x73, 0x4e, 0x08, 0x1b, 0x57, 0xe3, 0x24, 0xce, 0x52, + 0x59, 0xc0, 0xe7, 0x8d, 0x4c, 0xd9, 0x7b, 0x87, 0x09, + 0x76, 0x50, 0x3c, 0x09, 0x43, 0xf2, 0xcb, 0x5a, 0xe8, + 0xf0, 0x52, 0xc7, 0xb7, 0xd3, 0x92, 0x23, 0x95, 0x87, + 0xb8, 0x95, 0x60, 0x86, 0xbc, 0xab, 0x18, 0x83, 0x60, + 0x42, 0xe2, 0xe6, 0xce, 0x42, 0x43, 0x2a, 0x17, 0x10, + 0x5c, 0x53, 0xd0 }; + + uint8_t * out = (uint8_t *) calloc(len_bytes, + sizeof(uint8_t)); + + // encryption + err_lte = liblte_security_encryption_eea2(key, count, bearer, + direction, msg, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(ct, out, len_bytes); + assert(err_cmp == 0); + + // decryption + err_lte = liblte_security_decryption_eea2(key, count, bearer, + direction, ct, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(msg, out, len_bytes); + assert(err_cmp == 0); + + free(out); +} + +void test_set_3() +{ + LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS; + int32 err_cmp = 0; + + uint8_t key[] = { 0x0a, 0x8b, 0x6b, 0xd8, 0xd9, 0xb0, 0x8b, + 0x08, 0xd6, 0x4e, 0x32, 0xd1, 0x81, 0x77, 0x77, 0xfb }; + uint32_t count = 0x544d49cd; + uint8_t bearer = 0x04; + uint8_t direction = 0; + uint32_t len_bits = 310, len_bytes = (len_bits + 7) / 8; + uint8_t msg[] = { 0xfd, 0x40, 0xa4, 0x1d, 0x37, 0x0a, 0x1f, + 0x65, 0x74, 0x50, 0x95, 0x68, 0x7d, 0x47, 0xba, 0x1d, + 0x36, 0xd2, 0x34, 0x9e, 0x23, 0xf6, 0x44, 0x39, 0x2c, + 0x8e, 0xa9, 0xc4, 0x9d, 0x40, 0xc1, 0x32, 0x71, 0xaf, + 0xf2, 0x64, 0xd0, 0xf2, 0x48, 0x00 }; + uint8_t ct[] = { 0x75, 0x75, 0x0d, 0x37, 0xb4, 0xbb, 0xa2, + 0xa4, 0xde, 0xdb, 0x34, 0x23, 0x5b, 0xd6, 0x8c, 0x66, + 0x45, 0xac, 0xda, 0xac, 0xa4, 0x81, 0x38, 0xa3, 0xb0, + 0xc4, 0x71, 0xe2, 0xa7, 0x04, 0x1a, 0x57, 0x64, 0x23, + 0xd2, 0x92, 0x72, 0x87, 0xf0, 0x00 }; + + uint8_t * out = (uint8_t *) calloc(len_bytes, + sizeof(uint8_t)); + + // encryption + err_lte = liblte_security_encryption_eea2(key, count, bearer, + direction, msg, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(ct, out, len_bytes); + assert(err_cmp == 0); + + // decryption + err_lte = liblte_security_decryption_eea2(key, count, bearer, + direction, ct, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(msg, out, len_bytes); + assert(err_cmp == 0); + + free(out); +} + +void test_set_4() +{ + LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS; + int32 err_cmp = 0; + + uint8_t key[] = { 0xaa, 0x1f, 0x95, 0xae, 0xa5, 0x33, 0xbc, + 0xb3, 0x2e, 0xb6, 0x3b, 0xf5, 0x2d, 0x8f, 0x83, 0x1a }; + uint32_t count = 0x72d8c671; + uint8_t bearer = 0x10; + uint8_t direction = 1; + uint32_t len_bits = 1022, len_bytes = (len_bits + 7) / 8; + uint8_t msg[] = { 0xfb, 0x1b, 0x96, 0xc5, 0xc8, 0xba, 0xdf, + 0xb2, 0xe8, 0xe8, 0xed, 0xfd, 0xe7, 0x8e, 0x57, 0xf2, + 0xad, 0x81, 0xe7, 0x41, 0x03, 0xfc, 0x43, 0x0a, 0x53, + 0x4d, 0xcc, 0x37, 0xaf, 0xce, 0xc7, 0x0e, 0x15, 0x17, + 0xbb, 0x06, 0xf2, 0x72, 0x19, 0xda, 0xe4, 0x90, 0x22, + 0xdd, 0xc4, 0x7a, 0x06, 0x8d, 0xe4, 0xc9, 0x49, 0x6a, + 0x95, 0x1a, 0x6b, 0x09, 0xed, 0xbd, 0xc8, 0x64, 0xc7, + 0xad, 0xbd, 0x74, 0x0a, 0xc5, 0x0c, 0x02, 0x2f, 0x30, + 0x82, 0xba, 0xfd, 0x22, 0xd7, 0x81, 0x97, 0xc5, 0xd5, + 0x08, 0xb9, 0x77, 0xbc, 0xa1, 0x3f, 0x32, 0xe6, 0x52, + 0xe7, 0x4b, 0xa7, 0x28, 0x57, 0x60, 0x77, 0xce, 0x62, + 0x8c, 0x53, 0x5e, 0x87, 0xdc, 0x60, 0x77, 0xba, 0x07, + 0xd2, 0x90, 0x68, 0x59, 0x0c, 0x8c, 0xb5, 0xf1, 0x08, + 0x8e, 0x08, 0x2c, 0xfa, 0x0e, 0xc9, 0x61, 0x30, 0x2d, + 0x69, 0xcf, 0x3d, 0x44 }; + uint8_t ct[] = { 0xdf, 0xb4, 0x40, 0xac, 0xb3, 0x77, 0x35, + 0x49, 0xef, 0xc0, 0x46, 0x28, 0xae, 0xb8, 0xd8, 0x15, + 0x62, 0x75, 0x23, 0x0b, 0xdc, 0x69, 0x0d, 0x94, 0xb0, + 0x0d, 0x8d, 0x95, 0xf2, 0x8c, 0x4b, 0x56, 0x30, 0x7f, + 0x60, 0xf4, 0xca, 0x55, 0xeb, 0xa6, 0x61, 0xeb, 0xba, + 0x72, 0xac, 0x80, 0x8f, 0xa8, 0xc4, 0x9e, 0x26, 0x78, + 0x8e, 0xd0, 0x4a, 0x5d, 0x60, 0x6c, 0xb4, 0x18, 0xde, + 0x74, 0x87, 0x8b, 0x9a, 0x22, 0xf8, 0xef, 0x29, 0x59, + 0x0b, 0xc4, 0xeb, 0x57, 0xc9, 0xfa, 0xf7, 0xc4, 0x15, + 0x24, 0xa8, 0x85, 0xb8, 0x97, 0x9c, 0x42, 0x3f, 0x2f, + 0x8f, 0x8e, 0x05, 0x92, 0xa9, 0x87, 0x92, 0x01, 0xbe, + 0x7f, 0xf9, 0x77, 0x7a, 0x16, 0x2a, 0xb8, 0x10, 0xfe, + 0xb3, 0x24, 0xba, 0x74, 0xc4, 0xc1, 0x56, 0xe0, 0x4d, + 0x39, 0x09, 0x72, 0x09, 0x65, 0x3a, 0xc3, 0x3e, 0x5a, + 0x5f, 0x2d, 0x88, 0x64 }; + + uint8_t * out = (uint8_t *) calloc(len_bytes, + sizeof(uint8_t)); + + // encryption + err_lte = liblte_security_encryption_eea2(key, count, bearer, + direction, msg, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(ct, out, len_bytes); + assert(err_cmp == 0); + + // decryption + err_lte = liblte_security_decryption_eea2(key, count, bearer, + direction, ct, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(msg, out, len_bytes); + assert(err_cmp == 0); + + free(out); +} + +void test_set_5() +{ + LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS; + int32 err_cmp = 0; + + uint8_t key[] = { 0x96, 0x18, 0xae, 0x46, 0x89, 0x1f, 0x86, + 0x57, 0x8e, 0xeb, 0xe9, 0x0e, 0xf7, 0xa1, 0x20, 0x2e }; + uint32_t count = 0xc675a64b; + uint8_t bearer = 0x0c; + uint8_t direction = 1; + uint32_t len_bits = 1245, len_bytes = (len_bits + 7) / 8; + uint8_t msg[] = { 0x8d, 0xaa, 0x17, 0xb1, 0xae, 0x05, 0x05, + 0x29, 0xc6, 0x82, 0x7f, 0x28, 0xc0, 0xef, 0x6a, 0x12, + 0x42, 0xe9, 0x3f, 0x8b, 0x31, 0x4f, 0xb1, 0x8a, 0x77, + 0xf7, 0x90, 0xae, 0x04, 0x9f, 0xed, 0xd6, 0x12, 0x26, + 0x7f, 0xec, 0xae, 0xfc, 0x45, 0x01, 0x74, 0xd7, 0x6d, + 0x9f, 0x9a, 0xa7, 0x75, 0x5a, 0x30, 0xcd, 0x90, 0xa9, + 0xa5, 0x87, 0x4b, 0xf4, 0x8e, 0xaf, 0x70, 0xee, 0xa3, + 0xa6, 0x2a, 0x25, 0x0a, 0x8b, 0x6b, 0xd8, 0xd9, 0xb0, + 0x8b, 0x08, 0xd6, 0x4e, 0x32, 0xd1, 0x81, 0x77, 0x77, + 0xfb, 0x54, 0x4d, 0x49, 0xcd, 0x49, 0x72, 0x0e, 0x21, + 0x9d, 0xbf, 0x8b, 0xbe, 0xd3, 0x39, 0x04, 0xe1, 0xfd, + 0x40, 0xa4, 0x1d, 0x37, 0x0a, 0x1f, 0x65, 0x74, 0x50, + 0x95, 0x68, 0x7d, 0x47, 0xba, 0x1d, 0x36, 0xd2, 0x34, + 0x9e, 0x23, 0xf6, 0x44, 0x39, 0x2c, 0x8e, 0xa9, 0xc4, + 0x9d, 0x40, 0xc1, 0x32, 0x71, 0xaf, 0xf2, 0x64, 0xd0, + 0xf2, 0x48, 0x41, 0xd6, 0x46, 0x5f, 0x09, 0x96, 0xff, + 0x84, 0xe6, 0x5f, 0xc5, 0x17, 0xc5, 0x3e, 0xfc, 0x33, + 0x63, 0xc3, 0x84, 0x92, 0xa8 }; + uint8_t ct[] = { 0x91, 0x9c, 0x8c, 0x33, 0xd6, 0x67, 0x89, + 0x70, 0x3d, 0x05, 0xa0, 0xd7, 0xce, 0x82, 0xa2, 0xae, + 0xac, 0x4e, 0xe7, 0x6c, 0x0f, 0x4d, 0xa0, 0x50, 0x33, + 0x5e, 0x8a, 0x84, 0xe7, 0x89, 0x7b, 0xa5, 0xdf, 0x2f, + 0x36, 0xbd, 0x51, 0x3e, 0x3d, 0x0c, 0x85, 0x78, 0xc7, + 0xa0, 0xfc, 0xf0, 0x43, 0xe0, 0x3a, 0xa3, 0xa3, 0x9f, + 0xba, 0xad, 0x7d, 0x15, 0xbe, 0x07, 0x4f, 0xaa, 0x5d, + 0x90, 0x29, 0xf7, 0x1f, 0xb4, 0x57, 0xb6, 0x47, 0x83, + 0x47, 0x14, 0xb0, 0xe1, 0x8f, 0x11, 0x7f, 0xca, 0x10, + 0x67, 0x79, 0x45, 0x09, 0x6c, 0x8c, 0x5f, 0x32, 0x6b, + 0xa8, 0xd6, 0x09, 0x5e, 0xb2, 0x9c, 0x3e, 0x36, 0xcf, + 0x24, 0x5d, 0x16, 0x22, 0xaa, 0xfe, 0x92, 0x1f, 0x75, + 0x66, 0xc4, 0xf5, 0xd6, 0x44, 0xf2, 0xf1, 0xfc, 0x0e, + 0xc6, 0x84, 0xdd, 0xb2, 0x13, 0x49, 0x74, 0x76, 0x22, + 0xe2, 0x09, 0x29, 0x5d, 0x27, 0xff, 0x3f, 0x95, 0x62, + 0x33, 0x71, 0xd4, 0x9b, 0x14, 0x7c, 0x0a, 0xf4, 0x86, + 0x17, 0x1f, 0x22, 0xcd, 0x04, 0xb1, 0xcb, 0xeb, 0x26, + 0x58, 0x22, 0x3e, 0x69, 0x38 }; + + uint8_t * out = (uint8_t *) calloc(len_bytes, + sizeof(uint8_t)); + + // encryption + err_lte = liblte_security_encryption_eea2(key, count, bearer, + direction, msg, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(ct, out, len_bytes); + assert(err_cmp == 0); + + // decryption + err_lte = liblte_security_decryption_eea2(key, count, bearer, + direction, ct, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(msg, out, len_bytes); + assert(err_cmp == 0); + + free(out); +} + +void test_set_6() +{ + LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS; + int32 err_cmp = 0; + + uint8_t key[] = { 0x54, 0xf4, 0xe2, 0xe0, 0x4c, 0x83, 0x78, + 0x6e, 0xec, 0x8f, 0xb5, 0xab, 0xe8, 0xe3, 0x65, 0x66 }; + uint32_t count = 0xaca4f50f; + uint8_t bearer = 0x0b; + uint8_t direction = 0; + uint32_t len_bits = 3861, len_bytes = (len_bits + 7) / 8; + uint8_t msg[] = { 0x40, 0x98, 0x1b, 0xa6, 0x82, 0x4c, 0x1b, + 0xfb, 0x42, 0x86, 0xb2, 0x99, 0x78, 0x3d, 0xaf, 0x44, + 0x2c, 0x09, 0x9f, 0x7a, 0xb0, 0xf5, 0x8d, 0x5c, 0x8e, + 0x46, 0xb1, 0x04, 0xf0, 0x8f, 0x01, 0xb4, 0x1a, 0xb4, + 0x85, 0x47, 0x20, 0x29, 0xb7, 0x1d, 0x36, 0xbd, 0x1a, + 0x3d, 0x90, 0xdc, 0x3a, 0x41, 0xb4, 0x6d, 0x51, 0x67, + 0x2a, 0xc4, 0xc9, 0x66, 0x3a, 0x2b, 0xe0, 0x63, 0xda, + 0x4b, 0xc8, 0xd2, 0x80, 0x8c, 0xe3, 0x3e, 0x2c, 0xcc, + 0xbf, 0xc6, 0x34, 0xe1, 0xb2, 0x59, 0x06, 0x08, 0x76, + 0xa0, 0xfb, 0xb5, 0xa4, 0x37, 0xeb, 0xcc, 0x8d, 0x31, + 0xc1, 0x9e, 0x44, 0x54, 0x31, 0x87, 0x45, 0xe3, 0xfa, + 0x16, 0xbb, 0x11, 0xad, 0xae, 0x24, 0x88, 0x79, 0xfe, + 0x52, 0xdb, 0x25, 0x43, 0xe5, 0x3c, 0xf4, 0x45, 0xd3, + 0xd8, 0x28, 0xce, 0x0b, 0xf5, 0xc5, 0x60, 0x59, 0x3d, + 0x97, 0x27, 0x8a, 0x59, 0x76, 0x2d, 0xd0, 0xc2, 0xc9, + 0xcd, 0x68, 0xd4, 0x49, 0x6a, 0x79, 0x25, 0x08, 0x61, + 0x40, 0x14, 0xb1, 0x3b, 0x6a, 0xa5, 0x11, 0x28, 0xc1, + 0x8c, 0xd6, 0xa9, 0x0b, 0x87, 0x97, 0x8c, 0x2f, 0xf1, + 0xca, 0xbe, 0x7d, 0x9f, 0x89, 0x8a, 0x41, 0x1b, 0xfd, + 0xb8, 0x4f, 0x68, 0xf6, 0x72, 0x7b, 0x14, 0x99, 0xcd, + 0xd3, 0x0d, 0xf0, 0x44, 0x3a, 0xb4, 0xa6, 0x66, 0x53, + 0x33, 0x0b, 0xcb, 0xa1, 0x10, 0x5e, 0x4c, 0xec, 0x03, + 0x4c, 0x73, 0xe6, 0x05, 0xb4, 0x31, 0x0e, 0xaa, 0xad, + 0xcf, 0xd5, 0xb0, 0xca, 0x27, 0xff, 0xd8, 0x9d, 0x14, + 0x4d, 0xf4, 0x79, 0x27, 0x59, 0x42, 0x7c, 0x9c, 0xc1, + 0xf8, 0xcd, 0x8c, 0x87, 0x20, 0x23, 0x64, 0xb8, 0xa6, + 0x87, 0x95, 0x4c, 0xb0, 0x5a, 0x8d, 0x4e, 0x2d, 0x99, + 0xe7, 0x3d, 0xb1, 0x60, 0xde, 0xb1, 0x80, 0xad, 0x08, + 0x41, 0xe9, 0x67, 0x41, 0xa5, 0xd5, 0x9f, 0xe4, 0x18, + 0x9f, 0x15, 0x42, 0x00, 0x26, 0xfe, 0x4c, 0xd1, 0x21, + 0x04, 0x93, 0x2f, 0xb3, 0x8f, 0x73, 0x53, 0x40, 0x43, + 0x8a, 0xaf, 0x7e, 0xca, 0x6f, 0xd5, 0xcf, 0xd3, 0xa1, + 0x95, 0xce, 0x5a, 0xbe, 0x65, 0x27, 0x2a, 0xf6, 0x07, + 0xad, 0xa1, 0xbe, 0x65, 0xa6, 0xb4, 0xc9, 0xc0, 0x69, + 0x32, 0x34, 0x09, 0x2c, 0x4d, 0x01, 0x8f, 0x17, 0x56, + 0xc6, 0xdb, 0x9d, 0xc8, 0xa6, 0xd8, 0x0b, 0x88, 0x81, + 0x38, 0x61, 0x6b, 0x68, 0x12, 0x62, 0xf9, 0x54, 0xd0, + 0xe7, 0x71, 0x17, 0x48, 0x78, 0x0d, 0x92, 0x29, 0x1d, + 0x86, 0x29, 0x99, 0x72, 0xdb, 0x74, 0x1c, 0xfa, 0x4f, + 0x37, 0xb8, 0xb5, 0x6c, 0xdb, 0x18, 0xa7, 0xca, 0x82, + 0x18, 0xe8, 0x6e, 0x4b, 0x4b, 0x71, 0x6a, 0x4d, 0x04, + 0x37, 0x1f, 0xbe, 0xc2, 0x62, 0xfc, 0x5a, 0xd0, 0xb3, + 0x81, 0x9b, 0x18, 0x7b, 0x97, 0xe5, 0x5b, 0x1a, 0x4d, + 0x7c, 0x19, 0xee, 0x24, 0xc8, 0xb4, 0xd7, 0x72, 0x3c, + 0xfe, 0xdf, 0x04, 0x5b, 0x8a, 0xca, 0xe4, 0x86, 0x95, + 0x17, 0xd8, 0x0e, 0x50, 0x61, 0x5d, 0x90, 0x35, 0xd5, + 0xd9, 0xc5, 0xa4, 0x0a, 0xf6, 0x02, 0x28, 0x0b, 0x54, + 0x25, 0x97, 0xb0, 0xcb, 0x18, 0x61, 0x9e, 0xeb, 0x35, + 0x92, 0x57, 0x59, 0xd1, 0x95, 0xe1, 0x00, 0xe8, 0xe4, + 0xaa, 0x0c, 0x38, 0xa3, 0xc2, 0xab, 0xe0, 0xf3, 0xd8, + 0xff, 0x04, 0xf3, 0xc3, 0x3c, 0x29, 0x50, 0x69, 0xc2, + 0x36, 0x94, 0xb5, 0xbb, 0xea, 0xcd, 0xd5, 0x42, 0xe2, + 0x8e, 0x8a, 0x94, 0xed, 0xb9, 0x11, 0x9f, 0x41, 0x2d, + 0x05, 0x4b, 0xe1, 0xfa, 0x72, 0x00, 0xb0, 0x90, 0x00 }; + uint8_t ct[] = { 0x5c, 0xb7, 0x2c, 0x6e, 0xdc, 0x87, 0x8f, + 0x15, 0x66, 0xe1, 0x02, 0x53, 0xaf, 0xc3, 0x64, 0xc9, + 0xfa, 0x54, 0x0d, 0x91, 0x4d, 0xb9, 0x4c, 0xbe, 0xe2, + 0x75, 0xd0, 0x91, 0x7c, 0xa6, 0xaf, 0x0d, 0x77, 0xac, + 0xb4, 0xef, 0x3b, 0xbe, 0x1a, 0x72, 0x2b, 0x2e, 0xf5, + 0xbd, 0x1d, 0x4b, 0x8e, 0x2a, 0xa5, 0x02, 0x4e, 0xc1, + 0x38, 0x8a, 0x20, 0x1e, 0x7b, 0xce, 0x79, 0x20, 0xae, + 0xc6, 0x15, 0x89, 0x5f, 0x76, 0x3a, 0x55, 0x64, 0xdc, + 0xc4, 0xc4, 0x82, 0xa2, 0xee, 0x1d, 0x8b, 0xfe, 0xcc, + 0x44, 0x98, 0xec, 0xa8, 0x3f, 0xbb, 0x75, 0xf9, 0xab, + 0x53, 0x0e, 0x0d, 0xaf, 0xbe, 0xde, 0x2f, 0xa5, 0x89, + 0x5b, 0x82, 0x99, 0x1b, 0x62, 0x77, 0xc5, 0x29, 0xe0, + 0xf2, 0x52, 0x9d, 0x7f, 0x79, 0x60, 0x6b, 0xe9, 0x67, + 0x06, 0x29, 0x6d, 0xed, 0xfa, 0x9d, 0x74, 0x12, 0xb6, + 0x16, 0x95, 0x8c, 0xb5, 0x63, 0xc6, 0x78, 0xc0, 0x28, + 0x25, 0xc3, 0x0d, 0x0a, 0xee, 0x77, 0xc4, 0xc1, 0x46, + 0xd2, 0x76, 0x54, 0x12, 0x42, 0x1a, 0x80, 0x8d, 0x13, + 0xce, 0xc8, 0x19, 0x69, 0x4c, 0x75, 0xad, 0x57, 0x2e, + 0x9b, 0x97, 0x3d, 0x94, 0x8b, 0x81, 0xa9, 0x33, 0x7c, + 0x3b, 0x2a, 0x17, 0x19, 0x2e, 0x22, 0xc2, 0x06, 0x9f, + 0x7e, 0xd1, 0x16, 0x2a, 0xf4, 0x4c, 0xde, 0xa8, 0x17, + 0x60, 0x36, 0x65, 0xe8, 0x07, 0xce, 0x40, 0xc8, 0xe0, + 0xdd, 0x9d, 0x63, 0x94, 0xdc, 0x6e, 0x31, 0x15, 0x3f, + 0xe1, 0x95, 0x5c, 0x47, 0xaf, 0xb5, 0x1f, 0x26, 0x17, + 0xee, 0x0c, 0x5e, 0x3b, 0x8e, 0xf1, 0xad, 0x75, 0x74, + 0xed, 0x34, 0x3e, 0xdc, 0x27, 0x43, 0xcc, 0x94, 0xc9, + 0x90, 0xe1, 0xf1, 0xfd, 0x26, 0x42, 0x53, 0xc1, 0x78, + 0xde, 0xa7, 0x39, 0xc0, 0xbe, 0xfe, 0xeb, 0xcd, 0x9f, + 0x9b, 0x76, 0xd4, 0x9c, 0x10, 0x15, 0xc9, 0xfe, 0xcf, + 0x50, 0xe5, 0x3b, 0x8b, 0x52, 0x04, 0xdb, 0xcd, 0x3e, + 0xed, 0x86, 0x38, 0x55, 0xda, 0xbc, 0xdc, 0xc9, 0x4b, + 0x31, 0xe3, 0x18, 0x02, 0x15, 0x68, 0x85, 0x5c, 0x8b, + 0x9e, 0x52, 0xa9, 0x81, 0x95, 0x7a, 0x11, 0x28, 0x27, + 0xf9, 0x78, 0xba, 0x96, 0x0f, 0x14, 0x47, 0x91, 0x1b, + 0x31, 0x7b, 0x55, 0x11, 0xfb, 0xcc, 0x7f, 0xb1, 0x3a, + 0xc1, 0x53, 0xdb, 0x74, 0x25, 0x11, 0x17, 0xe4, 0x86, + 0x1e, 0xb9, 0xe8, 0x3b, 0xff, 0xff, 0xc4, 0xeb, 0x77, + 0x55, 0x57, 0x90, 0x38, 0xe5, 0x79, 0x24, 0xb1, 0xf7, + 0x8b, 0x3e, 0x1a, 0xd9, 0x0b, 0xab, 0x2a, 0x07, 0x87, + 0x1b, 0x72, 0xdb, 0x5e, 0xef, 0x96, 0xc3, 0x34, 0x04, + 0x49, 0x66, 0xdb, 0x0c, 0x37, 0xca, 0xfd, 0x1a, 0x89, + 0xe5, 0x64, 0x6a, 0x35, 0x80, 0xeb, 0x64, 0x65, 0xf1, + 0x21, 0xdc, 0xe9, 0xcb, 0x88, 0xd8, 0x5b, 0x96, 0xcf, + 0x23, 0xcc, 0xcc, 0xd4, 0x28, 0x07, 0x67, 0xbe, 0xe8, + 0xee, 0xb2, 0x3d, 0x86, 0x52, 0x46, 0x1d, 0xb6, 0x49, + 0x31, 0x03, 0x00, 0x3b, 0xaf, 0x89, 0xf5, 0xe1, 0x82, + 0x61, 0xea, 0x43, 0xc8, 0x4a, 0x92, 0xeb, 0xff, 0xff, + 0xe4, 0x90, 0x9d, 0xc4, 0x6c, 0x51, 0x92, 0xf8, 0x25, + 0xf7, 0x70, 0x60, 0x0b, 0x96, 0x02, 0xc5, 0x57, 0xb5, + 0xf8, 0xb4, 0x31, 0xa7, 0x9d, 0x45, 0x97, 0x7d, 0xd9, + 0xc4, 0x1b, 0x86, 0x3d, 0xa9, 0xe1, 0x42, 0xe9, 0x00, + 0x20, 0xcf, 0xd0, 0x74, 0xd6, 0x92, 0x7b, 0x7a, 0xb3, + 0xb6, 0x72, 0x5d, 0x1a, 0x6f, 0x3f, 0x98, 0xb9, 0xc9, + 0xda, 0xa8, 0x98, 0x2a, 0xff, 0x06, 0x78, 0x28, 0x00 }; + + uint8_t * out = (uint8_t *) calloc(len_bytes, + sizeof(uint8_t)); + + // encryption + err_lte = liblte_security_encryption_eea2(key, count, bearer, + direction, msg, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(ct, out, len_bytes); + assert(err_cmp == 0); + + // decryption + err_lte = liblte_security_decryption_eea2(key, count, bearer, + direction, ct, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(msg, out, len_bytes); + assert(err_cmp == 0); + + free(out); +} + +// set len_bitsgth to multiple of 8 respectively 128 +void test_set_1_block_size() +{ + LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS; + int32 err_cmp = 0; + + uint8_t key[] = { 0xd3, 0xc5, 0xd5, 0x92, 0x32, 0x7f, 0xb1, + 0x1c, 0x40, 0x35, 0xc6, 0x68, 0x0a, 0xf8, 0xc6, 0xd1 }; + uint32_t count = 0x398a59b4; + uint8_t bearer = 0x15; + uint8_t direction = 1; + uint32_t len_bits = 256, len_bytes = (len_bits + 7) / 8; + uint8_t msg[] = { 0x98, 0x1b, 0xa6, 0x82, 0x4c, 0x1b, 0xfb, + 0x1a, 0xb4, 0x85, 0x47, 0x20, 0x29, 0xb7, 0x1d, 0x80, + 0x8c, 0xe3, 0x3e, 0x2c, 0xc3, 0xc0, 0xb5, 0xfc, 0x1f, + 0x3d, 0xe8, 0xa6, 0xdc, 0x66, 0xb1, 0xf0 }; + uint8_t ct[] = { 0xe9, 0xfe, 0xd8, 0xa6, 0x3d, 0x15, 0x53, + 0x04, 0xd7, 0x1d, 0xf2, 0x0b, 0xf3, 0xe8, 0x22, 0x14, + 0xb2, 0x0e, 0xd7, 0xda, 0xd2, 0xf2, 0x33, 0xdc, 0x3c, + 0x22, 0xd7, 0xbd, 0xee, 0xed, 0x8e, 0x78 }; + + uint8_t * out = (uint8_t *) calloc(len_bytes, + sizeof(uint8_t)); + + // encryption + err_lte = liblte_security_encryption_eea2(key, count, bearer, + direction, msg, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(ct, out, len_bytes); + assert(err_cmp == 0); + + // decryption + err_lte = liblte_security_decryption_eea2(key, count, bearer, + direction, ct, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(msg, out, len_bytes); + assert(err_cmp == 0); + + free(out); +} + +// inserted bit flip in msg[0] +void test_set_1_invalid() +{ + LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS; + int32 err_cmp = 0; + + uint8_t key[] = { 0xd3, 0xc5, 0xd5, 0x92, 0x32, 0x7f, 0xb1, + 0x1c, 0x40, 0x35, 0xc6, 0x68, 0x0a, 0xf8, 0xc6, 0xd1 }; + uint32_t count = 0x398a59b4; + uint8_t bearer = 0x15; + uint8_t direction = 1; + uint32_t len_bits = 253, len_bytes = (len_bits + 7) / 8; + uint8_t msg[] = { 0x99, 0x1b, 0xa6, 0x82, 0x4c, 0x1b, 0xfb, + 0x1a, 0xb4, 0x85, 0x47, 0x20, 0x29, 0xb7, 0x1d, 0x80, + 0x8c, 0xe3, 0x3e, 0x2c, 0xc3, 0xc0, 0xb5, 0xfc, 0x1f, + 0x3d, 0xe8, 0xa6, 0xdc, 0x66, 0xb1, 0xf0 }; + uint8_t ct[] = { 0xe9, 0xfe, 0xd8, 0xa6, 0x3d, 0x15, 0x53, + 0x04, 0xd7, 0x1d, 0xf2, 0x0b, 0xf3, 0xe8, 0x22, 0x14, + 0xb2, 0x0e, 0xd7, 0xda, 0xd2, 0xf2, 0x33, 0xdc, 0x3c, + 0x22, 0xd7, 0xbd, 0xee, 0xed, 0x8e, 0x78 }; + + uint8_t * out = (uint8_t *) calloc(len_bytes, + sizeof(uint8_t)); + + // encryption + err_lte = liblte_security_encryption_eea2(key, count, bearer, + direction, msg, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(ct, out, len_bytes); + assert(err_cmp != 0); + + // decryption + err_lte = liblte_security_decryption_eea2(key, count, bearer, + direction, ct, len_bits, out); + assert(err_lte == LIBLTE_SUCCESS); + + // compare cipher text + err_cmp = arrcmp(msg, out, len_bytes); + assert(err_cmp != 0); + + free(out); +} + +/* + * Functions + */ + +int main(int argc, char * argv[]) { + test_set_1(); + test_set_2(); + test_set_3(); + test_set_4(); + test_set_5(); + test_set_6(); + test_set_1_block_size(); + test_set_1_invalid(); +} diff --git a/srsue/hdr/upper/nas.h b/srsue/hdr/upper/nas.h index 5ab77f28c..6038993e0 100644 --- a/srsue/hdr/upper/nas.h +++ b/srsue/hdr/upper/nas.h @@ -149,14 +149,13 @@ private: void integrity_generate(uint8_t *key_128, uint32_t count, - uint8_t rb_id, uint8_t direction, uint8_t *msg, uint32_t msg_len, uint8_t *mac); - bool integrity_check(uint32 lcid, byte_buffer_t *pdu); - void cipher_encrypt(uint32 lcid, byte_buffer_t *pdu); - void cipher_decrypt(uint32 lcid, byte_buffer_t *pdu); + bool integrity_check(byte_buffer_t *pdu); + void cipher_encrypt(byte_buffer_t *pdu); + void cipher_decrypt(byte_buffer_t *pdu); bool check_cap_replay(LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT *caps); diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index 99e237ba2..3886fd5b4 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -206,8 +206,8 @@ void nas::write_pdu(uint32_t lcid, byte_buffer_t *pdu) { case LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY: break; case LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED: - mac_valid = integrity_check(lcid, pdu); - cipher_decrypt(lcid, pdu); + mac_valid = integrity_check(pdu); + cipher_decrypt(pdu); break; case LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT: break; @@ -305,7 +305,6 @@ void nas::start_pcap(srslte::nas_pcap *pcap_) void nas::integrity_generate(uint8_t *key_128, uint32_t count, - uint8_t rb_id, uint8_t direction, uint8_t *msg, uint32_t msg_len, @@ -316,7 +315,7 @@ void nas::integrity_generate(uint8_t *key_128, case INTEGRITY_ALGORITHM_ID_128_EIA1: security_128_eia1(key_128, count, - rb_id, + 0, // Bearer always 0 for NAS direction, msg, msg_len, @@ -325,7 +324,7 @@ void nas::integrity_generate(uint8_t *key_128, case INTEGRITY_ALGORITHM_ID_128_EIA2: security_128_eia2(key_128, count, - rb_id, + 0, // Bearer always 0 for NAS direction, msg, msg_len, @@ -339,16 +338,14 @@ void nas::integrity_generate(uint8_t *key_128, // This function depends to a valid k_nas_int. // This key is generated in the security mode command. -bool nas::integrity_check(uint32 lcid, - byte_buffer_t *pdu) +bool nas::integrity_check(byte_buffer_t *pdu) { - uint8_t exp_mac[4]; uint8_t *mac = &pdu->msg[1]; int i; + integrity_generate(&k_nas_int[16], ctxt.rx_count, - lcid-1, SECURITY_DIRECTION_DOWNLINK, &pdu->msg[5], pdu->N_bytes-5, @@ -357,16 +354,19 @@ bool nas::integrity_check(uint32 lcid, // Check if expected mac equals the sent mac for(i=0; i<4; i++){ if(exp_mac[i] != mac[i]){ - nas_log->warning("Expected MAC [%02x %02x %02x %02x] does not match sent MAC [%02x %02x %02x %02x]\n", exp_mac[0], exp_mac[1], exp_mac[2], exp_mac[3], mac[0], mac[1], mac[2], mac[3]); + nas_log->warning("Integrity check failure. Local: count=%d, [%02x %02x %02x %02x], " + "Received: count=%d, [%02x %02x %02x %02x]\n", + ctxt.rx_count, exp_mac[0], exp_mac[1], exp_mac[2], exp_mac[3], + pdu->msg[5], mac[0], mac[1], mac[2], mac[3]); return false; } } - nas_log->info("Expected MAC [%02x %02x %02x %02x] equals sent MAC [%02x %02x %02x %02x]\n", exp_mac[0], exp_mac[1], exp_mac[2], exp_mac[3], mac[0], mac[1], mac[2], mac[3]); + nas_log->info("Integrity check ok. Local: count=%d, Received: count=%d\n", + ctxt.rx_count, pdu->msg[5]); return true; } -void nas::cipher_encrypt(uint32 lcid, - byte_buffer_t *pdu) +void nas::cipher_encrypt(byte_buffer_t *pdu) { byte_buffer_t pdu_tmp; switch(ctxt.cipher_algo) @@ -376,7 +376,7 @@ void nas::cipher_encrypt(uint32 lcid, case CIPHERING_ALGORITHM_ID_128_EEA1: security_128_eea1(&k_nas_enc[16], pdu->msg[5], - lcid-1, + 0, // Bearer always 0 for NAS SECURITY_DIRECTION_UPLINK, &pdu->msg[6], pdu->N_bytes-6, @@ -386,7 +386,7 @@ void nas::cipher_encrypt(uint32 lcid, case CIPHERING_ALGORITHM_ID_128_EEA2: security_128_eea2(&k_nas_enc[16], pdu->msg[5], - lcid-1, + 0, // Bearer always 0 for NAS SECURITY_DIRECTION_UPLINK, &pdu->msg[6], pdu->N_bytes-6, @@ -399,8 +399,7 @@ void nas::cipher_encrypt(uint32 lcid, } } -void nas::cipher_decrypt(uint32 lcid, - byte_buffer_t *pdu) +void nas::cipher_decrypt(byte_buffer_t *pdu) { byte_buffer_t tmp_pdu; switch(ctxt.cipher_algo) @@ -410,7 +409,7 @@ void nas::cipher_decrypt(uint32 lcid, case CIPHERING_ALGORITHM_ID_128_EEA1: security_128_eea1(&k_nas_enc[16], pdu->msg[5], - lcid-1, + 0, // Bearer always 0 for NAS SECURITY_DIRECTION_DOWNLINK, &pdu->msg[6], pdu->N_bytes-6, @@ -420,7 +419,7 @@ void nas::cipher_decrypt(uint32 lcid, case CIPHERING_ALGORITHM_ID_128_EEA2: security_128_eea2(&k_nas_enc[16], pdu->msg[5], - lcid-1, + 0, // Bearer always 0 for NAS SECURITY_DIRECTION_DOWNLINK, &pdu->msg[6], pdu->N_bytes-6, @@ -549,10 +548,9 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { pcap->write_nas(pdu->msg, pdu->N_bytes); } - cipher_encrypt(lcid, pdu); + cipher_encrypt(pdu); integrity_generate(&k_nas_int[16], ctxt.tx_count, - lcid - 1, SECURITY_DIRECTION_UPLINK, &pdu->msg[5], pdu->N_bytes - 5, @@ -726,7 +724,7 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu) nas_log->debug("Generating integrity check. integ_algo:%d, count_dl:%d, lcid:%d\n", ctxt.integ_algo, ctxt.rx_count, lcid); - if (integrity_check(lcid, pdu) != true) { + if (integrity_check(pdu) != true) { nas_log->warning("Sending Security Mode Reject due to integrity check failure\n"); send_security_mode_reject(LIBLTE_MME_EMM_CAUSE_MAC_FAILURE); pool->deallocate(pdu); @@ -757,10 +755,9 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu) if(pcap != NULL) { pcap->write_nas(sdu->msg, sdu->N_bytes); } - cipher_encrypt(lcid, sdu); + cipher_encrypt(sdu); integrity_generate(&k_nas_int[16], ctxt.tx_count, - lcid - 1, SECURITY_DIRECTION_UPLINK, &sdu->msg[5], sdu->N_bytes - 5, @@ -846,7 +843,6 @@ void nas::send_attach_request() { // Add MAC integrity_generate(&k_nas_int[16], ctxt.tx_count, - cfg.lcid-1, SECURITY_DIRECTION_UPLINK, &msg->msg[5], msg->N_bytes - 5, @@ -919,7 +915,6 @@ void nas::send_service_request() { uint8_t mac[4]; integrity_generate(&k_nas_int[16], ctxt.tx_count, - cfg.lcid-1, SECURITY_DIRECTION_UPLINK, &msg->msg[0], 2, From c0e79477b59a33151e260145f66611ac8167ea37 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 1 Dec 2017 14:05:54 +0100 Subject: [PATCH 181/242] Fixed cell reselection when radio-link failure --- lib/include/srslte/common/timers.h | 5 ++- lib/include/srslte/common/tti_sync.h | 2 + lib/include/srslte/common/tti_sync_cv.h | 3 +- lib/src/common/tti_sync_cv.cc | 7 +++ srsue/hdr/mac/dl_harq.h | 2 +- srsue/hdr/upper/rrc.h | 5 +-- srsue/src/mac/mac.cc | 5 +-- srsue/src/main.cc | 2 +- srsue/src/phy/phch_common.cc | 3 -- srsue/src/phy/phch_recv.cc | 9 ++-- srsue/src/phy/phch_worker.cc | 9 ++-- srsue/src/upper/rrc.cc | 58 +++++++++++++------------ 12 files changed, 61 insertions(+), 49 deletions(-) diff --git a/lib/include/srslte/common/timers.h b/lib/include/srslte/common/timers.h index a8563af37..d77692d5a 100644 --- a/lib/include/srslte/common/timers.h +++ b/lib/include/srslte/common/timers.h @@ -64,7 +64,7 @@ public: return (counter < timeout) && running; } bool is_expired() { - return callback && (counter >= timeout || !running); + return (timeout > 0) && (counter >= timeout || !running); } uint32_t get_timeout() { return timeout; @@ -72,6 +72,9 @@ public: void reset() { counter = 0; } + uint32_t value() { + return counter; + } void step() { if (running) { counter++; diff --git a/lib/include/srslte/common/tti_sync.h b/lib/include/srslte/common/tti_sync.h index 23061ea2d..fd62f442b 100644 --- a/lib/include/srslte/common/tti_sync.h +++ b/lib/include/srslte/common/tti_sync.h @@ -50,6 +50,7 @@ class tti_sync init_counters(0); } virtual void increase() = 0; + virtual void increase(uint32_t cnt) = 0; virtual void resync() = 0; virtual uint32_t wait() = 0; virtual void set_producer_cntr(uint32_t) = 0; @@ -60,6 +61,7 @@ class tti_sync } protected: void increase_producer() { producer_cntr = (producer_cntr + increment)%modulus; } + void increase_producer(uint32_t cnt) { producer_cntr = cnt%modulus; } void increase_consumer() { consumer_cntr = (consumer_cntr + increment)%modulus; } bool wait_condition() { return producer_cntr == consumer_cntr; } void init_counters(uint32_t val) diff --git a/lib/include/srslte/common/tti_sync_cv.h b/lib/include/srslte/common/tti_sync_cv.h index c04fa71f0..887ac4f04 100644 --- a/lib/include/srslte/common/tti_sync_cv.h +++ b/lib/include/srslte/common/tti_sync_cv.h @@ -44,7 +44,8 @@ class tti_sync_cv : public tti_sync tti_sync_cv(uint32_t modulus = 10240); ~tti_sync_cv(); void increase(); - uint32_t wait(); + void increase(uint32_t cnt); + uint32_t wait(); void resync(); void set_producer_cntr(uint32_t producer_cntr); diff --git a/lib/src/common/tti_sync_cv.cc b/lib/src/common/tti_sync_cv.cc index a3fc7ce4b..c48f0772a 100644 --- a/lib/src/common/tti_sync_cv.cc +++ b/lib/src/common/tti_sync_cv.cc @@ -75,4 +75,11 @@ namespace srslte { pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); } + void tti_sync_cv::increase(uint32_t tti) + { + pthread_mutex_lock(&mutex); + increase_producer(tti); + pthread_cond_signal(&cond); + pthread_mutex_unlock(&mutex); + } } diff --git a/srsue/hdr/mac/dl_harq.h b/srsue/hdr/mac/dl_harq.h index 521018d73..46c3fb0d0 100644 --- a/srsue/hdr/mac/dl_harq.h +++ b/srsue/hdr/mac/dl_harq.h @@ -259,7 +259,7 @@ private: memcpy(&cur_grant, &grant, sizeof(Tgrant)); // If data has not yet been successfully decoded - if (!ack || (grant.rv[tid]==0 && grant.phy_grant.dl.mcs[tid].idx < 29)) { + if (!ack) { // Instruct the PHY To combine the received data and attempt to decode it if (pid == HARQ_BCCH_PID) { diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index a1e3fbb5f..f587cc0ff 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -149,12 +149,11 @@ private: uint8_t transaction_id; bool drb_up; - bool paging_received; - rrc_args_t args; bool first_stimsi_attempt; bool reestablishment_in_progress; + bool connection_requested; bool pending_mob_reconf; LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT mob_reconf; @@ -186,8 +185,6 @@ private: // RRC constants and timers srslte::mac_interface_timers *mac_timers; - uint32_t sync_reset_cnt; - const static uint32_t SYNC_RESET_TIMEOUT = 10; uint32_t n310_cnt, N310; uint32_t n311_cnt, N311; uint32_t t301, t310, t311, t304; diff --git a/srsue/src/mac/mac.cc b/srsue/src/mac/mac.cc index 42d7c4b96..8813032f5 100644 --- a/srsue/src/mac/mac.cc +++ b/srsue/src/mac/mac.cc @@ -162,8 +162,7 @@ void mac::run_thread() { while(started) { /* Warning: Here order of invocation of procedures is important!! */ - ttisync.wait(); - tti = phy_h->get_current_tti(); + tti = ttisync.wait(); log_h->step(tti); timers.step_all(); @@ -229,7 +228,7 @@ void mac::pcch_stop_rx() void mac::tti_clock(uint32_t tti) { - ttisync.increase(); + ttisync.increase(tti); } void mac::bch_decoded_ok(uint8_t* payload, uint32_t len) diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 9fa5e55ae..978e08dd4 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -233,7 +233,7 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { ("expert.cfo_loop_pss_conv", - bpo::value(&args->expert.phy.cfo_loop_pss_conv)->default_value(50), + bpo::value(&args->expert.phy.cfo_loop_pss_conv)->default_value(20), "After the PSS estimation is below cfo_loop_pss_tol for cfo_loop_pss_timeout times consecutively, RS adjustments are allowed.") ("expert.average_subframe_enabled", diff --git a/srsue/src/phy/phch_common.cc b/srsue/src/phy/phch_common.cc index 961080a56..39a23e43d 100644 --- a/srsue/src/phy/phch_common.cc +++ b/srsue/src/phy/phch_common.cc @@ -257,9 +257,6 @@ void phch_common::worker_end(uint32_t tti, bool tx_enable, } // Trigger next transmission pthread_mutex_unlock(&tx_mutex[(tti+1)%nof_mutex]); - - // Trigger MAC clock - mac->tti_clock(tti); } diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index dc056f9c0..5fe63ccd4 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -596,10 +596,12 @@ void phch_recv::run_thread() } break; case sfn_sync::TIMEOUT: - if (phy_state == CELL_SELECT) { + if (cell_search_in_progress) { + log_h->warning("SYNC: Timeout while synchronizing SFN. Going back to cell search\n"); phy_state = CELL_SEARCH; } else { - phy_state = IDLE; + log_h->warning("SYNC: Timeout while synchronizing SFN. Reselecting cell\n"); + resync_sfn(true, true); } break; case sfn_sync::IDLE: @@ -706,8 +708,8 @@ void phch_recv::run_thread() } // Increase TTI counter and trigger MAC clock (lower priority) - tti = (tti+1) % 10240; mac->tti_clock(tti); + tti = (tti+1) % 10240; } } @@ -973,7 +975,6 @@ phch_recv::sfn_sync::ret_code phch_recv::sfn_sync::run_subframe(srslte_cell_t *c cnt++; if (cnt >= timeout) { cnt = 0; - log_h->warning("SYNC: Timeout while synchronizing SFN\n"); return TIMEOUT; } diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index bf5000ecf..47ca680af 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -230,14 +230,15 @@ void phch_worker::work_imp() /* Do FFT and extract PDCCH LLR, or quit if no actions are required in this subframe */ bool chest_ok = extract_fft_and_pdcch_llr(); - bool snr_th_ok = 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest))>-20.0; + bool snr_th_err = 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest))<-20.0; + bool snr_th_ok = 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest))>-15.0; // Call feedback loop for chest if (chest_loop && ((1<<(tti%10)) & phy->args->cfo_ref_mask)) { chest_loop->set_cfo(srslte_chest_dl_get_cfo(&ue_dl.chest)); } - if (chest_ok && snr_th_ok) { + if (chest_ok && !snr_th_err) { /***** Downlink Processing *******/ @@ -267,7 +268,7 @@ void phch_worker::work_imp() } } } - Debug("dl_ack={%d, %d}, generate_ack=%d\n", dl_ack[0], dl_ack[1], dl_action.generate_ack); + Info("dl_ack={%d, %d}, generate_ack=%d\n", dl_ack[0], dl_ack[1], dl_action.generate_ack); if (dl_action.generate_ack) { set_uci_ack(dl_ack, dl_mac_grant.tb_en); } @@ -393,7 +394,7 @@ void phch_worker::work_imp() if (snr_th_ok) { phy->rrc->in_sync(); log_h->debug("SYNC: Sending in-sync to RRC\n"); - } else { + } else if (snr_th_err) { phy->rrc->out_of_sync(); log_h->info("SNR=%.1f dB under threshold. Sending out-of-sync to RRC\n", 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest))); diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 6e73670f7..3d46f2fdb 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -49,7 +49,6 @@ rrc::rrc() ,drb_up(false) ,sysinfo_index(0) { - sync_reset_cnt = 0; n310_cnt = 0; n311_cnt = 0; } @@ -98,6 +97,7 @@ void rrc::init(phy_interface_rrc *phy_, first_stimsi_attempt = false; reestablishment_in_progress = false; + connection_requested = false; args.ue_category = SRSLTE_UE_CATEGORY; args.supported_bands[0] = 7; @@ -216,28 +216,31 @@ void rrc::run_thread() { state = RRC_STATE_CELL_SELECTED; } } - select_cell_timeout++; - if (select_cell_timeout >= RRC_SELECT_CELL_TIMEOUT) { - rrc_log->info("RRC Cell Selecting: timeout expired. Starting Cell Search...\n"); - state = RRC_STATE_PLMN_SELECTION; - plmn_select_timeout = 0; - phy->cell_search_start(); + if (!reestablishment_in_progress) { + select_cell_timeout++; + if (select_cell_timeout >= RRC_SELECT_CELL_TIMEOUT) { + rrc_log->info("RRC Cell Selecting: timeout expired. Starting Cell Search...\n"); + state = RRC_STATE_PLMN_SELECTION; + plmn_select_timeout = 0; + phy->cell_search_start(); + } } break; case RRC_STATE_CELL_SELECTED: - if (!nas->is_attached() || paging_received) { - paging_received = false; - rrc_log->info("RRC Cell Selected: Sending connection request...\n"); - send_con_request(); - state = RRC_STATE_CONNECTING; - connecting_timeout = 0; - } else if (reestablishment_in_progress) { + + if (mac_timers->timer_get(t311)->is_running()) { rrc_log->info("RRC Cell Selected: Sending connection reestablishment...\n"); con_restablish_cell_reselected(); state = RRC_STATE_CONNECTING; connecting_timeout = 0; + } else if (connection_requested) { + rrc_log->info("RRC Cell Selected: Sending connection request...\n"); + send_con_request(); + state = RRC_STATE_CONNECTING; + connecting_timeout = 0; + connection_requested = false; } else { - rrc_log->console("RRC Cell Selected: New PCI=%d\n", current_cell->phy_cell.id); + rrc_log->info("RRC Cell Selected: Starting paging and going to IDLE...\n"); mac->pcch_start_rx(); state = RRC_STATE_IDLE; } @@ -426,6 +429,7 @@ void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) { rrc_log->info("Already camping on selected PLMN, connecting...\n"); state = RRC_STATE_CELL_SELECTING; select_cell_timeout = 0; + connection_requested = true; } else { rrc_log->info("PLMN Id=%s selected\n", plmn_id_to_string(plmn_id).c_str()); // Sort cells according to RSRP @@ -434,6 +438,7 @@ void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) { last_selected_cell = -1; select_cell_timeout = 0; + connection_requested = true; state = RRC_STATE_CELL_SELECTING; select_next_cell_in_plmn(); } @@ -499,7 +504,7 @@ void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, uint32_t earfcn, ui // Verify cell selection criteria if (cell_selection_eval(known_cells[best_cell_idx].rsrp) && - known_cells[best_cell_idx].rsrp > current_cell->rsrp + 5 && + known_cells[best_cell_idx].rsrp > current_cell->rsrp + 5 && best_cell.id != phy->get_current_pci()) { rrc_log->info("Selecting best neighbour cell PCI=%d, rsrp=%.1f dBm\n", best_cell.id, known_cells[best_cell_idx].rsrp); @@ -674,12 +679,6 @@ float rrc::get_squal(float Qqualmeas) { // Detection of physical layer problems (5.3.11.1) void rrc::out_of_sync() { // attempt resync - sync_reset_cnt++; - if (sync_reset_cnt >= SYNC_RESET_TIMEOUT) { - rrc_log->info("Detected %d out-of-sync from PHY. Resynchronizing PHY.\n", sync_reset_cnt); - phy->sync_reset(); - sync_reset_cnt = 0; - } current_cell->in_sync = false; if (!mac_timers->timer_get(t311)->is_running() && !mac_timers->timer_get(t310)->is_running()) { n310_cnt++; @@ -748,8 +747,12 @@ void rrc::timer_expired(uint32_t timeout_id) { rrc_log->info("Timer T311 expired: Going to RRC IDLE\n"); state = RRC_STATE_LEAVE_CONNECTED; } else if (timeout_id == t301) { - rrc_log->info("Timer T301 expired: Going to RRC IDLE\n"); - state = RRC_STATE_LEAVE_CONNECTED; + if (state == RRC_STATE_IDLE) { + rrc_log->info("Timer T301 expired: Already in IDLE.\n"); + } else { + rrc_log->info("Timer T301 expired: Going to RRC IDLE\n"); + state = RRC_STATE_LEAVE_CONNECTED; + } } else if (timeout_id == t304) { rrc_log->console("Timer T304 expired: Handover failed\n"); // fw to measurement @@ -873,6 +876,7 @@ void rrc::send_con_restablish_request() { set_phy_default(); mac->reset(); set_mac_default(); + state = RRC_STATE_CELL_SELECTING; } // Actions following cell reselection 5.3.7.3 @@ -890,7 +894,7 @@ void rrc::con_restablish_cell_reselected() bit_buf.msg[bit_buf.N_bits + i] = 0; bit_buf.N_bits += 8 - (bit_buf.N_bits % 8); } - byte_buffer_t *pdcp_buf = pool_allocate;; + byte_buffer_t *pdcp_buf = pool_allocate; srslte_bit_pack_vector(bit_buf.msg, pdcp_buf->msg, bit_buf.N_bits); pdcp_buf->N_bytes = bit_buf.N_bits / 8; @@ -1296,8 +1300,8 @@ void rrc::write_pdu_pcch(byte_buffer_t *pdu) { mac->pcch_stop_rx(); if (RRC_STATE_IDLE == state) { rrc_log->info("RRC in IDLE state - sending connection request.\n"); - paging_received = true; - state = RRC_STATE_CELL_SELECTING; + send_con_request(); + state = RRC_STATE_CONNECTING; } } } From c69d4a37e8838913df3bd0c06d19a7f069f033ca Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 1 Dec 2017 17:00:30 +0100 Subject: [PATCH 182/242] Implemented proper cell reselection. Tested reestablishment from one cell to another. --- srsue/hdr/upper/rrc.h | 6 ++-- srsue/src/phy/phch_recv.cc | 27 +++++++++------- srsue/src/phy/phch_worker.cc | 2 +- srsue/src/upper/nas.cc | 6 +++- srsue/src/upper/rrc.cc | 62 ++++++++++++++++++++++++------------ 5 files changed, 66 insertions(+), 37 deletions(-) diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index f587cc0ff..085bf6b88 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -152,9 +152,6 @@ private: rrc_args_t args; bool first_stimsi_attempt; - bool reestablishment_in_progress; - bool connection_requested; - bool pending_mob_reconf; LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT mob_reconf; @@ -367,7 +364,8 @@ private: void cell_reselection_eval(float rsrp, float rsrq); bool cell_selection_eval(float rsrp, float rsrq = 0); - + bool connection_requested; + void plmn_select_rrc(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id); // RLC interface void max_retx_attempted(); diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 5fe63ccd4..941f7d025 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -301,16 +301,17 @@ void phch_recv::cell_search_inc() { cur_earfcn_index++; if (cur_earfcn_index >= 0) { - if (cur_earfcn_index >= (int) earfcn.size() - 1) { + if (cur_earfcn_index >= (int) earfcn.size()) { cur_earfcn_index = 0; rrc->earfcn_end(); + } else { + Info("SYNC: Cell Search idx %d/%d\n", cur_earfcn_index, earfcn.size()); + if (current_earfcn != earfcn[cur_earfcn_index]) { + current_earfcn = earfcn[cur_earfcn_index]; + set_frequency(); + } } } - Info("SYNC: Cell Search idx %d/%d\n", cur_earfcn_index, earfcn.size()); - if (current_earfcn != earfcn[cur_earfcn_index]) { - current_earfcn = earfcn[cur_earfcn_index]; - set_frequency(); - } } void phch_recv::cell_search_next(bool reset) { @@ -329,12 +330,16 @@ void phch_recv::cell_search_next(bool reset) { } void phch_recv::cell_search_start() { - if (earfcn.size() > 0) { - Info("SYNC: Starting Cell Search procedure in %d EARFCNs...\n", earfcn.size()); - cell_search_next(true); + if (phy_state == CELL_CAMP) { + Warning("SYNC: Can't start cell search procedure while camping on cell\n"); } else { - Info("SYNC: Empty EARFCN list. Stopping cell search...\n"); - log_h->console("Empty EARFCN list. Stopping cell search...\n"); + if (earfcn.size() > 0) { + Info("SYNC: Starting Cell Search procedure in %d EARFCNs...\n", earfcn.size()); + cell_search_next(true); + } else { + Info("SYNC: Empty EARFCN list. Stopping cell search...\n"); + log_h->console("Empty EARFCN list. Stopping cell search...\n"); + } } } diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 47ca680af..edd5f268c 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -268,7 +268,7 @@ void phch_worker::work_imp() } } } - Info("dl_ack={%d, %d}, generate_ack=%d\n", dl_ack[0], dl_ack[1], dl_action.generate_ack); + Debug("dl_ack={%d, %d}, generate_ack=%d\n", dl_ack[0], dl_ack[1], dl_action.generate_ack); if (dl_action.generate_ack) { set_uci_ack(dl_ack, dl_mac_grant.tb_en); } diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index 62e23d852..c53ef35a3 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -108,7 +108,6 @@ void nas::attach_request() { } else if (state == EMM_STATE_REGISTERED) { nas_log->info("NAS state is registered, connecting to same PLMN\n"); rrc->plmn_select(current_plmn); - selecting_plmn = current_plmn; } else { nas_log->info("Attach request ignored. State = %s\n", emm_state_text[state]); } @@ -125,6 +124,11 @@ void nas::deattach_request() { void nas::plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) { + // Do not process new PLMN if already selected + if (plmn_selection == PLMN_SELECTED) { + return; + } + // Check if already registered for (uint32_t i=0;iis_attaching()) { sleep(1); rrc_log->info("RRC IDLE: NAS is attaching and camping on cell, reselecting...\n"); - plmn_select(selected_plmn_id); + plmn_select_rrc(selected_plmn_id); } // If not camping on a cell } else { // If NAS is attached, perform cell reselection on current PLMN if (nas->is_attached()) { rrc_log->info("RRC IDLE: NAS is attached, PHY not synchronized. Re-selecting cell...\n"); - plmn_select(selected_plmn_id); + plmn_select_rrc(selected_plmn_id); } else if (nas->is_attaching()) { sleep(1); rrc_log->info("RRC IDLE: NAS is attaching, searching again PLMN\n"); @@ -204,6 +202,10 @@ void rrc::run_thread() { } break; case RRC_STATE_CELL_SELECTING: + + /* During cell selection, apply SIB configurations if available or receive them if not. + * Cell is selected when all SIBs downloaded or applied. + */ if (phy->sync_status()) { if (!current_cell->has_valid_sib1) { si_acquire_state = SI_ACQUIRE_SIB1; @@ -216,29 +218,36 @@ void rrc::run_thread() { state = RRC_STATE_CELL_SELECTED; } } - if (!reestablishment_in_progress) { + // Don't time out during restablishment (T311 running) + if (!mac_timers->timer_get(t311)->is_running()) { select_cell_timeout++; if (select_cell_timeout >= RRC_SELECT_CELL_TIMEOUT) { rrc_log->info("RRC Cell Selecting: timeout expired. Starting Cell Search...\n"); - state = RRC_STATE_PLMN_SELECTION; plmn_select_timeout = 0; + select_cell_timeout = 0; phy->cell_search_start(); } } break; case RRC_STATE_CELL_SELECTED: + /* The cell is selected when the SIBs are received and applied. + * If we were in RRC_CONNECTED and arrive here it means a RLF occurred and we are in Reestablishment procedure. + * If T311 is running means there is a reestablishment in progress, send ConnectionReestablishmentRequest. + * If not, do a ConnectionRequest if NAS is established or go to IDLE an camp on cell otherwise. + */ if (mac_timers->timer_get(t311)->is_running()) { + // rrc_log->info("RRC Cell Selected: Sending connection reestablishment...\n"); con_restablish_cell_reselected(); state = RRC_STATE_CONNECTING; connecting_timeout = 0; } else if (connection_requested) { + connection_requested = false; rrc_log->info("RRC Cell Selected: Sending connection request...\n"); send_con_request(); state = RRC_STATE_CONNECTING; connecting_timeout = 0; - connection_requested = false; } else { rrc_log->info("RRC Cell Selected: Starting paging and going to IDLE...\n"); mac->pcch_start_rx(); @@ -265,9 +274,9 @@ void rrc::run_thread() { break; case RRC_STATE_LEAVE_CONNECTED: usleep(60000); + rrc_log->console("RRC IDLE\n"); rrc_log->info("Leaving RRC_CONNECTED state\n"); drb_up = false; - reestablishment_in_progress = false; measurements.reset(); pdcp->reset(); rlc->reset(); @@ -275,12 +284,14 @@ void rrc::run_thread() { mac->reset(); set_phy_default(); set_mac_default(); - mac->pcch_start_rx(); mac_timers->timer_get(t310)->stop(); mac_timers->timer_get(t311)->stop(); - - // Instruct PHY to measure serving cell for cell reselection - phy->meas_start(phy->get_current_earfcn(), phy->get_current_pci()); + if (phy->sync_status()) { + // Instruct MAC to look for P-RNTI + mac->pcch_start_rx(); + // Instruct PHY to measure serving cell for cell reselection + phy->meas_start(phy->get_current_earfcn(), phy->get_current_pci()); + } // Move to RRC_IDLE state = RRC_STATE_IDLE; @@ -421,15 +432,24 @@ void rrc::plmn_search() { plmn_select_timeout = 0; } +/* This is the NAS interface. When NAS requests to select a PLMN we have to + * connect to either register or because there is pending higher layer traffic. + */ void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) { + connection_requested = true; + plmn_select_rrc(plmn_id); +} +/* This is called by RRC only. In this case, we do not want to connect, just camp on the + * selected PLMN + */ +void rrc::plmn_select_rrc(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) { // If already camping on the selected PLMN, select this cell if (state == RRC_STATE_IDLE || state == RRC_STATE_CONNECTED || state == RRC_STATE_PLMN_SELECTION) { if (phy->sync_status() && selected_plmn_id.mcc == plmn_id.mcc && selected_plmn_id.mnc == plmn_id.mnc) { rrc_log->info("Already camping on selected PLMN, connecting...\n"); state = RRC_STATE_CELL_SELECTING; select_cell_timeout = 0; - connection_requested = true; } else { rrc_log->info("PLMN Id=%s selected\n", plmn_id_to_string(plmn_id).c_str()); // Sort cells according to RSRP @@ -438,7 +458,6 @@ void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) { last_selected_cell = -1; select_cell_timeout = 0; - connection_requested = true; state = RRC_STATE_CELL_SELECTING; select_next_cell_in_plmn(); } @@ -477,7 +496,8 @@ void rrc::select_next_cell_in_plmn() { } } } - rrc_log->info("No more known cells...\n"); + rrc_log->info("No more known cells. Starting again\n"); + last_selected_cell = -1; } void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, uint32_t earfcn, uint32_t pci) { @@ -603,11 +623,15 @@ rrc::cell_t* rrc::add_new_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rs // PHY indicates that has gone through all known EARFCN void rrc::earfcn_end() { - rrc_log->debug("Finished searching cells in EARFCN set while in state %s\n", rrc_state_text[state]); + rrc_log->info("Finished searching cells in EARFCN set while in state %s\n", rrc_state_text[state]); // If searching for PLMN, indicate NAS we scanned all frequencies if (state == RRC_STATE_PLMN_SELECTION) { nas->plmn_search_end(); + } else if (state == RRC_STATE_CELL_SELECTING) { + select_cell_timeout = 0; + rrc_log->info("Starting cell search again\n"); + phy->cell_search_start(); } } @@ -631,7 +655,7 @@ void rrc::cell_reselection_eval(float rsrp, float rsrq) { // Intra-frequency cell-reselection criteria - if (get_srxlev(rsrp) > cell_resel_cfg.s_intrasearchP && rsrp > -80.0) { + if (get_srxlev(rsrp) > cell_resel_cfg.s_intrasearchP && rsrp > -70.0) { // UE may not perform intra-frequency measurements. phy->meas_reset(); // keep measuring serving cell @@ -864,8 +888,6 @@ 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(); @@ -882,7 +904,6 @@ void rrc::send_con_restablish_request() { // 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(); @@ -1218,6 +1239,7 @@ void rrc::handle_sib2() rrc_log->info("SIB2 received\n"); apply_sib2_configs(¤t_cell->sib2); + } void rrc::handle_sib3() From 8f39a622fea6414fa3a4d49f60bfc9373f92cbfc Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 1 Dec 2017 19:50:42 +0100 Subject: [PATCH 183/242] Added cancelation of self interference of PSS and SSS signals --- lib/src/phy/ch_estimation/chest_dl.c | 4 +- lib/src/phy/sync/sync.c | 2 +- srsue/hdr/phy/phch_common.h | 1 + srsue/hdr/phy/phch_recv.h | 2 + srsue/src/phy/phch_common.cc | 1 - srsue/src/phy/phch_recv.cc | 60 ++++++++++++++++++++++++---- srsue/src/phy/phch_worker.cc | 1 + srsue/src/phy/phy.cc | 1 + srsue/src/upper/rrc.cc | 6 +-- 9 files changed, 63 insertions(+), 15 deletions(-) diff --git a/lib/src/phy/ch_estimation/chest_dl.c b/lib/src/phy/ch_estimation/chest_dl.c index cdd1af7f8..35122958d 100644 --- a/lib/src/phy/ch_estimation/chest_dl.c +++ b/lib/src/phy/ch_estimation/chest_dl.c @@ -434,10 +434,10 @@ float srslte_chest_dl_rssi(srslte_chest_dl_t *q, cf_t *input, uint32_t port_id) uint32_t l; float rssi = 0; - uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(port_id); + uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(port_id); for (l=0;lcell.cp, port_id) * q->cell.nof_prb * SRSLTE_NRE]; - rssi += srslte_vec_dot_prod_conj_ccc(tmp, tmp, q->cell.nof_prb * SRSLTE_NRE); + rssi += srslte_vec_dot_prod_conj_ccc(tmp, tmp, q->cell.nof_prb * SRSLTE_NRE); } return rssi/nsymbols; } diff --git a/lib/src/phy/sync/sync.c b/lib/src/phy/sync/sync.c index ac29bac21..a74be30d6 100644 --- a/lib/src/phy/sync/sync.c +++ b/lib/src/phy/sync/sync.c @@ -620,7 +620,7 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, const cf_t *input, uin } - // If there is enough space for CP and PSS-based CFO estimation + // If there is enough space for CP and SSS estimation if (peak_pos + find_offset >= 2 * (q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) { // If SSS search is enabled, correlate SSS sequence diff --git a/srsue/hdr/phy/phch_common.h b/srsue/hdr/phy/phch_common.h index d7b960ea5..fd73d9421 100644 --- a/srsue/hdr/phy/phch_common.h +++ b/srsue/hdr/phy/phch_common.h @@ -46,6 +46,7 @@ namespace srsue { class chest_feedback_itf { public: + virtual void out_of_sync() = 0; virtual void set_cfo(float cfo) = 0; }; diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index 8bc310bf5..e6ef981d1 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -75,6 +75,7 @@ public: bool status_is_sync(); // from chest_feedback_itf + void out_of_sync(); void set_cfo(float cfo); void set_time_adv_sec(float time_adv_sec); @@ -319,6 +320,7 @@ private: bool cell_search_in_progress; uint32_t out_of_sync_cnt; + uint32_t out_of_sync2_cnt; float dl_freq; float ul_freq; diff --git a/srsue/src/phy/phch_common.cc b/srsue/src/phy/phch_common.cc index 39a23e43d..2a7044acd 100644 --- a/srsue/src/phy/phch_common.cc +++ b/srsue/src/phy/phch_common.cc @@ -257,7 +257,6 @@ void phch_common::worker_end(uint32_t tti, bool tx_enable, } // Trigger next transmission pthread_mutex_unlock(&tx_mutex[(tti+1)%nof_mutex]); - } diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 941f7d025..17ac71c54 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -549,6 +549,9 @@ void phch_recv::run_thread() phy_state = IDLE; is_in_idle = true; + uint32_t hf_len; + uint32_t fft_sz; + while (running) { if (phy_state != IDLE) { @@ -677,6 +680,24 @@ void phch_recv::run_thread() } workers_pool->start_worker(worker); + // Substract PSS/SSS from current cell before computing intrafrequency + hf_len = SRSLTE_SF_LEN_PRB(cell.nof_prb)/2; + fft_sz = srslte_symbol_sz(cell.nof_prb); + + if ((tti%5) == 0) { + srslte_vec_sc_prod_cfc(ue_sync.strack.pss_filt, 1.0/sqrtf(fft_sz), ue_sync.strack.pss_filt, fft_sz); + srslte_vec_sc_prod_cfc(ue_sync.strack.sss_filt, 1.0/sqrtf(fft_sz), ue_sync.strack.pss_filt, fft_sz); + + srslte_vec_sub_ccc(&buffer[0][hf_len-fft_sz], + ue_sync.strack.pss_filt, + &buffer[0][hf_len-fft_sz], + fft_sz); + + srslte_vec_sub_ccc(&buffer[0][hf_len-2*fft_sz-SRSLTE_CP_LEN(fft_sz, SRSLTE_CP_NORM_LEN)], + ue_sync.strack.sss_filt, + &buffer[0][hf_len-2*fft_sz-SRSLTE_CP_LEN(fft_sz, SRSLTE_CP_NORM_LEN)], + fft_sz); + } intra_freq_meas.write(tti, buffer[0], SRSLTE_SF_LEN_PRB(cell.nof_prb)); out_of_sync_cnt = 0; break; @@ -718,7 +739,15 @@ void phch_recv::run_thread() } } - +void phch_recv::out_of_sync() { + out_of_sync2_cnt++; + Info("SYNC: Received out_of_sync from channel estimator (%d)\n", out_of_sync2_cnt); + if (out_of_sync2_cnt >= 2) { + out_of_sync2_cnt = 0; + Info("SYNC: Trying to resync signal\n"); + resync_sfn(true, true); + } +} @@ -1068,6 +1097,7 @@ phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *in ret_code ret = IDLE; + Info("INTRA: Here offset=%d\n", offset); offset = offset-sf_len/2; if (offset < 0) { offset += sf_len; @@ -1103,6 +1133,10 @@ phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *in } } + if (found_best) { + Info("INTRA: fine-tuned offset=%d\n", best_test_offset); + } + offset = found_best?best_test_offset:offset; if (offset >= 0 && offset < sf_len*max_sf) { uint32_t nof_sf = (sf_len*max_sf - offset)/sf_len; @@ -1116,6 +1150,8 @@ phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *in return ret; } } + } else { + Info("INTRA: not running because offset=%d, sf_len*max_sf=%d*%d\n", offset, sf_len, max_sf); } return ret; } @@ -1176,18 +1212,18 @@ void phch_recv::scell_recv::init(srslte::log *log_h) measure_p.init(sf_buffer, log_h, 1, DEFAULT_MEASUREMENT_LEN); - if(srslte_sync_init(&sync_find, 5*max_sf_size, 5*max_sf_size, max_fft_sz)) { + if(srslte_sync_init(&sync_find, 15*max_sf_size, 5*max_sf_size, max_fft_sz)) { fprintf(stderr, "Error initiating sync_find\n"); return; } srslte_sync_cp_en(&sync_find, false); - srslte_sync_set_threshold(&sync_find, 1.2); + srslte_sync_set_threshold(&sync_find, 1.3); srslte_sync_set_em_alpha(&sync_find, 0.0); // Configure FIND object behaviour (this configuration is always the same) - srslte_sync_set_cfo_ema_alpha(&sync_find, 0.2); + srslte_sync_set_cfo_ema_alpha(&sync_find, 0.5); srslte_sync_set_cfo_i_enable(&sync_find, false); - srslte_sync_set_cfo_cp_enable(&sync_find, true); + srslte_sync_set_cfo_cp_enable(&sync_find, false); srslte_sync_set_cfo_pss_enable(&sync_find, true); srslte_sync_set_pss_filt_enable(&sync_find, true); srslte_sync_set_sss_filt_enable(&sync_find, true); @@ -1208,13 +1244,14 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, if (fft_sz != current_fft_sz) { if (srslte_sync_resize(&sync_find, nof_sf*sf_len, 5*sf_len, fft_sz)) { - fprintf(stderr, "Error resizing sync\n"); + fprintf(stderr, "Error resizing sync nof_sf=%d, sf_len=%d, fft_sz=%d\n", nof_sf, sf_len, fft_sz); return SRSLTE_ERROR; } current_fft_sz = fft_sz; } srslte_sync_reset(&sync_find); + srslte_sync_cfo_reset(&sync_find); int nof_cells = 0; uint32_t peak_idx = 0; @@ -1243,8 +1280,15 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, cell_id = srslte_sync_get_cell_id(&sync_find); if (cell_id != -1) { - Info("INTRA: found peak_idx=%d, n_id_2=%d, cell_id=%d, sf=%d\n", - peak_idx, n_id_2, cell_id, sf_idx); + Info("INTRA: found peak_idx=%d, n_id_2=%d, cell_id=%d, sf=%d, cfo=%.1f Hz, psr=%f\n", + peak_idx, n_id_2, cell_id, sf_idx, 15000*srslte_sync_get_cfo(&sync_find), sync_find.peak_value); + + /* + if (cell_id == 342) { + srslte_vec_save_file("input", input_buffer, 5*sf_len*sizeof(cf_t)); + srslte_vec_save_file("conv", sync_find.pss.conv_output, sync_find.pss.frame_size*sizeof(cf_t)); + exit(-1); + }*/ found_cell.id = cell_id; found_cell.nof_ports = 1; // Use port 0 only for measurement diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index edd5f268c..27503c9f7 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -395,6 +395,7 @@ void phch_worker::work_imp() phy->rrc->in_sync(); log_h->debug("SYNC: Sending in-sync to RRC\n"); } else if (snr_th_err) { + chest_loop->out_of_sync(); phy->rrc->out_of_sync(); log_h->info("SNR=%.1f dB under threshold. Sending out-of-sync to RRC\n", 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest))); diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index d871c384e..689426b2a 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -334,6 +334,7 @@ void phy::reset() workers[i].reset(); } workers_common.reset(); + usleep(4000); workers_common.reset_ul(); } diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 1684f3a52..2559d3645 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -1322,8 +1322,8 @@ void rrc::write_pdu_pcch(byte_buffer_t *pdu) { mac->pcch_stop_rx(); if (RRC_STATE_IDLE == state) { rrc_log->info("RRC in IDLE state - sending connection request.\n"); - send_con_request(); - state = RRC_STATE_CONNECTING; + connection_requested = true; + state = RRC_STATE_CELL_SELECTED; } } } @@ -1386,7 +1386,7 @@ void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) { send_ul_info_transfer(lcid, sdu); break; default: - rrc_log->error("SDU received from NAS while RRC state = %s", rrc_state_text[state]); + rrc_log->error("SDU received from NAS while RRC state = %s\n", rrc_state_text[state]); break; } } From 1a323770c94a0b2c94fdc239deec23b794a8e166 Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Fri, 1 Dec 2017 19:19:38 +0000 Subject: [PATCH 184/242] Added support for AS ciphering --- lib/include/srslte/common/pcap.h | 99 ++++---------- lib/include/srslte/interfaces/ue_interfaces.h | 5 +- lib/include/srslte/upper/pdcp.h | 5 +- lib/include/srslte/upper/pdcp_entity.h | 11 +- lib/src/common/mac_pcap.cc | 6 +- lib/src/common/nas_pcap.cc | 6 +- lib/src/upper/pdcp.cc | 12 +- lib/src/upper/pdcp_entity.cc | 124 +++++++++++------- srsue/src/upper/rrc.cc | 17 ++- 9 files changed, 150 insertions(+), 135 deletions(-) diff --git a/lib/include/srslte/common/pcap.h b/lib/include/srslte/common/pcap.h index 611aea72d..ce4fcf541 100644 --- a/lib/include/srslte/common/pcap.h +++ b/lib/include/srslte/common/pcap.h @@ -32,9 +32,8 @@ #include #include -#define MAC_LTE_DLT 147 -#define RRC_LTE_DLT 148 -#define NAS_LTE_DLT 149 +#define MAC_LTE_DLT 147 +#define NAS_LTE_DLT 148 /* This structure gets written to the start of the file */ @@ -74,30 +73,15 @@ typedef struct pcaprec_hdr_s { #define SPS_RNTI 5 #define M_RNTI 6 -#define MAC_LTE_START_STRING "mac-lte" - +#define MAC_LTE_START_STRING "mac-lte" +#define MAC_LTE_PAYLOAD_TAG 0x01 #define MAC_LTE_RNTI_TAG 0x02 -/* 2 bytes, network order */ - #define MAC_LTE_UEID_TAG 0x03 -/* 2 bytes, network order */ - #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 */ - #define MAC_LTE_RETX_TAG 0x06 -/* 1 byte */ - #define MAC_LTE_CRC_STATUS_TAG 0x07 -/* 1 byte */ -/* MAC PDU. Following this tag comes the actual MAC PDU (there is no length, the PDU - continues until the end of the frame) */ -#define MAC_LTE_PAYLOAD_TAG 0x01 /* Context information for every MAC PDU that will be logged */ @@ -112,7 +96,6 @@ typedef struct MAC_Context_Info_t { unsigned short sysFrameNumber; unsigned short subFrameNumber; - } MAC_Context_Info_t; /* Context information for every NAS PDU that will be logged */ @@ -121,11 +104,12 @@ typedef struct NAS_Context_Info_s { } NAS_Context_Info_t; -/**************************************************************************/ -/* API functions for opening/writing/closing MAC-LTE PCAP files */ +/************************************************************************** + * API functions for opening/closing LTE PCAP files * + **************************************************************************/ /* Open the file and write file header */ -inline FILE *MAC_LTE_PCAP_Open(const char *fileName) +inline FILE *LTE_PCAP_Open(uint32_t DLT, const char *fileName) { pcap_hdr_t file_header = { @@ -134,7 +118,7 @@ inline FILE *MAC_LTE_PCAP_Open(const char *fileName) 0, /* timezone */ 0, /* sigfigs - apparently all tools do this */ 65535, /* snaplen - this should be long enough */ - MAC_LTE_DLT /* Data Link Type (DLT). Set as unused value 147 for now */ + DLT /* Data Link Type (DLT). Set as unused value 147 for now */ }; FILE *fd = fopen(fileName, "w"); @@ -149,9 +133,21 @@ inline FILE *MAC_LTE_PCAP_Open(const char *fileName) return fd; } +/* Close the PCAP file */ +inline void LTE_PCAP_Close(FILE *fd) +{ + if(fd) + fclose(fd); +} + + +/************************************************************************** + * API functions for writing MAC-LTE PCAP files * + **************************************************************************/ + /* Write an individual PDU (PCAP packet header + mac-context + mac-pdu) */ -inline int MAC_LTE_PCAP_WritePDU(FILE *fd, MAC_Context_Info_t *context, - const unsigned char *PDU, unsigned int length) +inline int LTE_PCAP_MAC_WritePDU(FILE *fd, MAC_Context_Info_t *context, + const unsigned char *PDU, unsigned int length) { pcaprec_hdr_t packet_header; char context_header[256]; @@ -216,45 +212,15 @@ inline int MAC_LTE_PCAP_WritePDU(FILE *fd, MAC_Context_Info_t *context, return 1; } -/* Close the PCAP file */ -inline void MAC_LTE_PCAP_Close(FILE *fd) -{ - if(fd) - fclose(fd); -} - - -/**************************************************************************/ -/* API functions for opening/writing/closing NAS-LTE PCAP files */ - -/* Open the file and write file header */ -inline FILE *NAS_LTE_PCAP_Open(const char *fileName) -{ - pcap_hdr_t file_header = - { - 0xa1b2c3d4, /* magic number */ - 2, 4, /* version number is 2.4 */ - 0, /* timezone */ - 0, /* sigfigs - apparently all tools do this */ - 65535, /* snaplen - this should be long enough */ - NAS_LTE_DLT /* Data Link Type (DLT). Set as unused value 149 for now */ - }; - - FILE *fd = fopen(fileName, "w"); - if (fd == NULL) { - printf("Failed to open file \"%s\" for writing\n", fileName); - return NULL; - } - /* Write the file header */ - fwrite(&file_header, sizeof(pcap_hdr_t), 1, fd); - return fd; -} +/************************************************************************** + * API functions for writing NAS-EPS PCAP files * + **************************************************************************/ -/* Write an individual PDU (PCAP packet header + mac-context + mac-pdu) */ -inline int NAS_LTE_PCAP_WritePDU(FILE *fd, NAS_Context_Info_t *context, - const unsigned char *PDU, unsigned int length) +/* Write an individual PDU (PCAP packet header + nas-context + nas-pdu) */ +inline int LTE_PCAP_NAS_WritePDU(FILE *fd, NAS_Context_Info_t *context, + const unsigned char *PDU, unsigned int length) { pcaprec_hdr_t packet_header; @@ -281,11 +247,4 @@ inline int NAS_LTE_PCAP_WritePDU(FILE *fd, NAS_Context_Info_t *context, return 1; } -/* Close the PCAP file */ -inline void NAS_LTE_PCAP_Close(FILE *fd) -{ - if(fd) - fclose(fd); -} - #endif /* UEPCAP_H */ diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index 37d73b910..7b15e799d 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -197,10 +197,11 @@ public: virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu) = 0; virtual void add_bearer(uint32_t lcid, srslte::srslte_pdcp_config_t cnfg = srslte::srslte_pdcp_config_t()) = 0; virtual void config_security(uint32_t lcid, - uint8_t *k_rrc_enc_, - uint8_t *k_rrc_int_, + uint8_t *k_enc_, + uint8_t *k_int_, srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0; + virtual void enable_integrity(uint32_t lcid) = 0; virtual void enable_encryption(uint32_t lcid) = 0; }; diff --git a/lib/include/srslte/upper/pdcp.h b/lib/include/srslte/upper/pdcp.h index f52fdbe05..e4547acdf 100644 --- a/lib/include/srslte/upper/pdcp.h +++ b/lib/include/srslte/upper/pdcp.h @@ -58,10 +58,11 @@ public: void write_sdu(uint32_t lcid, byte_buffer_t *sdu); void add_bearer(uint32_t lcid, srslte_pdcp_config_t cnfg = srslte_pdcp_config_t()); void config_security(uint32_t lcid, - uint8_t *k_rrc_enc, - uint8_t *k_rrc_int, + uint8_t *k_enc, + uint8_t *k_int, CIPHERING_ALGORITHM_ID_ENUM cipher_algo, INTEGRITY_ALGORITHM_ID_ENUM integ_algo); + void enable_integrity(uint32_t lcid); void enable_encryption(uint32_t lcid); // RLC interface diff --git a/lib/include/srslte/upper/pdcp_entity.h b/lib/include/srslte/upper/pdcp_entity.h index bf1e8b5b2..f59866d5d 100644 --- a/lib/include/srslte/upper/pdcp_entity.h +++ b/lib/include/srslte/upper/pdcp_entity.h @@ -78,10 +78,11 @@ public: // RRC interface void write_sdu(byte_buffer_t *sdu); - void config_security(uint8_t *k_rrc_enc_, - uint8_t *k_rrc_int_, + void config_security(uint8_t *k_enc_, + uint8_t *k_int_, CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, INTEGRITY_ALGORITHM_ID_ENUM integ_algo_); + void enable_integrity(); void enable_encryption(); // RLC interface @@ -102,13 +103,14 @@ private: bool active; uint32_t lcid; srslte_pdcp_config_t cfg; + uint8_t sn_len_bytes; bool do_integrity; bool do_encryption; uint32_t rx_count; uint32_t tx_count; - uint8_t k_rrc_enc[32]; - uint8_t k_rrc_int[32]; + uint8_t k_enc[32]; + uint8_t k_int[32]; CIPHERING_ALGORITHM_ID_ENUM cipher_algo; INTEGRITY_ALGORITHM_ID_ENUM integ_algo; @@ -133,6 +135,7 @@ private: void run_thread(); + uint8_t get_bearer_id(uint8_t lcid); }; /**************************************************************************** diff --git a/lib/src/common/mac_pcap.cc b/lib/src/common/mac_pcap.cc index b73181e73..d73c196fb 100644 --- a/lib/src/common/mac_pcap.cc +++ b/lib/src/common/mac_pcap.cc @@ -40,14 +40,14 @@ void mac_pcap::enable(bool en) } void mac_pcap::open(const char* filename, uint32_t ue_id) { - pcap_file = MAC_LTE_PCAP_Open(filename); + pcap_file = LTE_PCAP_Open(MAC_LTE_DLT, filename); ue_id = ue_id; enable_write = true; } void mac_pcap::close() { fprintf(stdout, "Saving MAC PCAP file\n"); - MAC_LTE_PCAP_Close(pcap_file); + LTE_PCAP_Close(pcap_file); } void mac_pcap::pack_and_write(uint8_t* pdu, uint32_t pdu_len_bytes, uint32_t reTX, bool crc_ok, uint32_t tti, @@ -65,7 +65,7 @@ void mac_pcap::pack_and_write(uint8_t* pdu, uint32_t pdu_len_bytes, uint32_t reT (uint16_t)(tti%10) /* Subframe number */ }; if (pdu) { - MAC_LTE_PCAP_WritePDU(pcap_file, &context, pdu, pdu_len_bytes); + LTE_PCAP_MAC_WritePDU(pcap_file, &context, pdu, pdu_len_bytes); } } } diff --git a/lib/src/common/nas_pcap.cc b/lib/src/common/nas_pcap.cc index 80603f8d5..94e2cd9b0 100644 --- a/lib/src/common/nas_pcap.cc +++ b/lib/src/common/nas_pcap.cc @@ -12,14 +12,14 @@ void nas_pcap::enable() } void nas_pcap::open(const char* filename, uint32_t ue_id) { - pcap_file = NAS_LTE_PCAP_Open(filename); + pcap_file = LTE_PCAP_Open(NAS_LTE_DLT, filename); ue_id = ue_id; enable_write = true; } void nas_pcap::close() { fprintf(stdout, "Saving NAS PCAP file\n"); - MAC_LTE_PCAP_Close(pcap_file); + LTE_PCAP_Close(pcap_file); } void nas_pcap::write_nas(uint8_t *pdu, uint32_t pdu_len_bytes) @@ -27,7 +27,7 @@ void nas_pcap::write_nas(uint8_t *pdu, uint32_t pdu_len_bytes) if (enable_write) { NAS_Context_Info_t context; if (pdu) { - NAS_LTE_PCAP_WritePDU(pcap_file, &context, pdu, pdu_len_bytes); + LTE_PCAP_NAS_WritePDU(pcap_file, &context, pdu, pdu_len_bytes); } } } diff --git a/lib/src/upper/pdcp.cc b/lib/src/upper/pdcp.cc index ed7e13684..51d4950a5 100644 --- a/lib/src/upper/pdcp.cc +++ b/lib/src/upper/pdcp.cc @@ -99,13 +99,19 @@ void pdcp::add_bearer(uint32_t lcid, srslte_pdcp_config_t cfg) } void pdcp::config_security(uint32_t lcid, - uint8_t *k_rrc_enc, - uint8_t *k_rrc_int, + uint8_t *k_enc, + uint8_t *k_int, CIPHERING_ALGORITHM_ID_ENUM cipher_algo, INTEGRITY_ALGORITHM_ID_ENUM integ_algo) { if(valid_lcid(lcid)) - pdcp_array[lcid].config_security(k_rrc_enc, k_rrc_int, cipher_algo, integ_algo); + pdcp_array[lcid].config_security(k_enc, k_int, cipher_algo, integ_algo); +} + +void pdcp::enable_integrity(uint32_t lcid) +{ + if(valid_lcid(lcid)) + pdcp_array[lcid].enable_integrity(); } void pdcp::enable_encryption(uint32_t lcid) diff --git a/lib/src/upper/pdcp_entity.cc b/lib/src/upper/pdcp_entity.cc index 066bb127f..0ac426a6e 100644 --- a/lib/src/upper/pdcp_entity.cc +++ b/lib/src/upper/pdcp_entity.cc @@ -56,6 +56,12 @@ void pdcp_entity::init(srsue::rlc_interface_pdcp *rlc_, rx_count = 0; do_integrity = false; do_encryption = false; + if(cfg.is_control) { + cfg.sn_len = 5; + sn_len_bytes = 1; + } else { + sn_len_bytes = (cfg.sn_len+7)/8; + } start(PDCP_THREAD_PRIO); @@ -87,46 +93,57 @@ bool pdcp_entity::is_active() void pdcp_entity::write_sdu(byte_buffer_t *sdu) { log->info_hex(sdu->msg, sdu->N_bytes, - "TX %s SDU, do_integrity = %s, do_encryption = %s", get_rb_name(lcid), + "TX %s SDU, SN: %d, do_integrity = %s, do_encryption = %s", + get_rb_name(lcid), tx_count, (do_integrity) ? "true" : "false", (do_encryption) ? "true" : "false"); if (cfg.is_control) { pdcp_pack_control_pdu(tx_count, sdu); - if(do_integrity) - { + if(do_integrity) { integrity_generate(sdu->msg, sdu->N_bytes-4, &sdu->msg[sdu->N_bytes-4]); } - tx_count++; } if (cfg.is_data) { if(12 == cfg.sn_len) { - pdcp_pack_data_pdu_long_sn(tx_count++, sdu); + pdcp_pack_data_pdu_long_sn(tx_count, sdu); } else { - pdcp_pack_data_pdu_short_sn(tx_count++, sdu); + pdcp_pack_data_pdu_short_sn(tx_count, sdu); } } + if(do_encryption) { + cipher_encrypt(&sdu->msg[sn_len_bytes], + sdu->N_bytes-sn_len_bytes, + &sdu->msg[sn_len_bytes]); + log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU (encrypted)", get_rb_name(lcid)); + } + tx_count++; + rlc->write_sdu(lcid, sdu); } -void pdcp_entity::config_security(uint8_t *k_rrc_enc_, - uint8_t *k_rrc_int_, +void pdcp_entity::config_security(uint8_t *k_enc_, + uint8_t *k_int_, CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) { - do_integrity = true; for(int i=0; i<32; i++) { - k_rrc_enc[i] = k_rrc_enc_[i]; - k_rrc_int[i] = k_rrc_int_[i]; + k_enc[i] = k_enc_[i]; + k_int[i] = k_int_[i]; } cipher_algo = cipher_algo_; integ_algo = integ_algo_; } +void pdcp_entity::enable_integrity() +{ + do_integrity = true; +} + void pdcp_entity::enable_encryption() { do_encryption = true; @@ -142,24 +159,26 @@ void pdcp_entity::integrity_generate( uint8_t *msg, uint32_t msg_len, uint8_t *mac) { + uint8_t bearer; + switch(integ_algo) { case INTEGRITY_ALGORITHM_ID_EIA0: break; case INTEGRITY_ALGORITHM_ID_128_EIA1: - security_128_eia1(&k_rrc_int[16], + security_128_eia1(&k_int[16], tx_count, - lcid-1, + get_bearer_id(lcid), cfg.direction, msg, msg_len, mac); break; case INTEGRITY_ALGORITHM_ID_128_EIA2: - security_128_eia2(&k_rrc_int[16], + security_128_eia2(&k_int[16], tx_count, - lcid-1, - cfg.direction, + get_bearer_id(lcid), + cfg.direction, msg, msg_len, mac); @@ -183,19 +202,19 @@ bool pdcp_entity::integrity_verify(uint8_t *msg, case INTEGRITY_ALGORITHM_ID_EIA0: break; case INTEGRITY_ALGORITHM_ID_128_EIA1: - security_128_eia1(&k_rrc_int[16], + security_128_eia1(&k_int[16], count, - lcid-1, - ( cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK), + get_bearer_id(lcid), + (cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK), msg, msg_len, mac_exp); break; case INTEGRITY_ALGORITHM_ID_128_EIA2: - security_128_eia2(&k_rrc_int[16], + security_128_eia2(&k_int[16], count, - lcid-1, - ( cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK), + get_bearer_id(lcid), + (cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK), msg, msg_len, mac_exp); @@ -240,20 +259,20 @@ void pdcp_entity::cipher_encrypt(uint8_t *msg, case CIPHERING_ALGORITHM_ID_EEA0: break; case CIPHERING_ALGORITHM_ID_128_EEA1: - security_128_eea1(&(k_rrc_enc[16]), + security_128_eea1(&(k_enc[16]), tx_count, - lcid - 1, - cfg.direction, + get_bearer_id(lcid), + cfg.direction, msg, msg_len, ct_tmp.msg); memcpy(ct, ct_tmp.msg, msg_len); break; case CIPHERING_ALGORITHM_ID_128_EEA2: - security_128_eea2(&(k_rrc_enc[16]), + security_128_eea2(&(k_enc[16]), tx_count, - lcid - 1, - cfg.direction, + get_bearer_id(lcid), + cfg.direction, msg, msg_len, ct_tmp.msg); @@ -275,19 +294,19 @@ void pdcp_entity::cipher_decrypt(uint8_t *ct, case CIPHERING_ALGORITHM_ID_EEA0: break; case CIPHERING_ALGORITHM_ID_128_EEA1: - security_128_eea1(&(k_rrc_enc[16]), + security_128_eea1(&(k_enc[16]), count, - lcid - 1, - ( cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK), + get_bearer_id(lcid), + (cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK), ct, ct_len, msg_tmp.msg); break; case CIPHERING_ALGORITHM_ID_128_EEA2: - security_128_eea2(&(k_rrc_enc[16]), + security_128_eea2(&(k_enc[16]), count, - lcid - 1, - ( cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK), + get_bearer_id(lcid), + (cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK), ct, ct_len, msg_tmp.msg); @@ -306,39 +325,35 @@ void pdcp_entity::run_thread() while(running) { rx_pdu_queue.read(&pdu); + log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU", get_rb_name(lcid)); // Handle SRB messages switch(lcid) { case RB_ID_SRB0: // Simply pass on to RRC - log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU", get_rb_name(lcid)); rrc->write_pdu(RB_ID_SRB0, pdu); break; case RB_ID_SRB1: // Intentional fall-through case RB_ID_SRB2: uint32_t sn; - - log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU", get_rb_name(lcid)); - if (do_encryption) { - cipher_decrypt(&(pdu->msg[1]), - pdu->msg[0], - pdu->N_bytes - 1, - &(pdu->msg[1])); + cipher_decrypt(&(pdu->msg[sn_len_bytes]), + rx_count, + pdu->N_bytes - sn_len_bytes, + &(pdu->msg[sn_len_bytes])); log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU (decrypted)", get_rb_name(lcid)); } if (do_integrity) { integrity_verify(pdu->msg, - pdu->msg[0], + rx_count, pdu->N_bytes - 4, &(pdu->msg[pdu->N_bytes - 4])); } pdcp_unpack_control_pdu(pdu, &sn); - log->info_hex(pdu->msg, pdu->N_bytes, "RX %s SDU SN: %d", - get_rb_name(lcid), sn); + log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU SN: %d", get_rb_name(lcid), sn); rrc->write_pdu(lcid, pdu); break; } @@ -347,18 +362,35 @@ void pdcp_entity::run_thread() if(lcid >= RB_ID_DRB1) { uint32_t sn; + if (do_encryption) { + cipher_decrypt(&(pdu->msg[sn_len_bytes]), + rx_count, + pdu->N_bytes - sn_len_bytes, + &(pdu->msg[sn_len_bytes])); + log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU (decrypted)", get_rb_name(lcid)); + } if(12 == cfg.sn_len) { pdcp_unpack_data_pdu_long_sn(pdu, &sn); } else { pdcp_unpack_data_pdu_short_sn(pdu, &sn); } - log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU: %d", get_rb_name(lcid), sn); + log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU SN: %d", get_rb_name(lcid), sn); gw->write_pdu(lcid, pdu); } + + rx_count++; } } +uint8_t pdcp_entity::get_bearer_id(uint8_t lcid) +{ + if(lcid <= RB_ID_SRB2) { + return lcid - 1; + } else { + return lcid - RB_ID_SRB2 - 1; + } +} /**************************************************************************** diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 273a2d84d..d801d78d6 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -1164,11 +1164,21 @@ void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu) { cipher_algo = (CIPHERING_ALGORITHM_ID_ENUM) dl_dcch_msg.msg.security_mode_cmd.sec_algs.cipher_alg; integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM) dl_dcch_msg.msg.security_mode_cmd.sec_algs.int_alg; - // Configure PDCP for security + rrc_log->info("Received Security Mode Command eea: %s, eia: %s\n", + ciphering_algorithm_id_text[cipher_algo], + integrity_algorithm_id_text[integ_algo]); + + // Generate AS security keys uint8_t k_asme[32]; nas->get_k_asme(k_asme, 32); usim->generate_as_keys(k_asme, nas->get_ul_count()-1, k_rrc_enc, k_rrc_int, k_up_enc, k_up_int, cipher_algo, integ_algo); + rrc_log->debug_hex(k_rrc_enc, 32, "RRC encryption key - k_rrc_enc"); + rrc_log->debug_hex(k_rrc_int, 32, "RRC integrity key - k_rrc_int"); + rrc_log->debug_hex(k_up_enc, 32, "UP encryption key - k_up_enc"); + + // Configure PDCP for security pdcp->config_security(lcid, k_rrc_enc, k_rrc_int, cipher_algo, integ_algo); + pdcp->enable_integrity(lcid); send_security_mode_complete(lcid, pdu); pdcp->enable_encryption(lcid); break; @@ -1626,6 +1636,8 @@ void rrc::add_srb(LIBLTE_RRC_SRB_TO_ADD_MOD_STRUCT *srb_cnfg) { pdcp->add_bearer(srb_cnfg->srb_id, srslte_pdcp_config_t(true)); // Set PDCP config control flag if(RB_ID_SRB2 == srb_cnfg->srb_id) { pdcp->config_security(srb_cnfg->srb_id, k_rrc_enc, k_rrc_int, cipher_algo, integ_algo); + pdcp->enable_integrity(srb_cnfg->srb_id); + pdcp->enable_encryption(srb_cnfg->srb_id); } // Setup RLC @@ -1692,7 +1704,8 @@ void rrc::add_drb(LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT *drb_cnfg) { } } pdcp->add_bearer(lcid, pdcp_cfg); - // TODO: setup PDCP security (using k_up_enc) + pdcp->config_security(lcid, k_up_enc, k_up_int, cipher_algo, integ_algo); + pdcp->enable_encryption(lcid); // Setup RLC rlc->add_bearer(lcid, srslte_rlc_config_t(&drb_cnfg->rlc_cnfg)); From f3b1bc0e2ddc4f200d913074ea7d80e225021b27 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 2 Dec 2017 12:02:01 +0100 Subject: [PATCH 185/242] Look for multiple cells on each n_id_2 while cancelling the self interference --- srsue/hdr/phy/phch_recv.h | 5 ++ srsue/src/phy/phch_recv.cc | 170 ++++++++++++++++++++----------------- 2 files changed, 99 insertions(+), 76 deletions(-) diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index e6ef981d1..667f0a93c 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -102,6 +102,8 @@ private: bool set_frequency(); bool set_cell(); + static void substract_sync(cf_t *buffer, uint32_t nof_prb, srslte_sync_t *sync_obj); + void cell_search_inc(); void resync_sfn(bool is_connected = false, bool rx_now = false); bool stop_sync(); @@ -175,6 +177,7 @@ private: float rsrp(); float rsrq(); float snr(); + uint32_t frame_st_idx(); void set_rx_gain_offset(float rx_gain_offset); private: srslte::log *log_h; @@ -185,6 +188,7 @@ private: uint32_t current_prb; float rx_gain_offset; float mean_rsrp, mean_rsrq, mean_snr; + uint32_t final_offset; const static int RSRP_MEASURE_NOF_FRAMES = 5; }; @@ -205,6 +209,7 @@ private: const static int DEFAULT_MEASUREMENT_LEN = 10; + cf_t *input_cfo_corrected; cf_t *sf_buffer[SRSLTE_MAX_PORTS]; srslte::log *log_h; srslte_sync_t sync_find; diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 17ac71c54..95931e600 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -549,9 +549,6 @@ void phch_recv::run_thread() phy_state = IDLE; is_in_idle = true; - uint32_t hf_len; - uint32_t fft_sz; - while (running) { if (phy_state != IDLE) { @@ -680,23 +677,9 @@ void phch_recv::run_thread() } workers_pool->start_worker(worker); - // Substract PSS/SSS from current cell before computing intrafrequency - hf_len = SRSLTE_SF_LEN_PRB(cell.nof_prb)/2; - fft_sz = srslte_symbol_sz(cell.nof_prb); - + // Substract PSS/SSS from current cell before computing intra-frequency if ((tti%5) == 0) { - srslte_vec_sc_prod_cfc(ue_sync.strack.pss_filt, 1.0/sqrtf(fft_sz), ue_sync.strack.pss_filt, fft_sz); - srslte_vec_sc_prod_cfc(ue_sync.strack.sss_filt, 1.0/sqrtf(fft_sz), ue_sync.strack.pss_filt, fft_sz); - - srslte_vec_sub_ccc(&buffer[0][hf_len-fft_sz], - ue_sync.strack.pss_filt, - &buffer[0][hf_len-fft_sz], - fft_sz); - - srslte_vec_sub_ccc(&buffer[0][hf_len-2*fft_sz-SRSLTE_CP_LEN(fft_sz, SRSLTE_CP_NORM_LEN)], - ue_sync.strack.sss_filt, - &buffer[0][hf_len-2*fft_sz-SRSLTE_CP_LEN(fft_sz, SRSLTE_CP_NORM_LEN)], - fft_sz); + substract_sync(buffer[0], cell.nof_prb, &ue_sync.strack); } intra_freq_meas.write(tti, buffer[0], SRSLTE_SF_LEN_PRB(cell.nof_prb)); out_of_sync_cnt = 0; @@ -749,7 +732,24 @@ void phch_recv::out_of_sync() { } } +void phch_recv::substract_sync(cf_t *buffer, uint32_t nof_prb, srslte_sync_t *sync_obj) +{ + uint32_t hf_len = SRSLTE_SF_LEN_PRB(nof_prb)/2; + uint32_t fft_sz = srslte_symbol_sz(nof_prb); + + srslte_vec_sc_prod_cfc(sync_obj->pss_filt, 1.0/sqrtf(fft_sz), sync_obj->pss_filt, fft_sz); + srslte_vec_sc_prod_cfc(sync_obj->sss_filt, 1.0/sqrtf(fft_sz), sync_obj->sss_filt, fft_sz); + + srslte_vec_sub_ccc(&buffer[hf_len-fft_sz], + sync_obj->pss_filt, + &buffer[hf_len-fft_sz], + fft_sz); + srslte_vec_sub_ccc(&buffer[hf_len-2*fft_sz-SRSLTE_CP_LEN(fft_sz, SRSLTE_CP_NORM_LEN)], + sync_obj->sss_filt, + &buffer[hf_len-2*fft_sz-SRSLTE_CP_LEN(fft_sz, SRSLTE_CP_NORM_LEN)], + fft_sz); +} @@ -1070,6 +1070,10 @@ float phch_recv::measure::snr() { return mean_snr; } +uint32_t phch_recv::measure::frame_st_idx() { + return final_offset; +} + void phch_recv::measure::set_rx_gain_offset(float rx_gain_offset) { this->rx_gain_offset = rx_gain_offset; } @@ -1097,7 +1101,6 @@ phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *in ret_code ret = IDLE; - Info("INTRA: Here offset=%d\n", offset); offset = offset-sf_len/2; if (offset < 0) { offset += sf_len; @@ -1133,15 +1136,13 @@ phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *in } } - if (found_best) { - Info("INTRA: fine-tuned offset=%d\n", best_test_offset); - } - offset = found_best?best_test_offset:offset; if (offset >= 0 && offset < sf_len*max_sf) { uint32_t nof_sf = (sf_len*max_sf - offset)/sf_len; - Info("INTRA: fine-tuning offset: %d, found_best=%d, rem_sf=%d\n", offset, found_best, nof_sf); + Debug("INTRA: fine-tuning offset: %d, found_best=%d, rem_sf=%d\n", offset, found_best, nof_sf); + + final_offset = offset; for (uint32_t i=0;i= 0) { + // We found the same cell as before, look another N_id_2 + if ((uint32_t) cell_id == found_cell.id) { + sync_res = SRSLTE_SYNC_NOFOUND; + } else { + // We found a new cell ID + found_cell.id = cell_id; + found_cell.nof_ports = 1; // Use port 0 only for measurement + measure_p.set_cell(found_cell); + + // Correct CFO + srslte_cfo_correct(&sync_find.cfo_corr_frame, + input_buffer, + input_cfo_corrected, + -srslte_sync_get_cfo(&sync_find)/sync_find.fft_size); + + switch(measure_p.run_multiple_subframes(input_cfo_corrected, peak_idx, sf_idx, nof_sf)) { + case measure::MEASURE_OK: + cells[nof_cells].pci = found_cell.id; + cells[nof_cells].rsrp = measure_p.rsrp(); + cells[nof_cells].rsrq = measure_p.rsrq(); + cells[nof_cells].offset = measure_p.frame_st_idx(); + nof_cells++; + + // Substract interference from input buffer (for the next cell) + substract_sync(&input_buffer[measure_p.frame_st_idx()], cell.nof_prb, &sync_find); + + Info("INTRA: Found neighbour cell: pci=%d, rsrp=%.1f dBm, peak_idx=%d, n_id_2=%d, cfo=%.1f Hz\n", + cell_id, measure_p.rsrq(), peak_idx, n_id_2, 15000*srslte_sync_get_cfo(&sync_find)); + + break; + case measure::ERROR: + Error("Measuring neighbour cell\n"); + return SRSLTE_ERROR; + default: + break; + } + } + } else { + sync_res = SRSLTE_SYNC_NOFOUND; } - } - break; - case SRSLTE_SYNC_FOUND_NOSPACE: - /* If a peak was found but there is not enough space for SSS/CP detection, discard a few samples */ - break; - default: - break; - } + break; + case SRSLTE_SYNC_FOUND_NOSPACE: + /* If a peak was found but there is not enough space for SSS/CP detection, discard a few samples */ + break; + default: + break; + } + } while(sync_res == SRSLTE_SYNC_FOUND); } } return nof_cells; From aa41237961bbfa06a2d7ea7e5dcea9ff7cafd2af Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 2 Dec 2017 18:37:20 +0100 Subject: [PATCH 186/242] Fix adaptive UL retx. Fixes #99 --- srsue/hdr/mac/ul_harq.h | 82 ++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 42 deletions(-) diff --git a/srsue/hdr/mac/ul_harq.h b/srsue/hdr/mac/ul_harq.h index 72b691c00..d162d35a2 100644 --- a/srsue/hdr/mac/ul_harq.h +++ b/srsue/hdr/mac/ul_harq.h @@ -205,14 +205,16 @@ private: *ack = false; } } - set_harq_feedback(*ack); + harq_feedback = *ack; } - uint32_t max_retx; - if (is_msg3) { - max_retx = harq_entity->params->max_harq_msg3_tx; - } else { - max_retx = harq_entity->params->max_harq_tx; + // Reset HARQ process if TB has changed + if (harq_feedback && has_grant() && grant) { + if (grant->n_bytes[0] != cur_grant.n_bytes[0] && cur_grant.n_bytes[0] > 0) { + Debug("UL %d: Reset due to change of grant size last_grant=%d, new_grant=%d\n", + pid, cur_grant.n_bytes[0], grant->n_bytes[0]); + reset(); + } } // Receive and route HARQ feedbacks @@ -222,6 +224,7 @@ private: grant->is_from_rar) { // New transmission + reset(); // Uplink grant in a RAR if (grant->is_from_rar) { @@ -245,25 +248,13 @@ private: } } else if (has_grant()) { // Adaptive Re-TX - if (current_tx_nb >= max_retx) { - Info("UL %d: Maximum number of ReTX reached (%d). Discarting TB.\n", pid, max_retx); - reset(); - action->expect_ack = false; - } else { - generate_retx(tti_tx, grant, action); - } + generate_retx(tti_tx, grant, action); } else { Warning("UL %d: Received retransmission but no previous grant available for this PID.\n", pid); } } else if (has_grant()) { // Non-Adaptive Re-Tx - if (current_tx_nb >= max_retx) { - Info("UL %d: Maximum number of ReTX reached (%d). Discarting TB.\n", pid, max_retx); - reset(); - action->expect_ack = false; - } else { - generate_retx(tti_tx, action); - } + generate_retx(tti_tx, action); } if (harq_entity->pcap && grant) { if (grant->is_from_rar) { @@ -273,18 +264,6 @@ private: } } - void set_harq_feedback(bool ack) - { - harq_feedback = ack; - // UL packet successfully delivered - if (ack) { - Info("UL %d: HARQ = ACK for UL transmission. Discarting TB.\n", pid); - reset(); - } else { - Info("UL %d: HARQ = NACK for UL transmission\n", pid); - } - } - uint32_t get_rv() { int rv_of_irv[4] = {0, 2, 3, 1}; @@ -326,24 +305,43 @@ private: void generate_retx(uint32_t tti_tx, Tgrant *grant, Taction *action) { + uint32_t max_retx; + if (is_msg3) { + max_retx = harq_entity->params->max_harq_msg3_tx; + } else { + max_retx = harq_entity->params->max_harq_tx; + } + + if (current_tx_nb >= max_retx) { + Info("UL %d: Maximum number of ReTX reached (%d). Discarting TB.\n", pid, max_retx); + reset(); + action->expect_ack = false; + return; + } + int irv_of_rv[4] = {0, 3, 1, 2}; + + // HARQ entity requests an adaptive transmission if (grant) { - // HARQ entity requests an adaptive transmission if (grant->rv) { current_irv = irv_of_rv[grant->rv[0]%4]; } + memcpy(&cur_grant, grant, sizeof(Tgrant)); harq_feedback = false; - Info("UL %d: Adaptive retx=%d, RV=%d, TBS=%d\n", - pid, current_tx_nb, get_rv(), grant->n_bytes[0]); + + Info("UL %d: Adaptive retx=%d, RV=%d, TBS=%d, HI=%s\n", + pid, current_tx_nb, get_rv(), grant->n_bytes[0], harq_feedback?"ACK":"NACK"); + + generate_tx(tti_tx, action); + + // HARQ entity requests a non-adaptive transmission + } else if (!harq_feedback) { + // Non-adaptive retx are only sent if HI=NACK. If HI=ACK but no grant was received do not reset PID + Info("UL %d: Non-Adaptive retx=%d, RV=%d, TBS=%d, HI=%s\n", + pid, current_tx_nb, get_rv(), cur_grant.n_bytes[0], harq_feedback?"ACK":"NACK"); + generate_tx(tti_tx, action); - } else { - Info("UL %d: Non-Adaptive retx=%d, RV=%d, TBS=%d\n", - pid, current_tx_nb, get_rv(), cur_grant.n_bytes[0]); - // HARQ entity requests a non-adaptive transmission - if (!harq_feedback) { - generate_tx(tti_tx, action); - } } // On every Msg3 retransmission, restart mac-ContentionResolutionTimer as defined in Section 5.1.5 From c816be525e6baef55894e1d14e77a5e923758d21 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 2 Dec 2017 20:32:44 +0100 Subject: [PATCH 187/242] Testing Reestablishment --- srsue/hdr/upper/rrc.h | 26 +++- srsue/src/phy/phch_recv.cc | 6 - srsue/src/upper/rrc.cc | 308 ++++++++++++++++++++----------------- 3 files changed, 188 insertions(+), 152 deletions(-) diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index 085bf6b88..55ce12dee 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -139,8 +139,14 @@ private: nas_interface_rrc *nas; usim_interface_rrc *usim; - void send_ul_dcch_msg(byte_buffer_t *pdu = NULL); LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg; + LIBLTE_RRC_UL_CCCH_MSG_STRUCT ul_ccch_msg; + LIBLTE_RRC_DL_CCCH_MSG_STRUCT dl_ccch_msg; + LIBLTE_RRC_DL_DCCH_MSG_STRUCT dl_dcch_msg; + + byte_buffer_t* byte_align_and_pack(byte_buffer_t *pdu = NULL); + void send_ul_ccch_msg(byte_buffer_t *pdu = NULL); + void send_ul_dcch_msg(byte_buffer_t *pdu = NULL); srslte::bit_buffer_t bit_buf; pthread_mutex_t mutex; @@ -152,6 +158,10 @@ private: rrc_args_t args; bool first_stimsi_attempt; + uint16_t ho_src_rnti; + int ho_src_cell_idx; + phy_interface_rrc::phy_cfg_t ho_src_phy_cfg; + mac_interface_rrc::mac_cfg_t ho_src_mac_cfg; bool pending_mob_reconf; LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT mob_reconf; @@ -177,9 +187,6 @@ private: std::map srbs; std::map drbs; - LIBLTE_RRC_DL_CCCH_MSG_STRUCT dl_ccch_msg; - LIBLTE_RRC_DL_DCCH_MSG_STRUCT dl_dcch_msg; - // RRC constants and timers srslte::mac_interface_timers *mac_timers; uint32_t n310_cnt, N310; @@ -204,7 +211,9 @@ private: const static int MAX_KNOWN_CELLS = 64; cell_t known_cells[MAX_KNOWN_CELLS]; cell_t *current_cell; - cell_t* add_new_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp); + + int find_cell_idx(uint32_t earfcn, uint32_t pci); + cell_t* add_new_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp); uint32_t find_best_cell(uint32_t earfcn, srslte_cell_t *cell); typedef enum { @@ -372,13 +381,13 @@ private: // Senders void send_con_request(); - void send_con_restablish_request(); + void send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause, uint16_t crnti); void send_con_restablish_complete(); void send_con_setup_complete(byte_buffer_t *nas_msg); void send_ul_info_transfer(uint32_t lcid, byte_buffer_t *sdu); void send_security_mode_complete(uint32_t lcid, byte_buffer_t *pdu); void send_rrc_con_reconfig_complete(byte_buffer_t *pdu); - void send_rrc_ue_cap_info(uint32_t lcid, byte_buffer_t *pdu); + void send_rrc_ue_cap_info(byte_buffer_t *pdu); // Parsers void parse_dl_ccch(byte_buffer_t *pdu); @@ -386,7 +395,8 @@ private: void parse_dl_info_transfer(uint32_t lcid, byte_buffer_t *pdu); // Helpers - void ho_prepare(); + void ho_failed(); + bool ho_prepare(); void add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp); void rrc_connection_release(); void con_restablish_cell_reselected(); diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 95931e600..cd95f6d98 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -353,12 +353,6 @@ void phch_recv::cell_search_stop() { bool phch_recv::cell_handover(srslte_cell_t cell) { - int offset = intra_freq_meas.get_offset(cell.id); - if (offset < 0) { - log_h->error("Cell HO: Can't find PCI=%d\n", cell.id); - return false; - } - int cnt = 0; while(worker_com->is_any_pending_ack() && cnt < 10) { usleep(1000); diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 2559d3645..99c6894b0 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -159,6 +159,8 @@ void rrc::set_args(rrc_args_t *args) { */ void rrc::run_thread() { + uint32_t failure_test = 0; + while (thread_running) { if (state >= RRC_STATE_IDLE && state < RRC_STATE_CONNECTING) { @@ -263,11 +265,20 @@ void rrc::run_thread() { } break; case RRC_STATE_CONNECTED: + failure_test++; + if (failure_test >= 100) { + mac_interface_rrc::ue_rnti_t ue_rnti; + mac->get_rntis(&ue_rnti); + send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_OTHER_FAILURE, ue_rnti.crnti); + } // Take measurements, cell reselection, etc break; case RRC_STATE_HO_PREPARE: - ho_prepare(); - state = RRC_STATE_HO_PROCESS; + if (ho_prepare()) { + state = RRC_STATE_HO_PROCESS; + } else { + state = RRC_STATE_CONNECTED; + } break; case RRC_STATE_HO_PROCESS: // wait for HO to finish @@ -594,15 +605,13 @@ rrc::cell_t* rrc::add_new_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rs if (earfcn == 0) { return NULL; } - // First check it does not exist already - int j=0; - while(j= 0) { + known_cells[idx].rsrp = rsrp; + return &known_cells[idx]; } + + // if does not exist, find empty slot int i=0; while(i= 0) { + known_cells[idx].rsrp = rsrp; + return; + } + + rrc_log->info("Added neighbour cell earfcn=%d, pci=%d, rsrp=%f\n", earfcn, pci, rsrp); + + srslte_cell_t cell; + cell = current_cell->phy_cell; + cell.id = pci; + add_new_cell(earfcn, cell, rsrp); +} + +int rrc::find_cell_idx(uint32_t earfcn, uint32_t pci) { + for (uint32_t i = 0; i < MAX_KNOWN_CELLS; i++) { + if (earfcn == known_cells[i].earfcn && pci == known_cells[i].phy_cell.id) { + return (int) i; + } + } + return -1; +} + // PHY indicates that has gone through all known EARFCN void rrc::earfcn_end() { rrc_log->info("Finished searching cells in EARFCN set while in state %s\n", rrc_state_text[state]); @@ -635,22 +668,7 @@ void rrc::earfcn_end() { } } -void rrc::add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp) { - for (uint32_t i = 0; i < MAX_KNOWN_CELLS && known_cells[i].earfcn; i++) { - if (earfcn == known_cells[i].earfcn && pci == known_cells[i].phy_cell.id) { - known_cells[i].rsrp = rsrp; - return; - } - } - rrc_log->info("Added neighbour cell earfcn=%d, pci=%d, rsrp=%f\n", earfcn, pci, rsrp); - - srslte_cell_t cell; - cell = current_cell->phy_cell; - cell.id = pci; - add_new_cell(earfcn, cell, rsrp); -} - -// Cell reselction in IDLE Section 5.2.4 of 36.304 +// Cell reselection in IDLE Section 5.2.4 of 36.304 void rrc::cell_reselection_eval(float rsrp, float rsrq) { // Intra-frequency cell-reselection criteria @@ -740,7 +758,9 @@ void rrc::radio_link_failure() { if (state != RRC_STATE_CONNECTED) { state = RRC_STATE_LEAVE_CONNECTED; } else { - send_con_restablish_request(); + mac_interface_rrc::ue_rnti_t uernti; + mac->get_rntis(&uernti); + send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_OTHER_FAILURE, uernti.crnti); } } @@ -779,6 +799,7 @@ void rrc::timer_expired(uint32_t timeout_id) { } } else if (timeout_id == t304) { rrc_log->console("Timer T304 expired: Handover failed\n"); + ho_failed(); // fw to measurement } else if (!measurements.timer_expired(timeout_id)) { rrc_log->error("Timeout from unknown timer id %d\n", timeout_id); @@ -804,7 +825,6 @@ void rrc::timer_expired(uint32_t timeout_id) { void rrc::send_con_request() { rrc_log->debug("Preparing RRC Connection Request\n"); - LIBLTE_RRC_UL_CCCH_MSG_STRUCT ul_ccch_msg; LIBLTE_RRC_S_TMSI_STRUCT s_tmsi; // Prepare ConnectionRequest packet @@ -819,74 +839,63 @@ void rrc::send_con_request() { } ul_ccch_msg.msg.rrc_con_req.cause = LIBLTE_RRC_CON_REQ_EST_CAUSE_MO_SIGNALLING; - liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf); - - // Byte align and pack the message bits for PDCP - if ((bit_buf.N_bits % 8) != 0) { - for (uint32_t i = 0; i < 8 - (bit_buf.N_bits % 8); i++) - bit_buf.msg[bit_buf.N_bits + i] = 0; - bit_buf.N_bits += 8 - (bit_buf.N_bits % 8); - } - byte_buffer_t *pdcp_buf = pool_allocate;; - srslte_bit_pack_vector(bit_buf.msg, pdcp_buf->msg, bit_buf.N_bits); - pdcp_buf->N_bytes = bit_buf.N_bits / 8; - pdcp_buf->set_timestamp(); - - // Set UE contention resolution ID in MAC - uint64_t uecri = 0; - uint8_t *ue_cri_ptr = (uint8_t *) &uecri; - uint32_t nbytes = 6; - for (uint32_t i = 0; i < nbytes; i++) { - ue_cri_ptr[nbytes - i - 1] = pdcp_buf->msg[i]; - } - rrc_log->debug("Setting UE contention resolution ID: %d\n", uecri); - mac->set_contention_id(uecri); + send_ul_ccch_msg(); - rrc_log->info("Sending RRC Connection Request on SRB0\n"); - pdcp->write_sdu(RB_ID_SRB0, pdcp_buf); } /* RRC connection re-establishment procedure (5.3.7) */ -void rrc::send_con_restablish_request() { - - srslte_cell_t cell; - phy->get_current_cell(&cell); - - LIBLTE_RRC_UL_CCCH_MSG_STRUCT ul_ccch_msg; - LIBLTE_RRC_S_TMSI_STRUCT s_tmsi; - +void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause, uint16_t crnti) +{ // Compute shortMAC-I uint8_t varShortMAC[128], varShortMAC_packed[16]; bzero(varShortMAC, 128); bzero(varShortMAC_packed, 16); uint8_t *msg_ptr = varShortMAC; - liblte_rrc_pack_cell_identity_ie(0x1a2d0, &msg_ptr); - liblte_rrc_pack_phys_cell_id_ie(cell.id, &msg_ptr); - mac_interface_rrc::ue_rnti_t ue_rnti; - mac->get_rntis(&ue_rnti); - liblte_rrc_pack_c_rnti_ie(ue_rnti.crnti, &msg_ptr); - srslte_bit_pack_vector(varShortMAC, varShortMAC_packed, msg_ptr - varShortMAC); - uint8_t mac_key[4]; - security_128_eia2(&k_rrc_int[16], - 1, - 1, - 1, - varShortMAC_packed, - 7, - mac_key); + // ASN.1 encode byte-aligned VarShortMAC-Input + liblte_rrc_pack_cell_identity_ie(current_cell->sib1.cell_id, &msg_ptr); + msg_ptr = &varShortMAC[4]; + liblte_rrc_pack_phys_cell_id_ie(phy->get_current_pci(), &msg_ptr); + msg_ptr = &varShortMAC[4+2]; + liblte_rrc_pack_c_rnti_ie(crnti, &msg_ptr); + srslte_bit_pack_vector(varShortMAC, varShortMAC_packed, (4+2+4)*8); - mac_interface_rrc::ue_rnti_t uernti; - mac->get_rntis(&uernti); + rrc_log->info("Generated varShortMAC: cellId=0x%x, PCI=%d, rnti=%d\n", + current_cell->sib1.cell_id, phy->get_current_pci(), crnti); + + // Compute MAC-I + uint8_t mac_key[4]; + switch(integ_algo) { + case INTEGRITY_ALGORITHM_ID_128_EIA1: + security_128_eia1(&k_rrc_int[16], + 1, + 1, + 1, + varShortMAC_packed, + 10, + mac_key); + break; + case INTEGRITY_ALGORITHM_ID_128_EIA2: + security_128_eia2(&k_rrc_int[16], + 1, + 1, + 1, + varShortMAC_packed, + 10, + mac_key); + break; + default: + rrc_log->info("Unsupported integrity algorithm during reestablishment\n"); + return; + } // Prepare ConnectionRestalishmentRequest packet ul_ccch_msg.msg_type = LIBLTE_RRC_UL_CCCH_MSG_TYPE_RRC_CON_REEST_REQ; - ul_ccch_msg.msg.rrc_con_reest_req.ue_id.c_rnti = uernti.crnti; - ul_ccch_msg.msg.rrc_con_reest_req.ue_id.phys_cell_id = cell.id; - ul_ccch_msg.msg.rrc_con_reest_req.ue_id.short_mac_i = mac_key[2] << 8 | mac_key[3]; - 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); + ul_ccch_msg.msg.rrc_con_reest_req.ue_id.c_rnti = crnti; + ul_ccch_msg.msg.rrc_con_reest_req.ue_id.phys_cell_id = phy->get_current_pci(); + ul_ccch_msg.msg.rrc_con_reest_req.ue_id.short_mac_i = mac_key[1] << 8 | mac_key[0]; + ul_ccch_msg.msg.rrc_con_reest_req.cause = cause; rrc_log->info("Initiating RRC Connection Reestablishment Procedure\n"); rrc_log->console("RRC Connection Reestablishment\n"); @@ -904,33 +913,15 @@ void rrc::send_con_restablish_request() { // Actions following cell reselection 5.3.7.3 void rrc::con_restablish_cell_reselected() { + liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf); + 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(); - // Byte align and pack the message bits for PDCP - if ((bit_buf.N_bits % 8) != 0) { - for (uint32_t i = 0; i < 8 - (bit_buf.N_bits % 8); i++) - bit_buf.msg[bit_buf.N_bits + i] = 0; - bit_buf.N_bits += 8 - (bit_buf.N_bits % 8); - } - byte_buffer_t *pdcp_buf = pool_allocate; - srslte_bit_pack_vector(bit_buf.msg, pdcp_buf->msg, bit_buf.N_bits); - pdcp_buf->N_bytes = bit_buf.N_bits / 8; - - // Set UE contention resolution ID in MAC - uint64_t uecri = 0; - uint8_t *ue_cri_ptr = (uint8_t *) &uecri; - uint32_t nbytes = 6; - for (uint32_t i = 0; i < nbytes; i++) { - ue_cri_ptr[nbytes - i - 1] = pdcp_buf->msg[i]; - } - rrc_log->debug("Setting UE contention resolution ID: %d\n", uecri); - mac->set_contention_id(uecri); + send_ul_ccch_msg(); - rrc_log->info("Sending RRC Connection Reestablishment Request on SRB0\n"); - pdcp->write_sdu(RB_ID_SRB0, pdcp_buf); } void rrc::send_con_restablish_complete() { @@ -993,10 +984,16 @@ void rrc::send_rrc_con_reconfig_complete(byte_buffer_t *pdu) { send_ul_dcch_msg(pdu); } -void rrc::ho_prepare() { +bool rrc::ho_prepare() { if (pending_mob_reconf) { rrc_log->info("Processing HO command to target PCell=%d\n", mob_reconf.mob_ctrl_info.target_pci); + int cell_idx = find_cell_idx(phy->get_current_earfcn(), mob_reconf.mob_ctrl_info.target_pci); + if (cell_idx < 0) { + rrc_log->error("Could not find target cell pci=%d\n", mob_reconf.mob_ctrl_info.target_pci); + return false; + } + // Section 5.3.5.4 mac_timers->timer_get(t310)->stop(); mac_timers->timer_get(t304)->set(this, liblte_rrc_t304_num[mob_reconf.mob_ctrl_info.t304]); @@ -1005,6 +1002,19 @@ void rrc::ho_prepare() { rrc_log->warning("Received mobilityControlInfo for inter-frequency handover\n"); } + // Save cell and current configuration + ho_src_cell_idx = find_cell_idx(phy->get_current_earfcn(), phy->get_current_pci()); + if (ho_src_cell_idx < 0) { + rrc_log->error("Source cell not found in known cells. Reconnecting to cell 0 in case of failure\n"); + ho_src_cell_idx = 0; + } + phy->get_config(&ho_src_phy_cfg); + mac->get_config(&ho_src_mac_cfg); + mac_interface_rrc::ue_rnti_t uernti; + mac->get_rntis(&uernti); + ho_src_rnti = uernti.crnti; + + // Reset/Reestablish stack phy->meas_reset(); mac->wait_uplink(); pdcp->reestablish(); @@ -1014,21 +1024,10 @@ void rrc::ho_prepare() { mac->set_ho_rnti(mob_reconf.mob_ctrl_info.new_ue_id, mob_reconf.mob_ctrl_info.target_pci); apply_rr_config_common_dl(&mob_reconf.mob_ctrl_info.rr_cnfg_common); - bool found = false; - for (uint32_t i = 0; i < MAX_KNOWN_CELLS && known_cells[i].earfcn; i++) { - if (known_cells[i].earfcn == phy->get_current_earfcn() && - known_cells[i].phy_cell.id == mob_reconf.mob_ctrl_info.target_pci) { - rrc_log->info("Selecting new cell pci=%d\n", known_cells[i].phy_cell.id); - if (!phy->cell_handover(known_cells[i].phy_cell)) { - rrc_log->error("Could not synchronize with target cell pci=%d\n", known_cells[i].phy_cell.id); - } - found = true; - break; - } - } - if (!found) { - rrc_log->error("Could not find target cell pci=%d\n", mob_reconf.mob_ctrl_info.target_pci); - return; + rrc_log->info("Selecting new cell pci=%d\n", known_cells[cell_idx].phy_cell.id); + if (!phy->cell_handover(known_cells[cell_idx].phy_cell)) { + rrc_log->error("Could not synchronize with target cell pci=%d\n", known_cells[cell_idx].phy_cell.id); + return false; } if (mob_reconf.mob_ctrl_info.rach_cnfg_ded_present) { @@ -1049,6 +1048,7 @@ void rrc::ho_prepare() { pdcp->config_security(1, k_rrc_enc, k_rrc_int, cipher_algo, integ_algo); send_rrc_con_reconfig_complete(NULL); } + return true; } void rrc::ho_ra_completed(bool ra_successful) { @@ -1079,6 +1079,23 @@ void rrc::ho_ra_completed(bool ra_successful) { } } +// This is T304 expiry 5.3.5.6 +void rrc::ho_failed() { + + // Instruct PHY to resync with source PCI + if (!phy->cell_handover(known_cells[ho_src_cell_idx].phy_cell)) { + rrc_log->error("Could not synchronize with target cell pci=%d\n", known_cells[ho_src_cell_idx].phy_cell.id); + return; + } + + // Set previous PHY/MAC configuration + phy->set_config(&ho_src_phy_cfg); + mac->set_config(&ho_src_mac_cfg); + + // Start the Reestablishment Procedure + send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_HANDOVER_FAILURE, ho_src_rnti); +} + void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig, byte_buffer_t *pdu) { uint32_t i; @@ -1347,18 +1364,16 @@ void rrc::write_pdu_pcch(byte_buffer_t *pdu) { * Packet processing * * -* *******************************************************************************/ -void rrc::send_ul_dcch_msg(byte_buffer_t *pdu) +byte_buffer_t* rrc::byte_align_and_pack(byte_buffer_t *pdu) { - liblte_rrc_pack_ul_dcch_msg(&ul_dcch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf); - // Byte align and pack the message bits for PDCP if ((bit_buf.N_bits % 8) != 0) { for (uint32_t i = 0; i < 8 - (bit_buf.N_bits % 8); i++) bit_buf.msg[bit_buf.N_bits + i] = 0; bit_buf.N_bits += 8 - (bit_buf.N_bits % 8); } + // Reset and reuse sdu buffer if provided byte_buffer_t *pdcp_buf = pdu; @@ -1372,8 +1387,37 @@ void rrc::send_ul_dcch_msg(byte_buffer_t *pdu) pdcp_buf->N_bytes = bit_buf.N_bits / 8; pdcp_buf->set_timestamp(); + return pdcp_buf; +} + +void rrc::send_ul_ccch_msg(byte_buffer_t *pdu) +{ + liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf); + pdu = byte_align_and_pack(pdu); + + // Set UE contention resolution ID in MAC + uint64_t uecri = 0; + uint8_t *ue_cri_ptr = (uint8_t *) &uecri; + uint32_t nbytes = 6; + for (uint32_t i = 0; i < nbytes; i++) { + ue_cri_ptr[nbytes - i - 1] = pdu->msg[i]; + } + + rrc_log->debug("Setting UE contention resolution ID: %d\n", uecri); + mac->set_contention_id(uecri); + + rrc_log->info("Sending %s\n", liblte_rrc_ul_ccch_msg_type_text[ul_ccch_msg.msg_type]); + pdcp->write_sdu(RB_ID_SRB0, pdu); +} + +void rrc::send_ul_dcch_msg(byte_buffer_t *pdu) +{ + liblte_rrc_pack_ul_dcch_msg(&ul_dcch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf); + + pdu = byte_align_and_pack(pdu); + rrc_log->info("Sending %s\n", liblte_rrc_ul_dcch_msg_type_text[ul_dcch_msg.msg_type]); - pdcp->write_sdu(RB_ID_SRB1, pdcp_buf); + pdcp->write_sdu(RB_ID_SRB1, pdu); } void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) { @@ -1489,7 +1533,7 @@ void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu) { transaction_id = dl_dcch_msg.msg.ue_cap_enquiry.rrc_transaction_id; for (uint32_t i = 0; i < dl_dcch_msg.msg.ue_cap_enquiry.N_ue_cap_reqs; i++) { if (LIBLTE_RRC_RAT_TYPE_EUTRA == dl_dcch_msg.msg.ue_cap_enquiry.ue_capability_request[i]) { - send_rrc_ue_cap_info(lcid, pdu); + send_rrc_ue_cap_info(pdu); break; } } @@ -1525,9 +1569,8 @@ void rrc::enable_capabilities() { phy->set_config_64qam_en(enable_ul_64); } -void rrc::send_rrc_ue_cap_info(uint32_t lcid, byte_buffer_t *pdu) { +void rrc::send_rrc_ue_cap_info(byte_buffer_t *pdu) { rrc_log->debug("Preparing UE Capability Info\n"); - LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg; ul_dcch_msg.msg_type = LIBLTE_RRC_UL_DCCH_MSG_TYPE_UE_CAPABILITY_INFO; ul_dcch_msg.msg.ue_capability_info.rrc_transaction_id = transaction_id; @@ -1575,18 +1618,7 @@ void rrc::send_rrc_ue_cap_info(uint32_t lcid, byte_buffer_t *pdu) { liblte_rrc_pack_ul_dcch_msg(&ul_dcch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf); - // Byte align and pack the message bits for PDCP - if ((bit_buf.N_bits % 8) != 0) { - for (uint32_t i = 0; i < 8 - (bit_buf.N_bits % 8); i++) - bit_buf.msg[bit_buf.N_bits + i] = 0; - bit_buf.N_bits += 8 - (bit_buf.N_bits % 8); - } - srslte_bit_pack_vector(bit_buf.msg, pdu->msg, bit_buf.N_bits); - pdu->N_bytes = bit_buf.N_bits / 8; - pdu->set_timestamp(); - - rrc_log->info("Sending UE Capability Info\n"); - pdcp->write_sdu(lcid, pdu); + send_ul_dcch_msg(pdu); } From 997a22a1c6605ed2e33029884436ee0d6027b6c6 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 2 Dec 2017 20:53:09 +0100 Subject: [PATCH 188/242] Disabled test Restablishment --- srsue/src/upper/rrc.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 6c92a1bda..813ebec91 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -265,12 +265,13 @@ void rrc::run_thread() { } break; case RRC_STATE_CONNECTED: + /* failure_test++; if (failure_test >= 100) { mac_interface_rrc::ue_rnti_t ue_rnti; mac->get_rntis(&ue_rnti); send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_OTHER_FAILURE, ue_rnti.crnti); - } + }*/ // Take measurements, cell reselection, etc break; case RRC_STATE_HO_PREPARE: @@ -2015,7 +2016,7 @@ void rrc::handle_con_setup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *setup) { void rrc::handle_con_reest(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT *setup) { mac_timers->timer_get(t301)->stop(); - // TODO: Restablish DRB1. Not done because never was suspended + // TODO: Reestablish DRB1. Not done because never was suspended // Apply the Radio Resource configuration apply_rr_config_dedicated(&setup->rr_cnfg); From 5c31800ccb3c1c149f90404346f3970625476fe0 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 2 Dec 2017 22:43:35 +0100 Subject: [PATCH 189/242] Fixed HO with ciphering --- lib/include/srslte/interfaces/ue_interfaces.h | 5 +- lib/include/srslte/upper/pdcp.h | 4 + lib/include/srslte/upper/rlc.h | 1 - lib/src/upper/pdcp.cc | 12 ++ lib/src/upper/pdcp_entity.cc | 1 + lib/src/upper/rlc.cc | 5 - srsue/hdr/upper/rrc.h | 24 --- srsue/src/phy/phch_recv.cc | 146 +++++++++--------- srsue/src/upper/rrc.cc | 23 ++- 9 files changed, 111 insertions(+), 110 deletions(-) diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index f99f10c9a..540ccb715 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -191,7 +191,6 @@ class rrc_interface_rlc { public: virtual void max_retx_attempted() = 0; - virtual std::string get_rb_name(uint32_t lcid) = 0; }; // PDCP interface for GW @@ -215,6 +214,10 @@ public: uint8_t *k_int_, srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0; + virtual void config_security_all(uint8_t *k_enc_, + uint8_t *k_int_, + srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, + srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0; virtual void enable_integrity(uint32_t lcid) = 0; virtual void enable_encryption(uint32_t lcid) = 0; }; diff --git a/lib/include/srslte/upper/pdcp.h b/lib/include/srslte/upper/pdcp.h index e6483809d..584b231a3 100644 --- a/lib/include/srslte/upper/pdcp.h +++ b/lib/include/srslte/upper/pdcp.h @@ -63,6 +63,10 @@ public: uint8_t *k_int, CIPHERING_ALGORITHM_ID_ENUM cipher_algo, INTEGRITY_ALGORITHM_ID_ENUM integ_algo); + void config_security_all(uint8_t *k_enc, + uint8_t *k_int, + CIPHERING_ALGORITHM_ID_ENUM cipher_algo, + INTEGRITY_ALGORITHM_ID_ENUM integ_algo); void enable_integrity(uint32_t lcid); void enable_encryption(uint32_t lcid); diff --git a/lib/include/srslte/upper/rlc.h b/lib/include/srslte/upper/rlc.h index 8e40f7b6e..17f6bd82c 100644 --- a/lib/include/srslte/upper/rlc.h +++ b/lib/include/srslte/upper/rlc.h @@ -66,7 +66,6 @@ public: void write_sdu(uint32_t lcid, byte_buffer_t *sdu); bool rb_is_um(uint32_t lcid); - std::string get_rb_name(uint32_t lcid); // MAC interface uint32_t get_buffer_state(uint32_t lcid); diff --git a/lib/src/upper/pdcp.cc b/lib/src/upper/pdcp.cc index b3d86dfff..5d3b4d061 100644 --- a/lib/src/upper/pdcp.cc +++ b/lib/src/upper/pdcp.cc @@ -116,6 +116,18 @@ void pdcp::config_security(uint32_t lcid, pdcp_array[lcid].config_security(k_enc, k_int, cipher_algo, integ_algo); } +void pdcp::config_security_all(uint8_t *k_enc, + uint8_t *k_int, + CIPHERING_ALGORITHM_ID_ENUM cipher_algo, + INTEGRITY_ALGORITHM_ID_ENUM integ_algo) +{ + for(uint32_t i=0;irb_is_um(lcid)) { tx_count = 0; + rx_count = 0; } } } diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index baf3c6247..16319c268 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -135,11 +135,6 @@ bool rlc::rb_is_um(uint32_t lcid) { return rlc_array[lcid].get_mode()==RLC_MODE_UM; } -std::string rlc::get_rb_name(uint32_t lcid) -{ - return rrc->get_rb_name(lcid); -} - /******************************************************************************* MAC interface *******************************************************************************/ diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index 5499290e8..b5df0900a 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -238,30 +238,6 @@ private: bool thread_running; void run_thread(); - // Radio bearers - typedef enum{ - RB_ID_SRB0 = 0, - RB_ID_SRB1, - RB_ID_SRB2, - RB_ID_DRB1, - RB_ID_DRB2, - RB_ID_DRB3, - RB_ID_DRB4, - RB_ID_DRB5, - RB_ID_DRB6, - RB_ID_DRB7, - RB_ID_DRB8, - RB_ID_MAX - } rb_id_t; - - std::string get_rb_name(uint32_t lcid) { - if (lcid < RB_ID_MAX) { - return rb_id_str[lcid]; - } else { - return std::string("INVALID_RB"); - } - } - // Measurements sub-class class rrc_meas { public: diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index cd95f6d98..7a78fc11c 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -672,9 +672,9 @@ void phch_recv::run_thread() workers_pool->start_worker(worker); // Substract PSS/SSS from current cell before computing intra-frequency - if ((tti%5) == 0) { + /*if ((tti%5) == 0) { substract_sync(buffer[0], cell.nof_prb, &ue_sync.strack); - } + }*/ intra_freq_meas.write(tti, buffer[0], SRSLTE_SF_LEN_PRB(cell.nof_prb)); out_of_sync_cnt = 0; break; @@ -1164,7 +1164,7 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx) float snr = 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest)); if (cnt == 0) { - mean_rsrp = rsrp; + mean_rsrp = rsrp; mean_rsrq = rsrq; mean_snr = snr; } else { @@ -1175,7 +1175,7 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx) } cnt++; - log_h->info("SYNC: Measuring RSRP %d/%d, sf_idx=%d, RSRP=%.1f dBm, SNR=%.1f dB\n", + log_h->debug("SYNC: Measuring RSRP %d/%d, sf_idx=%d, RSRP=%.1f dBm, SNR=%.1f dB\n", cnt, nof_subframes, sf_idx, rsrp, snr); if (cnt >= nof_subframes) { @@ -1259,76 +1259,76 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, for (uint32_t n_id_2=0;n_id_2<3;n_id_2++) { - if (cell.id%3 != n_id_2) { - srslte_sync_set_N_id_2(&sync_find, n_id_2); - - srslte_sync_find_ret_t sync_res; - do { - - srslte_sync_reset(&sync_find); - srslte_sync_cfo_reset(&sync_find); - - sync_res = srslte_sync_find(&sync_find, input_buffer, 0, &peak_idx); - - switch(sync_res) { - case SRSLTE_SYNC_ERROR: - return SRSLTE_ERROR; - fprintf(stderr, "Error finding correlation peak\n"); - return SRSLTE_ERROR; - case SRSLTE_SYNC_FOUND: - sf_idx = srslte_sync_get_sf_idx(&sync_find); - cell_id = srslte_sync_get_cell_id(&sync_find); - - if (cell_id >= 0) { - // We found the same cell as before, look another N_id_2 - if ((uint32_t) cell_id == found_cell.id) { - sync_res = SRSLTE_SYNC_NOFOUND; - } else { - // We found a new cell ID - found_cell.id = cell_id; - found_cell.nof_ports = 1; // Use port 0 only for measurement - measure_p.set_cell(found_cell); - - // Correct CFO - srslte_cfo_correct(&sync_find.cfo_corr_frame, - input_buffer, - input_cfo_corrected, - -srslte_sync_get_cfo(&sync_find)/sync_find.fft_size); - - switch(measure_p.run_multiple_subframes(input_cfo_corrected, peak_idx, sf_idx, nof_sf)) { - case measure::MEASURE_OK: - cells[nof_cells].pci = found_cell.id; - cells[nof_cells].rsrp = measure_p.rsrp(); - cells[nof_cells].rsrq = measure_p.rsrq(); - cells[nof_cells].offset = measure_p.frame_st_idx(); - nof_cells++; - - // Substract interference from input buffer (for the next cell) - substract_sync(&input_buffer[measure_p.frame_st_idx()], cell.nof_prb, &sync_find); - - Info("INTRA: Found neighbour cell: pci=%d, rsrp=%.1f dBm, peak_idx=%d, n_id_2=%d, cfo=%.1f Hz\n", - cell_id, measure_p.rsrq(), peak_idx, n_id_2, 15000*srslte_sync_get_cfo(&sync_find)); - - break; - case measure::ERROR: - Error("Measuring neighbour cell\n"); - return SRSLTE_ERROR; - default: - break; - } - } - } else { + srslte_sync_set_N_id_2(&sync_find, n_id_2); + + srslte_sync_find_ret_t sync_res; + //do { + + srslte_sync_reset(&sync_find); + srslte_sync_cfo_reset(&sync_find); + + sync_res = srslte_sync_find(&sync_find, input_buffer, 0, &peak_idx); + + switch(sync_res) { + case SRSLTE_SYNC_ERROR: + return SRSLTE_ERROR; + fprintf(stderr, "Error finding correlation peak\n"); + return SRSLTE_ERROR; + case SRSLTE_SYNC_FOUND: + sf_idx = srslte_sync_get_sf_idx(&sync_find); + cell_id = srslte_sync_get_cell_id(&sync_find); + + if (cell_id >= 0) { + // We found the same cell as before, look another N_id_2 + if ((uint32_t) cell_id == found_cell.id || (uint32_t) cell_id == cell.id) { sync_res = SRSLTE_SYNC_NOFOUND; + } else { + // We found a new cell ID + found_cell.id = cell_id; + found_cell.nof_ports = 1; // Use port 0 only for measurement + measure_p.set_cell(found_cell); + + // Correct CFO + /* + srslte_cfo_correct(&sync_find.cfo_corr_frame, + input_buffer, + input_cfo_corrected, + -srslte_sync_get_cfo(&sync_find)/sync_find.fft_size); + */ + + switch(measure_p.run_multiple_subframes(input_buffer, peak_idx, sf_idx, nof_sf)) { + case measure::MEASURE_OK: + cells[nof_cells].pci = found_cell.id; + cells[nof_cells].rsrp = measure_p.rsrp(); + cells[nof_cells].rsrq = measure_p.rsrq(); + cells[nof_cells].offset = measure_p.frame_st_idx(); + nof_cells++; + + // Substract interference from input buffer (for the next cell) + //substract_sync(&input_buffer[measure_p.frame_st_idx()], cell.nof_prb, &sync_find); + + Info("INTRA: Found neighbour cell: PCI=%03d, RSRP=%5.1f dBm, peak_idx=%5d, peak_value=%3.2f n_id_2=%d, CFO=%6.1f Hz\n", + cell_id, measure_p.rsrp(), measure_p.frame_st_idx(), sync_find.peak_value, n_id_2, 15000*srslte_sync_get_cfo(&sync_find)); + + break; + case measure::ERROR: + Error("Measuring neighbour cell\n"); + return SRSLTE_ERROR; + default: + break; + } } - break; - case SRSLTE_SYNC_FOUND_NOSPACE: - /* If a peak was found but there is not enough space for SSS/CP detection, discard a few samples */ - break; - default: - break; - } - } while(sync_res == SRSLTE_SYNC_FOUND); - } + } else { + sync_res = SRSLTE_SYNC_NOFOUND; + } + break; + case SRSLTE_SYNC_FOUND_NOSPACE: + /* If a peak was found but there is not enough space for SSS/CP detection, discard a few samples */ + break; + default: + break; + } + //} while(sync_res == SRSLTE_SYNC_FOUND); } return nof_cells; } @@ -1476,8 +1476,6 @@ void phch_recv::intra_measure::run_thread() } if (running) { - Info("INTRA: Running intra-frequency measurements\n"); - // Read 15 ms data from buffer srslte_ringbuffer_read(&ring_buffer, search_buffer, CAPTURE_LEN_SF*current_sflen*sizeof(cf_t)); int found_cells = scell.find_cells(search_buffer, common->rx_gain_offset, primary_cell, CAPTURE_LEN_SF, info); diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 813ebec91..346a04ac0 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -30,6 +30,7 @@ #include #include #include +#include #include "upper/rrc.h" #include "srslte/asn1/liblte_rrc.h" #include "srslte/common/security.h" @@ -1041,12 +1042,24 @@ bool rrc::ho_prepare() { int ncc = -1; if (mob_reconf.sec_cnfg_ho_present) { ncc = mob_reconf.sec_cnfg_ho.intra_lte.next_hop_chaining_count; + if (mob_reconf.sec_cnfg_ho.intra_lte.key_change_ind) { + rrc_log->console("keyChangeIndicator in securityConfigHO not supported\n"); + return false; + } + if (mob_reconf.sec_cnfg_ho.intra_lte.sec_alg_cnfg_present) { + cipher_algo = (CIPHERING_ALGORITHM_ID_ENUM) mob_reconf.sec_cnfg_ho.intra_lte.sec_alg_cnfg.cipher_alg; + integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM) mob_reconf.sec_cnfg_ho.intra_lte.sec_alg_cnfg.int_alg; + rrc_log->console("Warning changed Cipering to %s and Integrity to %s\n", + ciphering_algorithm_id_text[cipher_algo], + integrity_algorithm_id_text[integ_algo]); + } } usim->generate_as_keys_ho(mob_reconf.mob_ctrl_info.target_pci, phy->get_current_earfcn(), ncc, k_rrc_enc, k_rrc_int, k_up_enc, k_up_int, cipher_algo, integ_algo); - pdcp->config_security(1, k_rrc_enc, k_rrc_int, cipher_algo, integ_algo); + + pdcp->config_security_all(k_rrc_enc, k_rrc_int, cipher_algo, integ_algo); send_rrc_con_reconfig_complete(NULL); } return true; @@ -1423,7 +1436,7 @@ void rrc::send_ul_dcch_msg(byte_buffer_t *pdu) void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) { - rrc_log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU", get_rb_name(lcid).c_str()); + rrc_log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU", get_rb_name(lcid)); switch (state) { case RRC_STATE_CONNECTING: send_con_setup_complete(sdu); @@ -1438,7 +1451,7 @@ void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) { } void rrc::write_pdu(uint32_t lcid, byte_buffer_t *pdu) { - rrc_log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU", get_rb_name(lcid).c_str()); + rrc_log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU", get_rb_name(lcid)); switch (lcid) { case RB_ID_SRB0: @@ -1528,8 +1541,8 @@ void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu) { nas->get_k_asme(k_asme, 32); usim->generate_as_keys(k_asme, nas->get_ul_count()-1, k_rrc_enc, k_rrc_int, k_up_enc, k_up_int, cipher_algo, integ_algo); rrc_log->debug_hex(k_rrc_enc, 32, "RRC encryption key - k_rrc_enc"); - rrc_log->debug_hex(k_rrc_int, 32, "RRC integrity key - k_rrc_int"); - rrc_log->debug_hex(k_up_enc, 32, "UP encryption key - k_up_enc"); + rrc_log->debug_hex(k_rrc_int, 32, "RRC integrity key - k_rrc_int"); + rrc_log->debug_hex(k_up_enc, 32, "UP encryption key - k_up_enc"); // Configure PDCP for security pdcp->config_security(lcid, k_rrc_enc, k_rrc_int, cipher_algo, integ_algo); From cfb059f0c2d8657757e834b1ceba6f3b05745d72 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 2 Dec 2017 22:52:17 +0100 Subject: [PATCH 190/242] Restart rx_counter for SRB in PDCP when restablishing --- lib/src/upper/pdcp_entity.cc | 1 + srsue/src/upper/rrc.cc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/upper/pdcp_entity.cc b/lib/src/upper/pdcp_entity.cc index ceb89a0bb..b4cc5b9d5 100644 --- a/lib/src/upper/pdcp_entity.cc +++ b/lib/src/upper/pdcp_entity.cc @@ -81,6 +81,7 @@ void pdcp_entity::reestablish() { // For SRBs if (cfg.is_control) { tx_count = 0; + rx_count = 0; } else { if (rlc->rb_is_um(lcid)) { tx_count = 0; diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 346a04ac0..461a4f9ee 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -514,7 +514,7 @@ void rrc::select_next_cell_in_plmn() { } void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, uint32_t earfcn, uint32_t pci) { - if (state == RRC_STATE_CONNECTED) { + if (state != RRC_STATE_IDLE) { measurements.new_phy_meas(earfcn, pci, rsrp, rsrq, tti); } else { // If measurement is of the serving cell, evaluate cell reselection criteria From 324ba02481050a4f36479d50725ff4d346908d6c Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Sun, 3 Dec 2017 18:16:05 +0000 Subject: [PATCH 191/242] Fix for PDCP EEA1 --- lib/src/upper/pdcp_entity.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/src/upper/pdcp_entity.cc b/lib/src/upper/pdcp_entity.cc index 0ac426a6e..731245e4f 100644 --- a/lib/src/upper/pdcp_entity.cc +++ b/lib/src/upper/pdcp_entity.cc @@ -301,6 +301,7 @@ void pdcp_entity::cipher_decrypt(uint8_t *ct, ct, ct_len, msg_tmp.msg); + memcpy(msg, msg_tmp.msg, ct_len); break; case CIPHERING_ALGORITHM_ID_128_EEA2: security_128_eea2(&(k_enc[16]), @@ -311,9 +312,9 @@ void pdcp_entity::cipher_decrypt(uint8_t *ct, ct_len, msg_tmp.msg); memcpy(msg, msg_tmp.msg, ct_len); - break; - default: - break; + break; + default: + break; } } @@ -325,7 +326,8 @@ void pdcp_entity::run_thread() while(running) { rx_pdu_queue.read(&pdu); - log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU", get_rb_name(lcid)); + log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU, do_integrity = %s, do_encryption = %s", + get_rb_name(lcid), (do_integrity) ? "true" : "false", (do_encryption) ? "true" : "false"); // Handle SRB messages switch(lcid) From 48dfc08fa3d84e7d58cc2242511b31fdaeea6dc8 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sun, 3 Dec 2017 22:13:07 -0600 Subject: [PATCH 192/242] Fixed SIC for PSS using channel estimates, added option to disable it (not usable on synchronous same-site cells). Use PSS CE in SSS decoding --- lib/examples/pdsch_ue.c | 2 +- lib/examples/synch_file.c | 28 +-- lib/include/srslte/interfaces/ue_interfaces.h | 1 + lib/include/srslte/phy/sync/pss.h | 44 +++-- lib/include/srslte/phy/sync/sss.h | 28 +-- lib/include/srslte/phy/sync/sync.h | 14 +- lib/src/phy/sync/find_sss.c | 10 +- lib/src/phy/sync/pss.c | 98 ++++++---- lib/src/phy/sync/sss.c | 22 +-- lib/src/phy/sync/sync.c | 72 +++---- lib/src/phy/sync/test/pss_file.c | 42 ++-- lib/src/phy/sync/test/pss_mex.c | 12 +- lib/src/phy/sync/test/pss_usrp.c | 44 ++--- lib/src/phy/sync/test/sss_mex.c | 20 +- lib/src/phy/ue/ue_sync.c | 4 +- srsue/hdr/phy/phch_recv.h | 5 +- srsue/src/mac/proc_ra.cc | 8 +- srsue/src/main.cc | 5 +- srsue/src/phy/phch_recv.cc | 182 +++++++++--------- srsue/src/upper/rrc.cc | 4 +- srsue/ue.conf.example | 5 + 21 files changed, 341 insertions(+), 309 deletions(-) diff --git a/lib/examples/pdsch_ue.c b/lib/examples/pdsch_ue.c index ae43a5260..6293d0e70 100644 --- a/lib/examples/pdsch_ue.c +++ b/lib/examples/pdsch_ue.c @@ -998,7 +998,7 @@ void *plot_thread_run(void *arg) { if (!prog_args.input_file_name) { if (plot_track) { - srslte_pss_synch_t *pss_obj = srslte_sync_get_cur_pss_obj(&ue_sync.strack); + srslte_pss_t *pss_obj = srslte_sync_get_cur_pss_obj(&ue_sync.strack); int max = srslte_vec_max_fi(pss_obj->conv_output_avg, pss_obj->frame_size+pss_obj->fft_size-1); srslte_vec_sc_prod_fff(pss_obj->conv_output_avg, 1/pss_obj->conv_output_avg[max], diff --git a/lib/examples/synch_file.c b/lib/examples/synch_file.c index 178e56e99..4d553bd38 100644 --- a/lib/examples/synch_file.c +++ b/lib/examples/synch_file.c @@ -102,8 +102,8 @@ void parse_args(int argc, char **argv) { int main(int argc, char **argv) { srslte_filesource_t fsrc; srslte_filesink_t fsink; - srslte_pss_synch_t pss[3]; // One for each N_id_2 - srslte_sss_synch_t sss[3]; // One for each N_id_2 + srslte_pss_t pss[3]; // One for each N_id_2 + srslte_sss_t sss[3]; // One for each N_id_2 srslte_cfo_t cfocorr; int peak_pos[3]; float *cfo; @@ -163,19 +163,19 @@ int main(int argc, char **argv) { * a) requries more memory but has less latency and is paralellizable. */ for (N_id_2=0;N_id_2<3;N_id_2++) { - if (srslte_pss_synch_init(&pss[N_id_2], frame_length)) { + if (srslte_pss_init(&pss[N_id_2], frame_length)) { fprintf(stderr, "Error initializing PSS object\n"); exit(-1); } - if (srslte_pss_synch_set_N_id_2(&pss[N_id_2], N_id_2)) { + if (srslte_pss_set_N_id_2(&pss[N_id_2], N_id_2)) { fprintf(stderr, "Error initializing N_id_2\n"); exit(-1); } - if (srslte_sss_synch_init(&sss[N_id_2], 128)) { + if (srslte_sss_init(&sss[N_id_2], 128)) { fprintf(stderr, "Error initializing SSS object\n"); exit(-1); } - if (srslte_sss_synch_set_N_id_2(&sss[N_id_2], N_id_2)) { + if (srslte_sss_set_N_id_2(&sss[N_id_2], N_id_2)) { fprintf(stderr, "Error initializing N_id_2\n"); exit(-1); } @@ -199,10 +199,10 @@ int main(int argc, char **argv) { if (force_N_id_2 != -1) { N_id_2 = force_N_id_2; - peak_pos[N_id_2] = srslte_pss_synch_find_pss(&pss[N_id_2], input, &peak_value[N_id_2]); + peak_pos[N_id_2] = srslte_pss_find_pss(&pss[N_id_2], input, &peak_value[N_id_2]); } else { for (N_id_2=0;N_id_2<3;N_id_2++) { - peak_pos[N_id_2] = srslte_pss_synch_find_pss(&pss[N_id_2], input, &peak_value[N_id_2]); + peak_pos[N_id_2] = srslte_pss_find_pss(&pss[N_id_2], input, &peak_value[N_id_2]); } float max_value=-99999; N_id_2=-1; @@ -220,13 +220,13 @@ int main(int argc, char **argv) { sss_idx = peak_pos[N_id_2]-2*(symbol_sz+SRSLTE_CP_LEN(symbol_sz,SRSLTE_CP_NORM_LEN)); if (sss_idx >= 0) { - srslte_sss_synch_m0m1_diff(&sss[N_id_2], &input[sss_idx], + srslte_sss_m0m1_diff(&sss[N_id_2], &input[sss_idx], &m0, &m0_value, &m1, &m1_value); - cfo[frame_cnt] = srslte_pss_synch_cfo_compute(&pss[N_id_2], &input[peak_pos[N_id_2]-128]); + cfo[frame_cnt] = srslte_pss_cfo_compute(&pss[N_id_2], &input[peak_pos[N_id_2]-128]); printf("\t%d\t%d\t%d\t%d\t%.3f\t\t%3d\t%d\t%d\t%.3f\n", - frame_cnt,N_id_2, srslte_sss_synch_N_id_1(&sss[N_id_2], m0, m1), - srslte_sss_synch_subframe(m0, m1), peak_value[N_id_2], + frame_cnt,N_id_2, srslte_sss_N_id_1(&sss[N_id_2], m0, m1), + srslte_sss_subframe(m0, m1), peak_value[N_id_2], peak_pos[N_id_2], m0, m1, cfo[frame_cnt]); } @@ -254,8 +254,8 @@ int main(int argc, char **argv) { printf("Average CFO: %.3f\n", cfo_mean); for (N_id_2=0;N_id_2<3;N_id_2++) { - srslte_pss_synch_free(&pss[N_id_2]); - srslte_sss_synch_free(&sss[N_id_2]); + srslte_pss_free(&pss[N_id_2]); + srslte_sss_free(&sss[N_id_2]); } srslte_filesource_free(&fsrc); diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index 540ccb715..e8a33c207 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -488,6 +488,7 @@ typedef struct { std::string sss_algorithm; float estimator_fil_w; bool rssi_sensor_enabled; + bool sic_pss_enabled; } phy_args_t; diff --git a/lib/include/srslte/phy/sync/pss.h b/lib/include/srslte/phy/sync/pss.h index aba84f5cd..922bc0286 100644 --- a/lib/include/srslte/phy/sync/pss.h +++ b/lib/include/srslte/phy/sync/pss.h @@ -29,9 +29,9 @@ * * Description: Primary synchronization signal (PSS) generation and detection. * - * The srslte_pss_synch_t object provides functions for fast + * The srslte_pss_t object provides functions for fast * computation of the crosscorrelation between the PSS and received - * signal and CFO estimation. Also, the function srslte_pss_synch_tperiodic() + * signal and CFO estimation. Also, the function srslte_pss_tperiodic() * is designed to be called periodically every subframe, taking * care of the correct data alignment with respect to the PSS sequence. * @@ -61,7 +61,7 @@ /* PSS processing options */ -#define SRSLTE_PSS_ACCUMULATE_ABS // If enabled, accumulates the correlation absolute value on consecutive calls to srslte_pss_synch_find_pss +#define SRSLTE_PSS_ACCUMULATE_ABS // If enabled, accumulates the correlation absolute value on consecutive calls to srslte_pss_find_pss #define SRSLTE_PSS_RETURN_PSR // If enabled returns peak to side-lobe ratio, otherwise returns absolute peak value @@ -85,6 +85,7 @@ typedef struct SRSLTE_API { cf_t *pss_signal_freq_full[3]; cf_t *pss_signal_time[3]; + cf_t *pss_signal_time_scale[3]; cf_t pss_signal_freq[3][SRSLTE_PSS_LEN]; // One sequence for each N_id_2 cf_t *tmp_input; @@ -100,41 +101,48 @@ typedef struct SRSLTE_API { cf_t tmp_fft[SRSLTE_SYMBOL_SZ_MAX]; cf_t tmp_fft2[SRSLTE_SYMBOL_SZ_MAX]; -}srslte_pss_synch_t; + cf_t tmp_ce[SRSLTE_PSS_LEN]; + + bool chest_on_filter; + +}srslte_pss_t; typedef enum { PSS_TX, PSS_RX } pss_direction_t; /* Basic functionality */ -SRSLTE_API int srslte_pss_synch_init_fft(srslte_pss_synch_t *q, +SRSLTE_API int srslte_pss_init_fft(srslte_pss_t *q, uint32_t frame_size, uint32_t fft_size); -SRSLTE_API int srslte_pss_synch_init_fft_offset(srslte_pss_synch_t *q, +SRSLTE_API int srslte_pss_init_fft_offset(srslte_pss_t *q, uint32_t frame_size, uint32_t fft_size, int cfo_i); -SRSLTE_API int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, +SRSLTE_API int srslte_pss_init_fft_offset_decim(srslte_pss_t *q, uint32_t frame_size, uint32_t fft_size, int cfo_i, int decimate); -SRSLTE_API int srslte_pss_synch_resize(srslte_pss_synch_t *q, uint32_t frame_size, +SRSLTE_API int srslte_pss_resize(srslte_pss_t *q, uint32_t frame_size, uint32_t fft_size, int offset); -SRSLTE_API int srslte_pss_synch_init(srslte_pss_synch_t *q, +SRSLTE_API int srslte_pss_init(srslte_pss_t *q, uint32_t frame_size); -SRSLTE_API void srslte_pss_synch_free(srslte_pss_synch_t *q); +SRSLTE_API void srslte_pss_free(srslte_pss_t *q); -SRSLTE_API void srslte_pss_synch_reset(srslte_pss_synch_t *q); +SRSLTE_API void srslte_pss_reset(srslte_pss_t *q); -SRSLTE_API void srslte_pss_synch_filter_enable(srslte_pss_synch_t *q, +SRSLTE_API void srslte_pss_filter_enable(srslte_pss_t *q, bool enable); -SRSLTE_API void srslte_pss_synch_filter(srslte_pss_synch_t *q, +SRSLTE_API void srslte_pss_sic(srslte_pss_t *q, + cf_t *input); + +SRSLTE_API void srslte_pss_filter(srslte_pss_t *q, const cf_t *input, cf_t *output); @@ -151,21 +159,21 @@ SRSLTE_API void srslte_pss_put_slot(cf_t *pss_signal, uint32_t nof_prb, srslte_cp_t cp); -SRSLTE_API void srslte_pss_synch_set_ema_alpha(srslte_pss_synch_t *q, +SRSLTE_API void srslte_pss_set_ema_alpha(srslte_pss_t *q, float alpha); -SRSLTE_API int srslte_pss_synch_set_N_id_2(srslte_pss_synch_t *q, +SRSLTE_API int srslte_pss_set_N_id_2(srslte_pss_t *q, uint32_t N_id_2); -SRSLTE_API int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, +SRSLTE_API int srslte_pss_find_pss(srslte_pss_t *q, const cf_t *input, float *corr_peak_value); -SRSLTE_API int srslte_pss_synch_chest(srslte_pss_synch_t *q, +SRSLTE_API int srslte_pss_chest(srslte_pss_t *q, const cf_t *input, cf_t ce[SRSLTE_PSS_LEN]); -SRSLTE_API float srslte_pss_synch_cfo_compute(srslte_pss_synch_t* q, +SRSLTE_API float srslte_pss_cfo_compute(srslte_pss_t* q, const cf_t *pss_recv); #endif // PSS_ diff --git a/lib/include/srslte/phy/sync/sss.h b/lib/include/srslte/phy/sync/sss.h index 4a0942d61..9f77d1ce6 100644 --- a/lib/include/srslte/phy/sync/sss.h +++ b/lib/include/srslte/phy/sync/sss.h @@ -83,17 +83,17 @@ typedef struct SRSLTE_API { float corr_output_m0[SRSLTE_SSS_N]; float corr_output_m1[SRSLTE_SSS_N]; -}srslte_sss_synch_t; +}srslte_sss_t; /* Basic functionality */ -SRSLTE_API int srslte_sss_synch_init(srslte_sss_synch_t *q, +SRSLTE_API int srslte_sss_init(srslte_sss_t *q, uint32_t fft_size); -SRSLTE_API int srslte_sss_synch_resize(srslte_sss_synch_t *q, +SRSLTE_API int srslte_sss_resize(srslte_sss_t *q, uint32_t fft_size); -SRSLTE_API void srslte_sss_synch_free(srslte_sss_synch_t *q); +SRSLTE_API void srslte_sss_free(srslte_sss_t *q); SRSLTE_API void srslte_sss_generate(float *signal0, float *signal5, @@ -104,10 +104,10 @@ SRSLTE_API void srslte_sss_put_slot(float *sss, uint32_t nof_prb, srslte_cp_t cp); -SRSLTE_API int srslte_sss_synch_set_N_id_2(srslte_sss_synch_t *q, +SRSLTE_API int srslte_sss_set_N_id_2(srslte_sss_t *q, uint32_t N_id_2); -SRSLTE_API int srslte_sss_synch_m0m1_partial(srslte_sss_synch_t *q, +SRSLTE_API int srslte_sss_m0m1_partial(srslte_sss_t *q, const cf_t *input, uint32_t M, cf_t ce[2*SRSLTE_SSS_N], @@ -116,7 +116,7 @@ SRSLTE_API int srslte_sss_synch_m0m1_partial(srslte_sss_synch_t *q, uint32_t *m1, float *m1_value); -SRSLTE_API int srslte_sss_synch_m0m1_diff_coh(srslte_sss_synch_t *q, +SRSLTE_API int srslte_sss_m0m1_diff_coh(srslte_sss_t *q, const cf_t *input, cf_t ce[2*SRSLTE_SSS_N], uint32_t *m0, @@ -124,7 +124,7 @@ SRSLTE_API int srslte_sss_synch_m0m1_diff_coh(srslte_sss_synch_t *q, uint32_t *m1, float *m1_value); -SRSLTE_API int srslte_sss_synch_m0m1_diff(srslte_sss_synch_t *q, +SRSLTE_API int srslte_sss_m0m1_diff(srslte_sss_t *q, const cf_t *input, uint32_t *m0, float *m0_value, @@ -132,25 +132,25 @@ SRSLTE_API int srslte_sss_synch_m0m1_diff(srslte_sss_synch_t *q, float *m1_value); -SRSLTE_API uint32_t srslte_sss_synch_subframe(uint32_t m0, +SRSLTE_API uint32_t srslte_sss_subframe(uint32_t m0, uint32_t m1); -SRSLTE_API int srslte_sss_synch_N_id_1(srslte_sss_synch_t *q, +SRSLTE_API int srslte_sss_N_id_1(srslte_sss_t *q, uint32_t m0, uint32_t m1); -SRSLTE_API int srslte_sss_synch_frame(srslte_sss_synch_t *q, +SRSLTE_API int srslte_sss_frame(srslte_sss_t *q, cf_t *input, uint32_t *subframe_idx, uint32_t *N_id_1); -SRSLTE_API void srslte_sss_synch_set_threshold(srslte_sss_synch_t *q, +SRSLTE_API void srslte_sss_set_threshold(srslte_sss_t *q, float threshold); -SRSLTE_API void srslte_sss_synch_set_symbol_sz(srslte_sss_synch_t *q, +SRSLTE_API void srslte_sss_set_symbol_sz(srslte_sss_t *q, uint32_t symbol_sz); -SRSLTE_API void srslte_sss_synch_set_subframe_sz(srslte_sss_synch_t *q, +SRSLTE_API void srslte_sss_set_subframe_sz(srslte_sss_t *q, uint32_t subframe_sz); #endif // SSS_ diff --git a/lib/include/srslte/phy/sync/sync.h b/lib/include/srslte/phy/sync/sync.h index 151c530b1..3146761ce 100644 --- a/lib/include/srslte/phy/sync/sync.h +++ b/lib/include/srslte/phy/sync/sync.h @@ -60,9 +60,9 @@ typedef enum {SSS_DIFF=0, SSS_PARTIAL_3=2, SSS_FULL=1} sss_alg_t; typedef struct SRSLTE_API { - srslte_pss_synch_t pss; - srslte_pss_synch_t pss_i[2]; - srslte_sss_synch_t sss; + srslte_pss_t pss; + srslte_pss_t pss_i[2]; + srslte_sss_t sss; srslte_cp_synch_t cp_synch; cf_t *cfo_i_corr[2]; int decimate; @@ -110,7 +110,7 @@ typedef struct SRSLTE_API { srslte_cfo_t cfo_corr_frame; srslte_cfo_t cfo_corr_symbol; - bool sss_filtering_enabled; + bool sss_channel_equalize; bool pss_filtering_enabled; cf_t sss_filt[SRSLTE_SYMBOL_SZ_MAX]; cf_t pss_filt[SRSLTE_SYMBOL_SZ_MAX]; @@ -186,8 +186,8 @@ SRSLTE_API int srslte_sync_get_cell_id(srslte_sync_t *q); SRSLTE_API void srslte_sync_set_pss_filt_enable(srslte_sync_t *q, bool enable); -SRSLTE_API void srslte_sync_set_sss_filt_enable(srslte_sync_t *q, - bool enable); +SRSLTE_API void srslte_sync_set_sss_eq_enable(srslte_sync_t *q, + bool enable); /* Gets the CFO estimation from the last call to synch_run() */ SRSLTE_API float srslte_sync_get_cfo(srslte_sync_t *q); @@ -227,7 +227,7 @@ SRSLTE_API void srslte_sync_set_cp(srslte_sync_t *q, SRSLTE_API void srslte_sync_sss_en(srslte_sync_t *q, bool enabled); -SRSLTE_API srslte_pss_synch_t* srslte_sync_get_cur_pss_obj(srslte_sync_t *q); +SRSLTE_API srslte_pss_t* srslte_sync_get_cur_pss_obj(srslte_sync_t *q); SRSLTE_API bool srslte_sync_sss_detected(srslte_sync_t *q); diff --git a/lib/src/phy/sync/find_sss.c b/lib/src/phy/sync/find_sss.c index 70b300bd3..6695d70c2 100644 --- a/lib/src/phy/sync/find_sss.c +++ b/lib/src/phy/sync/find_sss.c @@ -68,7 +68,7 @@ static void corr_all_sz_partial(cf_t z[SRSLTE_SSS_N], float s[SRSLTE_SSS_N][SRSL } } -static void extract_pair_sss(srslte_sss_synch_t *q, const cf_t *input, cf_t *ce, cf_t y[2][SRSLTE_SSS_N]) { +static void extract_pair_sss(srslte_sss_t *q, const cf_t *input, cf_t *ce, cf_t y[2][SRSLTE_SSS_N]) { cf_t input_fft[SRSLTE_SYMBOL_SZ_MAX]; srslte_dft_run_c(&q->dftp_input, input, input_fft); @@ -88,10 +88,10 @@ static void extract_pair_sss(srslte_sss_synch_t *q, const cf_t *input, cf_t *ce, } -int srslte_sss_synch_m0m1_diff(srslte_sss_synch_t *q, const cf_t *input, uint32_t *m0, float *m0_value, +int srslte_sss_m0m1_diff(srslte_sss_t *q, const cf_t *input, uint32_t *m0, float *m0_value, uint32_t *m1, float *m1_value) { - return srslte_sss_synch_m0m1_diff_coh(q, input, NULL, m0, m0_value, m1, m1_value); + return srslte_sss_m0m1_diff_coh(q, input, NULL, m0, m0_value, m1, m1_value); } /* Differential SSS estimation. @@ -102,7 +102,7 @@ int srslte_sss_synch_m0m1_diff(srslte_sss_synch_t *q, const cf_t *input, uint32_ * */ -int srslte_sss_synch_m0m1_diff_coh(srslte_sss_synch_t *q, const cf_t *input, cf_t ce[2*SRSLTE_SSS_N], uint32_t *m0, float *m0_value, +int srslte_sss_m0m1_diff_coh(srslte_sss_t *q, const cf_t *input, cf_t ce[2*SRSLTE_SSS_N], uint32_t *m0, float *m0_value, uint32_t *m1, float *m1_value) { @@ -145,7 +145,7 @@ int srslte_sss_synch_m0m1_diff_coh(srslte_sss_synch_t *q, const cf_t *input, cf_ * Jung-In Kim, Jung-Su Han, Hee-Jin Roh and Hyung-Jin Choi */ -int srslte_sss_synch_m0m1_partial(srslte_sss_synch_t *q, const cf_t *input, uint32_t M, cf_t ce[2*SRSLTE_SSS_N], uint32_t *m0, float *m0_value, +int srslte_sss_m0m1_partial(srslte_sss_t *q, const cf_t *input, uint32_t M, cf_t ce[2*SRSLTE_SSS_N], uint32_t *m0, float *m0_value, uint32_t *m1, float *m1_value) { diff --git a/lib/src/phy/sync/pss.c b/lib/src/phy/sync/pss.c index d93fe0896..1f56dfda9 100644 --- a/lib/src/phy/sync/pss.c +++ b/lib/src/phy/sync/pss.c @@ -35,7 +35,7 @@ #include "srslte/phy/utils/debug.h" -int srslte_pss_synch_init_N_id_2(cf_t *pss_signal_freq, cf_t *pss_signal_time, +int srslte_pss_init_N_id_2(cf_t *pss_signal_freq, cf_t *pss_signal_time, uint32_t N_id_2, uint32_t fft_size, int cfo_i) { srslte_dft_plan_t plan; cf_t pss_signal_pad[2048]; @@ -73,16 +73,16 @@ int srslte_pss_synch_init_N_id_2(cf_t *pss_signal_freq, cf_t *pss_signal_time, /* Initializes the PSS synchronization object with fft_size=128 */ -int srslte_pss_synch_init(srslte_pss_synch_t *q, uint32_t frame_size) { - return srslte_pss_synch_init_fft(q, frame_size, 128); +int srslte_pss_init(srslte_pss_t *q, uint32_t frame_size) { + return srslte_pss_init_fft(q, frame_size, 128); } -int srslte_pss_synch_init_fft(srslte_pss_synch_t *q, uint32_t frame_size, uint32_t fft_size) { - return srslte_pss_synch_init_fft_offset(q, frame_size, fft_size, 0); +int srslte_pss_init_fft(srslte_pss_t *q, uint32_t frame_size, uint32_t fft_size) { + return srslte_pss_init_fft_offset(q, frame_size, fft_size, 0); } -int srslte_pss_synch_init_fft_offset(srslte_pss_synch_t *q, uint32_t frame_size, uint32_t fft_size, int offset) { - return srslte_pss_synch_init_fft_offset_decim(q, frame_size, fft_size, offset, 1); +int srslte_pss_init_fft_offset(srslte_pss_t *q, uint32_t frame_size, uint32_t fft_size, int offset) { + return srslte_pss_init_fft_offset_decim(q, frame_size, fft_size, offset, 1); } /* Initializes the PSS synchronization object. @@ -90,7 +90,7 @@ int srslte_pss_synch_init_fft_offset(srslte_pss_synch_t *q, uint32_t frame_size, * It correlates a signal of frame_size samples with the PSS sequence in the frequency * domain. The PSS sequence is transformed using fft_size samples. */ -int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, +int srslte_pss_init_fft_offset_decim(srslte_pss_t *q, uint32_t max_frame_size, uint32_t max_fft_size, int offset, int decimate) { @@ -102,7 +102,7 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, uint32_t N_id_2; uint32_t buffer_size; - bzero(q, sizeof(srslte_pss_synch_t)); + bzero(q, sizeof(srslte_pss_t)); q->N_id_2 = 10; q->ema_alpha = 0.2; @@ -143,7 +143,7 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, } srslte_dft_plan_set_mirror(&q->idftp_input, true); srslte_dft_plan_set_dc(&q->idftp_input, true); - srslte_dft_plan_set_norm(&q->idftp_input, true); + srslte_dft_plan_set_norm(&q->idftp_input, false); bzero(q->tmp_fft2, sizeof(cf_t)*SRSLTE_SYMBOL_SZ_MAX); @@ -183,7 +183,7 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, goto clean_and_exit; } /* The PSS is translated into the time domain for each N_id_2 */ - if (srslte_pss_synch_init_N_id_2(q->pss_signal_freq[N_id_2], q->pss_signal_time[N_id_2], N_id_2, fft_size, offset)) { + if (srslte_pss_init_N_id_2(q->pss_signal_freq[N_id_2], q->pss_signal_time[N_id_2], N_id_2, fft_size, offset)) { fprintf(stderr, "Error initiating PSS detector for N_id_2=%d fft_size=%d\n", N_id_2, fft_size); goto clean_and_exit; } @@ -192,27 +192,25 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, #ifdef CONVOLUTION_FFT - for(N_id_2=0; N_id_2<3; N_id_2++) - q->pss_signal_freq_full[N_id_2] = srslte_vec_malloc(buffer_size * sizeof(cf_t)); - if (srslte_conv_fft_cc_init(&q->conv_fft, frame_size, fft_size)) { fprintf(stderr, "Error initiating convolution FFT\n"); goto clean_and_exit; } - for(int i=0; i<3; i++) { - srslte_dft_run_c(&q->conv_fft.filter_plan, q->pss_signal_time[i], q->pss_signal_freq_full[i]); + for(N_id_2=0; N_id_2<3; N_id_2++) { + q->pss_signal_freq_full[N_id_2] = srslte_vec_malloc(buffer_size * sizeof(cf_t)); + srslte_dft_run_c(&q->conv_fft.filter_plan, q->pss_signal_time[N_id_2], q->pss_signal_freq_full[N_id_2]); } #endif - srslte_pss_synch_reset(q); + srslte_pss_reset(q); ret = SRSLTE_SUCCESS; } clean_and_exit: if (ret == SRSLTE_ERROR) { - srslte_pss_synch_free(q); + srslte_pss_free(q); } return ret; @@ -224,7 +222,7 @@ clean_and_exit: * It correlates a signal of frame_size samples with the PSS sequence in the frequency * domain. The PSS sequence is transformed using fft_size samples. */ -int srslte_pss_synch_resize(srslte_pss_synch_t *q, uint32_t frame_size, uint32_t fft_size, int offset) { +int srslte_pss_resize(srslte_pss_t *q, uint32_t frame_size, uint32_t fft_size, int offset) { int ret = SRSLTE_ERROR_INVALID_INPUTS; @@ -233,7 +231,7 @@ int srslte_pss_synch_resize(srslte_pss_synch_t *q, uint32_t frame_size, uint32_t ret = SRSLTE_ERROR; if (fft_size > q->max_fft_size || frame_size > q->max_frame_size) { - fprintf(stderr, "Error in pss_synch_config(): fft_size and frame_size must be lower than initialized\n"); + fprintf(stderr, "Error in pss_config(): fft_size and frame_size must be lower than initialized\n"); return SRSLTE_ERROR; } @@ -273,7 +271,7 @@ int srslte_pss_synch_resize(srslte_pss_synch_t *q, uint32_t frame_size, uint32_t // Generate PSS sequences for this FFT size for (N_id_2=0;N_id_2<3;N_id_2++) { - if (srslte_pss_synch_init_N_id_2(q->pss_signal_freq[N_id_2], q->pss_signal_time[N_id_2], N_id_2, fft_size, offset)) { + if (srslte_pss_init_N_id_2(q->pss_signal_freq[N_id_2], q->pss_signal_time[N_id_2], N_id_2, fft_size, offset)) { fprintf(stderr, "Error initiating PSS detector for N_id_2=%d fft_size=%d\n", N_id_2, fft_size); return SRSLTE_ERROR; } @@ -291,7 +289,7 @@ int srslte_pss_synch_resize(srslte_pss_synch_t *q, uint32_t frame_size, uint32_t #endif - srslte_pss_synch_reset(q); + srslte_pss_reset(q); ret = SRSLTE_SUCCESS; } @@ -299,7 +297,7 @@ int srslte_pss_synch_resize(srslte_pss_synch_t *q, uint32_t frame_size, uint32_t } -void srslte_pss_synch_free(srslte_pss_synch_t *q) { +void srslte_pss_free(srslte_pss_t *q) { uint32_t i; if (q) { @@ -339,11 +337,11 @@ void srslte_pss_synch_free(srslte_pss_synch_t *q) { } - bzero(q, sizeof(srslte_pss_synch_t)); + bzero(q, sizeof(srslte_pss_t)); } } -void srslte_pss_synch_reset(srslte_pss_synch_t *q) { +void srslte_pss_reset(srslte_pss_t *q) { uint32_t buffer_size = q->fft_size + q->frame_size + 1; bzero(q->conv_output_avg, sizeof(float) * buffer_size); } @@ -401,7 +399,7 @@ void srslte_pss_get_slot(cf_t *slot, cf_t *pss_signal, uint32_t nof_prb, srslte_ /** Sets the current N_id_2 value. Returns -1 on error, 0 otherwise */ -int srslte_pss_synch_set_N_id_2(srslte_pss_synch_t *q, uint32_t N_id_2) { +int srslte_pss_set_N_id_2(srslte_pss_t *q, uint32_t N_id_2) { if (!srslte_N_id_2_isvalid((N_id_2))) { fprintf(stderr, "Invalid N_id_2 %d\n", N_id_2); return -1; @@ -413,11 +411,11 @@ int srslte_pss_synch_set_N_id_2(srslte_pss_synch_t *q, uint32_t N_id_2) { /* Sets the weight factor alpha for the exponential moving average of the PSS correlation output */ -void srslte_pss_synch_set_ema_alpha(srslte_pss_synch_t *q, float alpha) { +void srslte_pss_set_ema_alpha(srslte_pss_t *q, float alpha) { q->ema_alpha = alpha; } -float compute_peak_sidelobe(srslte_pss_synch_t *q, uint32_t corr_peak_pos, uint32_t conv_output_len) +float compute_peak_sidelobe(srslte_pss_t *q, uint32_t corr_peak_pos, uint32_t conv_output_len) { // Find end of peak lobe to the right int pl_ub = corr_peak_pos+1; @@ -455,7 +453,7 @@ float compute_peak_sidelobe(srslte_pss_synch_t *q, uint32_t corr_peak_pos, uint3 * * Input buffer must be subframe_size long. */ -int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, const cf_t *input, float *corr_peak_value) +int srslte_pss_find_pss(srslte_pss_t *q, const cf_t *input, float *corr_peak_value) { int ret = SRSLTE_ERROR_INVALID_INPUTS; @@ -474,7 +472,7 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, const cf_t *input, float *c /* Correlate input with PSS sequence * * We do not reverse time-domain PSS signal because it's conjugate is symmetric. - * The conjugate operation on pss_signal_time has been done in srslte_pss_synch_init_N_id_2 + * The conjugate operation on pss_signal_time has been done in srslte_pss_init_N_id_2 * This is why we can use FFT-based convolution */ if (q->frame_size >= q->fft_size) { @@ -545,9 +543,8 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, const cf_t *input, float *c * input signal is in the time-domain. * ce is the returned frequency-domain channel estimates. */ -int srslte_pss_synch_chest(srslte_pss_synch_t *q, const cf_t *input, cf_t ce[SRSLTE_PSS_LEN]) { +int srslte_pss_chest(srslte_pss_t *q, const cf_t *input, cf_t ce[SRSLTE_PSS_LEN]) { int ret = SRSLTE_ERROR_INVALID_INPUTS; - cf_t input_fft[SRSLTE_SYMBOL_SZ_MAX]; if (q != NULL && input != NULL) @@ -559,18 +556,41 @@ int srslte_pss_synch_chest(srslte_pss_synch_t *q, const cf_t *input, cf_t ce[SRS } /* Transform to frequency-domain */ - srslte_dft_run_c(&q->dftp_input, input, input_fft); + srslte_dft_run_c(&q->dftp_input, input, q->tmp_fft); /* Compute channel estimate taking the PSS sequence as reference */ - srslte_vec_prod_conj_ccc(&input_fft[(q->fft_size-SRSLTE_PSS_LEN)/2], q->pss_signal_freq[q->N_id_2], ce, SRSLTE_PSS_LEN); + srslte_vec_prod_conj_ccc(&q->tmp_fft[(q->fft_size-SRSLTE_PSS_LEN)/2], q->pss_signal_freq[q->N_id_2], ce, SRSLTE_PSS_LEN); ret = SRSLTE_SUCCESS; } return ret; } +/* input points to beginning of last OFDM symbol of slot 0 of subframe 0 or 5 + * It must be called after calling srslte_pss_cfo_compute() with filter enabled + */ +void srslte_pss_sic(srslte_pss_t *q, cf_t *input) { + if (q->chest_on_filter) { + + bzero(q->tmp_fft, sizeof(cf_t)*q->fft_size); + + // Pass transmitted PSS sequence through the channel + srslte_vec_prod_ccc(q->pss_signal_freq[q->N_id_2], q->tmp_ce, &q->tmp_fft[(q->fft_size-SRSLTE_PSS_LEN)/2], SRSLTE_PSS_LEN); + + // Get time-domain version of the received PSS + srslte_dft_run_c(&q->idftp_input, q->tmp_fft, q->tmp_fft2); + + // Substract received PSS from this N_id_2 from the input signal + srslte_vec_sc_prod_cfc(q->tmp_fft2, 1.0/q->fft_size, q->tmp_fft2, q->fft_size); + srslte_vec_sub_ccc(input, q->tmp_fft2, input, q->fft_size); + + } else { + fprintf(stderr, "Error calling srslte_pss_sic(): need to enable channel estimation on filtering\n"); + } +} + // Frequency-domain filtering of the central 64 sub-carriers -void srslte_pss_synch_filter(srslte_pss_synch_t *q, const cf_t *input, cf_t *output) +void srslte_pss_filter(srslte_pss_t *q, const cf_t *input, cf_t *output) { srslte_dft_run_c(&q->dftp_input, input, q->tmp_fft); @@ -578,6 +598,10 @@ void srslte_pss_synch_filter(srslte_pss_synch_t *q, const cf_t *input, cf_t *out &q->tmp_fft[q->fft_size/2-SRSLTE_PSS_LEN/2], sizeof(cf_t)*SRSLTE_PSS_LEN); + if (q->chest_on_filter) { + srslte_vec_prod_conj_ccc(&q->tmp_fft[(q->fft_size-SRSLTE_PSS_LEN)/2], q->pss_signal_freq[q->N_id_2], q->tmp_ce, SRSLTE_PSS_LEN); + } + srslte_dft_run_c(&q->idftp_input, q->tmp_fft2, output); } @@ -586,13 +610,13 @@ void srslte_pss_synch_filter(srslte_pss_synch_t *q, const cf_t *input, cf_t *out * Source: An Efficient CFO Estimation Algorithm for the Downlink of 3GPP-LTE * Feng Wang and Yu Zhu */ -float srslte_pss_synch_cfo_compute(srslte_pss_synch_t* q, const cf_t *pss_recv) { +float srslte_pss_cfo_compute(srslte_pss_t* q, const cf_t *pss_recv) { cf_t y0, y1; const cf_t *pss_ptr = pss_recv; if (q->filter_pss_enable) { - srslte_pss_synch_filter(q, pss_recv, q->tmp_fft); + srslte_pss_filter(q, pss_recv, q->tmp_fft); pss_ptr = (const cf_t*) q->tmp_fft; } diff --git a/lib/src/phy/sync/sss.c b/lib/src/phy/sync/sss.c index 4ed7b1d6c..31091bdb3 100644 --- a/lib/src/phy/sync/sss.c +++ b/lib/src/phy/sync/sss.c @@ -40,7 +40,7 @@ void generate_sss_all_tables(srslte_sss_tables_t *tables, uint32_t N_id_2); void convert_tables(srslte_sss_fc_tables_t *fc_tables, srslte_sss_tables_t *in); void generate_N_id_1_table(uint32_t table[30][30]); -int srslte_sss_synch_init(srslte_sss_synch_t *q, uint32_t fft_size) { +int srslte_sss_init(srslte_sss_t *q, uint32_t fft_size) { if (q != NULL && fft_size <= 2048) @@ -48,10 +48,10 @@ int srslte_sss_synch_init(srslte_sss_synch_t *q, uint32_t fft_size) { uint32_t N_id_2; srslte_sss_tables_t sss_tables; - bzero(q, sizeof(srslte_sss_synch_t)); + bzero(q, sizeof(srslte_sss_t)); if (srslte_dft_plan(&q->dftp_input, fft_size, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)) { - srslte_sss_synch_free(q); + srslte_sss_free(q); return SRSLTE_ERROR; } srslte_dft_plan_set_mirror(&q->dftp_input, true); @@ -72,7 +72,7 @@ int srslte_sss_synch_init(srslte_sss_synch_t *q, uint32_t fft_size) { return SRSLTE_ERROR_INVALID_INPUTS; } -int srslte_sss_synch_resize(srslte_sss_synch_t *q, uint32_t fft_size) { +int srslte_sss_resize(srslte_sss_t *q, uint32_t fft_size) { if (q != NULL && fft_size <= 2048) { @@ -81,7 +81,7 @@ int srslte_sss_synch_resize(srslte_sss_synch_t *q, uint32_t fft_size) { return SRSLTE_ERROR; } if (srslte_dft_replan(&q->dftp_input, fft_size)) { - srslte_sss_synch_free(q); + srslte_sss_free(q); return SRSLTE_ERROR; } q->fft_size = fft_size; @@ -90,13 +90,13 @@ int srslte_sss_synch_resize(srslte_sss_synch_t *q, uint32_t fft_size) { return SRSLTE_ERROR_INVALID_INPUTS; } -void srslte_sss_synch_free(srslte_sss_synch_t *q) { +void srslte_sss_free(srslte_sss_t *q) { srslte_dft_plan_free(&q->dftp_input); - bzero(q, sizeof(srslte_sss_synch_t)); + bzero(q, sizeof(srslte_sss_t)); } /** Sets the N_id_2 to search for */ -int srslte_sss_synch_set_N_id_2(srslte_sss_synch_t *q, uint32_t N_id_2) { +int srslte_sss_set_N_id_2(srslte_sss_t *q, uint32_t N_id_2) { if (!srslte_N_id_2_isvalid(N_id_2)) { fprintf(stderr, "Invalid N_id_2 %d\n", N_id_2); return SRSLTE_ERROR; @@ -124,12 +124,12 @@ void srslte_sss_put_slot(float *sss, cf_t *slot, uint32_t nof_prb, srslte_cp_t c } /** Sets the SSS correlation peak detection threshold */ -void srslte_sss_synch_set_threshold(srslte_sss_synch_t *q, float threshold) { +void srslte_sss_set_threshold(srslte_sss_t *q, float threshold) { q->corr_peak_threshold = threshold; } /** Returns the subframe index based on the m0 and m1 values */ -uint32_t srslte_sss_synch_subframe(uint32_t m0, uint32_t m1) { +uint32_t srslte_sss_subframe(uint32_t m0, uint32_t m1) { if (m1 > m0) { return 0; } else { @@ -138,7 +138,7 @@ uint32_t srslte_sss_synch_subframe(uint32_t m0, uint32_t m1) { } /** Returns the N_id_1 value based on the m0 and m1 values */ -int srslte_sss_synch_N_id_1(srslte_sss_synch_t *q, uint32_t m0, uint32_t m1) { +int srslte_sss_N_id_1(srslte_sss_t *q, uint32_t m0, uint32_t m1) { int N_id_1 = -1; if (m1 > m0) { if (m0 < 30 && m1 - 1 < 30) { diff --git a/lib/src/phy/sync/sync.c b/lib/src/phy/sync/sync.c index a74be30d6..13a5f7e69 100644 --- a/lib/src/phy/sync/sync.c +++ b/lib/src/phy/sync/sync.c @@ -77,7 +77,6 @@ int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_o q->cfo_cp_enable = false; q->cfo_i_initiated = false; q->pss_filtering_enabled = false; - q->sss_filtering_enabled = false; q->fft_size = fft_size; q->frame_size = frame_size; @@ -119,11 +118,11 @@ int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_o decimate = 1; } - if (srslte_pss_synch_init_fft_offset_decim(&q->pss, max_offset, fft_size, 0, decimate)) { + if (srslte_pss_init_fft_offset_decim(&q->pss, max_offset, fft_size, 0, decimate)) { fprintf(stderr, "Error initializing PSS object\n"); goto clean_exit; } - if (srslte_sss_synch_init(&q->sss, fft_size)) { + if (srslte_sss_init(&q->sss, fft_size)) { fprintf(stderr, "Error initializing SSS object\n"); goto clean_exit; } @@ -151,8 +150,8 @@ void srslte_sync_free(srslte_sync_t *q) { if (q) { - srslte_pss_synch_free(&q->pss); - srslte_sss_synch_free(&q->sss); + srslte_pss_free(&q->pss); + srslte_sss_free(&q->sss); srslte_cfo_free(&q->cfo_corr_frame); srslte_cfo_free(&q->cfo_corr_symbol); srslte_cp_synch_free(&q->cp_synch); @@ -162,7 +161,7 @@ void srslte_sync_free(srslte_sync_t *q) if (q->cfo_i_corr[i]) { free(q->cfo_i_corr[i]); } - srslte_pss_synch_free(&q->pss_i[i]); + srslte_pss_free(&q->pss_i[i]); } } if (q->temp) { @@ -188,11 +187,11 @@ int srslte_sync_resize(srslte_sync_t *q, uint32_t frame_size, uint32_t max_offse q->frame_size = frame_size; q->max_offset = max_offset; - if (srslte_pss_synch_resize(&q->pss, q->max_offset, q->fft_size, 0)) { + if (srslte_pss_resize(&q->pss, q->max_offset, q->fft_size, 0)) { fprintf(stderr, "Error resizing PSS object\n"); return SRSLTE_ERROR; } - if (srslte_sss_synch_resize(&q->sss, q->fft_size)) { + if (srslte_sss_resize(&q->sss, q->fft_size)) { fprintf(stderr, "Error resizing SSS object\n"); return SRSLTE_ERROR; } @@ -215,7 +214,7 @@ int srslte_sync_resize(srslte_sync_t *q, uint32_t frame_size, uint32_t max_offse if (q->cfo_i_initiated) { for (int i=0;i<2;i++) { int offset=(i==0)?-1:1; - if (srslte_pss_synch_resize(&q->pss_i[i], q->max_offset, q->fft_size, offset)) { + if (srslte_pss_resize(&q->pss_i[i], q->max_offset, q->fft_size, offset)) { fprintf(stderr, "Error initializing PSS object\n"); } for (int t=0;tframe_size;t++) { @@ -302,7 +301,7 @@ void srslte_sync_set_cfo_i_enable(srslte_sync_t *q, bool enable) { if (q->cfo_i_enable && !q->cfo_i_initiated) { for (int i=0;i<2;i++) { int offset=(i==0)?-1:1; - if (srslte_pss_synch_init_fft_offset(&q->pss_i[i], q->max_offset, q->fft_size, offset)) { + if (srslte_pss_init_fft_offset(&q->pss_i[i], q->max_offset, q->fft_size, offset)) { fprintf(stderr, "Error initializing PSS object\n"); } for (int t=0;tframe_size;t++) { @@ -313,8 +312,12 @@ void srslte_sync_set_cfo_i_enable(srslte_sync_t *q, bool enable) { } } -void srslte_sync_set_sss_filt_enable(srslte_sync_t *q, bool enable) { - q->sss_filtering_enabled = enable; +void srslte_sync_set_sss_eq_enable(srslte_sync_t *q, bool enable) { + q->sss_channel_equalize = enable; + if (enable) { + q->pss_filtering_enabled = true; + q->pss.chest_on_filter = true; + } } void srslte_sync_set_pss_filt_enable(srslte_sync_t *q, bool enable) { @@ -343,7 +346,7 @@ void srslte_sync_cp_en(srslte_sync_t *q, bool enabled) { void srslte_sync_set_em_alpha(srslte_sync_t *q, float alpha) { - srslte_pss_synch_set_ema_alpha(&q->pss, alpha); + srslte_pss_set_ema_alpha(&q->pss, alpha); } srslte_cp_t srslte_sync_get_cp(srslte_sync_t *q) @@ -434,22 +437,22 @@ int sync_sss_symbol(srslte_sync_t *q, const cf_t *input) { int ret; - srslte_sss_synch_set_N_id_2(&q->sss, q->N_id_2); + srslte_sss_set_N_id_2(&q->sss, q->N_id_2); switch(q->sss_alg) { case SSS_DIFF: - srslte_sss_synch_m0m1_diff(&q->sss, input, &q->m0, &q->m0_value, &q->m1, &q->m1_value); + srslte_sss_m0m1_diff(&q->sss, input, &q->m0, &q->m0_value, &q->m1, &q->m1_value); break; case SSS_PARTIAL_3: - srslte_sss_synch_m0m1_partial(&q->sss, input, 3, NULL, &q->m0, &q->m0_value, &q->m1, &q->m1_value); + srslte_sss_m0m1_partial(&q->sss, input, 3, NULL, &q->m0, &q->m0_value, &q->m1, &q->m1_value); break; case SSS_FULL: - srslte_sss_synch_m0m1_partial(&q->sss, input, 1, NULL, &q->m0, &q->m0_value, &q->m1, &q->m1_value); + srslte_sss_m0m1_partial(&q->sss, input, 1, NULL, &q->m0, &q->m0_value, &q->m1, &q->m1_value); break; } - q->sf_idx = srslte_sss_synch_subframe(q->m0, q->m1); - ret = srslte_sss_synch_N_id_1(&q->sss, q->m0, q->m1); + q->sf_idx = srslte_sss_subframe(q->m0, q->m1); + ret = srslte_sss_N_id_1(&q->sss, q->m0, q->m1); if (ret >= 0) { q->N_id_1 = (uint32_t) ret; DEBUG("SSS detected N_id_1=%d, sf_idx=%d, %s CP\n", @@ -461,9 +464,9 @@ int sync_sss_symbol(srslte_sync_t *q, const cf_t *input) } } -srslte_pss_synch_t* srslte_sync_get_cur_pss_obj(srslte_sync_t *q) +srslte_pss_t* srslte_sync_get_cur_pss_obj(srslte_sync_t *q) { - srslte_pss_synch_t *pss_obj[3] = {&q->pss_i[0], &q->pss, &q->pss_i[1]}; + srslte_pss_t *pss_obj[3] = {&q->pss_i[0], &q->pss, &q->pss_i[1]}; return pss_obj[q->cfo_i_value+1]; } @@ -481,10 +484,10 @@ static int cfo_i_estimate(srslte_sync_t *q, const cf_t *input, int find_offset, float peak_value; float max_peak_value = -99; int max_cfo_i = 0; - srslte_pss_synch_t *pss_obj[3] = {&q->pss_i[0], &q->pss, &q->pss_i[1]}; + srslte_pss_t *pss_obj[3] = {&q->pss_i[0], &q->pss, &q->pss_i[1]}; for (int cfo_i=0;cfo_i<3;cfo_i++) { - srslte_pss_synch_set_N_id_2(pss_obj[cfo_i], q->N_id_2); - int p = srslte_pss_synch_find_pss(pss_obj[cfo_i], &input[find_offset], &peak_value); + srslte_pss_set_N_id_2(pss_obj[cfo_i], q->N_id_2); + int p = srslte_pss_find_pss(pss_obj[cfo_i], &input[find_offset], &peak_value); if (p < 0) { return -1; } @@ -574,8 +577,8 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, const cf_t *input, uin /* Find maximum of PSS correlation. If Integer CFO is enabled, correlation is already done */ if (!q->cfo_i_enable) { - srslte_pss_synch_set_N_id_2(&q->pss, q->N_id_2); - peak_pos = srslte_pss_synch_find_pss(&q->pss, &input_ptr[find_offset], q->threshold>0?&q->peak_value:NULL); + srslte_pss_set_N_id_2(&q->pss, q->N_id_2); + peak_pos = srslte_pss_find_pss(&q->pss, &input_ptr[find_offset], q->threshold>0?&q->peak_value:NULL); if (peak_pos < 0) { fprintf(stderr, "Error calling finding PSS sequence at : %d \n", peak_pos); return SRSLTE_ERROR; @@ -602,12 +605,12 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, const cf_t *input, uin // Filter central bands before PSS-based CFO estimation const cf_t *pss_ptr = &input_ptr[find_offset + peak_pos - q->fft_size]; if (q->pss_filtering_enabled) { - srslte_pss_synch_filter(&q->pss, pss_ptr, q->pss_filt); + srslte_pss_filter(&q->pss, pss_ptr, q->pss_filt); pss_ptr = q->pss_filt; } // PSS-based CFO estimation - float cfo_pss = srslte_pss_synch_cfo_compute(&q->pss, pss_ptr); + float cfo_pss = srslte_pss_cfo_compute(&q->pss, pss_ptr); if (!q->cfo_pss_is_set) { q->cfo_pss_mean = cfo_pss; q->cfo_pss_is_set = true; @@ -637,12 +640,11 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, const cf_t *input, uin // Correct CFO if detected in PSS if (q->cfo_pss_enable) { srslte_cfo_correct(&q->cfo_corr_symbol, sss_ptr, q->sss_filt, -q->cfo_pss_mean / q->fft_size); - sss_ptr = q->sss_filt; - } - - // Filter central bands before SSS estimation - if (q->sss_filtering_enabled) { - srslte_pss_synch_filter(&q->pss, sss_ptr, q->sss_filt); + // Equalize channel if estimated in PSS + if (q->sss_channel_equalize && q->pss.chest_on_filter && q->pss_filtering_enabled) { + srslte_vec_prod_ccc(&q->sss_filt[q->fft_size/2-SRSLTE_PSS_LEN/2], q->pss.tmp_ce, + &q->sss_filt[q->fft_size/2-SRSLTE_PSS_LEN/2], SRSLTE_PSS_LEN); + } sss_ptr = q->sss_filt; } @@ -681,5 +683,5 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, const cf_t *input, uin void srslte_sync_reset(srslte_sync_t *q) { q->M_ext_avg = 0; q->M_norm_avg = 0; - srslte_pss_synch_reset(&q->pss); + srslte_pss_reset(&q->pss); } diff --git a/lib/src/phy/sync/test/pss_file.c b/lib/src/phy/sync/test/pss_file.c index 7f70ad8ff..4087366ec 100644 --- a/lib/src/phy/sync/test/pss_file.c +++ b/lib/src/phy/sync/test/pss_file.c @@ -121,9 +121,9 @@ int main(int argc, char **argv) { srslte_filesource_t fsrc; cf_t *buffer; int frame_cnt, n; - srslte_pss_synch_t pss; + srslte_pss_t pss; srslte_cfo_t cfocorr, cfocorr64; - srslte_sss_synch_t sss; + srslte_sss_t sss; int32_t flen; int peak_idx, last_peak; float peak_value; @@ -152,12 +152,12 @@ int main(int argc, char **argv) { exit(-1); } - if (srslte_pss_synch_init_fft(&pss, flen, fft_size)) { + if (srslte_pss_init_fft(&pss, flen, fft_size)) { fprintf(stderr, "Error initiating PSS\n"); exit(-1); } - if (srslte_pss_synch_set_N_id_2(&pss, N_id_2_sync)) { + if (srslte_pss_set_N_id_2(&pss, N_id_2_sync)) { fprintf(stderr, "Error setting N_id_2=%d\n",N_id_2_sync); exit(-1); } @@ -165,12 +165,12 @@ int main(int argc, char **argv) { srslte_cfo_init(&cfocorr, flen); srslte_cfo_init(&cfocorr64, flen); - if (srslte_sss_synch_init(&sss, fft_size)) { + if (srslte_sss_init(&sss, fft_size)) { fprintf(stderr, "Error initializing SSS object\n"); return SRSLTE_ERROR; } - srslte_sss_synch_set_N_id_2(&sss, N_id_2); + srslte_sss_set_N_id_2(&sss, N_id_2); printf("Opening file...\n"); if (srslte_filesource_init(&fsrc, input_file_name, SRSLTE_COMPLEX_FLOAT_BIN)) { @@ -210,7 +210,7 @@ int main(int argc, char **argv) { break; } - peak_idx = srslte_pss_synch_find_pss(&pss, buffer, &peak_value); + peak_idx = srslte_pss_find_pss(&pss, buffer, &peak_value); if (peak_idx < 0) { fprintf(stderr, "Error finding PSS peak\n"); exit(-1); @@ -224,14 +224,14 @@ int main(int argc, char **argv) { if (peak_idx >= fft_size) { // Estimate CFO - cfo = srslte_pss_synch_cfo_compute(&pss, &buffer[peak_idx-fft_size]); + cfo = srslte_pss_cfo_compute(&pss, &buffer[peak_idx-fft_size]); mean_cfo = SRSLTE_VEC_CMA(cfo, mean_cfo, frame_cnt); // Correct CFO srslte_cfo_correct(&cfocorr, buffer, buffer, -mean_cfo / fft_size); // Estimate channel - if (srslte_pss_synch_chest(&pss, &buffer[peak_idx-fft_size], ce)) { + if (srslte_pss_chest(&pss, &buffer[peak_idx-fft_size], ce)) { fprintf(stderr, "Error computing channel estimation\n"); exit(-1); } @@ -239,22 +239,22 @@ int main(int argc, char **argv) { // Find SSS int sss_idx = peak_idx-2*fft_size-(SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN(fft_size, SRSLTE_CP_NORM_LEN):SRSLTE_CP_LEN(fft_size, SRSLTE_CP_EXT_LEN)); if (sss_idx >= 0 && sss_idx < flen-fft_size) { - srslte_sss_synch_m0m1_partial(&sss, &buffer[sss_idx], 3, NULL, &m0, &m0_value, &m1, &m1_value); - if (srslte_sss_synch_N_id_1(&sss, m0, m1) != N_id_1) { + srslte_sss_m0m1_partial(&sss, &buffer[sss_idx], 3, NULL, &m0, &m0_value, &m1, &m1_value); + if (srslte_sss_N_id_1(&sss, m0, m1) != N_id_1) { sss_error2++; } - INFO("sf_idx = %d\n", srslte_sss_synch_subframe(m0, m1)); - INFO("Partial N_id_1: %d\n", srslte_sss_synch_N_id_1(&sss, m0, m1)); - srslte_sss_synch_m0m1_diff(&sss, &buffer[sss_idx], &m0, &m0_value, &m1, &m1_value); - if (srslte_sss_synch_N_id_1(&sss, m0, m1) != N_id_1) { + INFO("sf_idx = %d\n", srslte_sss_subframe(m0, m1)); + INFO("Partial N_id_1: %d\n", srslte_sss_N_id_1(&sss, m0, m1)); + srslte_sss_m0m1_diff(&sss, &buffer[sss_idx], &m0, &m0_value, &m1, &m1_value); + if (srslte_sss_N_id_1(&sss, m0, m1) != N_id_1) { sss_error3++; } - INFO("Diff N_id_1: %d\n", srslte_sss_synch_N_id_1(&sss, m0, m1)); - srslte_sss_synch_m0m1_partial(&sss, &buffer[sss_idx], 1, NULL, &m0, &m0_value, &m1, &m1_value); - if (srslte_sss_synch_N_id_1(&sss, m0, m1) != N_id_1) { + INFO("Diff N_id_1: %d\n", srslte_sss_N_id_1(&sss, m0, m1)); + srslte_sss_m0m1_partial(&sss, &buffer[sss_idx], 1, NULL, &m0, &m0_value, &m1, &m1_value); + if (srslte_sss_N_id_1(&sss, m0, m1) != N_id_1) { sss_error1++; } - INFO("Full N_id_1: %d\n", srslte_sss_synch_N_id_1(&sss, m0, m1)); + INFO("Full N_id_1: %d\n", srslte_sss_N_id_1(&sss, m0, m1)); } // Estimate CP @@ -269,7 +269,7 @@ int main(int argc, char **argv) { INFO("No space for CFO computation. Frame starts at \n",peak_idx); } - if(srslte_sss_synch_subframe(m0,m1) == 0) + if(srslte_sss_subframe(m0,m1) == 0) { #ifndef DISABLE_GRAPHICS if (!disable_plots) @@ -317,7 +317,7 @@ int main(int argc, char **argv) { } - srslte_pss_synch_free(&pss); + srslte_pss_free(&pss); free(buffer); srslte_filesource_free(&fsrc); #ifndef DISABLE_GRAPHICS diff --git a/lib/src/phy/sync/test/pss_mex.c b/lib/src/phy/sync/test/pss_mex.c index 77922a020..59cc0a897 100644 --- a/lib/src/phy/sync/test/pss_mex.c +++ b/lib/src/phy/sync/test/pss_mex.c @@ -47,7 +47,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { srslte_cell_t cell; - srslte_pss_synch_t pss; + srslte_pss_t pss; cf_t *input_symbols; int frame_len; @@ -74,17 +74,17 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) frame_len = (int) mxGetScalar(prhs[NOF_INPUTS]); } - if (srslte_pss_synch_init_fft(&pss, frame_len, srslte_symbol_sz(cell.nof_prb))) { + if (srslte_pss_init_fft(&pss, frame_len, srslte_symbol_sz(cell.nof_prb))) { fprintf(stderr, "Error initiating PSS\n"); exit(-1); } - if (srslte_pss_synch_set_N_id_2(&pss, cell.id%3)) { + if (srslte_pss_set_N_id_2(&pss, cell.id%3)) { fprintf(stderr, "Error setting N_id_2=%d\n",cell.id%3); exit(-1); } - srslte_pss_synch_set_ema_alpha(&pss, 1.0); + srslte_pss_set_ema_alpha(&pss, 1.0); - int peak_idx = srslte_pss_synch_find_pss(&pss, input_symbols, NULL); + int peak_idx = srslte_pss_find_pss(&pss, input_symbols, NULL); if (nlhs >= 1) { plhs[0] = mxCreateDoubleScalar(peak_idx); @@ -93,7 +93,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) mexutils_write_cf(pss.conv_output, &plhs[1], frame_len, 1); } - srslte_pss_synch_free(&pss); + srslte_pss_free(&pss); free(input_symbols); return; diff --git a/lib/src/phy/sync/test/pss_usrp.c b/lib/src/phy/sync/test/pss_usrp.c index 704340b2f..70881f15b 100644 --- a/lib/src/phy/sync/test/pss_usrp.c +++ b/lib/src/phy/sync/test/pss_usrp.c @@ -125,9 +125,9 @@ int main(int argc, char **argv) { cf_t *buffer; int frame_cnt, n; srslte_rf_t rf; - srslte_pss_synch_t pss; + srslte_pss_t pss; srslte_cfo_t cfocorr, cfocorr64; - srslte_sss_synch_t sss; + srslte_sss_t sss; int32_t flen; int peak_idx, last_peak; float peak_value; @@ -176,12 +176,12 @@ int main(int argc, char **argv) { exit(-1); } - if (srslte_pss_synch_init_fft(&pss, flen, fft_size)) { + if (srslte_pss_init_fft(&pss, flen, fft_size)) { fprintf(stderr, "Error initiating PSS\n"); exit(-1); } - if (srslte_pss_synch_set_N_id_2(&pss, N_id_2_sync)) { + if (srslte_pss_set_N_id_2(&pss, N_id_2_sync)) { fprintf(stderr, "Error setting N_id_2=%d\n",N_id_2_sync); exit(-1); } @@ -189,12 +189,12 @@ int main(int argc, char **argv) { srslte_cfo_init(&cfocorr, flen); srslte_cfo_init(&cfocorr64, flen); - if (srslte_sss_synch_init(&sss, fft_size)) { + if (srslte_sss_init(&sss, fft_size)) { fprintf(stderr, "Error initializing SSS object\n"); exit(-1); } - srslte_sss_synch_set_N_id_2(&sss, N_id_2); + srslte_sss_set_N_id_2(&sss, N_id_2); printf("N_id_2: %d\n", N_id_2); @@ -232,7 +232,7 @@ int main(int argc, char **argv) { exit(-1); } - peak_idx = srslte_pss_synch_find_pss(&pss, buffer, &peak_value); + peak_idx = srslte_pss_find_pss(&pss, buffer, &peak_value); if (peak_idx < 0) { fprintf(stderr, "Error finding PSS peak\n"); exit(-1); @@ -246,14 +246,14 @@ int main(int argc, char **argv) { if (peak_idx >= fft_size) { // Estimate CFO - cfo = srslte_pss_synch_cfo_compute(&pss, &buffer[peak_idx-fft_size]); + cfo = srslte_pss_cfo_compute(&pss, &buffer[peak_idx-fft_size]); mean_cfo = SRSLTE_VEC_CMA(cfo, mean_cfo, frame_cnt); // Correct CFO srslte_cfo_correct(&cfocorr, buffer, buffer, -mean_cfo / fft_size); // Estimate channel - if (srslte_pss_synch_chest(&pss, &buffer[peak_idx-fft_size], ce)) { + if (srslte_pss_chest(&pss, &buffer[peak_idx-fft_size], ce)) { fprintf(stderr, "Error computing channel estimation\n"); exit(-1); } @@ -263,22 +263,22 @@ int main(int argc, char **argv) { if (sss_idx >= 0 && sss_idx < flen-fft_size) { // Filter SSS - srslte_pss_synch_filter(&pss, &buffer[sss_idx], &buffer[sss_idx]); + srslte_pss_filter(&pss, &buffer[sss_idx], &buffer[sss_idx]); - INFO("Full N_id_1: %d\n", srslte_sss_synch_N_id_1(&sss, m0, m1)); - srslte_sss_synch_m0m1_partial(&sss, &buffer[sss_idx], 1, ce, &m0, &m0_value, &m1, &m1_value); - if (srslte_sss_synch_N_id_1(&sss, m0, m1) != N_id_1) { + INFO("Full N_id_1: %d\n", srslte_sss_N_id_1(&sss, m0, m1)); + srslte_sss_m0m1_partial(&sss, &buffer[sss_idx], 1, ce, &m0, &m0_value, &m1, &m1_value); + if (srslte_sss_N_id_1(&sss, m0, m1) != N_id_1) { sss_error2++; } - INFO("Partial N_id_1: %d\n", srslte_sss_synch_N_id_1(&sss, m0, m1)); - srslte_sss_synch_m0m1_diff_coh(&sss, &buffer[sss_idx], ce, &m0, &m0_value, &m1, &m1_value); - if (srslte_sss_synch_N_id_1(&sss, m0, m1) != N_id_1) { + INFO("Partial N_id_1: %d\n", srslte_sss_N_id_1(&sss, m0, m1)); + srslte_sss_m0m1_diff_coh(&sss, &buffer[sss_idx], ce, &m0, &m0_value, &m1, &m1_value); + if (srslte_sss_N_id_1(&sss, m0, m1) != N_id_1) { sss_error3++; } - INFO("Diff N_id_1: %d\n", srslte_sss_synch_N_id_1(&sss, m0, m1)); + INFO("Diff N_id_1: %d\n", srslte_sss_N_id_1(&sss, m0, m1)); } - srslte_sss_synch_m0m1_partial(&sss, &buffer[sss_idx], 1, NULL, &m0, &m0_value, &m1, &m1_value); - if (srslte_sss_synch_N_id_1(&sss, m0, m1) != N_id_1) { + srslte_sss_m0m1_partial(&sss, &buffer[sss_idx], 1, NULL, &m0, &m0_value, &m1, &m1_value); + if (srslte_sss_N_id_1(&sss, m0, m1) != N_id_1) { sss_error1++; } @@ -294,7 +294,7 @@ int main(int argc, char **argv) { INFO("No space for CFO computation. Frame starts at \n",peak_idx); } - if(srslte_sss_synch_subframe(m0,m1) == 0) + if(srslte_sss_subframe(m0,m1) == 0) { #ifndef DISABLE_GRAPHICS if (!disable_plots) @@ -358,8 +358,8 @@ int main(int argc, char **argv) { } - srslte_sss_synch_free(&sss); - srslte_pss_synch_free(&pss); + srslte_sss_free(&sss); + srslte_pss_free(&pss); free(buffer); srslte_rf_close(&rf); diff --git a/lib/src/phy/sync/test/sss_mex.c b/lib/src/phy/sync/test/sss_mex.c index 4c92d81ec..56165fe3d 100644 --- a/lib/src/phy/sync/test/sss_mex.c +++ b/lib/src/phy/sync/test/sss_mex.c @@ -50,7 +50,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { srslte_cell_t cell; - srslte_sss_synch_t sss; + srslte_sss_t sss; cf_t *input_symbols; int frame_len; uint32_t m0, m1; @@ -80,12 +80,12 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) return; } - if (srslte_sss_synch_init(&sss, srslte_symbol_sz(cell.nof_prb))) { + if (srslte_sss_init(&sss, srslte_symbol_sz(cell.nof_prb))) { mexErrMsgTxt("Error initializing SSS object\n"); return; } - srslte_sss_synch_set_N_id_2(&sss, cell.id%3); + srslte_sss_set_N_id_2(&sss, cell.id%3); // Find SSS uint32_t sss_idx = SRSLTE_SLOT_IDX_CPNORM(5,srslte_symbol_sz(cell.nof_prb)); @@ -95,23 +95,23 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) } //mexPrintf("SSS begins at %d/%d. Running algorithm %s\n", sss_idx, frame_len, alg); if (!strcmp(alg, "partial")) { - srslte_sss_synch_m0m1_partial(&sss, &input_symbols[sss_idx], 3, NULL, &m0, &m0_value, &m1, &m1_value); + srslte_sss_m0m1_partial(&sss, &input_symbols[sss_idx], 3, NULL, &m0, &m0_value, &m1, &m1_value); } else if (!strcmp(alg, "diff")) { - srslte_sss_synch_m0m1_diff(&sss, &input_symbols[sss_idx], &m0, &m0_value, &m1, &m1_value); + srslte_sss_m0m1_diff(&sss, &input_symbols[sss_idx], &m0, &m0_value, &m1, &m1_value); } else if (!strcmp(alg, "full")) { - srslte_sss_synch_m0m1_partial(&sss, &input_symbols[sss_idx], 1, NULL, &m0, &m0_value, &m1, &m1_value); + srslte_sss_m0m1_partial(&sss, &input_symbols[sss_idx], 1, NULL, &m0, &m0_value, &m1, &m1_value); } else { mexErrMsgTxt("Unsupported algorithm type\n"); return; } - //mexPrintf("m0: %d, m1: %d, N_id_1: %d\n", m0, m1, srslte_sss_synch_N_id_1(&sss, m0, m1)); + //mexPrintf("m0: %d, m1: %d, N_id_1: %d\n", m0, m1, srslte_sss_N_id_1(&sss, m0, m1)); if (nlhs >= 1) { - plhs[0] = mxCreateDoubleScalar(srslte_sss_synch_N_id_1(&sss, m0, m1)); + plhs[0] = mxCreateDoubleScalar(srslte_sss_N_id_1(&sss, m0, m1)); } if (nlhs >= 2) { - plhs[1] = mxCreateDoubleScalar(srslte_sss_synch_subframe(m0, m1)); + plhs[1] = mxCreateDoubleScalar(srslte_sss_subframe(m0, m1)); } if (nlhs >= 3) { mexutils_write_f(sss.corr_output_m0, &plhs[2], SRSLTE_SSS_N, 1); @@ -119,7 +119,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) if (nlhs >= 4) { mexutils_write_f(sss.corr_output_m1, &plhs[3], SRSLTE_SSS_N, 1); } - srslte_sss_synch_free(&sss); + srslte_sss_free(&sss); free(input_symbols); return; diff --git a/lib/src/phy/ue/ue_sync.c b/lib/src/phy/ue/ue_sync.c index b5d89743f..7eb877b3b 100644 --- a/lib/src/phy/ue/ue_sync.c +++ b/lib/src/phy/ue/ue_sync.c @@ -272,14 +272,14 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q, srslte_sync_set_cfo_cp_enable(&q->sfind, true); srslte_sync_set_cfo_pss_enable(&q->sfind, true); srslte_sync_set_pss_filt_enable(&q->sfind, true); - srslte_sync_set_sss_filt_enable(&q->sfind, true); + srslte_sync_set_sss_eq_enable(&q->sfind, true); // During track, we do CFO correction outside the sync object srslte_sync_set_cfo_i_enable(&q->strack, false); srslte_sync_set_cfo_cp_enable(&q->strack, false); srslte_sync_set_cfo_pss_enable(&q->strack, true); srslte_sync_set_pss_filt_enable(&q->strack, true); - srslte_sync_set_sss_filt_enable(&q->strack, false); + srslte_sync_set_sss_eq_enable(&q->strack, false); // FIXME: CP detection not working very well. Not supporting Extended CP right now srslte_sync_cp_en(&q->strack, false); diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index 667f0a93c..6c7ff7717 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -102,8 +102,6 @@ private: bool set_frequency(); bool set_cell(); - static void substract_sync(cf_t *buffer, uint32_t nof_prb, srslte_sync_t *sync_obj); - void cell_search_inc(); void resync_sfn(bool is_connected = false, bool rx_now = false); bool stop_sync(); @@ -202,7 +200,7 @@ private: float rsrq; uint32_t offset; } cell_info_t; - void init(srslte::log *log_h); + void init(srslte::log *log_h, bool sic_pss_enabled); void reset(); int find_cells(cf_t *input_buffer, float rx_gain_offset, srslte_cell_t current_cell, uint32_t nof_sf, cell_info_t found_cells[MAX_CELLS]); private: @@ -214,6 +212,7 @@ private: srslte::log *log_h; srslte_sync_t sync_find; + bool sic_pss_enabled; uint32_t current_fft_sz; measure measure_p; }; diff --git a/srsue/src/mac/proc_ra.cc b/srsue/src/mac/proc_ra.cc index 18548be23..0a1855c80 100644 --- a/srsue/src/mac/proc_ra.cc +++ b/srsue/src/mac/proc_ra.cc @@ -394,16 +394,14 @@ void ra_proc::step_response_reception() { void ra_proc::step_response_error() { - if (ra_is_ho) { - state = RA_PROBLEM; - rrc->ho_ra_completed(false); - return; - } preambleTransmissionCounter++; if (preambleTransmissionCounter >= preambleTransMax + 1) { rError("Maximum number of transmissions reached (%d)\n", preambleTransMax); rrc->ra_problem(); state = RA_PROBLEM; + if (ra_is_ho) { + rrc->ho_ra_completed(false); + } } else { backoff_interval_start = phy_h->get_current_tti(); if (backoff_param_ms) { diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 8a25801f2..09a382246 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -233,11 +233,14 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { bpo::value(&args->expert.phy.cfo_loop_ref_min)->default_value(0), "Tolerance (in Hz) of the RS estimation method. Below this value, RS estimation does not feeds back the loop") - ("expert.cfo_loop_pss_conv", bpo::value(&args->expert.phy.cfo_loop_pss_conv)->default_value(20), "After the PSS estimation is below cfo_loop_pss_tol for cfo_loop_pss_timeout times consecutively, RS adjustments are allowed.") + ("expert.sic_pss_enabled", + bpo::value(&args->expert.phy.sic_pss_enabled)->default_value(true), + "Applies Successive Interference Cancellation to PSS signals when searching for neighbour cells. Must be disabled if cells have identical channel and timing.") + ("expert.average_subframe_enabled", bpo::value(&args->expert.phy.average_subframe_enabled)->default_value(false), "Averages in the time domain the channel estimates within 1 subframe. Needs accurate CFO correction.") diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 7a78fc11c..9225c6f73 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -197,6 +197,8 @@ void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q) worker_com->args->cfo_loop_pss_tol, worker_com->args->cfo_loop_pss_conv); + q->strack.pss.chest_on_filter = true; + int time_correct_period = worker_com->args->time_correct_period; if (time_correct_period > 0) { srslte_ue_sync_set_sample_offset_correct_period(q, time_correct_period); @@ -629,7 +631,7 @@ void phch_recv::run_thread() worker = (phch_worker *) workers_pool->wait_worker(tti); if (worker) { - for (uint32_t i = 0; i < nof_rx_antennas; i++) { + for (uint32_t i = 0; i < SRSLTE_MAX_PORTS; i++) { buffer[i] = worker->get_buffer(i); } @@ -669,12 +671,12 @@ void phch_recv::run_thread() worker_com->p0_preamble = prach_buffer->get_p0_preamble(); worker_com->cur_radio_power = SRSLTE_MIN(SRSLTE_PC_MAX, worker_com->pathloss+worker_com->p0_preamble); } + workers_pool->start_worker(worker); - // Substract PSS/SSS from current cell before computing intra-frequency - /*if ((tti%5) == 0) { - substract_sync(buffer[0], cell.nof_prb, &ue_sync.strack); - }*/ + if ((tti%5) == 0 && worker_com->args->sic_pss_enabled) { + srslte_pss_sic(&ue_sync.strack.pss, &buffer[0][SRSLTE_SF_LEN_PRB(cell.nof_prb)/2-ue_sync.strack.fft_size]); + } intra_freq_meas.write(tti, buffer[0], SRSLTE_SF_LEN_PRB(cell.nof_prb)); out_of_sync_cnt = 0; break; @@ -726,24 +728,6 @@ void phch_recv::out_of_sync() { } } -void phch_recv::substract_sync(cf_t *buffer, uint32_t nof_prb, srslte_sync_t *sync_obj) -{ - uint32_t hf_len = SRSLTE_SF_LEN_PRB(nof_prb)/2; - uint32_t fft_sz = srslte_symbol_sz(nof_prb); - - srslte_vec_sc_prod_cfc(sync_obj->pss_filt, 1.0/sqrtf(fft_sz), sync_obj->pss_filt, fft_sz); - srslte_vec_sc_prod_cfc(sync_obj->sss_filt, 1.0/sqrtf(fft_sz), sync_obj->sss_filt, fft_sz); - - srslte_vec_sub_ccc(&buffer[hf_len-fft_sz], - sync_obj->pss_filt, - &buffer[hf_len-fft_sz], - fft_sz); - - srslte_vec_sub_ccc(&buffer[hf_len-2*fft_sz-SRSLTE_CP_LEN(fft_sz, SRSLTE_CP_NORM_LEN)], - sync_obj->sss_filt, - &buffer[hf_len-2*fft_sz-SRSLTE_CP_LEN(fft_sz, SRSLTE_CP_NORM_LEN)], - fft_sz); -} @@ -1194,9 +1178,10 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx) * Secondary cell receiver */ -void phch_recv::scell_recv::init(srslte::log *log_h) +void phch_recv::scell_recv::init(srslte::log *log_h, bool sic_pss_enabled) { this->log_h = log_h; + this->sic_pss_enabled = sic_pss_enabled; // and a separate ue_sync instance @@ -1213,16 +1198,18 @@ void phch_recv::scell_recv::init(srslte::log *log_h) return; } srslte_sync_cp_en(&sync_find, false); - srslte_sync_set_threshold(&sync_find, 1.3); + srslte_sync_set_threshold(&sync_find, 1.2); srslte_sync_set_em_alpha(&sync_find, 0.0); // Configure FIND object behaviour (this configuration is always the same) - srslte_sync_set_cfo_ema_alpha(&sync_find, 0.5); + srslte_sync_set_cfo_ema_alpha(&sync_find, 1.0); srslte_sync_set_cfo_i_enable(&sync_find, false); srslte_sync_set_cfo_cp_enable(&sync_find, false); srslte_sync_set_cfo_pss_enable(&sync_find, true); srslte_sync_set_pss_filt_enable(&sync_find, true); - srslte_sync_set_sss_filt_enable(&sync_find, true); + srslte_sync_set_sss_eq_enable(&sync_find, true); + + sync_find.pss.chest_on_filter = true; reset(); } @@ -1259,76 +1246,79 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, for (uint32_t n_id_2=0;n_id_2<3;n_id_2++) { - srslte_sync_set_N_id_2(&sync_find, n_id_2); - - srslte_sync_find_ret_t sync_res; - //do { - - srslte_sync_reset(&sync_find); - srslte_sync_cfo_reset(&sync_find); - - sync_res = srslte_sync_find(&sync_find, input_buffer, 0, &peak_idx); - - switch(sync_res) { - case SRSLTE_SYNC_ERROR: - return SRSLTE_ERROR; - fprintf(stderr, "Error finding correlation peak\n"); - return SRSLTE_ERROR; - case SRSLTE_SYNC_FOUND: - sf_idx = srslte_sync_get_sf_idx(&sync_find); - cell_id = srslte_sync_get_cell_id(&sync_find); - - if (cell_id >= 0) { - // We found the same cell as before, look another N_id_2 - if ((uint32_t) cell_id == found_cell.id || (uint32_t) cell_id == cell.id) { - sync_res = SRSLTE_SYNC_NOFOUND; - } else { - // We found a new cell ID - found_cell.id = cell_id; - found_cell.nof_ports = 1; // Use port 0 only for measurement - measure_p.set_cell(found_cell); - - // Correct CFO - /* - srslte_cfo_correct(&sync_find.cfo_corr_frame, - input_buffer, - input_cfo_corrected, - -srslte_sync_get_cfo(&sync_find)/sync_find.fft_size); - */ - - switch(measure_p.run_multiple_subframes(input_buffer, peak_idx, sf_idx, nof_sf)) { - case measure::MEASURE_OK: - cells[nof_cells].pci = found_cell.id; - cells[nof_cells].rsrp = measure_p.rsrp(); - cells[nof_cells].rsrq = measure_p.rsrq(); - cells[nof_cells].offset = measure_p.frame_st_idx(); - nof_cells++; - - // Substract interference from input buffer (for the next cell) - //substract_sync(&input_buffer[measure_p.frame_st_idx()], cell.nof_prb, &sync_find); - - Info("INTRA: Found neighbour cell: PCI=%03d, RSRP=%5.1f dBm, peak_idx=%5d, peak_value=%3.2f n_id_2=%d, CFO=%6.1f Hz\n", - cell_id, measure_p.rsrp(), measure_p.frame_st_idx(), sync_find.peak_value, n_id_2, 15000*srslte_sync_get_cfo(&sync_find)); - - break; - case measure::ERROR: - Error("Measuring neighbour cell\n"); - return SRSLTE_ERROR; - default: - break; + if (n_id_2 != (cell.id%3) || sic_pss_enabled) { + srslte_sync_set_N_id_2(&sync_find, n_id_2); + + srslte_sync_find_ret_t sync_res; + + do { + srslte_sync_reset(&sync_find); + srslte_sync_cfo_reset(&sync_find); + + sync_res = srslte_sync_find(&sync_find, input_buffer, 0, &peak_idx); + + switch(sync_res) { + case SRSLTE_SYNC_ERROR: + return SRSLTE_ERROR; + fprintf(stderr, "Error finding correlation peak\n"); + return SRSLTE_ERROR; + case SRSLTE_SYNC_FOUND: + sf_idx = srslte_sync_get_sf_idx(&sync_find); + cell_id = srslte_sync_get_cell_id(&sync_find); + + if (cell_id >= 0) { + // We found the same cell as before, look another N_id_2 + if ((uint32_t) cell_id == found_cell.id || (uint32_t) cell_id == cell.id) { + sync_res = SRSLTE_SYNC_NOFOUND; + } else { + // We found a new cell ID + found_cell.id = cell_id; + found_cell.nof_ports = 1; // Use port 0 only for measurement + measure_p.set_cell(found_cell); + + // Correct CFO + srslte_cfo_correct(&sync_find.cfo_corr_frame, + input_buffer, + input_cfo_corrected, + -srslte_sync_get_cfo(&sync_find)/sync_find.fft_size); + + + switch(measure_p.run_multiple_subframes(input_cfo_corrected, peak_idx, sf_idx, nof_sf)) { + case measure::MEASURE_OK: + cells[nof_cells].pci = found_cell.id; + cells[nof_cells].rsrp = measure_p.rsrp(); + cells[nof_cells].rsrq = measure_p.rsrq(); + cells[nof_cells].offset = measure_p.frame_st_idx(); + + Info("INTRA: Found neighbour cell %d: PCI=%03d, RSRP=%5.1f dBm, peak_idx=%5d, peak_value=%3.2f n_id_2=%d, CFO=%6.1f Hz\n", + nof_cells, cell_id, measure_p.rsrp(), measure_p.frame_st_idx(), sync_find.peak_value, n_id_2, 15000*srslte_sync_get_cfo(&sync_find)); + + nof_cells++; + + if (sic_pss_enabled) { + srslte_pss_sic(&sync_find.pss, &input_buffer[sf_len/2-fft_sz]); + } + + break; + case measure::ERROR: + Error("Measuring neighbour cell\n"); + return SRSLTE_ERROR; + default: + break; + } } + } else { + sync_res = SRSLTE_SYNC_NOFOUND; } - } else { - sync_res = SRSLTE_SYNC_NOFOUND; - } - break; - case SRSLTE_SYNC_FOUND_NOSPACE: - /* If a peak was found but there is not enough space for SSS/CP detection, discard a few samples */ - break; - default: - break; - } - //} while(sync_res == SRSLTE_SYNC_FOUND); + break; + case SRSLTE_SYNC_FOUND_NOSPACE: + /* If a peak was found but there is not enough space for SSS/CP detection, discard a few samples */ + break; + default: + break; + } + } while (sync_res == SRSLTE_SYNC_FOUND && sic_pss_enabled); + } } return nof_cells; } @@ -1380,7 +1370,7 @@ void phch_recv::intra_measure::init(phch_common *common, rrc_interface_phy *rrc, receive_enabled = false; // Start scell - scell.init(log_h); + scell.init(log_h, common->args->sic_pss_enabled); search_buffer = (cf_t*) srslte_vec_malloc(CAPTURE_LEN_SF*SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB)*sizeof(cf_t)); diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 461a4f9ee..55c39cfe0 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -1087,7 +1087,9 @@ void rrc::ho_ra_completed(bool ra_successful) { rrc_log->console("HO %ssuccessful\n", ra_successful?"":"un"); pending_mob_reconf = false; - state = RRC_STATE_CONNECTED; + if (ra_successful) { + state = RRC_STATE_CONNECTED; + } } else { rrc_log->error("Received HO random access completed but no pending mobility reconfiguration info\n"); } diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index 54b07f8ef..444f9e156 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -154,6 +154,10 @@ enable = false # average_subframe_enabled: Averages in the time domain the channel estimates within 1 subframe. # Needs accurate CFO correction. # +# sic_pss_enabled: Applies Successive Interference Cancellation to PSS signals when searching for neighbour cells. +# Must be disabled if cells have identical channel and timing, for instance if generated from +# the same source. +# # metrics_csv_enable: Write UE metrics to CSV file. # # metrics_csv_filename: File path to use for CSV metrics. @@ -191,6 +195,7 @@ enable = false #sss_algorithm = full #estimator_fil_w = 0.1 #average_subframe_enabled = false +#sic_pss_enabled = true #pregenerate_signals = false #metrics_csv_enable = false #metrics_csv_filename = /tmp/ue_metrics.csv From 78bd71dfa93a4c1ef889e62286f5c14f49217964 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Mon, 4 Dec 2017 11:58:16 -0600 Subject: [PATCH 193/242] Fixed ul retx when not needed --- srsue/hdr/mac/ul_harq.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/srsue/hdr/mac/ul_harq.h b/srsue/hdr/mac/ul_harq.h index d162d35a2..bd38fca97 100644 --- a/srsue/hdr/mac/ul_harq.h +++ b/srsue/hdr/mac/ul_harq.h @@ -219,7 +219,7 @@ private: // Receive and route HARQ feedbacks if (grant) { - if ((!(grant->rnti_type == SRSLTE_RNTI_TEMP) && grant->ndi[0] != get_ndi() && ack) || + if ((!(grant->rnti_type == SRSLTE_RNTI_TEMP) && grant->ndi[0] != get_ndi() && harq_feedback) || (grant->rnti_type == SRSLTE_RNTI_USER && !has_grant()) || grant->is_from_rar) { @@ -327,12 +327,12 @@ private: current_irv = irv_of_rv[grant->rv[0]%4]; } + Info("UL %d: Adaptive retx=%d, RV=%d, TBS=%d, HI=%s, ndi=%d, prev_ndi=%d\n", + pid, current_tx_nb, get_rv(), grant->n_bytes[0], harq_feedback?"ACK":"NACK", grant->ndi[0], cur_grant.ndi[0]); + memcpy(&cur_grant, grant, sizeof(Tgrant)); harq_feedback = false; - Info("UL %d: Adaptive retx=%d, RV=%d, TBS=%d, HI=%s\n", - pid, current_tx_nb, get_rv(), grant->n_bytes[0], harq_feedback?"ACK":"NACK"); - generate_tx(tti_tx, action); // HARQ entity requests a non-adaptive transmission From 0bd683b3c4455e1274450d4487a6077f231f0ba5 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 14 Nov 2017 17:11:48 +0100 Subject: [PATCH 194/242] Added UE Mode 3-1 aperiodic reporting --- lib/include/srslte/phy/phch/cqi.h | 21 +++- lib/include/srslte/phy/phch/uci.h | 1 + lib/src/phy/phch/cqi.c | 73 +++++++++++-- lib/src/phy/phch/pucch.c | 2 +- lib/src/phy/ue/ue_dl.c | 4 +- lib/src/phy/ue/ue_ul.c | 28 +++-- srsenb/src/phy/phch_worker.cc | 2 +- srsue/hdr/phy/phch_worker.h | 3 +- srsue/src/phy/phch_worker.cc | 175 ++++++++++++++++++++---------- 9 files changed, 221 insertions(+), 88 deletions(-) diff --git a/lib/include/srslte/phy/phch/cqi.h b/lib/include/srslte/phy/phch/cqi.h index cfc9e92e7..0d0c17fec 100644 --- a/lib/include/srslte/phy/phch/cqi.h +++ b/lib/include/srslte/phy/phch/cqi.h @@ -55,13 +55,22 @@ typedef struct { } srslte_cqi_periodic_cfg_t; /* Table 5.2.2.6.2-1: Fields for channel quality information feedback for higher layer configured subband -CQI reports -(transmission mode 1, transmission mode 2, transmission mode 3, transmission mode 7 and -transmission mode 8 configured without PMI/RI reporting). */ + CQI reports (transmission mode 1, transmission mode 2, transmission mode 3, transmission mode 7 and + transmission mode 8 configured without PMI/RI reporting). */ + +/* Table 5.2.2.6.2-2: Fields for channel quality information (CQI) feedback for higher layer configured subband CQI + reports (transmission mode 4, transmission mode 5 and transmission mode 6). */ + typedef struct SRSLTE_API { - uint8_t wideband_cqi; // 4-bit width - uint32_t subband_diff_cqi; // 2N-bit width - uint32_t N; + uint8_t wideband_cqi_cw0; // 4-bit width + uint32_t subband_diff_cqi_cw0; // 2N-bit width + uint8_t wideband_cqi_cw1; // if RI > 1 then 4-bit width otherwise 0-bit width + uint32_t subband_diff_cqi_cw1; // if RI > 1 then 2N-bit width otherwise 0-bit width + uint32_t pmi; // if RI > 1 then 2-bit width otherwise 1-bit width + uint32_t N; + bool pmi_present; + bool four_antenna_ports; // If cell has 4 antenna ports then true otherwise false + bool rank_is_not_one; // If rank > 1 then true otherwise false } srslte_cqi_hl_subband_t; /* Table 5.2.2.6.3-1: Fields for channel quality information feedback for UE selected subband CQI diff --git a/lib/include/srslte/phy/phch/uci.h b/lib/include/srslte/phy/phch/uci.h index ff315384e..91592501f 100644 --- a/lib/include/srslte/phy/phch/uci.h +++ b/lib/include/srslte/phy/phch/uci.h @@ -73,6 +73,7 @@ typedef struct SRSLTE_API { uint8_t uci_ack; // 1st codeword bit for HARQ-ACK uint8_t uci_ack_2; // 2st codeword bit for HARQ-ACK uint32_t uci_ack_len; + bool ri_periodic_report; bool scheduling_request; bool channel_selection; bool cqi_ack; diff --git a/lib/src/phy/phch/cqi.c b/lib/src/phy/phch/cqi.c index 0041c3fcb..2c0940af5 100644 --- a/lib/src/phy/phch/cqi.c +++ b/lib/src/phy/phch/cqi.c @@ -44,11 +44,38 @@ *******************************************************/ int srslte_cqi_hl_subband_pack(srslte_cqi_hl_subband_t *msg, uint8_t buff[SRSLTE_CQI_MAX_BITS]) { - uint8_t *body_ptr = buff; - srslte_bit_unpack(msg->wideband_cqi, &body_ptr, 4); - srslte_bit_unpack(msg->subband_diff_cqi, &body_ptr, 2*msg->N); - - return 4+2*msg->N; + uint8_t *body_ptr = buff; + uint32_t bit_count = 0; + + /* Unpack codeword 0, common for 3GPP 36.212 Tables 5.2.2.6.2-1 and 5.2.2.6.2-2 */ + srslte_bit_unpack(msg->wideband_cqi_cw0, &body_ptr, 4); + srslte_bit_unpack(msg->subband_diff_cqi_cw0, &body_ptr, 2*msg->N); + bit_count += 4+2*msg->N; + + /* Unpack codeword 1, 3GPP 36.212 Table 5.2.2.6.2-2 */ + if (msg->rank_is_not_one) { + srslte_bit_unpack(msg->wideband_cqi_cw1, &body_ptr, 4); + srslte_bit_unpack(msg->subband_diff_cqi_cw1, &body_ptr, 2*msg->N); + bit_count += 4+2*msg->N; + } + + /* If PMI is present, unpack it */ + if (msg->pmi_present) { + if (msg->four_antenna_ports) { + srslte_bit_unpack(msg->pmi, &body_ptr, 4); + bit_count += 4; + } else { + if (msg->rank_is_not_one) { + srslte_bit_unpack(msg->pmi, &body_ptr, 1); + bit_count += 1; + } else { + srslte_bit_unpack(msg->pmi, &body_ptr, 2); + bit_count += 2; + } + } + } + + return bit_count; } int srslte_cqi_ue_subband_pack(srslte_cqi_ue_subband_t *msg, uint8_t buff[SRSLTE_CQI_MAX_BITS]) @@ -98,11 +125,37 @@ int srslte_cqi_value_pack(srslte_cqi_value_t *value, uint8_t buff[SRSLTE_CQI_MAX int srslte_cqi_hl_subband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_hl_subband_t *msg) { - uint8_t *body_ptr = buff; - msg->wideband_cqi = srslte_bit_pack(&body_ptr, 4); - msg->subband_diff_cqi = srslte_bit_pack(&body_ptr, 2*msg->N); - - return 4+2*msg->N; + uint8_t *body_ptr = buff; + uint32_t bit_count = 0; + + msg->wideband_cqi_cw0 = (uint8_t) srslte_bit_pack(&body_ptr, 4); + msg->subband_diff_cqi_cw0 = srslte_bit_pack(&body_ptr, 2*msg->N); + bit_count += 4+2*msg->N; + + /* Unpack codeword 1, 3GPP 36.212 Table 5.2.2.6.2-2 */ + if (msg->rank_is_not_one) { + msg->wideband_cqi_cw1 = (uint8_t) srslte_bit_pack(&body_ptr, 4); + msg->subband_diff_cqi_cw1 = srslte_bit_pack(&body_ptr, 2*msg->N); + bit_count += 4+2*msg->N; + } + + /* If PMI is present, unpack it */ + if (msg->pmi_present) { + if (msg->four_antenna_ports) { + msg->pmi = (uint8_t) srslte_bit_pack(&body_ptr, 4); + bit_count += 4; + } else { + if (msg->rank_is_not_one) { + msg->pmi = (uint8_t) srslte_bit_pack(&body_ptr, 1); + bit_count += 1; + } else { + msg->pmi = (uint8_t) srslte_bit_pack(&body_ptr, 2); + bit_count += 2; + } + } + } + + return bit_count; } int srslte_cqi_ue_subband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_ue_subband_t *msg) diff --git a/lib/src/phy/phch/pucch.c b/lib/src/phy/phch/pucch.c index f9c6bebc1..f9c05104c 100644 --- a/lib/src/phy/phch/pucch.c +++ b/lib/src/phy/phch/pucch.c @@ -173,7 +173,7 @@ srslte_pucch_format_t srslte_pucch_get_format(srslte_uci_data_t *uci_data, srslt { srslte_pucch_format_t format = SRSLTE_PUCCH_FORMAT_ERROR; // No CQI data - if (uci_data->uci_cqi_len == 0) { + if (uci_data->uci_cqi_len == 0 && uci_data->uci_ri_len == 0) { // 1-bit ACK + optional SR if (uci_data->uci_ack_len == 1) { format = SRSLTE_PUCCH_FORMAT_1A; diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index 134c19ca6..db7118b0c 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -740,6 +740,7 @@ int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, uint8_t *ri, uint8_t *pmi, flo } /* Set RI */ + q->ri = best_ri; if (ri != NULL) { *ri = best_ri; } @@ -775,9 +776,10 @@ int srslte_ue_dl_ri_select(srslte_ue_dl_t *q, uint8_t *ri, float *cn) { *cn = _cn; } + q->ri = (uint8_t)((_cn < 17.0f)? 1:0); /* Set rank indicator */ if (!ret && ri) { - *ri = (uint8_t)((_cn < 17.0f)? 1:0); + *ri = (uint8_t) q->ri; } return ret; diff --git a/lib/src/phy/ue/ue_ul.c b/lib/src/phy/ue/ue_ul.c index bb4fd57ae..736fc3470 100644 --- a/lib/src/phy/ue/ue_ul.c +++ b/lib/src/phy/ue/ue_ul.c @@ -273,21 +273,33 @@ int srslte_ue_ul_cfg_grant(srslte_ue_ul_t *q, srslte_ra_ul_grant_t *grant, void pucch_encode_bits(srslte_uci_data_t *uci_data, srslte_pucch_format_t format, uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS], uint8_t pucch2_bits[SRSLTE_PUCCH_MAX_BITS]) -{ +{ + uint8_t uci_buffer[SRSLTE_CQI_MAX_BITS]; + uint8_t uci_buffer_len = 0; + if (format == SRSLTE_PUCCH_FORMAT_1A || format == SRSLTE_PUCCH_FORMAT_1B) { pucch_bits[0] = uci_data->uci_ack; pucch_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 1a } if (format >= SRSLTE_PUCCH_FORMAT_2) { - /* Append Differential CQI */ - memcpy(&uci_data->uci_cqi[uci_data->uci_cqi_len], uci_data->uci_dif_cqi, uci_data->uci_dif_cqi_len); - uci_data->uci_cqi_len += uci_data->uci_dif_cqi_len; + /* Put RI (goes alone) */ + if (uci_data->ri_periodic_report) { + uci_buffer[0] = uci_data->uci_ri; // It assumes only 1 bit of RI + uci_buffer_len += uci_data->uci_ri_len; + } else { + /* Append CQI */ + memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_cqi, uci_data->uci_cqi_len); + uci_buffer_len += uci_data->uci_cqi_len; - /* Append PMI */ - memcpy(&uci_data->uci_cqi[uci_data->uci_cqi_len], uci_data->uci_pmi, uci_data->uci_pmi_len); - uci_data->uci_cqi_len += uci_data->uci_pmi_len; + /* Append Differential CQI */ + memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_dif_cqi, uci_data->uci_dif_cqi_len); + uci_buffer_len += uci_data->uci_dif_cqi_len; - srslte_uci_encode_cqi_pucch(uci_data->uci_cqi, uci_data->uci_cqi_len, pucch_bits); + /* Append PMI */ + memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_pmi, uci_data->uci_pmi_len); + uci_buffer_len += uci_data->uci_pmi_len; + } + srslte_uci_encode_cqi_pucch(uci_buffer, uci_buffer_len, pucch_bits); if (format > SRSLTE_PUCCH_FORMAT_2) { pucch2_bits[0] = uci_data->uci_ack; pucch2_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 2a diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index c023c13e0..5298e6e7a 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -461,7 +461,7 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) if (ue_db[rnti].cqi_en) { wideband_cqi_value = cqi_value.wideband.wideband_cqi; } else if (grants[i].grant.cqi_request) { - wideband_cqi_value = cqi_value.subband_hl.wideband_cqi; + wideband_cqi_value = cqi_value.subband_hl.wideband_cqi_cw0; } snprintf(cqi_str, 64, ", cqi=%d", wideband_cqi_value); } diff --git a/srsue/hdr/phy/phch_worker.h b/srsue/hdr/phy/phch_worker.h index 4f8df27db..5378a9428 100644 --- a/srsue/hdr/phy/phch_worker.h +++ b/srsue/hdr/phy/phch_worker.h @@ -76,7 +76,8 @@ private: /* Internal methods */ bool extract_fft_and_pdcch_llr(); - + void compute_ri(); + /* ... for DL */ bool decode_pdcch_ul(mac_interface_phy::mac_grant_t *grant); bool decode_pdcch_dl(mac_interface_phy::mac_grant_t *grant); diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 27503c9f7..0068724b4 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -272,39 +272,6 @@ void phch_worker::work_imp() if (dl_action.generate_ack) { set_uci_ack(dl_ack, dl_mac_grant.tb_en); } - - /* Select Rank Indicator by computing Condition Number */ - if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) { - if (ue_dl.nof_rx_antennas > 1) { - /* If 2 ort more receiving antennas, select RI */ - float cn = 0.0f; - srslte_ue_dl_ri_select(&ue_dl, &uci_data.uci_ri, &cn); - uci_data.uci_ri_len = 1; - } else { - /* If only one receiving antenna, force RI for 1 layer */ - uci_data.uci_ri = 0; - uci_data.uci_ri_len = 1; - Warning("Only one receiving antenna with TM3. Forcing RI=1 layer.\n"); - } - } else if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4){ - float sinr = 0.0f; - uint8 packed_pmi = 0; - srslte_ue_dl_ri_pmi_select(&ue_dl, &uci_data.uci_ri, &packed_pmi, &sinr); - srslte_bit_unpack_vector(&packed_pmi, uci_data.uci_pmi, 2); - uci_data.uci_ri_len = 1; - if (uci_data.uci_ri == 0) { - uci_data.uci_pmi_len = 2; - uci_data.uci_dif_cqi_len = 0; - } else { - uci_data.uci_pmi_len = 1; - uci_data.uci_dif_cqi_len = 3; - } - - /* If only one antenna in TM4 print limitation warning */ - if (ue_dl.nof_rx_antennas < 2) { - Warning("Only one receiving antenna with TM4. Forcing RI=1 layer (PMI=%d).\n", packed_pmi); - } - } } } @@ -360,7 +327,7 @@ void phch_worker::work_imp() phy->set_pending_ack(TTI_RX_ACK(tti), ue_ul.pusch_cfg.grant.n_prb_tilde[0], ul_action.phy_grant.ul.ncs_dmrs); } - } else if (dl_action.generate_ack || uci_data.scheduling_request || uci_data.uci_cqi_len > 0) { + } else if (dl_action.generate_ack || uci_data.scheduling_request || uci_data.uci_cqi_len > 0 || uci_data.uci_ri_len > 0) { encode_pucch(); signal_ready = true; } else if (srs_is_ready_to_send()) { @@ -410,6 +377,42 @@ void phch_worker::work_imp() #endif } +void phch_worker::compute_ri() { + if (uci_data.uci_ri_len > 0) { + /* Do nothing */ + } else if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) { + if (ue_dl.nof_rx_antennas > 1) { + /* If 2 ort more receiving antennas, select RI */ + float cn = 0.0f; + srslte_ue_dl_ri_select(&ue_dl, &uci_data.uci_ri, &cn); + Info("RI select %d layers, κ=%fdB\n", uci_data.uci_ri + 1, cn); + } else { + /* If only one receiving antenna, force RI for 1 layer */ + uci_data.uci_ri = 0; + Warning("Only one receiving antenna with TM3. Forcing RI=1 layer.\n"); + } + uci_data.uci_ri_len = 1; + } else if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { + float sinr = 0.0f; + uint8 packed_pmi = 0; + srslte_ue_dl_ri_pmi_select(&ue_dl, &uci_data.uci_ri, &packed_pmi, &sinr); + if (uci_data.uci_ri == 0) { + uci_data.uci_pmi_len = 2; + uci_data.uci_dif_cqi_len = 0; + } else { + uci_data.uci_pmi_len = 1; + uci_data.uci_dif_cqi_len = 3; + } + srslte_bit_unpack_vector(&packed_pmi, uci_data.uci_pmi, uci_data.uci_pmi_len); + Info("ri=%d; pmi=%d; SINR=%.1fdB\n", ue_dl.ri, ue_dl.pmi[ue_dl.ri], 10*log10f(ue_dl.sinr[ue_dl.ri][ue_dl.pmi[ue_dl.ri]])); + + /* If only one antenna in TM4 print limitation warning */ + if (ue_dl.nof_rx_antennas < 2) { + Warning("Only one receiving antenna with TM4. Forcing RI=1 layer (PMI=%d).\n", packed_pmi); + } + uci_data.uci_ri_len = 1; + } +} bool phch_worker::extract_fft_and_pdcch_llr() { bool decode_pdcch = true; @@ -823,21 +826,15 @@ void phch_worker::reset_uci() void phch_worker::set_uci_ack(bool ack[SRSLTE_MAX_CODEWORDS], bool tb_en[SRSLTE_MAX_CODEWORDS]) { - uint32_t nof_tb = 0; - if (tb_en[0]) { - uci_data.uci_ack = (uint8_t) ((ack[0]) ? 1 : 0); - nof_tb = 1; - } else { - uci_data.uci_ack = 1; - } - - if (tb_en[1]) { - uci_data.uci_ack_2 = (uint8_t) ((ack[1]) ? 1 : 0); - nof_tb = 2; + /* Map ACK according to 3GPP 36.212 clause 5.2.3.1 */ + uint32_t nof_ack = 0; + for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { + if (tb_en[tb]) { + ((nof_ack == 0)?uci_data.uci_ack:uci_data.uci_ack_2) = (uint8_t)(ack[tb]?1:0); + nof_ack++; + } } - - uci_data.uci_ack_len = nof_tb; - + uci_data.uci_ack_len = nof_ack; } void phch_worker::set_uci_sr() @@ -862,14 +859,9 @@ void phch_worker::set_uci_periodic_cqi() if (period_cqi.configured && rnti_is_set) { if (period_cqi.ri_idx_present && srslte_ri_send(period_cqi.pmi_idx, period_cqi.ri_idx, TTI_TX(tti))) { - if (uci_data.uci_ri_len) { - uci_data.uci_cqi[0] = uci_data.uci_ri; - uci_data.uci_cqi_len = uci_data.uci_ri_len; - uci_data.uci_ri_len = 0; - uci_data.uci_dif_cqi_len = 0; - uci_data.uci_pmi_len = 0; - Info("PUCCH: Periodic RI=%d\n", uci_data.uci_cqi[0]); - } + compute_ri(); + uci_data.ri_periodic_report = true; + Info("PUCCH: Periodic RI=%d\n", uci_data.uci_ri); } else if (srslte_cqi_send(period_cqi.pmi_idx, TTI_TX(tti))) { srslte_cqi_value_t cqi_report; if (period_cqi.format_is_subband) { @@ -891,6 +883,16 @@ void phch_worker::set_uci_periodic_cqi() } Info("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.wideband.wideband_cqi, phy->avg_snr_db); } + if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { + if (ue_dl.ri == 0) { + uci_data.uci_pmi_len = 2; + } else { + uci_data.uci_pmi_len = 1; + uci_data.uci_dif_cqi_len = 3; + } + uint8_t *ptr = uci_data.uci_pmi; + srslte_bit_unpack(ue_dl.pmi[ue_dl.ri], &ptr, uci_data.uci_pmi_len); + } uci_data.uci_cqi_len = srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi); rar_cqi_request = false; } @@ -912,18 +914,71 @@ void phch_worker::set_uci_aperiodic_cqi() reported RI. For other transmission modes they are reported conditioned on rank 1. */ if (rnti_is_set) { - srslte_cqi_value_t cqi_report; + srslte_cqi_value_t cqi_report = {0}; cqi_report.type = SRSLTE_CQI_TYPE_SUBBAND_HL; - cqi_report.subband_hl.wideband_cqi = srslte_cqi_from_snr(phy->avg_snr_db); + cqi_report.subband_hl.wideband_cqi_cw0 = srslte_cqi_from_snr(phy->avg_snr_db); // TODO: implement subband CQI properly - cqi_report.subband_hl.subband_diff_cqi = 0; // Always report zero offset on all subbands + cqi_report.subband_hl.subband_diff_cqi_cw0 = 0; // Always report zero offset on all subbands cqi_report.subband_hl.N = (cell.nof_prb > 7) ? srslte_cqi_hl_get_no_subbands(cell.nof_prb) : 0; Info("PUSCH: Aperiodic CQI=%d, SNR=%.1f dB, for %d subbands\n", cqi_report.wideband.wideband_cqi, phy->avg_snr_db, cqi_report.subband_hl.N); uci_data.uci_cqi_len = srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi); } break; + case LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM31: + /* only Higher Layer-configured subband feedback support right now, according to TS36.213 section 7.2.1 + - A single precoding matrix is selected from the codebook subset assuming transmission on set S subbands + - A UE shall report one subband CQI value per codeword for each set S subband which are calculated assuming + the use of the single precoding matrix in all subbands and assuming transmission in the corresponding + subband. + - A UE shall report a wideband CQI value per codeword which is calculated assuming the use of the single + precoding matrix in all subbands and transmission on set S subbands + - The UE shall report the single selected precoding matrix indicator. + - For transmission mode 4 the reported PMI and CQI values are calculated conditioned on the reported RI. For + other transmission modes they are reported conditioned on rank 1. + */ + if (rnti_is_set) { + /* Compute RI, PMI and SINR */ + compute_ri(); + + /* Select RI, PMI and SINR */ + uint32_t ri = ue_dl.ri; // Select RI (0: 1 layer, 1: 2 layer, otherwise: not implemented) + uint32_t pmi = ue_dl.pmi[ri]; // Select PMI + float sinr_db = 10 * log10(ue_dl.sinr[ri][pmi]); + + /* Fill CQI Report */ + srslte_cqi_value_t cqi_report = {0}; + cqi_report.type = SRSLTE_CQI_TYPE_SUBBAND_HL; + + cqi_report.subband_hl.wideband_cqi_cw0 = srslte_cqi_from_snr(sinr_db); + cqi_report.subband_hl.subband_diff_cqi_cw0 = 0; // Always report zero offset on all subbands + + if (ri > 0) { + cqi_report.subband_hl.rank_is_not_one = true; + cqi_report.subband_hl.wideband_cqi_cw1 = srslte_cqi_from_snr(sinr_db); + cqi_report.subband_hl.subband_diff_cqi_cw1 = 0; // Always report zero offset on all subbands + } + + cqi_report.subband_hl.pmi = pmi; + cqi_report.subband_hl.pmi_present = true; + cqi_report.subband_hl.four_antenna_ports = (cell.nof_ports == 4); + + // TODO: implement subband CQI properly + cqi_report.subband_hl.N = (uint32_t) ((cell.nof_prb > 7) ? srslte_cqi_hl_get_no_subbands(cell.nof_prb) : 0); + + if (cqi_report.subband_hl.rank_is_not_one) { + Info("PUSCH: Aperiodic ri~1, CQI=%02d/%02d, SINR=%2.1f/%2.1fdB, pmi=%d for %d subbands\n", + cqi_report.subband_hl.wideband_cqi_cw0, cqi_report.subband_hl.wideband_cqi_cw1, + sinr_db, sinr_db, pmi, cqi_report.subband_hl.N); + } else { + Info("PUSCH: Aperiodic ri=1, CQI=%d/%d, SINR=%2.1f dB, for %d subbands\n", + cqi_report.wideband.wideband_cqi, + phy->avg_snr_db, cqi_report.subband_hl.N); + } + uci_data.uci_cqi_len = srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi); + } + break; default: Warning("Received CQI request but mode %s is not supported\n", liblte_rrc_cqi_report_mode_aperiodic_text[phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic]); @@ -1006,7 +1061,7 @@ void phch_worker::encode_pucch() char timestr[64]; timestr[0]='\0'; - if (uci_data.scheduling_request || uci_data.uci_ack_len > 0 || uci_data.uci_cqi_len > 0) + if (uci_data.scheduling_request || uci_data.uci_ack_len > 0 || uci_data.uci_cqi_len > 0 || uci_data.uci_ri_len > 0) { // Drop CQI if there is collision with ACK From 8ab196901f83caef3759e89b98b1b3b10d26cd1b Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 16 Nov 2017 14:48:03 +0100 Subject: [PATCH 195/242] Added Aperiodic mode 3-1 in enb and some more optimizations --- lib/include/srslte/phy/enb/enb_ul.h | 1 + lib/include/srslte/phy/phch/pusch.h | 1 + lib/include/srslte/phy/phch/uci.h | 36 ++- lib/src/phy/enb/enb_ul.c | 45 +++- lib/src/phy/phch/cqi.c | 37 ++- lib/src/phy/phch/pusch.c | 35 ++- lib/src/phy/phch/sch.c | 19 +- lib/src/phy/phch/test/pusch_test.c | 2 +- lib/src/phy/phch/uci.c | 230 ++++++++---------- lib/src/phy/ue/ue_dl.c | 3 +- srsenb/src/phy/phch_worker.cc | 362 +++++++++++++++++++--------- srsenb/src/upper/rrc.cc | 6 +- srsue/src/phy/phch_worker.cc | 14 +- 13 files changed, 491 insertions(+), 300 deletions(-) diff --git a/lib/include/srslte/phy/enb/enb_ul.h b/lib/include/srslte/phy/enb/enb_ul.h index 0957ccbc0..1b865b7f7 100644 --- a/lib/include/srslte/phy/enb/enb_ul.h +++ b/lib/include/srslte/phy/enb/enb_ul.h @@ -141,6 +141,7 @@ SRSLTE_API int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q, uint32_t rv_idx, uint32_t current_tx_nb, uint8_t *data, + srslte_cqi_value_t *cqi_value, srslte_uci_data_t *uci_data, uint32_t tti); diff --git a/lib/include/srslte/phy/phch/pusch.h b/lib/include/srslte/phy/phch/pusch.h index 2328c8ff3..01db068a5 100644 --- a/lib/include/srslte/phy/phch/pusch.h +++ b/lib/include/srslte/phy/phch/pusch.h @@ -142,6 +142,7 @@ SRSLTE_API int srslte_pusch_decode(srslte_pusch_t *q, float noise_estimate, uint16_t rnti, uint8_t *data, + srslte_cqi_value_t *cqi_value, srslte_uci_data_t *uci_data); SRSLTE_API float srslte_pusch_average_noi(srslte_pusch_t *q); diff --git a/lib/include/srslte/phy/phch/uci.h b/lib/include/srslte/phy/phch/uci.h index 91592501f..8e72b5793 100644 --- a/lib/include/srslte/phy/phch/uci.h +++ b/lib/include/srslte/phy/phch/uci.h @@ -131,31 +131,25 @@ SRSLTE_API int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, uint32_t H_prime_total, srslte_uci_bit_t *ri_bits); -SRSLTE_API int srslte_uci_decode_ack(srslte_pusch_cfg_t *cfg, - int16_t *q_bits, - uint8_t *c_seq, - float beta, - uint32_t H_prime_total, - uint32_t O_cqi, - srslte_uci_bit_t *ack_bits, - uint8_t acks[2], - uint32_t nof_acks); - -SRSLTE_API int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg, - uint8_t data, +SRSLTE_API int srslte_uci_encode_ack_ri(srslte_pusch_cfg_t *cfg, + uint8_t *data, + uint32_t data_len, uint32_t O_cqi, float beta, uint32_t H_prime_total, - srslte_uci_bit_t *ri_bits); - -SRSLTE_API int srslte_uci_decode_ri(srslte_pusch_cfg_t *cfg, - int16_t *q_bits, - uint8_t *c_seq, - float beta, - uint32_t H_prime_total, - uint32_t O_cqi, srslte_uci_bit_t *ri_bits, - uint8_t *data); + bool is_ri); + +SRSLTE_API int srslte_uci_decode_ack_ri(srslte_pusch_cfg_t *cfg, + int16_t *q_bits, + uint8_t *c_seq, + float beta, + uint32_t H_prime_total, + uint32_t O_cqi, + srslte_uci_bit_t *ack_ri_bits, + uint8_t data[2], + uint32_t nof_bits, + bool is_ri); #endif diff --git a/lib/src/phy/enb/enb_ul.c b/lib/src/phy/enb/enb_ul.c index f94eb0277..8ea5dd3e4 100644 --- a/lib/src/phy/enb/enb_ul.c +++ b/lib/src/phy/enb/enb_ul.c @@ -253,18 +253,22 @@ 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) +void srslte_enb_ul_fft(srslte_enb_ul_t *q) { srslte_ofdm_rx_sf(&q->fft); } int get_pucch(srslte_enb_ul_t *q, uint16_t rnti, uint32_t pdcch_n_cce, uint32_t sf_rx, - srslte_uci_data_t *uci_data, uint8_t bits[SRSLTE_PUCCH_MAX_BITS]) + srslte_uci_data_t *uci_data, uint8_t bits[SRSLTE_PUCCH_MAX_BITS], uint32_t nof_bits) { float noise_power = srslte_chest_ul_get_noise_estimate(&q->chest); srslte_pucch_format_t format = srslte_pucch_get_format(uci_data, q->cell.cp); + if (format == SRSLTE_PUCCH_FORMAT_ERROR) { + fprintf(stderr,"Error getting format\n"); + return SRSLTE_ERROR; + } uint32_t n_pucch = srslte_pucch_get_npucch(pdcch_n_cce, format, uci_data->scheduling_request, &q->users[rnti]->pucch_sched); @@ -273,7 +277,7 @@ int get_pucch(srslte_enb_ul_t *q, uint16_t rnti, return SRSLTE_ERROR; } - int ret_val = srslte_pucch_decode(&q->pucch, format, n_pucch, sf_rx, rnti, q->sf_symbols, q->ce, noise_power, bits); + int ret_val = srslte_pucch_decode(&q->pucch, format, n_pucch, sf_rx, rnti, q->sf_symbols, q->ce, noise_power, bits, nof_bits); if (ret_val < 0) { fprintf(stderr,"Error decoding PUCCH\n"); return SRSLTE_ERROR; @@ -286,16 +290,18 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti, srslte_uci_data_t *uci_data) { uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS]; - - if (q->users[rnti]) { - int ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, pucch_bits); + if (q->users[rnti]) { + uint32_t nof_uci_bits = uci_data->ri_periodic_report ? uci_data->uci_ri_len : (uci_data->uci_cqi_len + + uci_data->uci_dif_cqi_len + + uci_data->uci_pmi_len); + int ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, pucch_bits, nof_uci_bits); // If we are looking for SR and ACK at the same time and ret=0, means there is no SR. // try again to decode ACK only if (uci_data->scheduling_request && uci_data->uci_ack_len && ret_val != 1) { uci_data->scheduling_request = false; - ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, pucch_bits); + ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, pucch_bits, nof_uci_bits); } // update schedulign request @@ -305,12 +311,32 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti, // Save ACK bits if (uci_data->uci_ack_len > 0) { - uci_data->uci_ack = pucch_bits[0]; + uci_data->uci_ack = pucch_bits[0]; + } + + if (uci_data->uci_ack_len > 1) { + uci_data->uci_ack_2 = pucch_bits[1]; } // PUCCH2 CQI bits are decoded inside srslte_pucch_decode() if (uci_data->uci_cqi_len) { memcpy(uci_data->uci_cqi, pucch_bits, uci_data->uci_cqi_len*sizeof(uint8_t)); + } + + if (uci_data->uci_dif_cqi_len) { + memcpy(uci_data->uci_dif_cqi, pucch_bits + uci_data->uci_cqi_len, uci_data->uci_dif_cqi_len*sizeof(uint8_t)); + } + + if (uci_data->uci_pmi_len) { + memcpy(uci_data->uci_pmi, pucch_bits + uci_data->uci_cqi_len + uci_data->uci_dif_cqi_len, + uci_data->uci_pmi_len*sizeof(uint8_t)); + } + + if (uci_data->uci_ri_len) { + uci_data->uci_ri = pucch_bits[0]; /* Assume only one bit of RI */ + } + + if (uci_data->uci_cqi_len || uci_data->uci_ri_len) { if (uci_data->uci_ack_len >= 1) { uci_data->uci_ack = pucch_bits[20]; } @@ -328,7 +354,7 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti, int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q, srslte_ra_ul_grant_t *grant, srslte_softbuffer_rx_t *softbuffer, uint16_t rnti, uint32_t rv_idx, uint32_t current_tx_nb, - uint8_t *data, srslte_uci_data_t *uci_data, uint32_t tti) + uint8_t *data, srslte_cqi_value_t *cqi_value, srslte_uci_data_t *uci_data, uint32_t tti) { if (q->users[rnti]) { if (srslte_pusch_cfg(&q->pusch, @@ -364,6 +390,7 @@ int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q, srslte_ra_ul_grant_t *grant, srs softbuffer, q->sf_symbols, q->ce, noise_power, rnti, data, + cqi_value, uci_data); } diff --git a/lib/src/phy/phch/cqi.c b/lib/src/phy/phch/cqi.c index 2c0940af5..8589ee51a 100644 --- a/lib/src/phy/phch/cqi.c +++ b/lib/src/phy/phch/cqi.c @@ -199,17 +199,44 @@ int srslte_cqi_value_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_value_ } int srslte_cqi_size(srslte_cqi_value_t *value) { + int size = 0; + switch(value->type) { case SRSLTE_CQI_TYPE_WIDEBAND: - return 4; + size = 4; + break; case SRSLTE_CQI_TYPE_SUBBAND: - return 4+(value->subband.subband_label_2_bits)?2:1; + size = 4 + (value->subband.subband_label_2_bits) ? 2 : 1; + break; case SRSLTE_CQI_TYPE_SUBBAND_UE: - return 4+2+value->subband_ue.L; + size = 4 + 2 + value->subband_ue.L; + break; case SRSLTE_CQI_TYPE_SUBBAND_HL: - return 4+2*value->subband_hl.N; + /* First codeword */ + size += 4 + 2 * value->subband_hl.N; + + /* Add Second codeword if required */ + if (value->subband_hl.rank_is_not_one && value->subband_hl.pmi_present) { + size += 4 + 2 * value->subband_hl.N; + } + + /* Add PMI if required*/ + if (value->subband_hl.pmi_present) { + if (value->subband_hl.four_antenna_ports) { + size += 4; + } else { + if (value->subband_hl.rank_is_not_one) { + size += 1; + } else { + size += 2; + } + } + } + break; + default: + size = SRSLTE_ERROR; } - return -1; + return size; } static bool srslte_cqi_get_N(uint32_t I_cqi_pmi, uint32_t *N_p, uint32_t *N_offset) { diff --git a/lib/src/phy/phch/pusch.c b/lib/src/phy/phch/pusch.c index a8c6064fc..7876a4f86 100644 --- a/lib/src/phy/phch/pusch.c +++ b/lib/src/phy/phch/pusch.c @@ -566,9 +566,9 @@ int srslte_pusch_decode(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, cf_t *sf_symbols, cf_t *ce, float noise_estimate, uint16_t rnti, - uint8_t *data, srslte_uci_data_t *uci_data) + uint8_t *data, srslte_cqi_value_t *cqi_value, srslte_uci_data_t *uci_data) { - + int ret = SRSLTE_ERROR_INVALID_INPUTS; uint32_t n; if (q != NULL && @@ -607,19 +607,42 @@ int srslte_pusch_decode(srslte_pusch_t *q, // Generate scrambling sequence if not pre-generated srslte_sequence_t *seq = get_user_sequence(q, rnti, cfg->sf_idx, cfg->nbits.nof_bits); + // Set CQI len assuming RI = 1 (3GPP 36.212 Clause 5.2.4.1. Uplink control information on PUSCH without UL-SCH data) + if (cqi_value) { + if (cqi_value->type == SRSLTE_CQI_TYPE_SUBBAND_HL) { + cqi_value->subband_hl.rank_is_not_one = false; + } + uci_data->uci_cqi_len = (uint32_t) srslte_cqi_size(cqi_value); + uci_data->uci_ri_len = (q->cell.nof_ports == 4) ? 2 : 1; + } + // Decode RI/HARQ bits before descrambling if (srslte_ulsch_uci_decode_ri_ack(&q->ul_sch, cfg, softbuffer, q->q, seq->c, uci_data)) { fprintf(stderr, "Error decoding RI/HARQ bits\n"); return SRSLTE_ERROR; } + + // Set CQI len with corresponding RI + if (cqi_value) { + if (cqi_value->type == SRSLTE_CQI_TYPE_SUBBAND_HL) { + cqi_value->subband_hl.rank_is_not_one = (uci_data->uci_ri != 0); + } + uci_data->uci_cqi_len = (uint32_t) srslte_cqi_size(cqi_value); + } // Descrambling srslte_scrambling_s_offset(seq, q->q, 0, cfg->nbits.nof_bits); - - return srslte_ulsch_uci_decode(&q->ul_sch, cfg, softbuffer, q->q, q->g, data, uci_data); - } else { - return SRSLTE_ERROR_INVALID_INPUTS; + + // Decode + ret = srslte_ulsch_uci_decode(&q->ul_sch, cfg, softbuffer, q->q, q->g, data, uci_data); + + // Unpack CQI value if available + if (cqi_value) { + srslte_cqi_value_unpack(uci_data->uci_cqi, cqi_value); + } } + + return ret; } uint32_t srslte_pusch_last_noi(srslte_pusch_t *q) { diff --git a/lib/src/phy/phch/sch.c b/lib/src/phy/phch/sch.c index 930364725..1e972594d 100644 --- a/lib/src/phy/phch/sch.c +++ b/lib/src/phy/phch/sch.c @@ -658,7 +658,7 @@ int srslte_ulsch_uci_decode_ri_ack(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srs if (cfg->cb_segm.tbs == 0) { beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi]; } - ret = srslte_uci_decode_ack(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, acks, uci_data->uci_ack_len); + ret = srslte_uci_decode_ack_ri(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, acks, uci_data->uci_ack_len, false); if (ret < 0) { return ret; } @@ -678,7 +678,7 @@ int srslte_ulsch_uci_decode_ri_ack(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srs if (cfg->cb_segm.tbs == 0) { beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi]; } - ret = srslte_uci_decode_ri(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, &uci_data->uci_ri); + ret = srslte_uci_decode_ack_ri(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, &uci_data->uci_ri, uci_data->uci_ri_len, true); if (ret < 0) { return ret; } @@ -756,13 +756,18 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q, uint32_t nb_q = cfg->nbits.nof_bits; uint32_t Qm = cfg->grant.Qm; - // Encode RI - if (uci_data.uci_ri_len > 0) { + // Encode RI if CQI enabled + if (uci_data.uci_ri_len > 0 || uci_data.uci_cqi_len > 0) { + /* If no RI is reported set it to zero as specified in 3GPP 36.213 clause 7.2.1 */ + if (uci_data.uci_ri_len == 0) { + uci_data.uci_ri = 0; + } float beta = beta_ri_offset[cfg->uci_cfg.I_offset_ri]; if (cfg->cb_segm.tbs == 0) { beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi]; } - ret = srslte_uci_encode_ri(cfg, uci_data.uci_ri, uci_data.uci_cqi_len, beta, nb_q/Qm, q->ack_ri_bits); + uint8_t ri[2] = {uci_data.uci_ri, 0}; + ret = srslte_uci_encode_ack_ri(cfg, ri, uci_data.uci_ri_len, uci_data.uci_cqi_len, beta, nb_q/Qm, q->ack_ri_bits, true); if (ret < 0) { return ret; } @@ -809,8 +814,8 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q, if (cfg->cb_segm.tbs == 0) { beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi]; } - ret = srslte_uci_encode_ack(cfg, acks, uci_data.uci_ack_len, uci_data.uci_cqi_len, - beta, nb_q / Qm, &q->ack_ri_bits[Q_prime_ri * Qm]); + ret = srslte_uci_encode_ack_ri(cfg, acks, uci_data.uci_ack_len, uci_data.uci_cqi_len, + beta, nb_q / Qm, &q->ack_ri_bits[Q_prime_ri * Qm], false); if (ret < 0) { return ret; } diff --git a/lib/src/phy/phch/test/pusch_test.c b/lib/src/phy/phch/test/pusch_test.c index cf0be75c3..651803617 100644 --- a/lib/src/phy/phch/test/pusch_test.c +++ b/lib/src/phy/phch/test/pusch_test.c @@ -252,7 +252,7 @@ int main(int argc, char **argv) { } gettimeofday(&t[1], NULL); - int r = srslte_pusch_decode(&pusch_rx, &cfg, &softbuffer_rx, sf_symbols, ce, 0, rnti, data, &uci_data_rx); + int r = srslte_pusch_decode(&pusch_rx, &cfg, &softbuffer_rx, sf_symbols, ce, 0, rnti, data, NULL, &uci_data_rx); gettimeofday(&t[2], NULL); get_time_interval(t); if (r) { diff --git a/lib/src/phy/phch/uci.c b/lib/src/phy/phch/uci.c index cb09ca08b..8a1a36544 100644 --- a/lib/src/phy/phch/uci.c +++ b/lib/src/phy/phch/uci.c @@ -103,26 +103,29 @@ static uint8_t M_basis_seq_pucch[20][13]={ {1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1}, {1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0}, {1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, - }; + }; void srslte_uci_cqi_pucch_init(srslte_uci_cqi_pucch_t *q) { - uint8_t word[16]; - - uint32_t nwords = 16; - for (uint32_t w=0;wcqi_table[w] = srslte_vec_malloc(SRSLTE_UCI_CQI_CODED_PUCCH_B*sizeof(int8_t)); - q->cqi_table_s[w] = srslte_vec_malloc(SRSLTE_UCI_CQI_CODED_PUCCH_B*sizeof(int16_t)); + uint8_t word[16]; + + uint32_t nwords = 1 << SRSLTE_UCI_MAX_CQI_LEN_PUCCH; + q->cqi_table = srslte_vec_malloc(nwords * sizeof(int8_t *)); + q->cqi_table_s = srslte_vec_malloc(nwords * sizeof(int16_t *)); + + for (uint32_t w = 0; w < nwords; w++) { + q->cqi_table[w] = srslte_vec_malloc(SRSLTE_UCI_CQI_CODED_PUCCH_B * sizeof(int8_t)); + q->cqi_table_s[w] = srslte_vec_malloc(SRSLTE_UCI_CQI_CODED_PUCCH_B * sizeof(int16_t)); uint8_t *ptr = word; - srslte_bit_unpack(w, &ptr, 4); - srslte_uci_encode_cqi_pucch(word, 4, q->cqi_table[w]); - for (int j=0;jcqi_table_s[w][j] = 2*q->cqi_table[w][j]-1; + srslte_bit_unpack(w, &ptr, SRSLTE_UCI_MAX_CQI_LEN_PUCCH); + srslte_uci_encode_cqi_pucch(word, SRSLTE_UCI_MAX_CQI_LEN_PUCCH, q->cqi_table[w]); + for (int j = 0; j < SRSLTE_UCI_CQI_CODED_PUCCH_B; j++) { + q->cqi_table_s[w][j] = (int16_t)(2 * q->cqi_table[w][j] - 1); } } } void srslte_uci_cqi_pucch_free(srslte_uci_cqi_pucch_t *q) { - uint32_t nwords = 16; + uint32_t nwords = 1 << SRSLTE_UCI_MAX_CQI_LEN_PUCCH; for (uint32_t w=0;wcqi_table[w]) { free(q->cqi_table[w]); @@ -131,6 +134,8 @@ void srslte_uci_cqi_pucch_free(srslte_uci_cqi_pucch_t *q) { free(q->cqi_table_s[w]); } } + free(q->cqi_table); + free(q->cqi_table_s); } /* Encode UCI CQI/PMI as described in 5.2.3.3 of 36.212 @@ -151,17 +156,32 @@ int srslte_uci_encode_cqi_pucch(uint8_t *cqi_data, uint32_t cqi_len, uint8_t b_b } } +int srslte_uci_encode_cqi_pucch_from_table(srslte_uci_cqi_pucch_t *q, uint8_t *cqi_data, uint32_t cqi_len, uint8_t b_bits[SRSLTE_UCI_CQI_CODED_PUCCH_B]) +{ + if (cqi_len <= SRSLTE_UCI_MAX_CQI_LEN_PUCCH) { + bzero(&cqi_data[cqi_len], SRSLTE_UCI_MAX_CQI_LEN_PUCCH - cqi_len); + uint8_t *ptr = cqi_data; + uint32_t packed = srslte_bit_pack(&ptr, SRSLTE_UCI_MAX_CQI_LEN_PUCCH); + memcpy(b_bits, q->cqi_table[packed], SRSLTE_UCI_CQI_CODED_PUCCH_B); + + return SRSLTE_SUCCESS; + } else { + return SRSLTE_ERROR_INVALID_INPUTS; + } +} + /* Decode UCI CQI/PMI over PUCCH */ int16_t srslte_uci_decode_cqi_pucch(srslte_uci_cqi_pucch_t *q, int16_t b_bits[32], uint8_t *cqi_data, uint32_t cqi_len) { - if (cqi_len == 4 && + if (cqi_len < SRSLTE_UCI_MAX_CQI_LEN_PUCCH && b_bits != NULL && cqi_data != NULL) { uint32_t max_w = 0; - int32_t max_corr = INT32_MIN; - for (uint32_t w=0;w<16;w++) { + int32_t max_corr = INT32_MIN; + uint32_t nwords = 1 << SRSLTE_UCI_MAX_CQI_LEN_PUCCH; + for (uint32_t w=0;wcqi_table_s[w], b_bits, SRSLTE_UCI_CQI_CODED_PUCCH_B); @@ -172,7 +192,7 @@ int16_t srslte_uci_decode_cqi_pucch(srslte_uci_cqi_pucch_t *q, int16_t b_bits[32 } // Convert word to bits again uint8_t *ptr = cqi_data; - srslte_bit_unpack(max_w, &ptr, cqi_len); + srslte_bit_unpack(max_w, &ptr, SRSLTE_UCI_MAX_CQI_LEN_PUCCH); INFO("Decoded CQI: w=%d, corr=%d\n", max_w, max_corr); return max_corr; @@ -586,9 +606,7 @@ static uint32_t encode_ri_ack(uint8_t data[2], uint32_t data_len, srslte_uci_bit /* Decode UCI HARQ/ACK bits as described in 5.2.2.6 of 36.212 * Currently only supporting 1-bit HARQ */ -#ifndef MIMO_ENB - -static int32_t decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos) +static int32_t decode_ri_ack_1bit(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos) { uint32_t p0 = pos[0].position; uint32_t p1 = pos[1].position; @@ -598,33 +616,8 @@ static int32_t decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t * return -(q0+q1); } -int srslte_uci_decode_ack(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_seq, - float beta, uint32_t H_prime_total, - uint32_t O_cqi, srslte_uci_bit_t *ack_bits, uint8_t acks[2], uint32_t nof_acks) -{ - int32_t rx_ack = 0; - if (beta < 0) { - fprintf(stderr, "Error beta is reserved\n"); - return -1; - } - - uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta); - - // Use the same interleaver function to get the HARQ bit position - for (uint32_t i=0;igrant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ack_bits[cfg->grant.Qm*i]); - rx_ack += (int32_t) decode_ri_ack(q_bits, c_seq, &ack_bits[cfg->grant.Qm*i]); - } - - if (acks) { - acks[0] = rx_ack>0; - } - return (int) Qprime; -} -#else - -static void decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos, uint32_t Qm, int32_t data[3]) +static void decode_ri_ack_2bits(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos, uint32_t Qm, int32_t data[3]) { uint32_t p0 = pos[Qm * 0 + 0].position; uint32_t p1 = pos[Qm * 0 + 1].position; @@ -645,118 +638,91 @@ static void decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos data[2] -= q2 + q5; } -int srslte_uci_decode_ack(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_seq, - float beta, uint32_t H_prime_total, - uint32_t O_cqi, srslte_uci_bit_t *ack_bits, uint8_t acks[2], uint32_t nof_acks) -{ - int32_t acks_sum[3] = {0, 0, 0}; - +/* Encode UCI ACK/RI bits as described in 5.2.2.6 of 36.212 + * Currently only supporting 1-bit RI + */ +int srslte_uci_encode_ack_ri(srslte_pusch_cfg_t *cfg, + uint8_t *data, uint32_t data_len, + uint32_t O_cqi, float beta, uint32_t H_prime_total, + srslte_uci_bit_t *bits, bool ack_ri) { if (beta < 0) { fprintf(stderr, "Error beta is reserved\n"); - return -1; + return -1; } + uint32_t Qprime = Q_prime_ri_ack(cfg, data_len, O_cqi, beta); + srslte_uci_bit_type_t q_encoded_bits[18]; - uint32_t Qprime = Q_prime_ri_ack(cfg, nof_acks, O_cqi, beta); + uint32_t nof_encoded_bits = encode_ri_ack(data, data_len, q_encoded_bits, cfg->grant.Qm); - // Use the same interleaver function to get the HARQ bit position for (uint32_t i = 0; i < Qprime; i++) { - uci_ulsch_interleave_ack_gen(i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ack_bits[cfg->grant.Qm*i]); - if ((i % 3 == 0) && i > 0) { - decode_ri_ack(q_bits, &c_seq[0], &ack_bits[cfg->grant.Qm*(i-3)], cfg->grant.Qm, acks_sum); + if (ack_ri) { + uci_ulsch_interleave_ri_gen(i, + cfg->grant.Qm, + H_prime_total, + cfg->nbits.nof_symb, + cfg->cp, + &bits[cfg->grant.Qm * i]); + } else { + uci_ulsch_interleave_ack_gen(i, + cfg->grant.Qm, + H_prime_total, + cfg->nbits.nof_symb, + cfg->cp, + &bits[cfg->grant.Qm * i]); } + uci_ulsch_interleave_put(&q_encoded_bits[(i * cfg->grant.Qm) % nof_encoded_bits], + cfg->grant.Qm, + &bits[cfg->grant.Qm * i]); } - if (acks) { - acks[0] = (uint8_t)(acks_sum[0] > 0); - acks[1] = (uint8_t)(acks_sum[1] > 0); - // TODO: Do something with acks_sum[2] - } - return (int) Qprime; -} -#endif - -/* Encode UCI HARQ/ACK bits as described in 5.2.2.6 of 36.212 - * Currently only supporting 1-bit HARQ - */ -int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, uint8_t acks[2], uint32_t nof_acks, - uint32_t O_cqi, float beta, uint32_t H_prime_total, - srslte_uci_bit_t *ack_bits) -{ - if (beta < 0) { - fprintf(stderr, "Error beta is reserved\n"); - return -1; - } - - uint32_t Qprime = Q_prime_ri_ack(cfg, nof_acks, O_cqi, beta); - srslte_uci_bit_type_t q_encoded_bits[18]; - - uint32_t nof_encoded_bits = encode_ri_ack(acks, nof_acks, q_encoded_bits, cfg->grant.Qm); - - for (uint32_t i=0;igrant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ack_bits[cfg->grant.Qm*i]); - uci_ulsch_interleave_put(&q_encoded_bits[(i*cfg->grant.Qm)%nof_encoded_bits], cfg->grant.Qm, &ack_bits[cfg->grant.Qm*i]); - } - return (int) Qprime; } -/* Encode UCI RI bits as described in 5.2.2.6 of 36.212 +/* Decode UCI ACK/RI bits as described in 5.2.2.6 of 36.212 * Currently only supporting 1-bit RI */ -int srslte_uci_decode_ri(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_seq, - float beta, uint32_t H_prime_total, - uint32_t O_cqi, srslte_uci_bit_t *ri_bits, uint8_t *data) +int srslte_uci_decode_ack_ri(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_seq, + float beta, uint32_t H_prime_total, + uint32_t O_cqi, srslte_uci_bit_t *ack_ri_bits, uint8_t data[2], uint32_t nof_bits, bool is_ri) { - int32_t ri_sum[3] = {0, 0, 0}; - + int32_t sum[3] = {0, 0, 0}; + if (beta < 0) { fprintf(stderr, "Error beta is reserved\n"); - return -1; + return -1; } - uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta); + uint32_t Qprime = Q_prime_ri_ack(cfg, nof_bits, O_cqi, beta); - // Use the same interleaver function to get the HARQ bit position - for (uint32_t i=0;igrant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ri_bits[cfg->grant.Qm*i]); - if ((i % 3 == 0) && i > 0) { - //decode_ri_ack(q_bits, &c_seq[0], &ri_bits[cfg->grant.Qm*(i-3)], cfg->grant.Qm, ri_sum); - } - } + for (uint32_t i = 0; i < Qprime; i++) { + if (is_ri) { + uci_ulsch_interleave_ri_gen(i, + cfg->grant.Qm, + H_prime_total, + cfg->nbits.nof_symb, + cfg->cp, + &ack_ri_bits[cfg->grant.Qm * i]); + } else { + uci_ulsch_interleave_ack_gen(i, + cfg->grant.Qm, + H_prime_total, + cfg->nbits.nof_symb, + cfg->cp, + &ack_ri_bits[cfg->grant.Qm * i]); - if (data) { - *data = (uint8_t) ((ri_sum[0] + ri_sum[1] + ri_sum[2]) > 0); + } + if (nof_bits == 2 && (i % 3 == 0) && i > 0) { + decode_ri_ack_2bits(q_bits, &c_seq[0], &ack_ri_bits[cfg->grant.Qm * (i - 3)], cfg->grant.Qm, sum); + } else if (nof_bits == 1) { + sum[0] += (int32_t) decode_ri_ack_1bit(q_bits, c_seq, &ack_ri_bits[cfg->grant.Qm * i]); + } } - return (int) Qprime; -} - - -/* Encode UCI RI bits as described in 5.2.2.6 of 36.212 - * Currently only supporting 1-bit RI - */ -int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg, - uint8_t ri, - uint32_t O_cqi, float beta, uint32_t H_prime_total, - srslte_uci_bit_t *ri_bits) -{ - // FIXME: It supports RI of 1 bit only - uint8_t data[2] = {ri, 0}; - if (beta < 0) { - fprintf(stderr, "Error beta is reserved\n"); - return -1; + data[0] = (uint8_t) (sum[0] > 0); + if (nof_bits == 2) { + data[1] = (uint8_t) (sum[1] > 0); } - uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta); - srslte_uci_bit_type_t q_encoded_bits[18]; - uint32_t nof_encoded_bits = encode_ri_ack(data, 1, q_encoded_bits, cfg->grant.Qm); - - for (uint32_t i=0;igrant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ri_bits[cfg->grant.Qm*i]); - uci_ulsch_interleave_put(&q_encoded_bits[(i*cfg->grant.Qm)%nof_encoded_bits], cfg->grant.Qm, &ri_bits[cfg->grant.Qm*i]); - } - return (int) Qprime; } - diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index db7118b0c..4183016e0 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -725,7 +725,8 @@ int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, uint8_t *ri, uint8_t *pmi, flo /* Select the best Rank indicator (RI) and Precoding Matrix Indicator (PMI) */ for (uint32_t nof_layers = 1; nof_layers <= SRSLTE_MAX_LAYERS; nof_layers++) { float _sinr = q->sinr[nof_layers - 1][q->pmi[nof_layers - 1]] * nof_layers * nof_layers; - if (_sinr > best_sinr + 0.1) { + /* Find best SINR, force maximum number of layers if SNR is higher than 30 dB */ + if (_sinr > best_sinr + 0.1 || _sinr > 1.0e+3) { best_sinr = _sinr; best_pmi = (uint8_t) q->pmi[nof_layers - 1]; best_ri = (uint8_t) (nof_layers - 1); diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index 5298e6e7a..990633aa7 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -88,16 +88,19 @@ void phch_worker::init(phch_common* phy_, srslte::log *log_h_) pthread_mutex_init(&mutex, NULL); // Init cell here - signal_buffer_rx = (cf_t*) srslte_vec_malloc(2*SRSLTE_SF_LEN_PRB(phy->cell.nof_prb)*sizeof(cf_t)); - if (!signal_buffer_rx) { - fprintf(stderr, "Error allocating memory\n"); - return; - } - 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; + for(int p = 0; p < SRSLTE_MAX_PORTS; p++) { + signal_buffer_rx[p] = (cf_t *) srslte_vec_malloc(2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t)); + if (!signal_buffer_rx[p]) { + fprintf(stderr, "Error allocating memory\n"); + return; + } + bzero(signal_buffer_rx[p], 2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t)); + signal_buffer_tx[p] = (cf_t *) srslte_vec_malloc(2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t)); + if (!signal_buffer_tx[p]) { + fprintf(stderr, "Error allocating memory\n"); + return; + } + bzero(signal_buffer_tx[p], 2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t)); } if (srslte_enb_dl_init(&enb_dl, signal_buffer_tx, phy->cell.nof_prb)) { fprintf(stderr, "Error initiating ENB DL\n"); @@ -107,7 +110,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, signal_buffer_rx, phy->cell.nof_prb)) { + if (srslte_enb_ul_init(&enb_ul, signal_buffer_rx[0], phy->cell.nof_prb)) { fprintf(stderr, "Error initiating ENB UL\n"); return; } @@ -154,12 +157,12 @@ void phch_worker::stop() srslte_enb_dl_free(&enb_dl); srslte_enb_ul_free(&enb_ul); - if (signal_buffer_rx) { - free(signal_buffer_rx); - } - for (int i = 0; i < SRSLTE_MAX_PORTS; i++) { - if (signal_buffer_tx[i]) { - free(signal_buffer_tx[i]); + for (int p = 0; p < SRSLTE_MAX_PORTS; p++) { + if (signal_buffer_rx[p]) { + free(signal_buffer_rx[p]); + } + if (signal_buffer_tx[p]) { + free(signal_buffer_tx[p]); } } pthread_mutex_unlock(&mutex); @@ -171,9 +174,9 @@ void phch_worker::reset() ue_db.clear(); } -cf_t* phch_worker::get_buffer_rx() +cf_t* phch_worker::get_buffer_rx(uint32_t antenna_idx) { - return signal_buffer_rx; + return signal_buffer_rx[antenna_idx]; } void phch_worker::set_time(uint32_t tti_, uint32_t tx_mutex_cnt_, srslte_timestamp_t tx_time_) @@ -214,12 +217,29 @@ uint32_t phch_worker::get_nof_rnti() { return ue_db.size(); } +void phch_worker::set_conf_dedicated_ack(uint16_t rnti, bool ack){ + pthread_mutex_lock(&mutex); + if (ue_db.count(rnti)) { + ue_db[rnti].dedicated_ack = ack; + } else { + Error("Setting dedicated ack: rnti=0x%x does not exist\n"); + } + pthread_mutex_unlock(&mutex); +} + void phch_worker::set_config_dedicated(uint16_t rnti, srslte_uci_cfg_t *uci_cfg, srslte_pucch_sched_t *pucch_sched, - srslte_refsignal_srs_cfg_t *srs_cfg, - uint32_t I_sr, bool pucch_cqi, uint32_t pmi_idx, bool pucch_cqi_ack) + srslte_refsignal_srs_cfg_t *srs_cfg, + LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT* dedicated) { + uint32_t I_sr = dedicated->sched_request_cnfg.sr_cnfg_idx; + bool pucch_cqi = dedicated->cqi_report_cnfg.report_periodic_setup_present; + uint32_t pmi_idx = dedicated->cqi_report_cnfg.report_periodic.pmi_cnfg_idx; + bool pucch_cqi_ack = dedicated->cqi_report_cnfg.report_periodic.simult_ack_nack_and_cqi; + bool pucch_ri = dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx_present; + uint32_t ri_idx = dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx; + pthread_mutex_lock(&mutex); if (ue_db.count(rnti)) { pucch_sched->N_pucch_1 = phy->pucch_cfg.n1_pucch_an; @@ -237,6 +257,16 @@ void phch_worker::set_config_dedicated(uint16_t rnti, ue_db[rnti].cqi_en = false; } + if (pucch_ri) { + ue_db[rnti].ri_idx = ri_idx; + ue_db[rnti].ri_en = true; + } else { + ue_db[rnti].ri_idx = 0; + ue_db[rnti].ri_en = false; + } + + /* Copy all dedicated RRC configuration to UE */ + memcpy(&ue_db[rnti].dedicated, dedicated, sizeof(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT)); } else { Error("Setting config dedicated: rnti=0x%x does not exist\n"); } @@ -278,7 +308,7 @@ void phch_worker::work_imp() } pthread_mutex_lock(&mutex); - + mac_interface_phy::ul_sched_t *ul_grants = phy->ul_grants; mac_interface_phy::dl_sched_t *dl_grants = phy->dl_grants; mac_interface_phy *mac = phy->mac; @@ -293,7 +323,7 @@ void phch_worker::work_imp() } // Process UL signal - srslte_enb_ul_fft(&enb_ul, signal_buffer_rx); + srslte_enb_ul_fft(&enb_ul); // Decode pending UL grants for the tti they were scheduled decode_pusch(ul_grants[t_rx].sched_grants, ul_grants[t_rx].nof_grants); @@ -335,15 +365,22 @@ void phch_worker::work_imp() phy->ack_clear(TTIMOD(TTI_TX(t_tx_dl))); for (uint32_t i=0;i= SRSLTE_CRNTI_START && dl_grants[t_tx_dl].sched_grants[i].rnti <= SRSLTE_CRNTI_END) { - phy->ack_set_pending(TTIMOD(TTI_TX(t_tx_dl)), dl_grants[t_tx_dl].sched_grants[i].rnti, dl_grants[t_tx_dl].sched_grants[i].location.ncce); + uint16_t rnti = dl_grants[t_tx_dl].sched_grants[i].rnti; + if (rnti >= SRSLTE_CRNTI_START && rnti <= SRSLTE_CRNTI_END) { + /* For each TB */ + for (uint32_t tb_idx = 0; tb_idx < SRSLTE_MAX_TB; tb_idx++) { + /* If TB enabled, set pending ACK */ + if (dl_grants[t_tx_dl].sched_grants[i].grant.tb_en[tb_idx]) { + phy->ack_set_pending(TTIMOD(TTI_TX(t_tx_dl)), rnti, tb_idx, dl_grants[t_tx_dl].sched_grants[i].location.ncce); + } + } } } // Generate signal and transmit srslte_enb_dl_gen_signal(&enb_dl); Debug("Sending to radio\n"); - phy->worker_end(tx_mutex_cnt, signal_buffer_tx[0], SRSLTE_SF_LEN_PRB(phy->cell.nof_prb), tx_time); + phy->worker_end(tx_mutex_cnt, signal_buffer_tx, 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); @@ -387,24 +424,39 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) gettimeofday(&t[1], NULL); #endif + bool acks_pending[SRSLTE_MAX_TB] = {false}; + // Get pending ACKs with an associated PUSCH transmission - if (phy->ack_is_pending(t_rx, rnti)) { - uci_data.uci_ack_len = 1; + for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { + acks_pending[tb] = phy->ack_is_pending(t_rx, rnti, tb); + if (acks_pending[tb]) { + uci_data.uci_ack_len++; + } } + // Configure PUSCH CQI channel - srslte_cqi_value_t cqi_value; + srslte_cqi_value_t cqi_value = {0}; bool cqi_enabled = false; - if (ue_db[rnti].cqi_en && srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) { +#if 0 + if (ue_db[rnti].cqi_en && ue_db[rnti].ri_en && srslte_ri_send(ue_db[rnti].pmi_idx, ue_db[rnti].ri_idx, tti_rx) ) { + uci_data.uci_ri_len = 1; /* Asumes only 1 bit for RI */ + ri_enabled = true; + } else if (ue_db[rnti].cqi_en && srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) { cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND; cqi_enabled = true; - } else if (grants[i].grant.cqi_request) { + if (ue_db[rnti].dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { + //uci_data.uci_dif_cqi_len = 3; + uci_data.uci_pmi_len = 2; + } + } else +#endif + if (grants[i].grant.cqi_request) { cqi_value.type = SRSLTE_CQI_TYPE_SUBBAND_HL; cqi_value.subband_hl.N = (phy->cell.nof_prb > 7) ? srslte_cqi_hl_get_no_subbands(phy->cell.nof_prb) : 0; + cqi_value.subband_hl.four_antenna_ports = (phy->cell.nof_ports == 4); + cqi_value.subband_hl.pmi_present = (ue_db[rnti].dedicated.cqi_report_cnfg.report_mode_aperiodic == LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM31); cqi_enabled = true; } - if (cqi_enabled) { - uci_data.uci_cqi_len = srslte_cqi_size(&cqi_value); - } // mark this tti as having an ul grant to avoid pucch ue_db[rnti].has_grant_tti = tti_rx; @@ -412,22 +464,6 @@ 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)) { - - // Handle Format0 adaptive retx - // Use last TBS for this TB in case of mcs>28 - if (phy_grant.mcs.idx > 28) { - phy_grant.mcs.tbs = ue_db[rnti].last_ul_tbs[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)]; - Info("RETX: mcs=%d, old_tbs=%d pid=%d\n", phy_grant.mcs.idx, phy_grant.mcs.tbs, TTI_TX(tti_rx)%(2*HARQ_DELAY_MS)); - } - ue_db[rnti].last_ul_tbs[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)] = phy_grant.mcs.tbs; - - if (phy_grant.mcs.mod == SRSLTE_MOD_LAST) { - phy_grant.mcs.mod = ue_db[rnti].last_ul_mod[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)]; - phy_grant.Qm = srslte_mod_bits_x_symbol(phy_grant.mcs.mod); - } - ue_db[rnti].last_ul_mod[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)] = phy_grant.mcs.mod; - - if (phy_grant.mcs.mod == SRSLTE_MOD_64QAM) { phy_grant.mcs.mod = SRSLTE_MOD_16QAM; } @@ -436,6 +472,7 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) rnti, grants[i].rv_idx, grants[i].current_tx_nb, grants[i].data, + (cqi_enabled) ? &cqi_value : NULL, &uci_data, sf_rx); } else { @@ -457,11 +494,24 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) char cqi_str[64]; if (cqi_enabled) { - srslte_cqi_value_unpack(uci_data.uci_cqi, &cqi_value); if (ue_db[rnti].cqi_en) { wideband_cqi_value = cqi_value.wideband.wideband_cqi; } else if (grants[i].grant.cqi_request) { wideband_cqi_value = cqi_value.subband_hl.wideband_cqi_cw0; + if (cqi_value.subband_hl.pmi_present) { + if (cqi_value.subband_hl.rank_is_not_one) { + Info("PUSCH: Aperiodic ri~1, CQI=%02d/%02d, pmi=%d for %d subbands\n", + cqi_value.subband_hl.wideband_cqi_cw0, cqi_value.subband_hl.wideband_cqi_cw1, + cqi_value.subband_hl.pmi, cqi_value.subband_hl.N); + } else { + Info("PUSCH: Aperiodic ri=1, CQI=%02d, pmi=%d for %d subbands\n", + cqi_value.subband_hl.wideband_cqi_cw0, cqi_value.subband_hl.pmi, cqi_value.subband_hl.N); + } + } else { + Info("PUSCH: Aperiodic ri%s, CQI=%02d for %d subbands\n", + cqi_value.subband_hl.rank_is_not_one?"~1":"=1", + cqi_value.subband_hl.wideband_cqi_cw0, cqi_value.subband_hl.N); + } } snprintf(cqi_str, 64, ", cqi=%d", wideband_cqi_value); } @@ -481,14 +531,16 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) } */ log_h->info_hex(grants[i].data, phy_grant.mcs.tbs/8, - "PUSCH: rnti=0x%x, prb=(%d,%d), tbs=%d, mcs=%d, rv=%d, snr=%.1f dB, n_iter=%d, crc=%s%s%s%s\n", + "PUSCH: rnti=0x%x, prb=(%d,%d), tbs=%d, mcs=%d, rv=%d, snr=%.1f dB, n_iter=%d, crc=%s%s%s%s%s\n", rnti, phy_grant.n_prb[0], phy_grant.n_prb[0]+phy_grant.L_prb, phy_grant.mcs.tbs/8, phy_grant.mcs.idx, grants[i].grant.rv_idx, snr_db, srslte_pusch_last_noi(&enb_ul.pusch), crc_res?"OK":"KO", - uci_data.uci_ack_len>0?(uci_data.uci_ack?", ack=1":", ack=0"):"", + (uci_data.uci_ack_len)?(uci_data.uci_ack?"1":"0"):"", + (uci_data.uci_ack_len > 1)?(uci_data.uci_ack_2?"1":"0"):"", uci_data.uci_cqi_len>0?cqi_str:"", + uci_data.uci_ri_len>0?(uci_data.uci_ri?", ri=0":", ri=1"):"", timestr); // Notify MAC of RL status @@ -503,17 +555,28 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) // Notify MAC new received data and HARQ Indication value phy->mac->crc_info(tti_rx, rnti, phy_grant.mcs.tbs/8, crc_res); - if (uci_data.uci_ack_len) { - phy->mac->ack_info(tti_rx, rnti, uci_data.uci_ack && (crc_res || snr_db > PUSCH_RL_SNR_DB_TH)); + uint32_t ack_idx = 0; + for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { + if (acks_pending[tb]) { + bool ack = ((ack_idx++ == 0) ? uci_data.uci_ack : uci_data.uci_ack_2); + bool valid = (crc_res || snr_db > PUSCH_RL_SNR_DB_TH); + phy->mac->ack_info(tti_rx, rnti, tb, ack && valid); + } } - // Notify MAC of UL SNR and DL CQI + // Notify MAC of UL SNR, DL CQI and DL RI if (snr_db >= PUSCH_RL_SNR_DB_TH) { phy->mac->snr_info(tti_rx, rnti, snr_db); } if (uci_data.uci_cqi_len>0 && crc_res) { phy->mac->cqi_info(tti_rx, rnti, wideband_cqi_value); } + if (uci_data.uci_ri_len > 0 && crc_res) { + phy->mac->ri_info(tti_rx, rnti, uci_data.uci_ri); + } + if (cqi_value.subband_hl.pmi_present && crc_res) { + phy->mac->pmi_info(tti_rx, rnti, cqi_value.subband_hl.pmi); + } // Save metrics stats ue_db[rnti].metrics_ul(phy_grant.mcs.idx, 0, snr_db, srslte_pusch_last_noi(&enb_ul.pusch)); @@ -532,7 +595,8 @@ int phch_worker::decode_pucch() if (rnti >= SRSLTE_CRNTI_START && rnti <= SRSLTE_CRNTI_END && ue_db[rnti].has_grant_tti != (int) tti_rx) { // Check if user needs to receive PUCCH - bool needs_pucch = false, needs_ack=false, needs_sr=false, needs_cqi=false; + bool needs_pucch = false, needs_ack[SRSLTE_MAX_TB] = {false}, needs_sr = false, needs_cqi = false, + needs_ri = false; uint32_t last_n_pdcch = 0; bzero(&uci_data, sizeof(srslte_uci_data_t)); @@ -544,18 +608,32 @@ int phch_worker::decode_pucch() } } - if (phy->ack_is_pending(t_rx, rnti, &last_n_pdcch)) { - needs_pucch = true; - needs_ack = true; - uci_data.uci_ack_len = 1; + for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { + needs_ack[tb] = phy->ack_is_pending(t_rx, rnti, tb, &last_n_pdcch); + if (needs_ack[tb]) { + needs_pucch = true; + uci_data.uci_ack_len++; + } } srslte_cqi_value_t cqi_value; - if (ue_db[rnti].cqi_en && (ue_db[rnti].pucch_cqi_ack || !needs_ack)) { - if (srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) { + LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *dedicated = &ue_db[rnti].dedicated; + LIBLTE_RRC_TRANSMISSION_MODE_ENUM tx_mode = dedicated->antenna_info_explicit_value.tx_mode; + + if (ue_db[rnti].cqi_en && (ue_db[rnti].pucch_cqi_ack || !needs_ack[0] || !needs_ack[1])) { + if (ue_db[rnti].ri_en && srslte_ri_send(ue_db[rnti].pmi_idx, ue_db[rnti].ri_idx, tti_rx)) { + needs_pucch = true; + needs_ri = true; + uci_data.uci_ri_len = 1; + uci_data.ri_periodic_report = true; + } else if (srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) { needs_pucch = true; needs_cqi = true; cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND; uci_data.uci_cqi_len = srslte_cqi_size(&cqi_value); + if (tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { + //uci_data.uci_dif_cqi_len = 3; + uci_data.uci_pmi_len = 2; + } } } @@ -564,26 +642,48 @@ int phch_worker::decode_pucch() fprintf(stderr, "Error getting PUCCH\n"); return SRSLTE_ERROR; } - if (uci_data.uci_ack_len > 0) { - phy->mac->ack_info(tti_rx, rnti, uci_data.uci_ack && (srslte_pucch_get_last_corr(&enb_ul.pucch) >= PUCCH_RL_CORR_TH)); + /* If only one ACK is required, it can be for TB0 or TB1 */ + uint32_t ack_idx = 0; + for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { + if (needs_ack[tb]) { + bool ack = ((ack_idx++ == 0) ? uci_data.uci_ack : uci_data.uci_ack_2); + bool valid = srslte_pucch_get_last_corr(&enb_ul.pucch) >= PUCCH_RL_CORR_TH; + phy->mac->ack_info(tti_rx, rnti, tb, ack && valid); + } } if (uci_data.scheduling_request) { phy->mac->sr_detected(tti_rx, rnti); } + + char cqi_ri_str[64]; + if (srslte_pucch_get_last_corr(&enb_ul.pucch) > PUCCH_RL_CORR_TH) { + if (uci_data.uci_ri_len && needs_ri) { + phy->mac->ri_info(tti_rx, rnti, uci_data.uci_ri); + sprintf(cqi_ri_str, ", ri=%d", uci_data.uci_ri); + } else if (uci_data.uci_cqi_len && needs_cqi) { + srslte_cqi_value_unpack(uci_data.uci_cqi, &cqi_value); + phy->mac->cqi_info(tti_rx, rnti, cqi_value.wideband.wideband_cqi); + sprintf(cqi_ri_str, ", cqi=%d", cqi_value.wideband.wideband_cqi); + + if (uci_data.uci_pmi_len) { + uint32_t packed_pmi = uci_data.uci_pmi[0]; + if (uci_data.uci_pmi_len > 1) { + packed_pmi = (packed_pmi << 1) + uci_data.uci_pmi[1]; + } + phy->mac->pmi_info(tti_rx, rnti, packed_pmi); + sprintf(cqi_ri_str, "%s, pmi=%c", cqi_ri_str, packed_pmi + 0x30); + } - char cqi_str[64]; - if (uci_data.uci_cqi_len) { - srslte_cqi_value_unpack(uci_data.uci_cqi, &cqi_value); - phy->mac->cqi_info(tti_rx, rnti, cqi_value.wideband.wideband_cqi); - sprintf(cqi_str, ", cqi=%d", cqi_value.wideband.wideband_cqi); + } } - log_h->info("PUCCH: rnti=0x%x, corr=%.2f, n_pucch=%d, n_prb=%d%s%s%s\n", + log_h->info("PUCCH: rnti=0x%x, corr=%.2f, n_pucch=%d, n_prb=%d%s%s%s%s\n", rnti, srslte_pucch_get_last_corr(&enb_ul.pucch), enb_ul.pucch.last_n_pucch, enb_ul.pucch.last_n_prb, - needs_ack?(uci_data.uci_ack?", ack=1":", ack=0"):"", + (uci_data.uci_ack_len)?(uci_data.uci_ack?", ack=1":", ack=0"):"", + (uci_data.uci_ack_len > 1)?(uci_data.uci_ack_2?"1":"0"):"", needs_sr?(uci_data.scheduling_request?", sr=yes":", sr=no"):"", - needs_cqi?cqi_str:""); + (needs_cqi || needs_ri)?cqi_ri_str:""); // Notify MAC of RL status @@ -642,25 +742,16 @@ int phch_worker::encode_pdcch_ul(srslte_enb_ul_pusch_t *grants, uint32_t nof_gra int phch_worker::encode_pdcch_dl(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants) { for (uint32_t i=0;irnti; if (rnti) { - srslte_dci_format_t format = SRSLTE_DCI_FORMAT1; - switch(grants[i].grant.alloc_type) { - case SRSLTE_RA_ALLOC_TYPE0: - case SRSLTE_RA_ALLOC_TYPE1: - format = SRSLTE_DCI_FORMAT1; - break; - case SRSLTE_RA_ALLOC_TYPE2: - format = SRSLTE_DCI_FORMAT1A; - break; - } - if (srslte_enb_dl_put_pdcch_dl(&enb_dl, &grants[i].grant, format, grants[i].location, rnti, sf_tx)) { + if (srslte_enb_dl_put_pdcch_dl(&enb_dl, &grants[i].grant, grant->dci_format, grants[i].location, rnti, sf_tx)) { fprintf(stderr, "Error putting PDCCH %d\n",i); return SRSLTE_ERROR; } if (LOG_THIS(rnti)) { - Info("PDCCH: DL DCI %s rnti=0x%x, cce_index=%d, L=%d, tti_tx_dl=%d\n", srslte_dci_format_string(format), + Info("PDCCH: DL DCI %s rnti=0x%x, cce_index=%d, L=%d, tti_tx_dl=%d\n", srslte_dci_format_string(grant->dci_format), rnti, grants[i].location.ncce, (1<info_hex(ptr, len, - "PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tbs=%d, mcs=%d, rv=%d, tti_tx_dl=%d\n", - rnti, phy_grant.nof_prb, grant_str, grants[i].grant.harq_process, - phy_grant.mcs[0].tbs/8, phy_grant.mcs[0].idx, grants[i].grant.rv_idx, tti_tx_dl); + "PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tti_tx_dl=%d, tx_scheme=%s%s%s%s\n", + rnti, phy_grant.nof_prb, grant_str, grants[i].grant.harq_process, tti_tx_dl, + srslte_mimotype2str(mimo_type), pinfo_str, tbstr[0], tbstr[1]); } - srslte_softbuffer_tx_t *sb[SRSLTE_MAX_CODEWORDS] = {grants[i].softbuffer, NULL}; - uint8_t *d[SRSLTE_MAX_CODEWORDS] = {grants[i].data, NULL}; - int rv[SRSLTE_MAX_CODEWORDS] = {grants[i].grant.rv_idx, 0}; + int rv[SRSLTE_MAX_CODEWORDS] = {grants[i].grant.rv_idx, grants[i].grant.rv_idx_1}; - - if (srslte_enb_dl_put_pdsch(&enb_dl, &phy_grant, sb, rnti, rv, sf_tx, d, SRSLTE_MIMO_TYPE_SINGLE_ANTENNA, 0)) - { - fprintf(stderr, "Error putting PDSCH %d\n",i); - return SRSLTE_ERROR; + if (srslte_enb_dl_put_pdsch(&enb_dl, &phy_grant, grants[i].softbuffers, rnti, rv, sf_tx, grants[i].data, mimo_type)) { + fprintf(stderr, "Error putting PDSCH %d\n", i); + return SRSLTE_ERROR; } - // Save metrics stats + // Save metrics stats ue_db[rnti].metrics_dl(phy_grant.mcs[0].idx); } } - return SRSLTE_SUCCESS; + return SRSLTE_SUCCESS; } diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index e176e8ac5..29cbdef8e 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -1142,7 +1142,11 @@ void rrc::ue::send_connection_setup(bool is_setup) phy_cfg->cqi_report_cnfg_present = true; if(parent->cfg.cqi_cfg.mode == RRC_CFG_CQI_MODE_APERIODIC) { phy_cfg->cqi_report_cnfg.report_mode_aperiodic_present = true; - phy_cfg->cqi_report_cnfg.report_mode_aperiodic = LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30; + if (phy_cfg->antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { + phy_cfg->cqi_report_cnfg.report_mode_aperiodic = LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM31; + } else { + phy_cfg->cqi_report_cnfg.report_mode_aperiodic = LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30; + } } else { phy_cfg->cqi_report_cnfg.report_periodic_present = true; phy_cfg->cqi_report_cnfg.report_periodic_setup_present = true; diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 0068724b4..2beff5900 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -859,7 +859,9 @@ void phch_worker::set_uci_periodic_cqi() if (period_cqi.configured && rnti_is_set) { if (period_cqi.ri_idx_present && srslte_ri_send(period_cqi.pmi_idx, period_cqi.ri_idx, TTI_TX(tti))) { + /* Compute RI, PMI and SINR */ compute_ri(); + uci_data.ri_periodic_report = true; Info("PUCCH: Periodic RI=%d\n", uci_data.uci_ri); } else if (srslte_cqi_send(period_cqi.pmi_idx, TTI_TX(tti))) { @@ -902,6 +904,9 @@ void phch_worker::set_uci_periodic_cqi() void phch_worker::set_uci_aperiodic_cqi() { if (phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic_present) { + /* Compute RI, PMI and SINR */ + compute_ri(); + switch(phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic) { case LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30: /* only Higher Layer-configured subband feedback support right now, according to TS36.213 section 7.2.1 @@ -939,9 +944,6 @@ void phch_worker::set_uci_aperiodic_cqi() other transmission modes they are reported conditioned on rank 1. */ if (rnti_is_set) { - /* Compute RI, PMI and SINR */ - compute_ri(); - /* Select RI, PMI and SINR */ uint32_t ri = ue_dl.ri; // Select RI (0: 1 layer, 1: 2 layer, otherwise: not implemented) uint32_t pmi = ue_dl.pmi[ri]; // Select PMI @@ -972,9 +974,9 @@ void phch_worker::set_uci_aperiodic_cqi() cqi_report.subband_hl.wideband_cqi_cw0, cqi_report.subband_hl.wideband_cqi_cw1, sinr_db, sinr_db, pmi, cqi_report.subband_hl.N); } else { - Info("PUSCH: Aperiodic ri=1, CQI=%d/%d, SINR=%2.1f dB, for %d subbands\n", - cqi_report.wideband.wideband_cqi, - phy->avg_snr_db, cqi_report.subband_hl.N); + Info("PUSCH: Aperiodic ri=1, CQI=%02d, SINR=%2.1f, pmi=%d for %d subbands\n", + cqi_report.subband_hl.wideband_cqi_cw0, + sinr_db, pmi, cqi_report.subband_hl.N); } uci_data.uci_cqi_len = srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi); } From eefbdbc9132a4d8f5d0e6aece6062dcc58c2bf7e Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Mon, 4 Dec 2017 12:07:49 -0600 Subject: [PATCH 196/242] Revert "Added Aperiodic mode 3-1 in enb and some more optimizations" This reverts commit 8ab196901f83caef3759e89b98b1b3b10d26cd1b. --- lib/include/srslte/phy/enb/enb_ul.h | 1 - lib/include/srslte/phy/phch/pusch.h | 1 - lib/include/srslte/phy/phch/uci.h | 36 +-- lib/src/phy/enb/enb_ul.c | 45 +--- lib/src/phy/phch/cqi.c | 37 +-- lib/src/phy/phch/pusch.c | 35 +-- lib/src/phy/phch/sch.c | 19 +- lib/src/phy/phch/test/pusch_test.c | 2 +- lib/src/phy/phch/uci.c | 230 ++++++++++-------- lib/src/phy/ue/ue_dl.c | 3 +- srsenb/src/phy/phch_worker.cc | 362 +++++++++------------------- srsenb/src/upper/rrc.cc | 6 +- srsue/src/phy/phch_worker.cc | 14 +- 13 files changed, 300 insertions(+), 491 deletions(-) diff --git a/lib/include/srslte/phy/enb/enb_ul.h b/lib/include/srslte/phy/enb/enb_ul.h index 1b865b7f7..0957ccbc0 100644 --- a/lib/include/srslte/phy/enb/enb_ul.h +++ b/lib/include/srslte/phy/enb/enb_ul.h @@ -141,7 +141,6 @@ SRSLTE_API int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q, uint32_t rv_idx, uint32_t current_tx_nb, uint8_t *data, - srslte_cqi_value_t *cqi_value, srslte_uci_data_t *uci_data, uint32_t tti); diff --git a/lib/include/srslte/phy/phch/pusch.h b/lib/include/srslte/phy/phch/pusch.h index 01db068a5..2328c8ff3 100644 --- a/lib/include/srslte/phy/phch/pusch.h +++ b/lib/include/srslte/phy/phch/pusch.h @@ -142,7 +142,6 @@ SRSLTE_API int srslte_pusch_decode(srslte_pusch_t *q, float noise_estimate, uint16_t rnti, uint8_t *data, - srslte_cqi_value_t *cqi_value, srslte_uci_data_t *uci_data); SRSLTE_API float srslte_pusch_average_noi(srslte_pusch_t *q); diff --git a/lib/include/srslte/phy/phch/uci.h b/lib/include/srslte/phy/phch/uci.h index 8e72b5793..91592501f 100644 --- a/lib/include/srslte/phy/phch/uci.h +++ b/lib/include/srslte/phy/phch/uci.h @@ -131,25 +131,31 @@ SRSLTE_API int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, uint32_t H_prime_total, srslte_uci_bit_t *ri_bits); -SRSLTE_API int srslte_uci_encode_ack_ri(srslte_pusch_cfg_t *cfg, - uint8_t *data, - uint32_t data_len, +SRSLTE_API int srslte_uci_decode_ack(srslte_pusch_cfg_t *cfg, + int16_t *q_bits, + uint8_t *c_seq, + float beta, + uint32_t H_prime_total, + uint32_t O_cqi, + srslte_uci_bit_t *ack_bits, + uint8_t acks[2], + uint32_t nof_acks); + +SRSLTE_API int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg, + uint8_t data, uint32_t O_cqi, float beta, uint32_t H_prime_total, + srslte_uci_bit_t *ri_bits); + +SRSLTE_API int srslte_uci_decode_ri(srslte_pusch_cfg_t *cfg, + int16_t *q_bits, + uint8_t *c_seq, + float beta, + uint32_t H_prime_total, + uint32_t O_cqi, srslte_uci_bit_t *ri_bits, - bool is_ri); - -SRSLTE_API int srslte_uci_decode_ack_ri(srslte_pusch_cfg_t *cfg, - int16_t *q_bits, - uint8_t *c_seq, - float beta, - uint32_t H_prime_total, - uint32_t O_cqi, - srslte_uci_bit_t *ack_ri_bits, - uint8_t data[2], - uint32_t nof_bits, - bool is_ri); + uint8_t *data); #endif diff --git a/lib/src/phy/enb/enb_ul.c b/lib/src/phy/enb/enb_ul.c index 8ea5dd3e4..f94eb0277 100644 --- a/lib/src/phy/enb/enb_ul.c +++ b/lib/src/phy/enb/enb_ul.c @@ -253,22 +253,18 @@ int srslte_enb_ul_cfg_ue(srslte_enb_ul_t *q, uint16_t rnti, } } -void srslte_enb_ul_fft(srslte_enb_ul_t *q) +void srslte_enb_ul_fft(srslte_enb_ul_t *q, cf_t *signal_buffer) { srslte_ofdm_rx_sf(&q->fft); } int get_pucch(srslte_enb_ul_t *q, uint16_t rnti, uint32_t pdcch_n_cce, uint32_t sf_rx, - srslte_uci_data_t *uci_data, uint8_t bits[SRSLTE_PUCCH_MAX_BITS], uint32_t nof_bits) + srslte_uci_data_t *uci_data, uint8_t bits[SRSLTE_PUCCH_MAX_BITS]) { float noise_power = srslte_chest_ul_get_noise_estimate(&q->chest); srslte_pucch_format_t format = srslte_pucch_get_format(uci_data, q->cell.cp); - if (format == SRSLTE_PUCCH_FORMAT_ERROR) { - fprintf(stderr,"Error getting format\n"); - return SRSLTE_ERROR; - } uint32_t n_pucch = srslte_pucch_get_npucch(pdcch_n_cce, format, uci_data->scheduling_request, &q->users[rnti]->pucch_sched); @@ -277,7 +273,7 @@ int get_pucch(srslte_enb_ul_t *q, uint16_t rnti, return SRSLTE_ERROR; } - int ret_val = srslte_pucch_decode(&q->pucch, format, n_pucch, sf_rx, rnti, q->sf_symbols, q->ce, noise_power, bits, nof_bits); + int ret_val = srslte_pucch_decode(&q->pucch, format, n_pucch, sf_rx, rnti, q->sf_symbols, q->ce, noise_power, bits); if (ret_val < 0) { fprintf(stderr,"Error decoding PUCCH\n"); return SRSLTE_ERROR; @@ -290,18 +286,16 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti, srslte_uci_data_t *uci_data) { uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS]; - + if (q->users[rnti]) { - uint32_t nof_uci_bits = uci_data->ri_periodic_report ? uci_data->uci_ri_len : (uci_data->uci_cqi_len + - uci_data->uci_dif_cqi_len + - uci_data->uci_pmi_len); - int ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, pucch_bits, nof_uci_bits); + + int ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, pucch_bits); // If we are looking for SR and ACK at the same time and ret=0, means there is no SR. // try again to decode ACK only if (uci_data->scheduling_request && uci_data->uci_ack_len && ret_val != 1) { uci_data->scheduling_request = false; - ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, pucch_bits, nof_uci_bits); + ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, pucch_bits); } // update schedulign request @@ -311,32 +305,12 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti, // Save ACK bits if (uci_data->uci_ack_len > 0) { - uci_data->uci_ack = pucch_bits[0]; - } - - if (uci_data->uci_ack_len > 1) { - uci_data->uci_ack_2 = pucch_bits[1]; + uci_data->uci_ack = pucch_bits[0]; } // PUCCH2 CQI bits are decoded inside srslte_pucch_decode() if (uci_data->uci_cqi_len) { memcpy(uci_data->uci_cqi, pucch_bits, uci_data->uci_cqi_len*sizeof(uint8_t)); - } - - if (uci_data->uci_dif_cqi_len) { - memcpy(uci_data->uci_dif_cqi, pucch_bits + uci_data->uci_cqi_len, uci_data->uci_dif_cqi_len*sizeof(uint8_t)); - } - - if (uci_data->uci_pmi_len) { - memcpy(uci_data->uci_pmi, pucch_bits + uci_data->uci_cqi_len + uci_data->uci_dif_cqi_len, - uci_data->uci_pmi_len*sizeof(uint8_t)); - } - - if (uci_data->uci_ri_len) { - uci_data->uci_ri = pucch_bits[0]; /* Assume only one bit of RI */ - } - - if (uci_data->uci_cqi_len || uci_data->uci_ri_len) { if (uci_data->uci_ack_len >= 1) { uci_data->uci_ack = pucch_bits[20]; } @@ -354,7 +328,7 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti, int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q, srslte_ra_ul_grant_t *grant, srslte_softbuffer_rx_t *softbuffer, uint16_t rnti, uint32_t rv_idx, uint32_t current_tx_nb, - uint8_t *data, srslte_cqi_value_t *cqi_value, srslte_uci_data_t *uci_data, uint32_t tti) + uint8_t *data, srslte_uci_data_t *uci_data, uint32_t tti) { if (q->users[rnti]) { if (srslte_pusch_cfg(&q->pusch, @@ -390,7 +364,6 @@ int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q, srslte_ra_ul_grant_t *grant, srs softbuffer, q->sf_symbols, q->ce, noise_power, rnti, data, - cqi_value, uci_data); } diff --git a/lib/src/phy/phch/cqi.c b/lib/src/phy/phch/cqi.c index 8589ee51a..2c0940af5 100644 --- a/lib/src/phy/phch/cqi.c +++ b/lib/src/phy/phch/cqi.c @@ -199,44 +199,17 @@ int srslte_cqi_value_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_value_ } int srslte_cqi_size(srslte_cqi_value_t *value) { - int size = 0; - switch(value->type) { case SRSLTE_CQI_TYPE_WIDEBAND: - size = 4; - break; + return 4; case SRSLTE_CQI_TYPE_SUBBAND: - size = 4 + (value->subband.subband_label_2_bits) ? 2 : 1; - break; + return 4+(value->subband.subband_label_2_bits)?2:1; case SRSLTE_CQI_TYPE_SUBBAND_UE: - size = 4 + 2 + value->subband_ue.L; - break; + return 4+2+value->subband_ue.L; case SRSLTE_CQI_TYPE_SUBBAND_HL: - /* First codeword */ - size += 4 + 2 * value->subband_hl.N; - - /* Add Second codeword if required */ - if (value->subband_hl.rank_is_not_one && value->subband_hl.pmi_present) { - size += 4 + 2 * value->subband_hl.N; - } - - /* Add PMI if required*/ - if (value->subband_hl.pmi_present) { - if (value->subband_hl.four_antenna_ports) { - size += 4; - } else { - if (value->subband_hl.rank_is_not_one) { - size += 1; - } else { - size += 2; - } - } - } - break; - default: - size = SRSLTE_ERROR; + return 4+2*value->subband_hl.N; } - return size; + return -1; } static bool srslte_cqi_get_N(uint32_t I_cqi_pmi, uint32_t *N_p, uint32_t *N_offset) { diff --git a/lib/src/phy/phch/pusch.c b/lib/src/phy/phch/pusch.c index 7876a4f86..a8c6064fc 100644 --- a/lib/src/phy/phch/pusch.c +++ b/lib/src/phy/phch/pusch.c @@ -566,9 +566,9 @@ int srslte_pusch_decode(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, cf_t *sf_symbols, cf_t *ce, float noise_estimate, uint16_t rnti, - uint8_t *data, srslte_cqi_value_t *cqi_value, srslte_uci_data_t *uci_data) + uint8_t *data, srslte_uci_data_t *uci_data) { - int ret = SRSLTE_ERROR_INVALID_INPUTS; + uint32_t n; if (q != NULL && @@ -607,42 +607,19 @@ int srslte_pusch_decode(srslte_pusch_t *q, // Generate scrambling sequence if not pre-generated srslte_sequence_t *seq = get_user_sequence(q, rnti, cfg->sf_idx, cfg->nbits.nof_bits); - // Set CQI len assuming RI = 1 (3GPP 36.212 Clause 5.2.4.1. Uplink control information on PUSCH without UL-SCH data) - if (cqi_value) { - if (cqi_value->type == SRSLTE_CQI_TYPE_SUBBAND_HL) { - cqi_value->subband_hl.rank_is_not_one = false; - } - uci_data->uci_cqi_len = (uint32_t) srslte_cqi_size(cqi_value); - uci_data->uci_ri_len = (q->cell.nof_ports == 4) ? 2 : 1; - } - // Decode RI/HARQ bits before descrambling if (srslte_ulsch_uci_decode_ri_ack(&q->ul_sch, cfg, softbuffer, q->q, seq->c, uci_data)) { fprintf(stderr, "Error decoding RI/HARQ bits\n"); return SRSLTE_ERROR; } - - // Set CQI len with corresponding RI - if (cqi_value) { - if (cqi_value->type == SRSLTE_CQI_TYPE_SUBBAND_HL) { - cqi_value->subband_hl.rank_is_not_one = (uci_data->uci_ri != 0); - } - uci_data->uci_cqi_len = (uint32_t) srslte_cqi_size(cqi_value); - } // Descrambling srslte_scrambling_s_offset(seq, q->q, 0, cfg->nbits.nof_bits); - - // Decode - ret = srslte_ulsch_uci_decode(&q->ul_sch, cfg, softbuffer, q->q, q->g, data, uci_data); - - // Unpack CQI value if available - if (cqi_value) { - srslte_cqi_value_unpack(uci_data->uci_cqi, cqi_value); - } + + return srslte_ulsch_uci_decode(&q->ul_sch, cfg, softbuffer, q->q, q->g, data, uci_data); + } else { + return SRSLTE_ERROR_INVALID_INPUTS; } - - return ret; } uint32_t srslte_pusch_last_noi(srslte_pusch_t *q) { diff --git a/lib/src/phy/phch/sch.c b/lib/src/phy/phch/sch.c index 1e972594d..930364725 100644 --- a/lib/src/phy/phch/sch.c +++ b/lib/src/phy/phch/sch.c @@ -658,7 +658,7 @@ int srslte_ulsch_uci_decode_ri_ack(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srs if (cfg->cb_segm.tbs == 0) { beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi]; } - ret = srslte_uci_decode_ack_ri(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, acks, uci_data->uci_ack_len, false); + ret = srslte_uci_decode_ack(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, acks, uci_data->uci_ack_len); if (ret < 0) { return ret; } @@ -678,7 +678,7 @@ int srslte_ulsch_uci_decode_ri_ack(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srs if (cfg->cb_segm.tbs == 0) { beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi]; } - ret = srslte_uci_decode_ack_ri(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, &uci_data->uci_ri, uci_data->uci_ri_len, true); + ret = srslte_uci_decode_ri(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, &uci_data->uci_ri); if (ret < 0) { return ret; } @@ -756,18 +756,13 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q, uint32_t nb_q = cfg->nbits.nof_bits; uint32_t Qm = cfg->grant.Qm; - // Encode RI if CQI enabled - if (uci_data.uci_ri_len > 0 || uci_data.uci_cqi_len > 0) { - /* If no RI is reported set it to zero as specified in 3GPP 36.213 clause 7.2.1 */ - if (uci_data.uci_ri_len == 0) { - uci_data.uci_ri = 0; - } + // Encode RI + if (uci_data.uci_ri_len > 0) { float beta = beta_ri_offset[cfg->uci_cfg.I_offset_ri]; if (cfg->cb_segm.tbs == 0) { beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi]; } - uint8_t ri[2] = {uci_data.uci_ri, 0}; - ret = srslte_uci_encode_ack_ri(cfg, ri, uci_data.uci_ri_len, uci_data.uci_cqi_len, beta, nb_q/Qm, q->ack_ri_bits, true); + ret = srslte_uci_encode_ri(cfg, uci_data.uci_ri, uci_data.uci_cqi_len, beta, nb_q/Qm, q->ack_ri_bits); if (ret < 0) { return ret; } @@ -814,8 +809,8 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q, if (cfg->cb_segm.tbs == 0) { beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi]; } - ret = srslte_uci_encode_ack_ri(cfg, acks, uci_data.uci_ack_len, uci_data.uci_cqi_len, - beta, nb_q / Qm, &q->ack_ri_bits[Q_prime_ri * Qm], false); + ret = srslte_uci_encode_ack(cfg, acks, uci_data.uci_ack_len, uci_data.uci_cqi_len, + beta, nb_q / Qm, &q->ack_ri_bits[Q_prime_ri * Qm]); if (ret < 0) { return ret; } diff --git a/lib/src/phy/phch/test/pusch_test.c b/lib/src/phy/phch/test/pusch_test.c index 651803617..cf0be75c3 100644 --- a/lib/src/phy/phch/test/pusch_test.c +++ b/lib/src/phy/phch/test/pusch_test.c @@ -252,7 +252,7 @@ int main(int argc, char **argv) { } gettimeofday(&t[1], NULL); - int r = srslte_pusch_decode(&pusch_rx, &cfg, &softbuffer_rx, sf_symbols, ce, 0, rnti, data, NULL, &uci_data_rx); + int r = srslte_pusch_decode(&pusch_rx, &cfg, &softbuffer_rx, sf_symbols, ce, 0, rnti, data, &uci_data_rx); gettimeofday(&t[2], NULL); get_time_interval(t); if (r) { diff --git a/lib/src/phy/phch/uci.c b/lib/src/phy/phch/uci.c index 8a1a36544..cb09ca08b 100644 --- a/lib/src/phy/phch/uci.c +++ b/lib/src/phy/phch/uci.c @@ -103,29 +103,26 @@ static uint8_t M_basis_seq_pucch[20][13]={ {1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1}, {1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0}, {1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, - }; + }; void srslte_uci_cqi_pucch_init(srslte_uci_cqi_pucch_t *q) { - uint8_t word[16]; - - uint32_t nwords = 1 << SRSLTE_UCI_MAX_CQI_LEN_PUCCH; - q->cqi_table = srslte_vec_malloc(nwords * sizeof(int8_t *)); - q->cqi_table_s = srslte_vec_malloc(nwords * sizeof(int16_t *)); - - for (uint32_t w = 0; w < nwords; w++) { - q->cqi_table[w] = srslte_vec_malloc(SRSLTE_UCI_CQI_CODED_PUCCH_B * sizeof(int8_t)); - q->cqi_table_s[w] = srslte_vec_malloc(SRSLTE_UCI_CQI_CODED_PUCCH_B * sizeof(int16_t)); + uint8_t word[16]; + + uint32_t nwords = 16; + for (uint32_t w=0;wcqi_table[w] = srslte_vec_malloc(SRSLTE_UCI_CQI_CODED_PUCCH_B*sizeof(int8_t)); + q->cqi_table_s[w] = srslte_vec_malloc(SRSLTE_UCI_CQI_CODED_PUCCH_B*sizeof(int16_t)); uint8_t *ptr = word; - srslte_bit_unpack(w, &ptr, SRSLTE_UCI_MAX_CQI_LEN_PUCCH); - srslte_uci_encode_cqi_pucch(word, SRSLTE_UCI_MAX_CQI_LEN_PUCCH, q->cqi_table[w]); - for (int j = 0; j < SRSLTE_UCI_CQI_CODED_PUCCH_B; j++) { - q->cqi_table_s[w][j] = (int16_t)(2 * q->cqi_table[w][j] - 1); + srslte_bit_unpack(w, &ptr, 4); + srslte_uci_encode_cqi_pucch(word, 4, q->cqi_table[w]); + for (int j=0;jcqi_table_s[w][j] = 2*q->cqi_table[w][j]-1; } } } void srslte_uci_cqi_pucch_free(srslte_uci_cqi_pucch_t *q) { - uint32_t nwords = 1 << SRSLTE_UCI_MAX_CQI_LEN_PUCCH; + uint32_t nwords = 16; for (uint32_t w=0;wcqi_table[w]) { free(q->cqi_table[w]); @@ -134,8 +131,6 @@ void srslte_uci_cqi_pucch_free(srslte_uci_cqi_pucch_t *q) { free(q->cqi_table_s[w]); } } - free(q->cqi_table); - free(q->cqi_table_s); } /* Encode UCI CQI/PMI as described in 5.2.3.3 of 36.212 @@ -156,32 +151,17 @@ int srslte_uci_encode_cqi_pucch(uint8_t *cqi_data, uint32_t cqi_len, uint8_t b_b } } -int srslte_uci_encode_cqi_pucch_from_table(srslte_uci_cqi_pucch_t *q, uint8_t *cqi_data, uint32_t cqi_len, uint8_t b_bits[SRSLTE_UCI_CQI_CODED_PUCCH_B]) -{ - if (cqi_len <= SRSLTE_UCI_MAX_CQI_LEN_PUCCH) { - bzero(&cqi_data[cqi_len], SRSLTE_UCI_MAX_CQI_LEN_PUCCH - cqi_len); - uint8_t *ptr = cqi_data; - uint32_t packed = srslte_bit_pack(&ptr, SRSLTE_UCI_MAX_CQI_LEN_PUCCH); - memcpy(b_bits, q->cqi_table[packed], SRSLTE_UCI_CQI_CODED_PUCCH_B); - - return SRSLTE_SUCCESS; - } else { - return SRSLTE_ERROR_INVALID_INPUTS; - } -} - /* Decode UCI CQI/PMI over PUCCH */ int16_t srslte_uci_decode_cqi_pucch(srslte_uci_cqi_pucch_t *q, int16_t b_bits[32], uint8_t *cqi_data, uint32_t cqi_len) { - if (cqi_len < SRSLTE_UCI_MAX_CQI_LEN_PUCCH && + if (cqi_len == 4 && b_bits != NULL && cqi_data != NULL) { uint32_t max_w = 0; - int32_t max_corr = INT32_MIN; - uint32_t nwords = 1 << SRSLTE_UCI_MAX_CQI_LEN_PUCCH; - for (uint32_t w=0;wcqi_table_s[w], b_bits, SRSLTE_UCI_CQI_CODED_PUCCH_B); @@ -192,7 +172,7 @@ int16_t srslte_uci_decode_cqi_pucch(srslte_uci_cqi_pucch_t *q, int16_t b_bits[32 } // Convert word to bits again uint8_t *ptr = cqi_data; - srslte_bit_unpack(max_w, &ptr, SRSLTE_UCI_MAX_CQI_LEN_PUCCH); + srslte_bit_unpack(max_w, &ptr, cqi_len); INFO("Decoded CQI: w=%d, corr=%d\n", max_w, max_corr); return max_corr; @@ -606,7 +586,9 @@ static uint32_t encode_ri_ack(uint8_t data[2], uint32_t data_len, srslte_uci_bit /* Decode UCI HARQ/ACK bits as described in 5.2.2.6 of 36.212 * Currently only supporting 1-bit HARQ */ -static int32_t decode_ri_ack_1bit(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos) +#ifndef MIMO_ENB + +static int32_t decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos) { uint32_t p0 = pos[0].position; uint32_t p1 = pos[1].position; @@ -616,8 +598,33 @@ static int32_t decode_ri_ack_1bit(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bi return -(q0+q1); } +int srslte_uci_decode_ack(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_seq, + float beta, uint32_t H_prime_total, + uint32_t O_cqi, srslte_uci_bit_t *ack_bits, uint8_t acks[2], uint32_t nof_acks) +{ + int32_t rx_ack = 0; -static void decode_ri_ack_2bits(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos, uint32_t Qm, int32_t data[3]) + if (beta < 0) { + fprintf(stderr, "Error beta is reserved\n"); + return -1; + } + + uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta); + + // Use the same interleaver function to get the HARQ bit position + for (uint32_t i=0;igrant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ack_bits[cfg->grant.Qm*i]); + rx_ack += (int32_t) decode_ri_ack(q_bits, c_seq, &ack_bits[cfg->grant.Qm*i]); + } + + if (acks) { + acks[0] = rx_ack>0; + } + return (int) Qprime; +} +#else + +static void decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos, uint32_t Qm, int32_t data[3]) { uint32_t p0 = pos[Qm * 0 + 0].position; uint32_t p1 = pos[Qm * 0 + 1].position; @@ -638,91 +645,118 @@ static void decode_ri_ack_2bits(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_ data[2] -= q2 + q5; } -/* Encode UCI ACK/RI bits as described in 5.2.2.6 of 36.212 - * Currently only supporting 1-bit RI - */ -int srslte_uci_encode_ack_ri(srslte_pusch_cfg_t *cfg, - uint8_t *data, uint32_t data_len, - uint32_t O_cqi, float beta, uint32_t H_prime_total, - srslte_uci_bit_t *bits, bool ack_ri) { +int srslte_uci_decode_ack(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_seq, + float beta, uint32_t H_prime_total, + uint32_t O_cqi, srslte_uci_bit_t *ack_bits, uint8_t acks[2], uint32_t nof_acks) +{ + int32_t acks_sum[3] = {0, 0, 0}; + if (beta < 0) { fprintf(stderr, "Error beta is reserved\n"); - return -1; + return -1; } - uint32_t Qprime = Q_prime_ri_ack(cfg, data_len, O_cqi, beta); - srslte_uci_bit_type_t q_encoded_bits[18]; - uint32_t nof_encoded_bits = encode_ri_ack(data, data_len, q_encoded_bits, cfg->grant.Qm); + uint32_t Qprime = Q_prime_ri_ack(cfg, nof_acks, O_cqi, beta); + // Use the same interleaver function to get the HARQ bit position for (uint32_t i = 0; i < Qprime; i++) { - if (ack_ri) { - uci_ulsch_interleave_ri_gen(i, - cfg->grant.Qm, - H_prime_total, - cfg->nbits.nof_symb, - cfg->cp, - &bits[cfg->grant.Qm * i]); - } else { - uci_ulsch_interleave_ack_gen(i, - cfg->grant.Qm, - H_prime_total, - cfg->nbits.nof_symb, - cfg->cp, - &bits[cfg->grant.Qm * i]); + uci_ulsch_interleave_ack_gen(i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ack_bits[cfg->grant.Qm*i]); + if ((i % 3 == 0) && i > 0) { + decode_ri_ack(q_bits, &c_seq[0], &ack_bits[cfg->grant.Qm*(i-3)], cfg->grant.Qm, acks_sum); } - uci_ulsch_interleave_put(&q_encoded_bits[(i * cfg->grant.Qm) % nof_encoded_bits], - cfg->grant.Qm, - &bits[cfg->grant.Qm * i]); } + if (acks) { + acks[0] = (uint8_t)(acks_sum[0] > 0); + acks[1] = (uint8_t)(acks_sum[1] > 0); + // TODO: Do something with acks_sum[2] + } + return (int) Qprime; +} +#endif + +/* Encode UCI HARQ/ACK bits as described in 5.2.2.6 of 36.212 + * Currently only supporting 1-bit HARQ + */ +int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, uint8_t acks[2], uint32_t nof_acks, + uint32_t O_cqi, float beta, uint32_t H_prime_total, + srslte_uci_bit_t *ack_bits) +{ + if (beta < 0) { + fprintf(stderr, "Error beta is reserved\n"); + return -1; + } + + uint32_t Qprime = Q_prime_ri_ack(cfg, nof_acks, O_cqi, beta); + srslte_uci_bit_type_t q_encoded_bits[18]; + + uint32_t nof_encoded_bits = encode_ri_ack(acks, nof_acks, q_encoded_bits, cfg->grant.Qm); + + for (uint32_t i=0;igrant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ack_bits[cfg->grant.Qm*i]); + uci_ulsch_interleave_put(&q_encoded_bits[(i*cfg->grant.Qm)%nof_encoded_bits], cfg->grant.Qm, &ack_bits[cfg->grant.Qm*i]); + } + return (int) Qprime; } -/* Decode UCI ACK/RI bits as described in 5.2.2.6 of 36.212 +/* Encode UCI RI bits as described in 5.2.2.6 of 36.212 * Currently only supporting 1-bit RI */ -int srslte_uci_decode_ack_ri(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_seq, - float beta, uint32_t H_prime_total, - uint32_t O_cqi, srslte_uci_bit_t *ack_ri_bits, uint8_t data[2], uint32_t nof_bits, bool is_ri) +int srslte_uci_decode_ri(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_seq, + float beta, uint32_t H_prime_total, + uint32_t O_cqi, srslte_uci_bit_t *ri_bits, uint8_t *data) { - int32_t sum[3] = {0, 0, 0}; - + int32_t ri_sum[3] = {0, 0, 0}; + if (beta < 0) { fprintf(stderr, "Error beta is reserved\n"); - return -1; + return -1; } - uint32_t Qprime = Q_prime_ri_ack(cfg, nof_bits, O_cqi, beta); + uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta); - for (uint32_t i = 0; i < Qprime; i++) { - if (is_ri) { - uci_ulsch_interleave_ri_gen(i, - cfg->grant.Qm, - H_prime_total, - cfg->nbits.nof_symb, - cfg->cp, - &ack_ri_bits[cfg->grant.Qm * i]); - } else { - uci_ulsch_interleave_ack_gen(i, - cfg->grant.Qm, - H_prime_total, - cfg->nbits.nof_symb, - cfg->cp, - &ack_ri_bits[cfg->grant.Qm * i]); - - } - if (nof_bits == 2 && (i % 3 == 0) && i > 0) { - decode_ri_ack_2bits(q_bits, &c_seq[0], &ack_ri_bits[cfg->grant.Qm * (i - 3)], cfg->grant.Qm, sum); - } else if (nof_bits == 1) { - sum[0] += (int32_t) decode_ri_ack_1bit(q_bits, c_seq, &ack_ri_bits[cfg->grant.Qm * i]); + // Use the same interleaver function to get the HARQ bit position + for (uint32_t i=0;igrant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ri_bits[cfg->grant.Qm*i]); + if ((i % 3 == 0) && i > 0) { + //decode_ri_ack(q_bits, &c_seq[0], &ri_bits[cfg->grant.Qm*(i-3)], cfg->grant.Qm, ri_sum); } } - data[0] = (uint8_t) (sum[0] > 0); - if (nof_bits == 2) { - data[1] = (uint8_t) (sum[1] > 0); + if (data) { + *data = (uint8_t) ((ri_sum[0] + ri_sum[1] + ri_sum[2]) > 0); } + return (int) Qprime; +} + + +/* Encode UCI RI bits as described in 5.2.2.6 of 36.212 + * Currently only supporting 1-bit RI + */ +int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg, + uint8_t ri, + uint32_t O_cqi, float beta, uint32_t H_prime_total, + srslte_uci_bit_t *ri_bits) +{ + // FIXME: It supports RI of 1 bit only + uint8_t data[2] = {ri, 0}; + if (beta < 0) { + fprintf(stderr, "Error beta is reserved\n"); + return -1; + } + uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta); + srslte_uci_bit_type_t q_encoded_bits[18]; + + uint32_t nof_encoded_bits = encode_ri_ack(data, 1, q_encoded_bits, cfg->grant.Qm); + + for (uint32_t i=0;igrant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ri_bits[cfg->grant.Qm*i]); + uci_ulsch_interleave_put(&q_encoded_bits[(i*cfg->grant.Qm)%nof_encoded_bits], cfg->grant.Qm, &ri_bits[cfg->grant.Qm*i]); + } + return (int) Qprime; } + diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index 4183016e0..db7118b0c 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -725,8 +725,7 @@ int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, uint8_t *ri, uint8_t *pmi, flo /* Select the best Rank indicator (RI) and Precoding Matrix Indicator (PMI) */ for (uint32_t nof_layers = 1; nof_layers <= SRSLTE_MAX_LAYERS; nof_layers++) { float _sinr = q->sinr[nof_layers - 1][q->pmi[nof_layers - 1]] * nof_layers * nof_layers; - /* Find best SINR, force maximum number of layers if SNR is higher than 30 dB */ - if (_sinr > best_sinr + 0.1 || _sinr > 1.0e+3) { + if (_sinr > best_sinr + 0.1) { best_sinr = _sinr; best_pmi = (uint8_t) q->pmi[nof_layers - 1]; best_ri = (uint8_t) (nof_layers - 1); diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index 990633aa7..5298e6e7a 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -88,19 +88,16 @@ void phch_worker::init(phch_common* phy_, srslte::log *log_h_) pthread_mutex_init(&mutex, NULL); // Init cell here - for(int p = 0; p < SRSLTE_MAX_PORTS; p++) { - signal_buffer_rx[p] = (cf_t *) srslte_vec_malloc(2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t)); - if (!signal_buffer_rx[p]) { - fprintf(stderr, "Error allocating memory\n"); - return; - } - bzero(signal_buffer_rx[p], 2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t)); - signal_buffer_tx[p] = (cf_t *) srslte_vec_malloc(2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t)); - if (!signal_buffer_tx[p]) { - fprintf(stderr, "Error allocating memory\n"); - return; - } - bzero(signal_buffer_tx[p], 2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t)); + signal_buffer_rx = (cf_t*) srslte_vec_malloc(2*SRSLTE_SF_LEN_PRB(phy->cell.nof_prb)*sizeof(cf_t)); + if (!signal_buffer_rx) { + fprintf(stderr, "Error allocating memory\n"); + return; + } + 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, signal_buffer_tx, phy->cell.nof_prb)) { fprintf(stderr, "Error initiating ENB DL\n"); @@ -110,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, signal_buffer_rx[0], 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; } @@ -157,12 +154,12 @@ void phch_worker::stop() srslte_enb_dl_free(&enb_dl); srslte_enb_ul_free(&enb_ul); - for (int p = 0; p < SRSLTE_MAX_PORTS; p++) { - if (signal_buffer_rx[p]) { - free(signal_buffer_rx[p]); - } - if (signal_buffer_tx[p]) { - free(signal_buffer_tx[p]); + if (signal_buffer_rx) { + free(signal_buffer_rx); + } + for (int i = 0; i < SRSLTE_MAX_PORTS; i++) { + if (signal_buffer_tx[i]) { + free(signal_buffer_tx[i]); } } pthread_mutex_unlock(&mutex); @@ -174,9 +171,9 @@ void phch_worker::reset() ue_db.clear(); } -cf_t* phch_worker::get_buffer_rx(uint32_t antenna_idx) +cf_t* phch_worker::get_buffer_rx() { - return signal_buffer_rx[antenna_idx]; + return signal_buffer_rx; } void phch_worker::set_time(uint32_t tti_, uint32_t tx_mutex_cnt_, srslte_timestamp_t tx_time_) @@ -217,29 +214,12 @@ uint32_t phch_worker::get_nof_rnti() { return ue_db.size(); } -void phch_worker::set_conf_dedicated_ack(uint16_t rnti, bool ack){ - pthread_mutex_lock(&mutex); - if (ue_db.count(rnti)) { - ue_db[rnti].dedicated_ack = ack; - } else { - Error("Setting dedicated ack: rnti=0x%x does not exist\n"); - } - pthread_mutex_unlock(&mutex); -} - void phch_worker::set_config_dedicated(uint16_t rnti, srslte_uci_cfg_t *uci_cfg, srslte_pucch_sched_t *pucch_sched, - srslte_refsignal_srs_cfg_t *srs_cfg, - LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT* dedicated) + srslte_refsignal_srs_cfg_t *srs_cfg, + uint32_t I_sr, bool pucch_cqi, uint32_t pmi_idx, bool pucch_cqi_ack) { - uint32_t I_sr = dedicated->sched_request_cnfg.sr_cnfg_idx; - bool pucch_cqi = dedicated->cqi_report_cnfg.report_periodic_setup_present; - uint32_t pmi_idx = dedicated->cqi_report_cnfg.report_periodic.pmi_cnfg_idx; - bool pucch_cqi_ack = dedicated->cqi_report_cnfg.report_periodic.simult_ack_nack_and_cqi; - bool pucch_ri = dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx_present; - uint32_t ri_idx = dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx; - pthread_mutex_lock(&mutex); if (ue_db.count(rnti)) { pucch_sched->N_pucch_1 = phy->pucch_cfg.n1_pucch_an; @@ -257,16 +237,6 @@ void phch_worker::set_config_dedicated(uint16_t rnti, ue_db[rnti].cqi_en = false; } - if (pucch_ri) { - ue_db[rnti].ri_idx = ri_idx; - ue_db[rnti].ri_en = true; - } else { - ue_db[rnti].ri_idx = 0; - ue_db[rnti].ri_en = false; - } - - /* Copy all dedicated RRC configuration to UE */ - memcpy(&ue_db[rnti].dedicated, dedicated, sizeof(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT)); } else { Error("Setting config dedicated: rnti=0x%x does not exist\n"); } @@ -308,7 +278,7 @@ void phch_worker::work_imp() } pthread_mutex_lock(&mutex); - + mac_interface_phy::ul_sched_t *ul_grants = phy->ul_grants; mac_interface_phy::dl_sched_t *dl_grants = phy->dl_grants; mac_interface_phy *mac = phy->mac; @@ -323,7 +293,7 @@ void phch_worker::work_imp() } // Process UL signal - srslte_enb_ul_fft(&enb_ul); + srslte_enb_ul_fft(&enb_ul, signal_buffer_rx); // Decode pending UL grants for the tti they were scheduled decode_pusch(ul_grants[t_rx].sched_grants, ul_grants[t_rx].nof_grants); @@ -365,22 +335,15 @@ void phch_worker::work_imp() phy->ack_clear(TTIMOD(TTI_TX(t_tx_dl))); for (uint32_t i=0;i= SRSLTE_CRNTI_START && rnti <= SRSLTE_CRNTI_END) { - /* For each TB */ - for (uint32_t tb_idx = 0; tb_idx < SRSLTE_MAX_TB; tb_idx++) { - /* If TB enabled, set pending ACK */ - if (dl_grants[t_tx_dl].sched_grants[i].grant.tb_en[tb_idx]) { - phy->ack_set_pending(TTIMOD(TTI_TX(t_tx_dl)), rnti, tb_idx, dl_grants[t_tx_dl].sched_grants[i].location.ncce); - } - } + if (dl_grants[t_tx_dl].sched_grants[i].rnti >= SRSLTE_CRNTI_START && dl_grants[t_tx_dl].sched_grants[i].rnti <= SRSLTE_CRNTI_END) { + phy->ack_set_pending(TTIMOD(TTI_TX(t_tx_dl)), dl_grants[t_tx_dl].sched_grants[i].rnti, dl_grants[t_tx_dl].sched_grants[i].location.ncce); } } // Generate signal and transmit 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); @@ -424,39 +387,24 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) gettimeofday(&t[1], NULL); #endif - bool acks_pending[SRSLTE_MAX_TB] = {false}; - // Get pending ACKs with an associated PUSCH transmission - for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { - acks_pending[tb] = phy->ack_is_pending(t_rx, rnti, tb); - if (acks_pending[tb]) { - uci_data.uci_ack_len++; - } + if (phy->ack_is_pending(t_rx, rnti)) { + uci_data.uci_ack_len = 1; } - // Configure PUSCH CQI channel - srslte_cqi_value_t cqi_value = {0}; + srslte_cqi_value_t cqi_value; bool cqi_enabled = false; -#if 0 - if (ue_db[rnti].cqi_en && ue_db[rnti].ri_en && srslte_ri_send(ue_db[rnti].pmi_idx, ue_db[rnti].ri_idx, tti_rx) ) { - uci_data.uci_ri_len = 1; /* Asumes only 1 bit for RI */ - ri_enabled = true; - } else if (ue_db[rnti].cqi_en && srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) { + if (ue_db[rnti].cqi_en && srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) { cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND; cqi_enabled = true; - if (ue_db[rnti].dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { - //uci_data.uci_dif_cqi_len = 3; - uci_data.uci_pmi_len = 2; - } - } else -#endif - if (grants[i].grant.cqi_request) { + } else if (grants[i].grant.cqi_request) { cqi_value.type = SRSLTE_CQI_TYPE_SUBBAND_HL; cqi_value.subband_hl.N = (phy->cell.nof_prb > 7) ? srslte_cqi_hl_get_no_subbands(phy->cell.nof_prb) : 0; - cqi_value.subband_hl.four_antenna_ports = (phy->cell.nof_ports == 4); - cqi_value.subband_hl.pmi_present = (ue_db[rnti].dedicated.cqi_report_cnfg.report_mode_aperiodic == LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM31); cqi_enabled = true; } + if (cqi_enabled) { + uci_data.uci_cqi_len = srslte_cqi_size(&cqi_value); + } // mark this tti as having an ul grant to avoid pucch ue_db[rnti].has_grant_tti = tti_rx; @@ -464,6 +412,22 @@ 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)) { + + // Handle Format0 adaptive retx + // Use last TBS for this TB in case of mcs>28 + if (phy_grant.mcs.idx > 28) { + phy_grant.mcs.tbs = ue_db[rnti].last_ul_tbs[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)]; + Info("RETX: mcs=%d, old_tbs=%d pid=%d\n", phy_grant.mcs.idx, phy_grant.mcs.tbs, TTI_TX(tti_rx)%(2*HARQ_DELAY_MS)); + } + ue_db[rnti].last_ul_tbs[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)] = phy_grant.mcs.tbs; + + if (phy_grant.mcs.mod == SRSLTE_MOD_LAST) { + phy_grant.mcs.mod = ue_db[rnti].last_ul_mod[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)]; + phy_grant.Qm = srslte_mod_bits_x_symbol(phy_grant.mcs.mod); + } + ue_db[rnti].last_ul_mod[TTI_RX(tti_rx)%(2*HARQ_DELAY_MS)] = phy_grant.mcs.mod; + + if (phy_grant.mcs.mod == SRSLTE_MOD_64QAM) { phy_grant.mcs.mod = SRSLTE_MOD_16QAM; } @@ -472,7 +436,6 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) rnti, grants[i].rv_idx, grants[i].current_tx_nb, grants[i].data, - (cqi_enabled) ? &cqi_value : NULL, &uci_data, sf_rx); } else { @@ -494,24 +457,11 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) char cqi_str[64]; if (cqi_enabled) { + srslte_cqi_value_unpack(uci_data.uci_cqi, &cqi_value); if (ue_db[rnti].cqi_en) { wideband_cqi_value = cqi_value.wideband.wideband_cqi; } else if (grants[i].grant.cqi_request) { wideband_cqi_value = cqi_value.subband_hl.wideband_cqi_cw0; - if (cqi_value.subband_hl.pmi_present) { - if (cqi_value.subband_hl.rank_is_not_one) { - Info("PUSCH: Aperiodic ri~1, CQI=%02d/%02d, pmi=%d for %d subbands\n", - cqi_value.subband_hl.wideband_cqi_cw0, cqi_value.subband_hl.wideband_cqi_cw1, - cqi_value.subband_hl.pmi, cqi_value.subband_hl.N); - } else { - Info("PUSCH: Aperiodic ri=1, CQI=%02d, pmi=%d for %d subbands\n", - cqi_value.subband_hl.wideband_cqi_cw0, cqi_value.subband_hl.pmi, cqi_value.subband_hl.N); - } - } else { - Info("PUSCH: Aperiodic ri%s, CQI=%02d for %d subbands\n", - cqi_value.subband_hl.rank_is_not_one?"~1":"=1", - cqi_value.subband_hl.wideband_cqi_cw0, cqi_value.subband_hl.N); - } } snprintf(cqi_str, 64, ", cqi=%d", wideband_cqi_value); } @@ -531,16 +481,14 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) } */ log_h->info_hex(grants[i].data, phy_grant.mcs.tbs/8, - "PUSCH: rnti=0x%x, prb=(%d,%d), tbs=%d, mcs=%d, rv=%d, snr=%.1f dB, n_iter=%d, crc=%s%s%s%s%s\n", + "PUSCH: rnti=0x%x, prb=(%d,%d), tbs=%d, mcs=%d, rv=%d, snr=%.1f dB, n_iter=%d, crc=%s%s%s%s\n", rnti, phy_grant.n_prb[0], phy_grant.n_prb[0]+phy_grant.L_prb, phy_grant.mcs.tbs/8, phy_grant.mcs.idx, grants[i].grant.rv_idx, snr_db, srslte_pusch_last_noi(&enb_ul.pusch), crc_res?"OK":"KO", - (uci_data.uci_ack_len)?(uci_data.uci_ack?"1":"0"):"", - (uci_data.uci_ack_len > 1)?(uci_data.uci_ack_2?"1":"0"):"", + uci_data.uci_ack_len>0?(uci_data.uci_ack?", ack=1":", ack=0"):"", uci_data.uci_cqi_len>0?cqi_str:"", - uci_data.uci_ri_len>0?(uci_data.uci_ri?", ri=0":", ri=1"):"", timestr); // Notify MAC of RL status @@ -555,28 +503,17 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) // Notify MAC new received data and HARQ Indication value phy->mac->crc_info(tti_rx, rnti, phy_grant.mcs.tbs/8, crc_res); - uint32_t ack_idx = 0; - for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { - if (acks_pending[tb]) { - bool ack = ((ack_idx++ == 0) ? uci_data.uci_ack : uci_data.uci_ack_2); - bool valid = (crc_res || snr_db > PUSCH_RL_SNR_DB_TH); - phy->mac->ack_info(tti_rx, rnti, tb, ack && valid); - } + if (uci_data.uci_ack_len) { + phy->mac->ack_info(tti_rx, rnti, uci_data.uci_ack && (crc_res || snr_db > PUSCH_RL_SNR_DB_TH)); } - // Notify MAC of UL SNR, DL CQI and DL RI + // Notify MAC of UL SNR and DL CQI if (snr_db >= PUSCH_RL_SNR_DB_TH) { phy->mac->snr_info(tti_rx, rnti, snr_db); } if (uci_data.uci_cqi_len>0 && crc_res) { phy->mac->cqi_info(tti_rx, rnti, wideband_cqi_value); } - if (uci_data.uci_ri_len > 0 && crc_res) { - phy->mac->ri_info(tti_rx, rnti, uci_data.uci_ri); - } - if (cqi_value.subband_hl.pmi_present && crc_res) { - phy->mac->pmi_info(tti_rx, rnti, cqi_value.subband_hl.pmi); - } // Save metrics stats ue_db[rnti].metrics_ul(phy_grant.mcs.idx, 0, snr_db, srslte_pusch_last_noi(&enb_ul.pusch)); @@ -595,8 +532,7 @@ int phch_worker::decode_pucch() if (rnti >= SRSLTE_CRNTI_START && rnti <= SRSLTE_CRNTI_END && ue_db[rnti].has_grant_tti != (int) tti_rx) { // Check if user needs to receive PUCCH - bool needs_pucch = false, needs_ack[SRSLTE_MAX_TB] = {false}, needs_sr = false, needs_cqi = false, - needs_ri = false; + bool needs_pucch = false, needs_ack=false, needs_sr=false, needs_cqi=false; uint32_t last_n_pdcch = 0; bzero(&uci_data, sizeof(srslte_uci_data_t)); @@ -608,32 +544,18 @@ int phch_worker::decode_pucch() } } - for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { - needs_ack[tb] = phy->ack_is_pending(t_rx, rnti, tb, &last_n_pdcch); - if (needs_ack[tb]) { - needs_pucch = true; - uci_data.uci_ack_len++; - } + if (phy->ack_is_pending(t_rx, rnti, &last_n_pdcch)) { + needs_pucch = true; + needs_ack = true; + uci_data.uci_ack_len = 1; } srslte_cqi_value_t cqi_value; - LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *dedicated = &ue_db[rnti].dedicated; - LIBLTE_RRC_TRANSMISSION_MODE_ENUM tx_mode = dedicated->antenna_info_explicit_value.tx_mode; - - if (ue_db[rnti].cqi_en && (ue_db[rnti].pucch_cqi_ack || !needs_ack[0] || !needs_ack[1])) { - if (ue_db[rnti].ri_en && srslte_ri_send(ue_db[rnti].pmi_idx, ue_db[rnti].ri_idx, tti_rx)) { - needs_pucch = true; - needs_ri = true; - uci_data.uci_ri_len = 1; - uci_data.ri_periodic_report = true; - } else if (srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) { + if (ue_db[rnti].cqi_en && (ue_db[rnti].pucch_cqi_ack || !needs_ack)) { + if (srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) { needs_pucch = true; needs_cqi = true; cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND; uci_data.uci_cqi_len = srslte_cqi_size(&cqi_value); - if (tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { - //uci_data.uci_dif_cqi_len = 3; - uci_data.uci_pmi_len = 2; - } } } @@ -642,48 +564,26 @@ int phch_worker::decode_pucch() fprintf(stderr, "Error getting PUCCH\n"); return SRSLTE_ERROR; } - /* If only one ACK is required, it can be for TB0 or TB1 */ - uint32_t ack_idx = 0; - for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { - if (needs_ack[tb]) { - bool ack = ((ack_idx++ == 0) ? uci_data.uci_ack : uci_data.uci_ack_2); - bool valid = srslte_pucch_get_last_corr(&enb_ul.pucch) >= PUCCH_RL_CORR_TH; - phy->mac->ack_info(tti_rx, rnti, tb, ack && valid); - } + if (uci_data.uci_ack_len > 0) { + phy->mac->ack_info(tti_rx, rnti, uci_data.uci_ack && (srslte_pucch_get_last_corr(&enb_ul.pucch) >= PUCCH_RL_CORR_TH)); } if (uci_data.scheduling_request) { phy->mac->sr_detected(tti_rx, rnti); } - - char cqi_ri_str[64]; - if (srslte_pucch_get_last_corr(&enb_ul.pucch) > PUCCH_RL_CORR_TH) { - if (uci_data.uci_ri_len && needs_ri) { - phy->mac->ri_info(tti_rx, rnti, uci_data.uci_ri); - sprintf(cqi_ri_str, ", ri=%d", uci_data.uci_ri); - } else if (uci_data.uci_cqi_len && needs_cqi) { - srslte_cqi_value_unpack(uci_data.uci_cqi, &cqi_value); - phy->mac->cqi_info(tti_rx, rnti, cqi_value.wideband.wideband_cqi); - sprintf(cqi_ri_str, ", cqi=%d", cqi_value.wideband.wideband_cqi); - - if (uci_data.uci_pmi_len) { - uint32_t packed_pmi = uci_data.uci_pmi[0]; - if (uci_data.uci_pmi_len > 1) { - packed_pmi = (packed_pmi << 1) + uci_data.uci_pmi[1]; - } - phy->mac->pmi_info(tti_rx, rnti, packed_pmi); - sprintf(cqi_ri_str, "%s, pmi=%c", cqi_ri_str, packed_pmi + 0x30); - } - } + char cqi_str[64]; + if (uci_data.uci_cqi_len) { + srslte_cqi_value_unpack(uci_data.uci_cqi, &cqi_value); + phy->mac->cqi_info(tti_rx, rnti, cqi_value.wideband.wideband_cqi); + sprintf(cqi_str, ", cqi=%d", cqi_value.wideband.wideband_cqi); } - log_h->info("PUCCH: rnti=0x%x, corr=%.2f, n_pucch=%d, n_prb=%d%s%s%s%s\n", + log_h->info("PUCCH: rnti=0x%x, corr=%.2f, n_pucch=%d, n_prb=%d%s%s%s\n", rnti, srslte_pucch_get_last_corr(&enb_ul.pucch), enb_ul.pucch.last_n_pucch, enb_ul.pucch.last_n_prb, - (uci_data.uci_ack_len)?(uci_data.uci_ack?", ack=1":", ack=0"):"", - (uci_data.uci_ack_len > 1)?(uci_data.uci_ack_2?"1":"0"):"", + needs_ack?(uci_data.uci_ack?", ack=1":", ack=0"):"", needs_sr?(uci_data.scheduling_request?", sr=yes":", sr=no"):"", - (needs_cqi || needs_ri)?cqi_ri_str:""); + needs_cqi?cqi_str:""); // Notify MAC of RL status @@ -742,16 +642,25 @@ int phch_worker::encode_pdcch_ul(srslte_enb_ul_pusch_t *grants, uint32_t nof_gra int phch_worker::encode_pdcch_dl(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants) { for (uint32_t i=0;irnti; + uint16_t rnti = grants[i].rnti; if (rnti) { - if (srslte_enb_dl_put_pdcch_dl(&enb_dl, &grants[i].grant, grant->dci_format, grants[i].location, rnti, sf_tx)) { + srslte_dci_format_t format = SRSLTE_DCI_FORMAT1; + switch(grants[i].grant.alloc_type) { + case SRSLTE_RA_ALLOC_TYPE0: + case SRSLTE_RA_ALLOC_TYPE1: + format = SRSLTE_DCI_FORMAT1; + break; + case SRSLTE_RA_ALLOC_TYPE2: + format = SRSLTE_DCI_FORMAT1A; + break; + } + if (srslte_enb_dl_put_pdcch_dl(&enb_dl, &grants[i].grant, format, grants[i].location, rnti, sf_tx)) { fprintf(stderr, "Error putting PDCCH %d\n",i); return SRSLTE_ERROR; } if (LOG_THIS(rnti)) { - Info("PDCCH: DL DCI %s rnti=0x%x, cce_index=%d, L=%d, tti_tx_dl=%d\n", srslte_dci_format_string(grant->dci_format), + Info("PDCCH: DL DCI %s rnti=0x%x, cce_index=%d, L=%d, tti_tx_dl=%d\n", srslte_dci_format_string(format), rnti, grants[i].location.ncce, (1<info_hex(ptr, len, - "PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tti_tx_dl=%d, tx_scheme=%s%s%s%s\n", - rnti, phy_grant.nof_prb, grant_str, grants[i].grant.harq_process, tti_tx_dl, - srslte_mimotype2str(mimo_type), pinfo_str, tbstr[0], tbstr[1]); + "PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tbs=%d, mcs=%d, rv=%d, tti_tx_dl=%d\n", + rnti, phy_grant.nof_prb, grant_str, grants[i].grant.harq_process, + phy_grant.mcs[0].tbs/8, phy_grant.mcs[0].idx, grants[i].grant.rv_idx, tti_tx_dl); } - int rv[SRSLTE_MAX_CODEWORDS] = {grants[i].grant.rv_idx, grants[i].grant.rv_idx_1}; + srslte_softbuffer_tx_t *sb[SRSLTE_MAX_CODEWORDS] = {grants[i].softbuffer, NULL}; + uint8_t *d[SRSLTE_MAX_CODEWORDS] = {grants[i].data, NULL}; + int rv[SRSLTE_MAX_CODEWORDS] = {grants[i].grant.rv_idx, 0}; - if (srslte_enb_dl_put_pdsch(&enb_dl, &phy_grant, grants[i].softbuffers, rnti, rv, sf_tx, grants[i].data, mimo_type)) { - fprintf(stderr, "Error putting PDSCH %d\n", i); - return SRSLTE_ERROR; + + if (srslte_enb_dl_put_pdsch(&enb_dl, &phy_grant, sb, rnti, rv, sf_tx, d, SRSLTE_MIMO_TYPE_SINGLE_ANTENNA, 0)) + { + fprintf(stderr, "Error putting PDSCH %d\n",i); + return SRSLTE_ERROR; } - // Save metrics stats + // Save metrics stats ue_db[rnti].metrics_dl(phy_grant.mcs[0].idx); } } - return SRSLTE_SUCCESS; + return SRSLTE_SUCCESS; } diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index 29cbdef8e..e176e8ac5 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -1142,11 +1142,7 @@ void rrc::ue::send_connection_setup(bool is_setup) phy_cfg->cqi_report_cnfg_present = true; if(parent->cfg.cqi_cfg.mode == RRC_CFG_CQI_MODE_APERIODIC) { phy_cfg->cqi_report_cnfg.report_mode_aperiodic_present = true; - if (phy_cfg->antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { - phy_cfg->cqi_report_cnfg.report_mode_aperiodic = LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM31; - } else { - phy_cfg->cqi_report_cnfg.report_mode_aperiodic = LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30; - } + phy_cfg->cqi_report_cnfg.report_mode_aperiodic = LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30; } else { phy_cfg->cqi_report_cnfg.report_periodic_present = true; phy_cfg->cqi_report_cnfg.report_periodic_setup_present = true; diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 2beff5900..0068724b4 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -859,9 +859,7 @@ void phch_worker::set_uci_periodic_cqi() if (period_cqi.configured && rnti_is_set) { if (period_cqi.ri_idx_present && srslte_ri_send(period_cqi.pmi_idx, period_cqi.ri_idx, TTI_TX(tti))) { - /* Compute RI, PMI and SINR */ compute_ri(); - uci_data.ri_periodic_report = true; Info("PUCCH: Periodic RI=%d\n", uci_data.uci_ri); } else if (srslte_cqi_send(period_cqi.pmi_idx, TTI_TX(tti))) { @@ -904,9 +902,6 @@ void phch_worker::set_uci_periodic_cqi() void phch_worker::set_uci_aperiodic_cqi() { if (phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic_present) { - /* Compute RI, PMI and SINR */ - compute_ri(); - switch(phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic) { case LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30: /* only Higher Layer-configured subband feedback support right now, according to TS36.213 section 7.2.1 @@ -944,6 +939,9 @@ void phch_worker::set_uci_aperiodic_cqi() other transmission modes they are reported conditioned on rank 1. */ if (rnti_is_set) { + /* Compute RI, PMI and SINR */ + compute_ri(); + /* Select RI, PMI and SINR */ uint32_t ri = ue_dl.ri; // Select RI (0: 1 layer, 1: 2 layer, otherwise: not implemented) uint32_t pmi = ue_dl.pmi[ri]; // Select PMI @@ -974,9 +972,9 @@ void phch_worker::set_uci_aperiodic_cqi() cqi_report.subband_hl.wideband_cqi_cw0, cqi_report.subband_hl.wideband_cqi_cw1, sinr_db, sinr_db, pmi, cqi_report.subband_hl.N); } else { - Info("PUSCH: Aperiodic ri=1, CQI=%02d, SINR=%2.1f, pmi=%d for %d subbands\n", - cqi_report.subband_hl.wideband_cqi_cw0, - sinr_db, pmi, cqi_report.subband_hl.N); + Info("PUSCH: Aperiodic ri=1, CQI=%d/%d, SINR=%2.1f dB, for %d subbands\n", + cqi_report.wideband.wideband_cqi, + phy->avg_snr_db, cqi_report.subband_hl.N); } uci_data.uci_cqi_len = srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi); } From e720568e82bddff75fd5da98302ab0d460bf7052 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Mon, 4 Dec 2017 12:08:02 -0600 Subject: [PATCH 197/242] Revert "Added UE Mode 3-1 aperiodic reporting" This reverts commit 0bd683b3c4455e1274450d4487a6077f231f0ba5. --- lib/include/srslte/phy/phch/cqi.h | 21 +--- lib/include/srslte/phy/phch/uci.h | 1 - lib/src/phy/phch/cqi.c | 73 ++----------- lib/src/phy/phch/pucch.c | 2 +- lib/src/phy/ue/ue_dl.c | 4 +- lib/src/phy/ue/ue_ul.c | 28 ++--- srsenb/src/phy/phch_worker.cc | 2 +- srsue/hdr/phy/phch_worker.h | 3 +- srsue/src/phy/phch_worker.cc | 175 ++++++++++-------------------- 9 files changed, 88 insertions(+), 221 deletions(-) diff --git a/lib/include/srslte/phy/phch/cqi.h b/lib/include/srslte/phy/phch/cqi.h index 0d0c17fec..cfc9e92e7 100644 --- a/lib/include/srslte/phy/phch/cqi.h +++ b/lib/include/srslte/phy/phch/cqi.h @@ -55,22 +55,13 @@ typedef struct { } srslte_cqi_periodic_cfg_t; /* Table 5.2.2.6.2-1: Fields for channel quality information feedback for higher layer configured subband - CQI reports (transmission mode 1, transmission mode 2, transmission mode 3, transmission mode 7 and - transmission mode 8 configured without PMI/RI reporting). */ - -/* Table 5.2.2.6.2-2: Fields for channel quality information (CQI) feedback for higher layer configured subband CQI - reports (transmission mode 4, transmission mode 5 and transmission mode 6). */ - +CQI reports +(transmission mode 1, transmission mode 2, transmission mode 3, transmission mode 7 and +transmission mode 8 configured without PMI/RI reporting). */ typedef struct SRSLTE_API { - uint8_t wideband_cqi_cw0; // 4-bit width - uint32_t subband_diff_cqi_cw0; // 2N-bit width - uint8_t wideband_cqi_cw1; // if RI > 1 then 4-bit width otherwise 0-bit width - uint32_t subband_diff_cqi_cw1; // if RI > 1 then 2N-bit width otherwise 0-bit width - uint32_t pmi; // if RI > 1 then 2-bit width otherwise 1-bit width - uint32_t N; - bool pmi_present; - bool four_antenna_ports; // If cell has 4 antenna ports then true otherwise false - bool rank_is_not_one; // If rank > 1 then true otherwise false + uint8_t wideband_cqi; // 4-bit width + uint32_t subband_diff_cqi; // 2N-bit width + uint32_t N; } srslte_cqi_hl_subband_t; /* Table 5.2.2.6.3-1: Fields for channel quality information feedback for UE selected subband CQI diff --git a/lib/include/srslte/phy/phch/uci.h b/lib/include/srslte/phy/phch/uci.h index 91592501f..ff315384e 100644 --- a/lib/include/srslte/phy/phch/uci.h +++ b/lib/include/srslte/phy/phch/uci.h @@ -73,7 +73,6 @@ typedef struct SRSLTE_API { uint8_t uci_ack; // 1st codeword bit for HARQ-ACK uint8_t uci_ack_2; // 2st codeword bit for HARQ-ACK uint32_t uci_ack_len; - bool ri_periodic_report; bool scheduling_request; bool channel_selection; bool cqi_ack; diff --git a/lib/src/phy/phch/cqi.c b/lib/src/phy/phch/cqi.c index 2c0940af5..0041c3fcb 100644 --- a/lib/src/phy/phch/cqi.c +++ b/lib/src/phy/phch/cqi.c @@ -44,38 +44,11 @@ *******************************************************/ int srslte_cqi_hl_subband_pack(srslte_cqi_hl_subband_t *msg, uint8_t buff[SRSLTE_CQI_MAX_BITS]) { - uint8_t *body_ptr = buff; - uint32_t bit_count = 0; - - /* Unpack codeword 0, common for 3GPP 36.212 Tables 5.2.2.6.2-1 and 5.2.2.6.2-2 */ - srslte_bit_unpack(msg->wideband_cqi_cw0, &body_ptr, 4); - srslte_bit_unpack(msg->subband_diff_cqi_cw0, &body_ptr, 2*msg->N); - bit_count += 4+2*msg->N; - - /* Unpack codeword 1, 3GPP 36.212 Table 5.2.2.6.2-2 */ - if (msg->rank_is_not_one) { - srslte_bit_unpack(msg->wideband_cqi_cw1, &body_ptr, 4); - srslte_bit_unpack(msg->subband_diff_cqi_cw1, &body_ptr, 2*msg->N); - bit_count += 4+2*msg->N; - } - - /* If PMI is present, unpack it */ - if (msg->pmi_present) { - if (msg->four_antenna_ports) { - srslte_bit_unpack(msg->pmi, &body_ptr, 4); - bit_count += 4; - } else { - if (msg->rank_is_not_one) { - srslte_bit_unpack(msg->pmi, &body_ptr, 1); - bit_count += 1; - } else { - srslte_bit_unpack(msg->pmi, &body_ptr, 2); - bit_count += 2; - } - } - } - - return bit_count; + uint8_t *body_ptr = buff; + srslte_bit_unpack(msg->wideband_cqi, &body_ptr, 4); + srslte_bit_unpack(msg->subband_diff_cqi, &body_ptr, 2*msg->N); + + return 4+2*msg->N; } int srslte_cqi_ue_subband_pack(srslte_cqi_ue_subband_t *msg, uint8_t buff[SRSLTE_CQI_MAX_BITS]) @@ -125,37 +98,11 @@ int srslte_cqi_value_pack(srslte_cqi_value_t *value, uint8_t buff[SRSLTE_CQI_MAX int srslte_cqi_hl_subband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_hl_subband_t *msg) { - uint8_t *body_ptr = buff; - uint32_t bit_count = 0; - - msg->wideband_cqi_cw0 = (uint8_t) srslte_bit_pack(&body_ptr, 4); - msg->subband_diff_cqi_cw0 = srslte_bit_pack(&body_ptr, 2*msg->N); - bit_count += 4+2*msg->N; - - /* Unpack codeword 1, 3GPP 36.212 Table 5.2.2.6.2-2 */ - if (msg->rank_is_not_one) { - msg->wideband_cqi_cw1 = (uint8_t) srslte_bit_pack(&body_ptr, 4); - msg->subband_diff_cqi_cw1 = srslte_bit_pack(&body_ptr, 2*msg->N); - bit_count += 4+2*msg->N; - } - - /* If PMI is present, unpack it */ - if (msg->pmi_present) { - if (msg->four_antenna_ports) { - msg->pmi = (uint8_t) srslte_bit_pack(&body_ptr, 4); - bit_count += 4; - } else { - if (msg->rank_is_not_one) { - msg->pmi = (uint8_t) srslte_bit_pack(&body_ptr, 1); - bit_count += 1; - } else { - msg->pmi = (uint8_t) srslte_bit_pack(&body_ptr, 2); - bit_count += 2; - } - } - } - - return bit_count; + uint8_t *body_ptr = buff; + msg->wideband_cqi = srslte_bit_pack(&body_ptr, 4); + msg->subband_diff_cqi = srslte_bit_pack(&body_ptr, 2*msg->N); + + return 4+2*msg->N; } int srslte_cqi_ue_subband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_ue_subband_t *msg) diff --git a/lib/src/phy/phch/pucch.c b/lib/src/phy/phch/pucch.c index f9c05104c..f9c6bebc1 100644 --- a/lib/src/phy/phch/pucch.c +++ b/lib/src/phy/phch/pucch.c @@ -173,7 +173,7 @@ srslte_pucch_format_t srslte_pucch_get_format(srslte_uci_data_t *uci_data, srslt { srslte_pucch_format_t format = SRSLTE_PUCCH_FORMAT_ERROR; // No CQI data - if (uci_data->uci_cqi_len == 0 && uci_data->uci_ri_len == 0) { + if (uci_data->uci_cqi_len == 0) { // 1-bit ACK + optional SR if (uci_data->uci_ack_len == 1) { format = SRSLTE_PUCCH_FORMAT_1A; diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index db7118b0c..134c19ca6 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -740,7 +740,6 @@ int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, uint8_t *ri, uint8_t *pmi, flo } /* Set RI */ - q->ri = best_ri; if (ri != NULL) { *ri = best_ri; } @@ -776,10 +775,9 @@ int srslte_ue_dl_ri_select(srslte_ue_dl_t *q, uint8_t *ri, float *cn) { *cn = _cn; } - q->ri = (uint8_t)((_cn < 17.0f)? 1:0); /* Set rank indicator */ if (!ret && ri) { - *ri = (uint8_t) q->ri; + *ri = (uint8_t)((_cn < 17.0f)? 1:0); } return ret; diff --git a/lib/src/phy/ue/ue_ul.c b/lib/src/phy/ue/ue_ul.c index 736fc3470..bb4fd57ae 100644 --- a/lib/src/phy/ue/ue_ul.c +++ b/lib/src/phy/ue/ue_ul.c @@ -273,33 +273,21 @@ int srslte_ue_ul_cfg_grant(srslte_ue_ul_t *q, srslte_ra_ul_grant_t *grant, void pucch_encode_bits(srslte_uci_data_t *uci_data, srslte_pucch_format_t format, uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS], uint8_t pucch2_bits[SRSLTE_PUCCH_MAX_BITS]) -{ - uint8_t uci_buffer[SRSLTE_CQI_MAX_BITS]; - uint8_t uci_buffer_len = 0; - +{ if (format == SRSLTE_PUCCH_FORMAT_1A || format == SRSLTE_PUCCH_FORMAT_1B) { pucch_bits[0] = uci_data->uci_ack; pucch_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 1a } if (format >= SRSLTE_PUCCH_FORMAT_2) { - /* Put RI (goes alone) */ - if (uci_data->ri_periodic_report) { - uci_buffer[0] = uci_data->uci_ri; // It assumes only 1 bit of RI - uci_buffer_len += uci_data->uci_ri_len; - } else { - /* Append CQI */ - memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_cqi, uci_data->uci_cqi_len); - uci_buffer_len += uci_data->uci_cqi_len; + /* Append Differential CQI */ + memcpy(&uci_data->uci_cqi[uci_data->uci_cqi_len], uci_data->uci_dif_cqi, uci_data->uci_dif_cqi_len); + uci_data->uci_cqi_len += uci_data->uci_dif_cqi_len; - /* Append Differential CQI */ - memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_dif_cqi, uci_data->uci_dif_cqi_len); - uci_buffer_len += uci_data->uci_dif_cqi_len; + /* Append PMI */ + memcpy(&uci_data->uci_cqi[uci_data->uci_cqi_len], uci_data->uci_pmi, uci_data->uci_pmi_len); + uci_data->uci_cqi_len += uci_data->uci_pmi_len; - /* Append PMI */ - memcpy(&uci_buffer[uci_buffer_len], uci_data->uci_pmi, uci_data->uci_pmi_len); - uci_buffer_len += uci_data->uci_pmi_len; - } - srslte_uci_encode_cqi_pucch(uci_buffer, uci_buffer_len, pucch_bits); + srslte_uci_encode_cqi_pucch(uci_data->uci_cqi, uci_data->uci_cqi_len, pucch_bits); if (format > SRSLTE_PUCCH_FORMAT_2) { pucch2_bits[0] = uci_data->uci_ack; pucch2_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 2a diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index 5298e6e7a..c023c13e0 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -461,7 +461,7 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) if (ue_db[rnti].cqi_en) { wideband_cqi_value = cqi_value.wideband.wideband_cqi; } else if (grants[i].grant.cqi_request) { - wideband_cqi_value = cqi_value.subband_hl.wideband_cqi_cw0; + wideband_cqi_value = cqi_value.subband_hl.wideband_cqi; } snprintf(cqi_str, 64, ", cqi=%d", wideband_cqi_value); } diff --git a/srsue/hdr/phy/phch_worker.h b/srsue/hdr/phy/phch_worker.h index 5378a9428..4f8df27db 100644 --- a/srsue/hdr/phy/phch_worker.h +++ b/srsue/hdr/phy/phch_worker.h @@ -76,8 +76,7 @@ private: /* Internal methods */ bool extract_fft_and_pdcch_llr(); - void compute_ri(); - + /* ... for DL */ bool decode_pdcch_ul(mac_interface_phy::mac_grant_t *grant); bool decode_pdcch_dl(mac_interface_phy::mac_grant_t *grant); diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 0068724b4..27503c9f7 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -272,6 +272,39 @@ void phch_worker::work_imp() if (dl_action.generate_ack) { set_uci_ack(dl_ack, dl_mac_grant.tb_en); } + + /* Select Rank Indicator by computing Condition Number */ + if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) { + if (ue_dl.nof_rx_antennas > 1) { + /* If 2 ort more receiving antennas, select RI */ + float cn = 0.0f; + srslte_ue_dl_ri_select(&ue_dl, &uci_data.uci_ri, &cn); + uci_data.uci_ri_len = 1; + } else { + /* If only one receiving antenna, force RI for 1 layer */ + uci_data.uci_ri = 0; + uci_data.uci_ri_len = 1; + Warning("Only one receiving antenna with TM3. Forcing RI=1 layer.\n"); + } + } else if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4){ + float sinr = 0.0f; + uint8 packed_pmi = 0; + srslte_ue_dl_ri_pmi_select(&ue_dl, &uci_data.uci_ri, &packed_pmi, &sinr); + srslte_bit_unpack_vector(&packed_pmi, uci_data.uci_pmi, 2); + uci_data.uci_ri_len = 1; + if (uci_data.uci_ri == 0) { + uci_data.uci_pmi_len = 2; + uci_data.uci_dif_cqi_len = 0; + } else { + uci_data.uci_pmi_len = 1; + uci_data.uci_dif_cqi_len = 3; + } + + /* If only one antenna in TM4 print limitation warning */ + if (ue_dl.nof_rx_antennas < 2) { + Warning("Only one receiving antenna with TM4. Forcing RI=1 layer (PMI=%d).\n", packed_pmi); + } + } } } @@ -327,7 +360,7 @@ void phch_worker::work_imp() phy->set_pending_ack(TTI_RX_ACK(tti), ue_ul.pusch_cfg.grant.n_prb_tilde[0], ul_action.phy_grant.ul.ncs_dmrs); } - } else if (dl_action.generate_ack || uci_data.scheduling_request || uci_data.uci_cqi_len > 0 || uci_data.uci_ri_len > 0) { + } else if (dl_action.generate_ack || uci_data.scheduling_request || uci_data.uci_cqi_len > 0) { encode_pucch(); signal_ready = true; } else if (srs_is_ready_to_send()) { @@ -377,42 +410,6 @@ void phch_worker::work_imp() #endif } -void phch_worker::compute_ri() { - if (uci_data.uci_ri_len > 0) { - /* Do nothing */ - } else if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) { - if (ue_dl.nof_rx_antennas > 1) { - /* If 2 ort more receiving antennas, select RI */ - float cn = 0.0f; - srslte_ue_dl_ri_select(&ue_dl, &uci_data.uci_ri, &cn); - Info("RI select %d layers, κ=%fdB\n", uci_data.uci_ri + 1, cn); - } else { - /* If only one receiving antenna, force RI for 1 layer */ - uci_data.uci_ri = 0; - Warning("Only one receiving antenna with TM3. Forcing RI=1 layer.\n"); - } - uci_data.uci_ri_len = 1; - } else if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { - float sinr = 0.0f; - uint8 packed_pmi = 0; - srslte_ue_dl_ri_pmi_select(&ue_dl, &uci_data.uci_ri, &packed_pmi, &sinr); - if (uci_data.uci_ri == 0) { - uci_data.uci_pmi_len = 2; - uci_data.uci_dif_cqi_len = 0; - } else { - uci_data.uci_pmi_len = 1; - uci_data.uci_dif_cqi_len = 3; - } - srslte_bit_unpack_vector(&packed_pmi, uci_data.uci_pmi, uci_data.uci_pmi_len); - Info("ri=%d; pmi=%d; SINR=%.1fdB\n", ue_dl.ri, ue_dl.pmi[ue_dl.ri], 10*log10f(ue_dl.sinr[ue_dl.ri][ue_dl.pmi[ue_dl.ri]])); - - /* If only one antenna in TM4 print limitation warning */ - if (ue_dl.nof_rx_antennas < 2) { - Warning("Only one receiving antenna with TM4. Forcing RI=1 layer (PMI=%d).\n", packed_pmi); - } - uci_data.uci_ri_len = 1; - } -} bool phch_worker::extract_fft_and_pdcch_llr() { bool decode_pdcch = true; @@ -826,15 +823,21 @@ void phch_worker::reset_uci() void phch_worker::set_uci_ack(bool ack[SRSLTE_MAX_CODEWORDS], bool tb_en[SRSLTE_MAX_CODEWORDS]) { - /* Map ACK according to 3GPP 36.212 clause 5.2.3.1 */ - uint32_t nof_ack = 0; - for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { - if (tb_en[tb]) { - ((nof_ack == 0)?uci_data.uci_ack:uci_data.uci_ack_2) = (uint8_t)(ack[tb]?1:0); - nof_ack++; - } + uint32_t nof_tb = 0; + if (tb_en[0]) { + uci_data.uci_ack = (uint8_t) ((ack[0]) ? 1 : 0); + nof_tb = 1; + } else { + uci_data.uci_ack = 1; } - uci_data.uci_ack_len = nof_ack; + + if (tb_en[1]) { + uci_data.uci_ack_2 = (uint8_t) ((ack[1]) ? 1 : 0); + nof_tb = 2; + } + + uci_data.uci_ack_len = nof_tb; + } void phch_worker::set_uci_sr() @@ -859,9 +862,14 @@ void phch_worker::set_uci_periodic_cqi() if (period_cqi.configured && rnti_is_set) { if (period_cqi.ri_idx_present && srslte_ri_send(period_cqi.pmi_idx, period_cqi.ri_idx, TTI_TX(tti))) { - compute_ri(); - uci_data.ri_periodic_report = true; - Info("PUCCH: Periodic RI=%d\n", uci_data.uci_ri); + if (uci_data.uci_ri_len) { + uci_data.uci_cqi[0] = uci_data.uci_ri; + uci_data.uci_cqi_len = uci_data.uci_ri_len; + uci_data.uci_ri_len = 0; + uci_data.uci_dif_cqi_len = 0; + uci_data.uci_pmi_len = 0; + Info("PUCCH: Periodic RI=%d\n", uci_data.uci_cqi[0]); + } } else if (srslte_cqi_send(period_cqi.pmi_idx, TTI_TX(tti))) { srslte_cqi_value_t cqi_report; if (period_cqi.format_is_subband) { @@ -883,16 +891,6 @@ void phch_worker::set_uci_periodic_cqi() } Info("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.wideband.wideband_cqi, phy->avg_snr_db); } - if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { - if (ue_dl.ri == 0) { - uci_data.uci_pmi_len = 2; - } else { - uci_data.uci_pmi_len = 1; - uci_data.uci_dif_cqi_len = 3; - } - uint8_t *ptr = uci_data.uci_pmi; - srslte_bit_unpack(ue_dl.pmi[ue_dl.ri], &ptr, uci_data.uci_pmi_len); - } uci_data.uci_cqi_len = srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi); rar_cqi_request = false; } @@ -914,71 +912,18 @@ void phch_worker::set_uci_aperiodic_cqi() reported RI. For other transmission modes they are reported conditioned on rank 1. */ if (rnti_is_set) { - srslte_cqi_value_t cqi_report = {0}; + srslte_cqi_value_t cqi_report; cqi_report.type = SRSLTE_CQI_TYPE_SUBBAND_HL; - cqi_report.subband_hl.wideband_cqi_cw0 = srslte_cqi_from_snr(phy->avg_snr_db); + cqi_report.subband_hl.wideband_cqi = srslte_cqi_from_snr(phy->avg_snr_db); // TODO: implement subband CQI properly - cqi_report.subband_hl.subband_diff_cqi_cw0 = 0; // Always report zero offset on all subbands + cqi_report.subband_hl.subband_diff_cqi = 0; // Always report zero offset on all subbands cqi_report.subband_hl.N = (cell.nof_prb > 7) ? srslte_cqi_hl_get_no_subbands(cell.nof_prb) : 0; Info("PUSCH: Aperiodic CQI=%d, SNR=%.1f dB, for %d subbands\n", cqi_report.wideband.wideband_cqi, phy->avg_snr_db, cqi_report.subband_hl.N); uci_data.uci_cqi_len = srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi); } break; - case LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM31: - /* only Higher Layer-configured subband feedback support right now, according to TS36.213 section 7.2.1 - - A single precoding matrix is selected from the codebook subset assuming transmission on set S subbands - - A UE shall report one subband CQI value per codeword for each set S subband which are calculated assuming - the use of the single precoding matrix in all subbands and assuming transmission in the corresponding - subband. - - A UE shall report a wideband CQI value per codeword which is calculated assuming the use of the single - precoding matrix in all subbands and transmission on set S subbands - - The UE shall report the single selected precoding matrix indicator. - - For transmission mode 4 the reported PMI and CQI values are calculated conditioned on the reported RI. For - other transmission modes they are reported conditioned on rank 1. - */ - if (rnti_is_set) { - /* Compute RI, PMI and SINR */ - compute_ri(); - - /* Select RI, PMI and SINR */ - uint32_t ri = ue_dl.ri; // Select RI (0: 1 layer, 1: 2 layer, otherwise: not implemented) - uint32_t pmi = ue_dl.pmi[ri]; // Select PMI - float sinr_db = 10 * log10(ue_dl.sinr[ri][pmi]); - - /* Fill CQI Report */ - srslte_cqi_value_t cqi_report = {0}; - cqi_report.type = SRSLTE_CQI_TYPE_SUBBAND_HL; - - cqi_report.subband_hl.wideband_cqi_cw0 = srslte_cqi_from_snr(sinr_db); - cqi_report.subband_hl.subband_diff_cqi_cw0 = 0; // Always report zero offset on all subbands - - if (ri > 0) { - cqi_report.subband_hl.rank_is_not_one = true; - cqi_report.subband_hl.wideband_cqi_cw1 = srslte_cqi_from_snr(sinr_db); - cqi_report.subband_hl.subband_diff_cqi_cw1 = 0; // Always report zero offset on all subbands - } - - cqi_report.subband_hl.pmi = pmi; - cqi_report.subband_hl.pmi_present = true; - cqi_report.subband_hl.four_antenna_ports = (cell.nof_ports == 4); - - // TODO: implement subband CQI properly - cqi_report.subband_hl.N = (uint32_t) ((cell.nof_prb > 7) ? srslte_cqi_hl_get_no_subbands(cell.nof_prb) : 0); - - if (cqi_report.subband_hl.rank_is_not_one) { - Info("PUSCH: Aperiodic ri~1, CQI=%02d/%02d, SINR=%2.1f/%2.1fdB, pmi=%d for %d subbands\n", - cqi_report.subband_hl.wideband_cqi_cw0, cqi_report.subband_hl.wideband_cqi_cw1, - sinr_db, sinr_db, pmi, cqi_report.subband_hl.N); - } else { - Info("PUSCH: Aperiodic ri=1, CQI=%d/%d, SINR=%2.1f dB, for %d subbands\n", - cqi_report.wideband.wideband_cqi, - phy->avg_snr_db, cqi_report.subband_hl.N); - } - uci_data.uci_cqi_len = srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi); - } - break; default: Warning("Received CQI request but mode %s is not supported\n", liblte_rrc_cqi_report_mode_aperiodic_text[phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic]); @@ -1061,7 +1006,7 @@ void phch_worker::encode_pucch() char timestr[64]; timestr[0]='\0'; - if (uci_data.scheduling_request || uci_data.uci_ack_len > 0 || uci_data.uci_cqi_len > 0 || uci_data.uci_ri_len > 0) + if (uci_data.scheduling_request || uci_data.uci_ack_len > 0 || uci_data.uci_cqi_len > 0) { // Drop CQI if there is collision with ACK From 93a47df01568a8ce66ec40151fb6e770eb282245 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Mon, 4 Dec 2017 15:00:23 -0600 Subject: [PATCH 198/242] Fixed segfault when exit due to prach destructor --- srsue/hdr/phy/prach.h | 4 ++-- srsue/src/phy/prach.cc | 19 +++++++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/srsue/hdr/phy/prach.h b/srsue/hdr/phy/prach.h index 2872c374c..8218ca644 100644 --- a/srsue/hdr/phy/prach.h +++ b/srsue/hdr/phy/prach.h @@ -49,7 +49,7 @@ namespace srsue { target_power_dbm = 0; mem_initiated = false; cell_initiated = false; - bzero(signal_buffer, sizeof(signal_buffer)); + signal_buffer = NULL; } ~prach(); void init(LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT *config, uint32_t max_prb, phy_args_t *args, srslte::log *log_h); @@ -78,7 +78,7 @@ namespace srsue { srslte_prach_t prach_obj; int transmitted_tti; srslte_cell_t cell; - cf_t *signal_buffer[SRSLTE_MAX_PORTS]; + cf_t *signal_buffer; srslte_cfo_t cfo_h; float target_power_dbm; diff --git a/srsue/src/phy/prach.cc b/srsue/src/phy/prach.cc index bd7550457..182a66aa7 100644 --- a/srsue/src/phy/prach.cc +++ b/srsue/src/phy/prach.cc @@ -75,12 +75,10 @@ void prach::init(LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT *config_, uint32_t max_prb, return; } srslte_cfo_set_tol(&cfo_h, 0); - for (int p = 0; p < SRSLTE_MAX_PORTS; p++) { - signal_buffer[p] = (cf_t *) srslte_vec_malloc(SRSLTE_PRACH_MAX_LEN * sizeof(cf_t)); - if (!signal_buffer[p]) { - perror("malloc"); - return; - } + signal_buffer = (cf_t *) srslte_vec_malloc(SRSLTE_PRACH_MAX_LEN * sizeof(cf_t)); + if (!signal_buffer) { + perror("malloc"); + return; } if (srslte_prach_init(&prach_obj, srslte_symbol_sz(max_prb))) { Error("Initiating PRACH library\n"); @@ -184,7 +182,7 @@ void prach::send(srslte::radio *radio_handler, float cfo, float pathloss, srslte float old_gain = radio_handler->get_tx_gain(); // Correct CFO before transmission FIXME: UL SISO Only - srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer[0], cfo / srslte_symbol_sz(cell.nof_prb)); + srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer, cfo / srslte_symbol_sz(cell.nof_prb)); // If power control is enabled, choose amplitude and power if (args->ul_pwr_ctrl_en) { @@ -195,10 +193,10 @@ void prach::send(srslte::radio *radio_handler, float cfo, float pathloss, srslte radio_handler->set_tx_power(tx_power); // Scale signal - float digital_power = srslte_vec_avg_power_cf(signal_buffer[0], len); + float digital_power = srslte_vec_avg_power_cf(signal_buffer, len); float scale = sqrtf(pow(10,tx_power/10)/digital_power); - srslte_vec_sc_prod_cfc(signal_buffer[0], scale, signal_buffer[0], len); + srslte_vec_sc_prod_cfc(signal_buffer, scale, signal_buffer, len); log_h->console("PRACH: Pathloss=%.2f dB, Target power %.2f dBm, TX_power %.2f dBm, TX_gain %.1f dB\n", pathloss, target_power_dbm, tx_power, radio_handler->get_tx_gain(), scale); @@ -210,7 +208,8 @@ void prach::send(srslte::radio *radio_handler, float cfo, float pathloss, srslte Debug("TX PRACH: Power control for PRACH is disabled, setting gain to %.0f dB\n", prach_gain); } - radio_handler->tx((void **) signal_buffer, len, tx_time); + void *tmp_buffer[SRSLTE_MAX_PORTS] = {signal_buffer, NULL, NULL, NULL}; + radio_handler->tx(tmp_buffer, len, tx_time); radio_handler->tx_end(); Info("PRACH: Transmitted preamble=%d, CFO=%.2f KHz, tx_time=%f\n", From 3705baddc3c25800d9f45b1e095843956f10a902 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 5 Dec 2017 22:06:30 +0100 Subject: [PATCH 199/242] nas: initialize ctxt variable and only check ksi if ctxt is present --- srsue/src/upper/nas.cc | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index 62e23d852..5927c3c64 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -44,7 +44,7 @@ namespace srsue { ********************************************************************/ nas::nas() - : state(EMM_STATE_DEREGISTERED), plmn_selection(PLMN_SELECTED), have_guti(false), ip_addr(0), eps_bearer_id(0) + : state(EMM_STATE_DEREGISTERED), plmn_selection(PLMN_SELECTED), have_guti(false), have_ctxt(false), ip_addr(0), eps_bearer_id(0) { ctxt.rx_count = 0; ctxt.tx_count = 0; @@ -548,13 +548,15 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu) return; } - if(sec_mode_cmd.nas_ksi.nas_ksi != ctxt.ksi) - { - nas_log->warning("Sending Security Mode Reject due to key set ID mismatch\n"); - send_security_mode_reject(LIBLTE_MME_EMM_CAUSE_SECURITY_MODE_REJECTED_UNSPECIFIED); - pool->deallocate(pdu); - return; + if (have_ctxt) { + if(sec_mode_cmd.nas_ksi.nas_ksi != ctxt.ksi) { + nas_log->warning("Sending Security Mode Reject due to key set ID mismatch\n"); + send_security_mode_reject(LIBLTE_MME_EMM_CAUSE_SECURITY_MODE_REJECTED_UNSPECIFIED); + pool->deallocate(pdu); + return; + } } + // MME is setting up security context // TODO: check nonce (not sent by Amari) @@ -744,7 +746,7 @@ void nas::send_attach_request() { nas_log->info("Sending attach request\n"); rrc->write_sdu(cfg.lcid, msg); - if(have_ctxt) { + if (have_ctxt) { ctxt.tx_count++; } } From 0641fee20b0422bec5837eecde0cf32a9ae3472b Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 5 Dec 2017 22:15:57 +0100 Subject: [PATCH 200/242] nas: fix IMSI print --- srsue/src/upper/nas.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index 5927c3c64..801cab581 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -697,7 +697,6 @@ void nas::send_attach_request() { attach_req.additional_guti_present = false; attach_req.last_visited_registered_tai_present = false; attach_req.drx_param_present = false; - attach_req.ms_network_cap_present = false; attach_req.old_lai_present = false; attach_req.tmsi_status_present = false; attach_req.ms_cm2_present = false; @@ -739,7 +738,7 @@ void nas::send_attach_request() { } else { attach_req.eps_mobile_id.type_of_id = LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI; usim->get_imsi_vec(attach_req.eps_mobile_id.imsi, 15); - nas_log->info("Requesting IMSI attach. imsi: %s\n", usim->get_imsi_str()); + nas_log->info("Requesting IMSI attach (IMSI=%s)\n", usim->get_imsi_str().c_str()); liblte_mme_pack_attach_request_msg(&attach_req, (LIBLTE_BYTE_MSG_STRUCT *) msg); } From 082da2f7b605143d225a264b3f2a60f1bf4e5f0b Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 13 Dec 2017 10:00:38 +0100 Subject: [PATCH 201/242] Added filter for maximum PSS CFO detection value. Increased averaging for PSS CFO estimation --- lib/src/phy/sync/sync.c | 4 +++- srsue/src/main.cc | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/src/phy/sync/sync.c b/lib/src/phy/sync/sync.c index 13a5f7e69..8b7bbd69c 100644 --- a/lib/src/phy/sync/sync.c +++ b/lib/src/phy/sync/sync.c @@ -42,6 +42,8 @@ #define DEFAULT_CFO_TOL 0.0 // Hz +#define MAX_CFO_PSS_OFFSET 7000 + static bool fft_size_isvalid(uint32_t fft_size) { if (fft_size >= SRSLTE_SYNC_FFT_SZ_MIN && fft_size <= SRSLTE_SYNC_FFT_SZ_MAX && (fft_size%64) == 0) { return true; @@ -614,7 +616,7 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, const cf_t *input, uin if (!q->cfo_pss_is_set) { q->cfo_pss_mean = cfo_pss; q->cfo_pss_is_set = true; - } else { + } else if (15000*fabsf(cfo_pss) < MAX_CFO_PSS_OFFSET) { q->cfo_pss_mean = SRSLTE_VEC_EMA(cfo_pss, q->cfo_pss_mean, q->cfo_ema_alpha); } diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 09a382246..6df1cac99 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -205,7 +205,7 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { "Tolerance (in Hz) for digital CFO compensation (needs to be low if average_subframe_enabled=true.") ("expert.cfo_pss_ema", - bpo::value(&args->expert.phy.cfo_pss_ema)->default_value(0.1), + bpo::value(&args->expert.phy.cfo_pss_ema)->default_value(0.01), "CFO Exponential Moving Average coefficient for PSS estimation during TRACK.") ("expert.cfo_ref_ema", From 4c2b6fbd294f0f1418d1c8df44e728d4aff6d4f3 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 13 Dec 2017 10:03:39 +0100 Subject: [PATCH 202/242] Added check for serving PCI target HO --- srsue/src/upper/rrc.cc | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index d6ba7d5df..8a03e21a6 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -1118,15 +1118,20 @@ void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGU if (reconfig->mob_ctrl_info_present) { - rrc_log->info("Received HO command to target PCell=%d\n", reconfig->mob_ctrl_info.target_pci); - rrc_log->console("Received HO command to target PCell=%d, NCC=%d\n", - reconfig->mob_ctrl_info.target_pci, reconfig->sec_cnfg_ho.intra_lte.next_hop_chaining_count); + if (reconfig->mob_ctrl_info.target_pci == phy->get_current_pci()) { + rrc_log->warning("Received HO command to own cell\n"); + send_rrc_con_reconfig_complete(pdu); + } else { + rrc_log->info("Received HO command to target PCell=%d\n", reconfig->mob_ctrl_info.target_pci); + rrc_log->console("Received HO command to target PCell=%d, NCC=%d\n", + reconfig->mob_ctrl_info.target_pci, reconfig->sec_cnfg_ho.intra_lte.next_hop_chaining_count); - // store mobilityControlInfo - memcpy(&mob_reconf, reconfig, sizeof(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT)); - pending_mob_reconf = true; + // store mobilityControlInfo + memcpy(&mob_reconf, reconfig, sizeof(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT)); + pending_mob_reconf = true; - state = RRC_STATE_HO_PREPARE; + state = RRC_STATE_HO_PREPARE; + } } else { // Section 5.3.5.3 @@ -2741,16 +2746,14 @@ void rrc::rrc_meas::parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *cfg) void rrc::rrc_meas::update_phy() { phy->meas_reset(); - if (pcell_measurement.ms[RSRP] < s_measure_value || !s_measure_enabled) { - for(std::map::iterator iter=active.begin(); iter!=active.end(); ++iter) { - meas_t m = iter->second; - meas_obj_t o = objects[m.object_id]; - // Instruct PHY to look for neighbour cells on this frequency - phy->meas_start(o.earfcn); - for(std::map::iterator iter=o.cells.begin(); iter!=o.cells.end(); ++iter) { - // Instruct PHY to look for cells IDs on this frequency - phy->meas_start(o.earfcn, iter->second.pci); - } + for(std::map::iterator iter=active.begin(); iter!=active.end(); ++iter) { + meas_t m = iter->second; + meas_obj_t o = objects[m.object_id]; + // Instruct PHY to look for neighbour cells on this frequency + phy->meas_start(o.earfcn); + for(std::map::iterator iter=o.cells.begin(); iter!=o.cells.end(); ++iter) { + // Instruct PHY to look for cells IDs on this frequency + phy->meas_start(o.earfcn, iter->second.pci); } } } From f3ee6c0009e91e07f81aef91c35765ba3b7d63a3 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 13 Dec 2017 10:18:52 +0100 Subject: [PATCH 203/242] Minor logging changes --- srsue/src/upper/rrc.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 8a03e21a6..2ea1b877d 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -675,7 +675,7 @@ void rrc::cell_reselection_eval(float rsrp, float rsrq) { // Intra-frequency cell-reselection criteria - if (get_srxlev(rsrp) > cell_resel_cfg.s_intrasearchP && rsrp > -70.0) { + if (get_srxlev(rsrp) > cell_resel_cfg.s_intrasearchP && rsrp > -95.0) { // UE may not perform intra-frequency measurements. phy->meas_reset(); // keep measuring serving cell @@ -1033,9 +1033,13 @@ bool rrc::ho_prepare() { } if (mob_reconf.mob_ctrl_info.rach_cnfg_ded_present) { + rrc_log->info("Starting non-contention based RA with preamble_idx=%d, mask_idx=%d\n", + mob_reconf.mob_ctrl_info.rach_cnfg_ded.preamble_index, + mob_reconf.mob_ctrl_info.rach_cnfg_ded.prach_mask_index); mac->start_noncont_ho(mob_reconf.mob_ctrl_info.rach_cnfg_ded.preamble_index, mob_reconf.mob_ctrl_info.rach_cnfg_ded.prach_mask_index); } else { + rrc_log->info("Starting contention-based RA\n"); mac->start_cont_ho(); } @@ -1049,7 +1053,7 @@ bool rrc::ho_prepare() { if (mob_reconf.sec_cnfg_ho.intra_lte.sec_alg_cnfg_present) { cipher_algo = (CIPHERING_ALGORITHM_ID_ENUM) mob_reconf.sec_cnfg_ho.intra_lte.sec_alg_cnfg.cipher_alg; integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM) mob_reconf.sec_cnfg_ho.intra_lte.sec_alg_cnfg.int_alg; - rrc_log->console("Warning changed Cipering to %s and Integrity to %s\n", + rrc_log->info("Changed Ciphering to %s and Integrity to %s\n", ciphering_algorithm_id_text[cipher_algo], integrity_algorithm_id_text[integ_algo]); } @@ -2237,13 +2241,13 @@ void rrc::rrc_meas::init(rrc *parent) { void rrc::rrc_meas::reset() { - bzero(&pcell_measurement, sizeof(meas_value_t)); filter_k_rsrp = liblte_rrc_filter_coefficient_num[LIBLTE_RRC_FILTER_COEFFICIENT_FC4]; filter_k_rsrq = liblte_rrc_filter_coefficient_num[LIBLTE_RRC_FILTER_COEFFICIENT_FC4]; objects.clear(); active.clear(); reports_cfg.clear(); phy->meas_reset(); + bzero(&pcell_measurement, sizeof(meas_value_t)); } /* L3 filtering 5.5.3.2 */ From 09dc96a3700f667c97a7a7d538f19515f9de07f5 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 13 Dec 2017 10:20:19 +0100 Subject: [PATCH 204/242] Changed neighbour cell to find PSS over multiple frames --- srsue/src/phy/phch_recv.cc | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 9225c6f73..9b728cddd 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -155,7 +155,6 @@ void phch_recv::radio_error() } void phch_recv::set_cfo(float cfo) { - Debug("set_ref_cfo=%f\n",cfo*15000); srslte_ue_sync_set_cfo_ref(&ue_sync, cfo); } @@ -645,9 +644,6 @@ void phch_recv::run_thread() worker->set_cfo(ul_dl_factor * metrics.cfo / 15000); worker_com->set_sync_metrics(metrics); - Debug("current_cfo=%f, pss_stable_cnt=%d, cfo_pss=%f Hz\n", - metrics.cfo, ue_sync.pss_stable_cnt, srslte_sync_get_cfo(&ue_sync.strack)*15000); - worker->set_sample_offset(srslte_ue_sync_get_sfo(&ue_sync)/1000); /* Compute TX time: Any transmission happens in TTI+4 thus advance 4 ms the reception time */ @@ -1193,7 +1189,8 @@ void phch_recv::scell_recv::init(srslte::log *log_h, bool sic_pss_enabled) measure_p.init(sf_buffer, log_h, 1, DEFAULT_MEASUREMENT_LEN); - if(srslte_sync_init(&sync_find, 15*max_sf_size, 5*max_sf_size, max_fft_sz)) { + //do this different we don't need all this search window. + if(srslte_sync_init(&sync_find, 50*max_sf_size, 5*max_sf_size, max_fft_sz)) { fprintf(stderr, "Error initiating sync_find\n"); return; } @@ -1211,6 +1208,10 @@ void phch_recv::scell_recv::init(srslte::log *log_h, bool sic_pss_enabled) sync_find.pss.chest_on_filter = true; + if (!sic_pss_enabled) { + sync_find.sss_channel_equalize = false; + } + reset(); } @@ -1255,7 +1256,10 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, srslte_sync_reset(&sync_find); srslte_sync_cfo_reset(&sync_find); - sync_res = srslte_sync_find(&sync_find, input_buffer, 0, &peak_idx); + int sf5_cnt=0; + do { + sync_res = srslte_sync_find(&sync_find, input_buffer, sf5_cnt*5*sf_len, &peak_idx); + } while(sync_res != SRSLTE_SYNC_FOUND && sf5_cnt < nof_sf/5); switch(sync_res) { case SRSLTE_SYNC_ERROR: From dff5a6f628a46ce3df2b2be35235413320061c75 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 13 Dec 2017 18:26:26 +0100 Subject: [PATCH 205/242] Initialize variables in rrc/enb. Fixes #122 --- srsenb/hdr/upper/rrc.h | 2 +- srsenb/src/upper/rrc.cc | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/srsenb/hdr/upper/rrc.h b/srsenb/hdr/upper/rrc.h index e0b9dd158..f30b91794 100644 --- a/srsenb/hdr/upper/rrc.h +++ b/srsenb/hdr/upper/rrc.h @@ -264,7 +264,7 @@ public: uint32_t cqi_idx; bool cqi_allocated; int cqi_sched_sf_idx; - bool cqi_sched_prb_idx; + int cqi_sched_prb_idx; int get_drbid_config(LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT *drb, int drbid); }; diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index e176e8ac5..9c0422357 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -699,10 +699,19 @@ rrc::ue::ue() { parent = NULL; set_activity(); - sr_allocated = false; has_tmsi = false; connect_notified = false; transaction_id = 0; + sr_allocated = false; + sr_sched_sf_idx = 0; + sr_sched_prb_idx = 0; + sr_N_pucch = 0; + sr_I = 0; + cqi_allocated = false; + cqi_pucch = 0; + cqi_idx = 0; + cqi_sched_sf_idx = 0; + cqi_sched_prb_idx = 0; state = RRC_STATE_IDLE; } From a66db9569fc456b2269d54d4535dddfc3c7a178b Mon Sep 17 00:00:00 2001 From: yagoda Date: Wed, 13 Dec 2017 22:11:25 +0000 Subject: [PATCH 206/242] adding cmake SIMD check --- CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index fe2d99690..60484ae5a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,6 +66,7 @@ configure_file( ######################################################################## option(ENABLE_SRSUE "Build srsUE application" ON) option(ENABLE_SRSENB "Build srsENB application" ON) +option(DISABLE_SIMD "disable simd instructions" OFF) option(ENABLE_GUI "Enable GUI (using srsGUI)" ON) option(ENABLE_BLADERF "Enable BladeRF" ON) @@ -287,9 +288,16 @@ if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon -march=native -DIS_ARM -DHAVE_NEON") message(STATUS "have ARM") + set(HAVE_NEON "True") + else(${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm") + set(HAVE_NEON "False") endif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm") set(CMAKE_REQUIRED_FLAGS ${CMAKE_C_FLAGS}) + if(NOT HAVE_SSE AND NOT HAVE_NEON AND NOT DISABLE_SIMD) + message(FATAL_ERROR "no SIMD instructions found") + endif(NOT HAVE_SSE AND NOT HAVE_NEON AND NOT DISABLE_SIMD) + if(NOT WIN32) ADD_CXX_COMPILER_FLAG_IF_AVAILABLE(-fvisibility=hidden HAVE_VISIBILITY_HIDDEN) endif(NOT WIN32) From 7e29430c81436763eabc876c01546cf7d53ef0d1 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 14 Dec 2017 11:15:26 +0100 Subject: [PATCH 207/242] remove unused function --- srsue/hdr/phy/phch_worker.h | 4 +--- srsue/src/phy/phch_recv.cc | 2 +- srsue/src/phy/phch_worker.cc | 4 ---- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/srsue/hdr/phy/phch_worker.h b/srsue/hdr/phy/phch_worker.h index 5378a9428..f711ade09 100644 --- a/srsue/hdr/phy/phch_worker.h +++ b/srsue/hdr/phy/phch_worker.h @@ -67,9 +67,7 @@ public: int read_pdsch_d(cf_t *pdsch_d); void start_plot(); - float get_ref_cfo(); - -private: +private: /* Inherited from thread_pool::worker. Function called every subframe to run the DL/UL processing */ void work_imp(); diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 9b728cddd..473011d7b 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -1256,7 +1256,7 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, srslte_sync_reset(&sync_find); srslte_sync_cfo_reset(&sync_find); - int sf5_cnt=0; + uint32_t sf5_cnt=0; do { sync_res = srslte_sync_find(&sync_find, input_buffer, sf5_cnt*5*sf_len, &peak_idx); } while(sync_res != SRSLTE_SYNC_FOUND && sf5_cnt < nof_sf/5); diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index a5ccc9982..934be8aa7 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -141,10 +141,6 @@ bool phch_worker::init(uint32_t max_prb, srslte::log *log_h, chest_feedback_itf return true; } -float phch_worker::get_ref_cfo() { - return srslte_chest_dl_get_cfo(&ue_dl.chest); -} - bool phch_worker::set_cell(srslte_cell_t cell_) { if (cell.id != cell_.id || !cell_initiated) { From 39f9f15232aaa13d1a0748c05d9d5553e0bf9a0a Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 14 Dec 2017 12:34:57 +0100 Subject: [PATCH 208/242] Fixed bug with 2 rx antennas --- lib/src/phy/rf/rf_utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/phy/rf/rf_utils.c b/lib/src/phy/rf/rf_utils.c index 68857d41d..892ad817e 100644 --- a/lib/src/phy/rf/rf_utils.c +++ b/lib/src/phy/rf/rf_utils.c @@ -122,7 +122,7 @@ int rf_mib_decoder(srslte_rf_t *rf, uint32_t nof_rx_antennas,cell_search_cfg_t * srslte_rf_set_rx_srate(rf, (float) srate); INFO("Starting receiver...\n", 0); - srslte_rf_start_rx_stream(rf, true); + srslte_rf_start_rx_stream(rf, false); /* Find and decody MIB */ ret = srslte_ue_mib_sync_decode(&ue_mib, config->max_frames_pbch, bch_payload, &cell->nof_ports, NULL); From 95f6eb87c8d197a123503b4a7eb473290d1167ad Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 14 Dec 2017 12:57:10 +0100 Subject: [PATCH 209/242] Minor issue with paging --- srsue/src/mac/mac.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/srsue/src/mac/mac.cc b/srsue/src/mac/mac.cc index 8813032f5..86b644b8d 100644 --- a/srsue/src/mac/mac.cc +++ b/srsue/src/mac/mac.cc @@ -278,6 +278,7 @@ void mac::new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy:: memcpy(&action->phy_grant, &grant.phy_grant, sizeof(srslte_phy_grant_t)); action->generate_ack = false; action->decode_enabled[0] = true; + action->decode_enabled[1] = false; srslte_softbuffer_rx_reset_cb(&pch_softbuffer, 1); action->payload_ptr[0] = pch_payload_buffer; action->softbuffers[0] = &pch_softbuffer; From 60b81f47f1cb941cbde08b47930538d33d662d19 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 14 Dec 2017 12:57:44 +0100 Subject: [PATCH 210/242] Do chest on filter only when sic_pss is enabled. Do not equalize SSS by default (something is not ok and takes more time to decode it) --- lib/src/phy/ue/ue_sync.c | 2 +- srsue/src/phy/phch_recv.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/phy/ue/ue_sync.c b/lib/src/phy/ue/ue_sync.c index 7eb877b3b..511cdde2f 100644 --- a/lib/src/phy/ue/ue_sync.c +++ b/lib/src/phy/ue/ue_sync.c @@ -272,7 +272,7 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q, srslte_sync_set_cfo_cp_enable(&q->sfind, true); srslte_sync_set_cfo_pss_enable(&q->sfind, true); srslte_sync_set_pss_filt_enable(&q->sfind, true); - srslte_sync_set_sss_eq_enable(&q->sfind, true); + srslte_sync_set_sss_eq_enable(&q->sfind, false); // During track, we do CFO correction outside the sync object srslte_sync_set_cfo_i_enable(&q->strack, false); diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 473011d7b..06ae1baa2 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -196,7 +196,7 @@ void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q) worker_com->args->cfo_loop_pss_tol, worker_com->args->cfo_loop_pss_conv); - q->strack.pss.chest_on_filter = true; + q->strack.pss.chest_on_filter = worker_com->args->sic_pss_enabled; int time_correct_period = worker_com->args->time_correct_period; if (time_correct_period > 0) { From abbbae9e81fdb937b7fe7e8778579baed986fc6d Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 14 Dec 2017 17:36:58 +0100 Subject: [PATCH 211/242] rf_uhd_imp tx forces zeros if null pointer buffer --- lib/src/phy/rf/rf_uhd_imp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/phy/rf/rf_uhd_imp.c b/lib/src/phy/rf/rf_uhd_imp.c index c39bb2604..75482eaa1 100644 --- a/lib/src/phy/rf/rf_uhd_imp.c +++ b/lib/src/phy/rf/rf_uhd_imp.c @@ -790,7 +790,7 @@ int rf_uhd_send_timed_multi(void *h, int n = 0; cf_t *data_c[4]; for (int i = 0; i < 4; i++) { - data_c[i] = data[i]; + data_c[i] = data[i] ? data[i] : zero_mem; } do { size_t tx_samples = handler->tx_nof_samples; From a99d6318dba10fddc840e297c8369655a1c18e95 Mon Sep 17 00:00:00 2001 From: yagoda Date: Thu, 14 Dec 2017 17:26:54 +0000 Subject: [PATCH 212/242] fixing viterbi testing bug --- lib/src/phy/fec/test/viterbi_test.h | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/src/phy/fec/test/viterbi_test.h b/lib/src/phy/fec/test/viterbi_test.h index 7d94e7c7e..38665305e 100644 --- a/lib/src/phy/fec/test/viterbi_test.h +++ b/lib/src/phy/fec/test/viterbi_test.h @@ -52,7 +52,24 @@ static expected_errors_t expected_errors[] = { {-1, -1, -1, true, -1.0, -1} }; -#else +#elif HAVE_NEON + +static expected_errors_t expected_errors[] = { + {1000, 1, 40, true, 0.0, 7282}, + {1000, 1, 40, true, 2.0, 725}, + {1000, 1, 40, true, 3.0, 176}, + {1000, 1, 40, true, 4.5, 24}, + + {100, 1, 1000, true, 0.0, 13208}, + {100, 1, 1000, true, 2.0, 939}, + {100, 1, 1000, true, 3.0, 110}, + {100, 1, 1000, true, 4.5, 5}, + + {-1, -1, -1, true, -1.0, -1} +}; + + +#else static expected_errors_t expected_errors[] = { {1000, 1, 40, true, 0.0, 5363}, From 56f95ec8be53f12a41438ffec27280b9b2d8d7b1 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 16 Dec 2017 12:45:35 +0100 Subject: [PATCH 213/242] Avoid changing master clock rate if it's the same --- lib/src/phy/rf/rf_uhd_imp.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/lib/src/phy/rf/rf_uhd_imp.c b/lib/src/phy/rf/rf_uhd_imp.c index c39bb2604..fb91669b3 100644 --- a/lib/src/phy/rf/rf_uhd_imp.c +++ b/lib/src/phy/rf/rf_uhd_imp.c @@ -55,7 +55,9 @@ typedef struct { int nof_tx_channels; srslte_rf_error_handler_t uhd_error_handler; - + + float current_master_clock; + bool async_thread_running; pthread_t async_thread; } rf_uhd_handler_t; @@ -229,7 +231,7 @@ int rf_uhd_start_rx_stream(void *h, bool now) }; if (!now) { uhd_usrp_get_time_now(handler->usrp, 0, &stream_cmd.time_spec_full_secs, &stream_cmd.time_spec_frac_secs); - stream_cmd.time_spec_frac_secs += 0.1; + stream_cmd.time_spec_frac_secs += 0.2; if (stream_cmd.time_spec_frac_secs > 1) { stream_cmd.time_spec_frac_secs -= 1; stream_cmd.time_spec_full_secs += 1; @@ -410,23 +412,27 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels) if (find_string(devices_str, "type=b200") && !strstr(args, "recv_frame_size")) { // If B200 is available, use it args = "type=b200,master_clock_rate=30.72e6"; + handler->current_master_clock = 30720000; handler->devname = DEVNAME_B200; } else if (find_string(devices_str, "type=x300")) { // Else if X300 is available, set master clock rate now (can't be changed later) args = "type=x300,master_clock_rate=184.32e6"; - handler->dynamic_rate = false; + handler->current_master_clock = 184320000; + handler->dynamic_rate = false; handler->devname = DEVNAME_X300; } } else { // If args is set and x300 type is specified, make sure master_clock_rate is defined if (strstr(args, "type=x300") && !strstr(args, "master_clock_rate")) { sprintf(args2, "%s,master_clock_rate=184.32e6",args); - args = args2; - handler->dynamic_rate = false; + args = args2; + handler->current_master_clock = 184320000; + handler->dynamic_rate = false; handler->devname = DEVNAME_X300; } else if (strstr(args, "type=b200")) { snprintf(args2, sizeof(args2), "%s,master_clock_rate=30.72e6", args); args = args2; + handler->current_master_clock = 30720000; handler->devname = DEVNAME_B200; } } @@ -434,11 +440,7 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels) uhd_string_vector_free(&devices_str); /* Create UHD handler */ - if (strstr(args, "silent")) { - rf_uhd_suppress_stdout(NULL); - } else { - printf("Opening USRP with args: %s\n", args); - } + printf("Opening USRP with args: %s\n", args); uhd_error error = uhd_usrp_make(&handler->usrp, args); if (error) { fprintf(stderr, "Error opening UHD: code %d\n", error); @@ -578,8 +580,11 @@ int rf_uhd_close(void *h) void rf_uhd_set_master_clock_rate(void *h, double rate) { rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; - if (handler->dynamic_rate) { - uhd_usrp_set_master_clock_rate(handler->usrp, rate, 0); + if (rate != handler->current_master_clock) { + if (handler->dynamic_rate) { + uhd_usrp_set_master_clock_rate(handler->usrp, rate, 0); + } + handler->current_master_clock = rate; } } From 9355cd57322983b9ab3b8d9d5fbc7c407e24232b Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 16 Dec 2017 12:46:29 +0100 Subject: [PATCH 214/242] Improved CFO loop. Fixed issue with sinusoid tolerance --- lib/examples/pdsch_ue.c | 2 +- .../srslte/phy/ch_estimation/chest_dl.h | 4 +- lib/include/srslte/phy/sync/cfo.h | 3 -- lib/include/srslte/phy/sync/sync.h | 1 + lib/include/srslte/phy/ue/ue_sync.h | 10 +++++ lib/src/phy/ch_estimation/chest_dl.c | 13 +++---- lib/src/phy/sync/cfo.c | 2 +- lib/src/phy/sync/pss.c | 1 + lib/src/phy/sync/sync.c | 12 +++--- lib/src/phy/ue/ue_sync.c | 37 +++++++++++-------- lib/src/phy/ue/ue_ul.c | 2 +- srsue/hdr/phy/phch_worker.h | 2 + srsue/src/main.cc | 17 +++++---- srsue/src/phy/phch_recv.cc | 10 +++++ srsue/src/phy/phch_worker.cc | 7 +++- srsue/ue.conf.example | 9 ++--- 16 files changed, 81 insertions(+), 51 deletions(-) diff --git a/lib/examples/pdsch_ue.c b/lib/examples/pdsch_ue.c index 6293d0e70..ef8b643e4 100644 --- a/lib/examples/pdsch_ue.c +++ b/lib/examples/pdsch_ue.c @@ -546,7 +546,7 @@ int main(int argc, char **argv) { exit(-1); } - srslte_chest_dl_cfo_estimate_enable(&ue_dl.chest, prog_args.enable_cfo_ref, 0xff, 0.005); + srslte_chest_dl_cfo_estimate_enable(&ue_dl.chest, prog_args.enable_cfo_ref, 1023); srslte_chest_dl_average_subframe(&ue_dl.chest, prog_args.average_subframe); /* Configure downlink receiver for the SI-RNTI since will be the only one we'll use */ diff --git a/lib/include/srslte/phy/ch_estimation/chest_dl.h b/lib/include/srslte/phy/ch_estimation/chest_dl.h index 91fda41e4..5bfc1d165 100644 --- a/lib/include/srslte/phy/ch_estimation/chest_dl.h +++ b/lib/include/srslte/phy/ch_estimation/chest_dl.h @@ -87,7 +87,6 @@ typedef struct { bool cfo_estimate_enable; uint32_t cfo_estimate_sf_mask; - float cfo_ema; /* Use PSS for noise estimation in LS linear interpolation mode */ cf_t pss_signal[SRSLTE_PSS_LEN]; @@ -153,8 +152,7 @@ SRSLTE_API int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, SRSLTE_API void srslte_chest_dl_cfo_estimate_enable(srslte_chest_dl_t *q, bool enable, - uint32_t mask, - float ema); + uint32_t mask); SRSLTE_API void srslte_chest_dl_average_subframe(srslte_chest_dl_t *q, bool enable); diff --git a/lib/include/srslte/phy/sync/cfo.h b/lib/include/srslte/phy/sync/cfo.h index 5b9b3c0dd..506732b74 100644 --- a/lib/include/srslte/phy/sync/cfo.h +++ b/lib/include/srslte/phy/sync/cfo.h @@ -40,9 +40,6 @@ #include "srslte/config.h" #include "srslte/phy/utils/cexptab.h" -/** If the frequency is changed more than the tolerance, a new table is generated */ -#define SRSLTE_CFO_TOLERANCE 0.00001 - #define SRSLTE_CFO_CEXPTAB_SIZE 4096 typedef struct SRSLTE_API { diff --git a/lib/include/srslte/phy/sync/sync.h b/lib/include/srslte/phy/sync/sync.h index 3146761ce..791ef641b 100644 --- a/lib/include/srslte/phy/sync/sync.h +++ b/lib/include/srslte/phy/sync/sync.h @@ -102,6 +102,7 @@ typedef struct SRSLTE_API { bool cfo_i_initiated; float cfo_cp_mean; + float cfo_pss; float cfo_pss_mean; int cfo_i_value; diff --git a/lib/include/srslte/phy/ue/ue_sync.h b/lib/include/srslte/phy/ue/ue_sync.h index 16936c062..83f64bab6 100644 --- a/lib/include/srslte/phy/ue/ue_sync.h +++ b/lib/include/srslte/phy/ue/ue_sync.h @@ -62,6 +62,16 @@ #include "srslte/phy/io/filesource.h" +#define DEFAULT_CFO_BW_PSS 0.05 +#define DEFAULT_CFO_PSS_MIN 400 // typical bias of PSS estimation. +#define DEFAULT_CFO_BW_REF 0.01 +#define DEFAULT_CFO_REF_MIN 0 // typical bias of REF estimation +#define DEFAULT_CFO_REF_MAX DEFAULT_CFO_PSS_MIN // Maximum detection offset of REF based estimation + +#define DEFAULT_PSS_STABLE_TIMEOUT 20 // Time after which the PSS is considered to be stable and we accept REF-CFO + +#define DEFAULT_CFO_EMA_TRACK 0.05 + typedef enum SRSLTE_API { SF_FIND, SF_TRACK} srslte_ue_sync_state_t; //#define MEASURE_EXEC_TIME diff --git a/lib/src/phy/ch_estimation/chest_dl.c b/lib/src/phy/ch_estimation/chest_dl.c index 35122958d..3814fb6fb 100644 --- a/lib/src/phy/ch_estimation/chest_dl.c +++ b/lib/src/phy/ch_estimation/chest_dl.c @@ -467,7 +467,11 @@ float chest_estimate_cfo(srslte_chest_dl_t *q) } void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id, uint32_t rxant_id, srslte_sf_t ch_mode){ - if (ce != NULL) { + if (q->cfo_estimate_enable && ((1<cfo_estimate_sf_mask)) { + q->cfo = chest_estimate_cfo(q); + } + + if (ce != NULL) { /* Smooth estimates (if applicable) and interpolate */ if (q->smooth_filter_len == 0 || (q->smooth_filter_len == 3 && q->smooth_filter[0] == 0)) { interpolate_pilots(q, q->pilot_estimates, ce, port_id, ch_mode); @@ -490,10 +494,6 @@ void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, ui } } - if (q->cfo_estimate_enable && ((1<cfo_estimate_sf_mask)) { - q->cfo = SRSLTE_VEC_EMA(chest_estimate_cfo(q), q->cfo, q->cfo_ema); - } - /* Compute RSRP for the channel estimates in this port */ uint32_t npilots = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id); float energy = cabsf(srslte_vec_acc_cc(q->pilot_estimates, npilots)/npilots); @@ -581,9 +581,8 @@ void srslte_chest_dl_average_subframe(srslte_chest_dl_t *q, bool enable) q->average_subframe = enable; } -void srslte_chest_dl_cfo_estimate_enable(srslte_chest_dl_t *q, bool enable, uint32_t mask, float ema) +void srslte_chest_dl_cfo_estimate_enable(srslte_chest_dl_t *q, bool enable, uint32_t mask) { - q->cfo_ema = ema; q->cfo_estimate_enable = enable; q->cfo_estimate_sf_mask = mask; } diff --git a/lib/src/phy/sync/cfo.c b/lib/src/phy/sync/cfo.c index 44c795c19..806701a9a 100644 --- a/lib/src/phy/sync/cfo.c +++ b/lib/src/phy/sync/cfo.c @@ -45,7 +45,7 @@ int srslte_cfo_init(srslte_cfo_t *h, uint32_t nsamples) { if (!h->cur_cexp) { goto clean; } - h->tol = SRSLTE_CFO_TOLERANCE; + h->tol = 0; h->last_freq = 0; h->nsamples = nsamples; h->max_samples = nsamples; diff --git a/lib/src/phy/sync/pss.c b/lib/src/phy/sync/pss.c index 1f56dfda9..ac54264eb 100644 --- a/lib/src/phy/sync/pss.c +++ b/lib/src/phy/sync/pss.c @@ -120,6 +120,7 @@ int srslte_pss_init_fft_offset_decim(srslte_pss_t *q, buffer_size = fft_size + frame_size + 1; q->filter_pss_enable = false; + q->chest_on_filter = false; if(q->decimate > 1) { int filter_order = 3; diff --git a/lib/src/phy/sync/sync.c b/lib/src/phy/sync/sync.c index 8b7bbd69c..1508f4afb 100644 --- a/lib/src/phy/sync/sync.c +++ b/lib/src/phy/sync/sync.c @@ -475,7 +475,7 @@ srslte_pss_t* srslte_sync_get_cur_pss_obj(srslte_sync_t *q) static float cfo_cp_estimate(srslte_sync_t *q, const cf_t *input) { uint32_t cp_offset = 0; - cp_offset = srslte_cp_synch(&q->cp_synch, input, q->max_offset, 7, SRSLTE_CP_LEN_NORM(1,q->fft_size)); + cp_offset = srslte_cp_synch(&q->cp_synch, input, q->max_offset, 1, SRSLTE_CP_LEN_NORM(1,q->fft_size)); cf_t cp_corr_max = srslte_cp_synch_corr_output(&q->cp_synch, cp_offset); float cfo = -carg(cp_corr_max) / M_PI / 2; return cfo; @@ -612,16 +612,16 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, const cf_t *input, uin } // PSS-based CFO estimation - float cfo_pss = srslte_pss_cfo_compute(&q->pss, pss_ptr); + q->cfo_pss = srslte_pss_cfo_compute(&q->pss, pss_ptr); if (!q->cfo_pss_is_set) { - q->cfo_pss_mean = cfo_pss; + q->cfo_pss_mean = q->cfo_pss; q->cfo_pss_is_set = true; - } else if (15000*fabsf(cfo_pss) < MAX_CFO_PSS_OFFSET) { - q->cfo_pss_mean = SRSLTE_VEC_EMA(cfo_pss, q->cfo_pss_mean, q->cfo_ema_alpha); + } else if (15000*fabsf(q->cfo_pss) < MAX_CFO_PSS_OFFSET) { + q->cfo_pss_mean = SRSLTE_VEC_EMA(q->cfo_pss, q->cfo_pss_mean, q->cfo_ema_alpha); } INFO("PSS-CFO: filter=%s, estimated=%f, mean=%f\n", - q->pss_filtering_enabled?"yes":"no", cfo_pss, q->cfo_pss_mean); + q->pss_filtering_enabled?"yes":"no", q->cfo_pss, q->cfo_pss_mean); } diff --git a/lib/src/phy/ue/ue_sync.c b/lib/src/phy/ue/ue_sync.c index 511cdde2f..0a6c1c9ff 100644 --- a/lib/src/phy/ue/ue_sync.c +++ b/lib/src/phy/ue/ue_sync.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include "srslte/srslte.h" #include "srslte/phy/ue/ue_sync.h" @@ -47,14 +47,6 @@ #define DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD 0 #define DEFAULT_SFO_EMA_COEFF 0.1 -#define DEFAULT_CFO_BW 0.2 -#define DEFAULT_CFO_PSS_MIN 500 // typical bias of PSS estimation. -#define DEFAULT_CFO_REF_MIN 0 // typical bias of REF estimation -#define DEFAULT_CFO_REF_MAX 500 // Maximum detection offset of REF based estimation - -#define DEFAULT_PSS_STABLE_TIMEOUT 100 // Time after which the PSS is considered to be stable and we accept REF-CFO - -#define DEFAULT_CFO_EMA_TRACK 0.1 cf_t dummy_buffer0[15*2048/2]; cf_t dummy_buffer1[15*2048/2]; @@ -226,8 +218,8 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q, q->cfo_ref_max = DEFAULT_CFO_REF_MAX; q->cfo_ref_min = DEFAULT_CFO_REF_MIN; q->cfo_pss_min = DEFAULT_CFO_PSS_MIN; - q->cfo_loop_bw_pss = DEFAULT_CFO_BW; - q->cfo_loop_bw_ref = DEFAULT_CFO_BW; + q->cfo_loop_bw_pss = DEFAULT_CFO_BW_PSS; + q->cfo_loop_bw_ref = DEFAULT_CFO_BW_REF; q->cfo_correct_enable = true; q->pss_stable_cnt = 0; @@ -679,6 +671,8 @@ int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer) { return srslte_ue_sync_zerocopy_multi(q, _input_buffer); } +int track_time, find_time; + /* Returns 1 if the subframe is synchronized in time, 0 otherwise */ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE_MAX_PORTS]) { int ret = SRSLTE_ERROR_INVALID_INPUTS; @@ -723,10 +717,16 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE fprintf(stderr, "Error receiving samples\n"); return SRSLTE_ERROR; } - + int n; + struct timeval t[3]; switch (q->state) { case SF_FIND: - switch(srslte_sync_find(&q->sfind, input_buffer[0], 0, &q->peak_idx)) { + gettimeofday(&t[1], NULL); + n = srslte_sync_find(&q->sfind, input_buffer[0], 0, &q->peak_idx); + gettimeofday(&t[2], NULL); + get_time_interval(t); + find_time = t[0].tv_usec; + switch(n) { case SRSLTE_SYNC_ERROR: ret = SRSLTE_ERROR; fprintf(stderr, "Error finding correlation peak (%d)\n", ret); @@ -781,9 +781,14 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE * In tracking phase, the subframe carrying the PSS is always the last one of the frame */ track_idx = 0; - switch(srslte_sync_find(&q->strack, input_buffer[0], - q->frame_len - q->sf_len/2 - q->fft_size - q->strack.max_offset/2, - &track_idx)) + gettimeofday(&t[1], NULL); + int n = srslte_sync_find(&q->strack, input_buffer[0], + q->frame_len - q->sf_len/2 - q->fft_size - q->strack.max_offset/2, + &track_idx); + gettimeofday(&t[2], NULL); + get_time_interval(t); + track_time = t[0].tv_usec; + switch(n) { case SRSLTE_SYNC_ERROR: fprintf(stderr, "Error tracking correlation peak\n"); diff --git a/lib/src/phy/ue/ue_ul.c b/lib/src/phy/ue/ue_ul.c index 736fc3470..63411fb25 100644 --- a/lib/src/phy/ue/ue_ul.c +++ b/lib/src/phy/ue/ue_ul.c @@ -38,7 +38,7 @@ #define MAX_SFLEN SRSLTE_SF_LEN(srslte_symbol_sz(max_prb)) -#define DEFAULT_CFO_TOL 0.0 // Hz +#define DEFAULT_CFO_TOL 1.0 // Hz int srslte_ue_ul_init(srslte_ue_ul_t *q, cf_t *out_buffer, diff --git a/srsue/hdr/phy/phch_worker.h b/srsue/hdr/phy/phch_worker.h index f711ade09..a63f84b4a 100644 --- a/srsue/hdr/phy/phch_worker.h +++ b/srsue/hdr/phy/phch_worker.h @@ -67,6 +67,8 @@ public: int read_pdsch_d(cf_t *pdsch_d); void start_plot(); + float get_ref_cfo(); + private: /* Inherited from thread_pool::worker. Function called every subframe to run the DL/UL processing */ void work_imp(); diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 6df1cac99..7a117dd6b 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -37,6 +37,7 @@ #include #include "ue.h" +#include "srslte/srslte.h" #include "metrics_stdout.h" #include "metrics_csv.h" #include "srslte/common/metrics_hub.h" @@ -201,40 +202,42 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { "Enables integer CFO estimation and correction.") ("expert.cfo_correct_tol_hz", - bpo::value(&args->expert.phy.cfo_correct_tol_hz)->default_value(0.0), + bpo::value(&args->expert.phy.cfo_correct_tol_hz)->default_value(1.0), "Tolerance (in Hz) for digital CFO compensation (needs to be low if average_subframe_enabled=true.") ("expert.cfo_pss_ema", - bpo::value(&args->expert.phy.cfo_pss_ema)->default_value(0.01), + bpo::value(&args->expert.phy.cfo_pss_ema)->default_value(DEFAULT_CFO_EMA_TRACK), "CFO Exponential Moving Average coefficient for PSS estimation during TRACK.") + /* REF EMA is currently not used ("expert.cfo_ref_ema", bpo::value(&args->expert.phy.cfo_ref_ema)->default_value(0.01), "CFO Exponential Moving Average coefficient for RS estimation after PSS acquisition") + */ ("expert.cfo_ref_mask", bpo::value(&args->expert.phy.cfo_ref_mask)->default_value(1023), "Bitmask for subframes on which to run RS estimation (set to 0 to disable, default all sf)") ("expert.cfo_loop_bw_pss", - bpo::value(&args->expert.phy.cfo_loop_bw_pss)->default_value(0.05), + bpo::value(&args->expert.phy.cfo_loop_bw_pss)->default_value(DEFAULT_CFO_BW_PSS), "CFO feedback loop bandwidth for samples from PSS") ("expert.cfo_loop_bw_ref", - bpo::value(&args->expert.phy.cfo_loop_bw_ref)->default_value(0.01), + bpo::value(&args->expert.phy.cfo_loop_bw_ref)->default_value(DEFAULT_CFO_BW_REF), "CFO feedback loop bandwidth for samples from RS") ("expert.cfo_loop_pss_tol", - bpo::value(&args->expert.phy.cfo_loop_pss_tol)->default_value(300), + bpo::value(&args->expert.phy.cfo_loop_pss_tol)->default_value(DEFAULT_CFO_PSS_MIN), "Tolerance (in Hz) of the PSS estimation method. Below this value, PSS estimation does not feeds back the loop" "and RS estimations are used instead (when available)") ("expert.cfo_loop_ref_min", - bpo::value(&args->expert.phy.cfo_loop_ref_min)->default_value(0), + bpo::value(&args->expert.phy.cfo_loop_ref_min)->default_value(DEFAULT_CFO_REF_MIN), "Tolerance (in Hz) of the RS estimation method. Below this value, RS estimation does not feeds back the loop") ("expert.cfo_loop_pss_conv", - bpo::value(&args->expert.phy.cfo_loop_pss_conv)->default_value(20), + bpo::value(&args->expert.phy.cfo_loop_pss_conv)->default_value(DEFAULT_PSS_STABLE_TIMEOUT), "After the PSS estimation is below cfo_loop_pss_tol for cfo_loop_pss_timeout times consecutively, RS adjustments are allowed.") ("expert.sic_pss_enabled", diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 06ae1baa2..4f70999dd 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -539,6 +539,7 @@ double phch_recv::set_rx_gain(double gain) { void phch_recv::run_thread() { phch_worker *worker = NULL; + phch_worker *last_worker = NULL; cf_t *buffer[SRSLTE_MAX_PORTS] = {NULL}; uint32_t sf_idx = 0; phy_state = IDLE; @@ -637,6 +638,15 @@ void phch_recv::run_thread() switch(srslte_ue_sync_zerocopy_multi(&ue_sync, buffer)) { case 1: + if (last_worker) { + Warning("SF: cfo=%7.1f Hz, ref=%f Hz, pss=%f Hz\n", + srslte_ue_sync_get_cfo(&ue_sync), + 15000*last_worker->get_ref_cfo(), + 15000*ue_sync.strack.cfo_pss_mean); + } + + last_worker = worker; + Debug("SYNC: Worker %d synchronized\n", worker->get_id()); metrics.sfo = srslte_ue_sync_get_sfo(&ue_sync); diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 934be8aa7..116507ddc 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -132,7 +132,7 @@ bool phch_worker::init(uint32_t max_prb, srslte::log *log_h, chest_feedback_itf } srslte_chest_dl_average_subframe(&ue_dl.chest, phy->args->average_subframe_enabled); - srslte_chest_dl_cfo_estimate_enable(&ue_dl.chest, phy->args->cfo_ref_mask!=0, phy->args->cfo_ref_mask, phy->args->cfo_ref_ema); + srslte_chest_dl_cfo_estimate_enable(&ue_dl.chest, phy->args->cfo_ref_mask!=0, phy->args->cfo_ref_mask); srslte_ue_ul_set_normalization(&ue_ul, true); srslte_ue_ul_set_cfo_enable(&ue_ul, true); @@ -195,6 +195,11 @@ void phch_worker::set_crnti(uint16_t rnti) rnti_is_set = true; } +float phch_worker::get_ref_cfo() +{ + return srslte_chest_dl_get_cfo(&ue_dl.chest); +} + void phch_worker::work_imp() { if (!cell_initiated) { diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index 444f9e156..17e133bb9 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -202,15 +202,14 @@ enable = false # CFO related values #cfo_integer_enabled = false -#cfo_correct_tol_hz = 0 -#cfo_pss_ema = 0.1 -#cfo_ref_ema = 0.01 +#cfo_correct_tol_hz = 1.0 +#cfo_pss_ema = 0.05 #cfo_ref_mask = 1023 #cfo_loop_bw_pss = 0.05 #cfo_loop_bw_ref = 0.01 -#cfo_loop_pss_tol = 300 +#cfo_loop_pss_tol = 400 #cfo_loop_ref_min = 0 -#cfo_loop_pss_conv = 50 +#cfo_loop_pss_conv = 20 ##################################################################### # Manual RF calibration From 88e19ca19d89dbd886ba2a9334bb6c236c3a13ed Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 16 Dec 2017 13:12:31 +0100 Subject: [PATCH 215/242] Start AGC from half maximum gain --- lib/src/phy/rf/rf_uhd_imp.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/src/phy/rf/rf_uhd_imp.c b/lib/src/phy/rf/rf_uhd_imp.c index c8a4d71ab..a697f52ff 100644 --- a/lib/src/phy/rf/rf_uhd_imp.c +++ b/lib/src/phy/rf/rf_uhd_imp.c @@ -536,9 +536,17 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels) uhd_rx_metadata_make(&handler->rx_md); uhd_rx_metadata_make(&handler->rx_md_first); uhd_tx_metadata_make(&handler->tx_md, false, 0, 0, false, false); - - - // Start low priority thread to receive async commands + + // Set starting gain to half maximum in case of using AGC + uhd_meta_range_handle gain_range; + uhd_meta_range_make(&gain_range); + uhd_usrp_get_rx_gain_range(handler->usrp, "", 0, gain_range); + double max_gain; + uhd_meta_range_stop(gain_range, &max_gain); + rf_uhd_set_rx_gain(handler, max_gain*0.7); + uhd_meta_range_free(&gain_range); + + // Start low priority thread to receive async commands handler->async_thread_running = true; if (pthread_create(&handler->async_thread, NULL, async_thread, handler)) { perror("pthread_create"); From 845fc87945f2f605fee3e4cb969305812ce67c9b Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sun, 17 Dec 2017 11:01:50 +0100 Subject: [PATCH 216/242] Added option to log_filter to customize time source --- lib/include/srslte/common/log_filter.h | 17 ++++++++++ lib/src/common/log_filter.cc | 46 ++++++++++++++++++++------ srsenb/src/mac/scheduler_harq.cc | 1 - 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/lib/include/srslte/common/log_filter.h b/lib/include/srslte/common/log_filter.h index ae232f135..6902b7740 100644 --- a/lib/include/srslte/common/log_filter.h +++ b/lib/include/srslte/common/log_filter.h @@ -37,6 +37,8 @@ #include #include + +#include "srslte/phy/common/timestamp.h" #include "srslte/common/log.h" #include "srslte/common/logger.h" #include "srslte/common/logger_stdout.h" @@ -71,10 +73,25 @@ public: void info_line(std::string file, int line, std::string message, ...); void debug_line(std::string file, int line, std::string message, ...); + class time_itf { + public: + virtual srslte_timestamp_t get_time() = 0; + }; + + typedef enum { + TIME, + EPOCH + } time_format_t; + + void set_time_src(time_itf *source, time_format_t format); + private: logger *logger_h; bool do_tti; + time_itf *time_src; + time_format_t time_format; + logger_stdout def_logger_stdout; void all_log(srslte::LOG_LEVEL_ENUM level, uint32_t tti, char *msg); diff --git a/lib/src/common/log_filter.cc b/lib/src/common/log_filter.cc index 899a224d6..85380e745 100644 --- a/lib/src/common/log_filter.cc +++ b/lib/src/common/log_filter.cc @@ -37,7 +37,9 @@ namespace srslte{ log_filter::log_filter() { - do_tti = false; + do_tti = false; + time_src = NULL; + time_format = TIME; } log_filter::log_filter(std::string layer) @@ -278,7 +280,10 @@ void log_filter::debug_line(std::string file, int line, std::string message, ... } } - +void log_filter::set_time_src(time_itf *source, time_format_t format) { + this->time_src = source; + this->time_format = format; +} std::string log_filter::now_time() { @@ -286,15 +291,34 @@ std::string log_filter::now_time() struct tm * timeinfo; char buffer[64]; char us[16]; - - gettimeofday(&rawtime, NULL); - timeinfo = localtime(&rawtime.tv_sec); - - strftime(buffer,64,"%H:%M:%S",timeinfo); - strcat(buffer,"."); - snprintf(us,16,"%06ld",rawtime.tv_usec); - strcat(buffer,us); - + + srslte_timestamp_t now; + uint64_t usec_epoch; + + if (!time_src) { + gettimeofday(&rawtime, NULL); + timeinfo = localtime(&rawtime.tv_sec); + + if (time_format == TIME) { + strftime(buffer, 64, "%H:%M:%S", timeinfo); + strcat(buffer, "."); + snprintf(us, 16, "%06ld", rawtime.tv_usec); + strcat(buffer, us); + } else { + usec_epoch = rawtime.tv_sec * 1000000 + rawtime.tv_usec; + snprintf(buffer, 64, "%ld", usec_epoch); + } + } else { + now = time_src->get_time(); + + if (time_format == TIME) { + snprintf(buffer, 64, "%ld:%06u", now.full_secs, (uint32_t) (now.frac_secs * 1e6)); + } else { + usec_epoch = now.full_secs * 1000000 + (uint32_t) (now.frac_secs * 1e6); + snprintf(buffer, 64, "%ld", usec_epoch); + } + } + return std::string(buffer); } diff --git a/srsenb/src/mac/scheduler_harq.cc b/srsenb/src/mac/scheduler_harq.cc index 6e1596850..6c97e6f14 100644 --- a/srsenb/src/mac/scheduler_harq.cc +++ b/srsenb/src/mac/scheduler_harq.cc @@ -25,7 +25,6 @@ */ #include -#include #include "srslte/srslte.h" #include "srslte/common/pdu.h" From 6711387ad7e141ca9ed9c390577f85aeafd72920 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sun, 17 Dec 2017 23:05:28 +0100 Subject: [PATCH 217/242] Disabled AGC for initial cell search. Copy CFO from search and disable CP based CFO after search to reduce overhead --- lib/examples/pdsch_ue.c | 13 +++++++-- lib/include/srslte/phy/sync/sync.h | 6 +++- lib/include/srslte/phy/ue/ue_sync.h | 3 +- lib/src/phy/rf/rf_utils.c | 33 ++++++++------------- lib/src/phy/sync/sync.c | 8 +++-- lib/src/phy/ue/ue_sync.c | 45 +++++++++++++++-------------- srsue/hdr/phy/phch_recv.h | 2 +- srsue/src/phy/phch_recv.cc | 24 ++++++++------- 8 files changed, 72 insertions(+), 62 deletions(-) diff --git a/lib/examples/pdsch_ue.c b/lib/examples/pdsch_ue.c index ef8b643e4..032ef5c47 100644 --- a/lib/examples/pdsch_ue.c +++ b/lib/examples/pdsch_ue.c @@ -417,8 +417,8 @@ int main(int argc, char **argv) { fprintf(stderr, "Error opening rf\n"); exit(-1); } - srslte_rf_set_rx_gain(&rf, 50); - cell_detect_config.init_agc = 50; + srslte_rf_set_rx_gain(&rf, srslte_rf_get_rx_gain(&rf)); + cell_detect_config.init_agc = srslte_rf_get_rx_gain(&rf); } sigset_t sigset; @@ -546,6 +546,13 @@ int main(int argc, char **argv) { exit(-1); } + // Disable CP based CFO estimation during find + ue_sync.cfo_current_value = cfo/15000; + ue_sync.cfo_is_copied = true; + ue_sync.cfo_correct_enable_find = true; + srslte_sync_set_cfo_cp_enable(&ue_sync.sfind, false, 0); + + srslte_chest_dl_cfo_estimate_enable(&ue_dl.chest, prog_args.enable_cfo_ref, 1023); srslte_chest_dl_average_subframe(&ue_dl.chest, prog_args.average_subframe); @@ -595,7 +602,7 @@ int main(int argc, char **argv) { bzero(&old_dl_dci, sizeof(srslte_ra_dl_dci_t)); #endif - ue_sync.cfo_correct_enable = !prog_args.disable_cfo; + ue_sync.cfo_correct_enable_track = !prog_args.disable_cfo; srslte_pbch_decode_reset(&ue_mib.pbch); diff --git a/lib/include/srslte/phy/sync/sync.h b/lib/include/srslte/phy/sync/sync.h index 791ef641b..232bc5fc4 100644 --- a/lib/include/srslte/phy/sync/sync.h +++ b/lib/include/srslte/phy/sync/sync.h @@ -108,6 +108,8 @@ typedef struct SRSLTE_API { float cfo_ema_alpha; + uint32_t cfo_cp_nsymbols; + srslte_cfo_t cfo_corr_frame; srslte_cfo_t cfo_corr_symbol; @@ -204,7 +206,9 @@ SRSLTE_API void srslte_sync_copy_cfo(srslte_sync_t *q, SRSLTE_API void srslte_sync_set_cfo_i_enable(srslte_sync_t *q, bool enable); SRSLTE_API void srslte_sync_set_cfo_cp_enable(srslte_sync_t *q, - bool enable); + bool enable, + uint32_t nof_symbols); + SRSLTE_API void srslte_sync_set_cfo_pss_enable(srslte_sync_t *q, bool enable); diff --git a/lib/include/srslte/phy/ue/ue_sync.h b/lib/include/srslte/phy/ue/ue_sync.h index 83f64bab6..ff863c3f9 100644 --- a/lib/include/srslte/phy/ue/ue_sync.h +++ b/lib/include/srslte/phy/ue/ue_sync.h @@ -122,7 +122,8 @@ typedef struct SRSLTE_API { bool decode_sss_on_track; bool cfo_is_copied; - bool cfo_correct_enable; + bool cfo_correct_enable_track; + bool cfo_correct_enable_find; float cfo_current_value; float cfo_loop_bw_pss; float cfo_loop_bw_ref; diff --git a/lib/src/phy/rf/rf_utils.c b/lib/src/phy/rf/rf_utils.c index 892ad817e..ea016c721 100644 --- a/lib/src/phy/rf/rf_utils.c +++ b/lib/src/phy/rf/rf_utils.c @@ -113,10 +113,6 @@ int rf_mib_decoder(srslte_rf_t *rf, uint32_t nof_rx_antennas,cell_search_cfg_t * goto clean_exit; } - if (config->init_agc > 0) { - srslte_ue_sync_start_agc(&ue_mib.ue_sync, srslte_rf_set_rx_gain_th_wrapper, config->init_agc); - } - int srate = srslte_sampling_freq_hz(SRSLTE_UE_MIB_NOF_PRB); INFO("Setting sampling frequency %.2f MHz for PSS search\n", (float) srate/1000000); srslte_rf_set_rx_srate(rf, (float) srate); @@ -124,7 +120,15 @@ int rf_mib_decoder(srslte_rf_t *rf, uint32_t nof_rx_antennas,cell_search_cfg_t * INFO("Starting receiver...\n", 0); srslte_rf_start_rx_stream(rf, false); - /* Find and decody MIB */ + // Copy CFO estimate if provided and disable CP estimation during find + if (cfo) { + ue_mib.ue_sync.cfo_current_value = *cfo/15000; + ue_mib.ue_sync.cfo_is_copied = true; + ue_mib.ue_sync.cfo_correct_enable_find = true; + srslte_sync_set_cfo_cp_enable(&ue_mib.ue_sync.sfind, false, 0); + } + + /* Find and decode MIB */ ret = srslte_ue_mib_sync_decode(&ue_mib, config->max_frames_pbch, bch_payload, &cell->nof_ports, NULL); if (ret < 0) { fprintf(stderr, "Error decoding MIB\n"); @@ -133,12 +137,7 @@ int rf_mib_decoder(srslte_rf_t *rf, uint32_t nof_rx_antennas,cell_search_cfg_t * if (ret == 1) { srslte_pbch_mib_unpack(bch_payload, cell, NULL); } - - // Save AGC value - if (config->init_agc > 0) { - config->init_agc = srslte_agc_get_gain(&ue_mib.ue_sync.agc); - } - + // Save CFO if (cfo) { *cfo = srslte_ue_sync_get_cfo(&ue_mib.ue_sync); @@ -171,10 +170,7 @@ int rf_cell_search(srslte_rf_t *rf, uint32_t nof_rx_antennas, if (config->nof_valid_pss_frames) { srslte_ue_cellsearch_set_nof_valid_frames(&cs, config->nof_valid_pss_frames); } - if (config->init_agc > 0) { - srslte_ue_sync_start_agc(&cs.ue_sync, srslte_rf_set_rx_gain_th_wrapper, config->init_agc); - } - + INFO("Setting sampling frequency %.2f MHz for PSS search\n", SRSLTE_CS_SAMP_FREQ/1000000); srslte_rf_set_rx_srate(rf, SRSLTE_CS_SAMP_FREQ); @@ -217,12 +213,7 @@ int rf_cell_search(srslte_rf_t *rf, uint32_t nof_rx_antennas, // Save CFO if (cfo) { - *cfo = found_cells[max_peak_cell].cfo; - } - - // Save AGC value for MIB decoding - if (config->init_agc > 0) { - config->init_agc = srslte_agc_get_gain(&cs.ue_sync.agc); + *cfo = found_cells[max_peak_cell].cfo; } srslte_rf_stop_rx_stream(rf); diff --git a/lib/src/phy/sync/sync.c b/lib/src/phy/sync/sync.c index 1508f4afb..bf86eef4d 100644 --- a/lib/src/phy/sync/sync.c +++ b/lib/src/phy/sync/sync.c @@ -80,6 +80,7 @@ int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_o q->cfo_i_initiated = false; q->pss_filtering_enabled = false; + q->cfo_cp_nsymbols = 3; q->fft_size = fft_size; q->frame_size = frame_size; q->max_offset = max_offset; @@ -326,8 +327,9 @@ void srslte_sync_set_pss_filt_enable(srslte_sync_t *q, bool enable) { q->pss_filtering_enabled = enable; } -void srslte_sync_set_cfo_cp_enable(srslte_sync_t *q, bool enable) { - q->cfo_cp_enable = enable; +void srslte_sync_set_cfo_cp_enable(srslte_sync_t *q, bool enable, uint32_t nof_symbols) { + q->cfo_cp_enable = enable; + q->cfo_cp_nsymbols = nof_symbols; } void srslte_sync_set_cfo_pss_enable(srslte_sync_t *q, bool enable) { @@ -475,7 +477,7 @@ srslte_pss_t* srslte_sync_get_cur_pss_obj(srslte_sync_t *q) static float cfo_cp_estimate(srslte_sync_t *q, const cf_t *input) { uint32_t cp_offset = 0; - cp_offset = srslte_cp_synch(&q->cp_synch, input, q->max_offset, 1, SRSLTE_CP_LEN_NORM(1,q->fft_size)); + cp_offset = srslte_cp_synch(&q->cp_synch, input, q->max_offset, q->cfo_cp_nsymbols, SRSLTE_CP_LEN_NORM(1,q->fft_size)); cf_t cp_corr_max = srslte_cp_synch_corr_output(&q->cp_synch, cp_offset); float cfo = -carg(cp_corr_max) / M_PI / 2; return cfo; diff --git a/lib/src/phy/ue/ue_sync.c b/lib/src/phy/ue/ue_sync.c index 0a6c1c9ff..f3360dda7 100644 --- a/lib/src/phy/ue/ue_sync.c +++ b/lib/src/phy/ue/ue_sync.c @@ -74,8 +74,9 @@ int srslte_ue_sync_init_file_multi(srslte_ue_sync_t *q, uint32_t nof_prb, char * q->fft_size = srslte_symbol_sz(nof_prb); q->nof_rx_antennas = nof_rx_ant; - q->cfo_correct_enable = true; - + q->cfo_correct_enable_find = false; + q->cfo_correct_enable_track = true; + if (srslte_cfo_init(&q->file_cfo_correct, 2*q->sf_len)) { fprintf(stderr, "Error initiating CFO\n"); goto clean_exit; @@ -220,7 +221,9 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q, q->cfo_pss_min = DEFAULT_CFO_PSS_MIN; q->cfo_loop_bw_pss = DEFAULT_CFO_BW_PSS; q->cfo_loop_bw_ref = DEFAULT_CFO_BW_REF; - q->cfo_correct_enable = true; + + q->cfo_correct_enable_find = false; + q->cfo_correct_enable_track = true; q->pss_stable_cnt = 0; q->pss_stable_timeout = DEFAULT_PSS_STABLE_TIMEOUT; @@ -261,14 +264,12 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q, // Configure FIND and TRACK sync objects behaviour (this configuration is always the same) srslte_sync_set_cfo_i_enable(&q->sfind, false); - srslte_sync_set_cfo_cp_enable(&q->sfind, true); srslte_sync_set_cfo_pss_enable(&q->sfind, true); srslte_sync_set_pss_filt_enable(&q->sfind, true); srslte_sync_set_sss_eq_enable(&q->sfind, false); // During track, we do CFO correction outside the sync object srslte_sync_set_cfo_i_enable(&q->strack, false); - srslte_sync_set_cfo_cp_enable(&q->strack, false); srslte_sync_set_cfo_pss_enable(&q->strack, true); srslte_sync_set_pss_filt_enable(&q->strack, true); srslte_sync_set_sss_eq_enable(&q->strack, false); @@ -277,11 +278,9 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q, srslte_sync_cp_en(&q->strack, false); srslte_sync_cp_en(&q->sfind, false); - srslte_sync_sss_en(&q->strack, true); q->decode_sss_on_track = true; - ret = SRSLTE_SUCCESS; } @@ -392,8 +391,13 @@ int srslte_ue_sync_set_cell(srslte_ue_sync_t *q, srslte_cell_t cell) srslte_sync_set_em_alpha(&q->strack, 0.2); srslte_sync_set_threshold(&q->strack, 1.2); + } + // When cell is unknown, do CP CFO correction + srslte_sync_set_cfo_cp_enable(&q->sfind, true, q->frame_len<10000?14:3); + q->cfo_correct_enable_find = false; + srslte_ue_sync_reset(q); ret = SRSLTE_SUCCESS; @@ -671,8 +675,6 @@ int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer) { return srslte_ue_sync_zerocopy_multi(q, _input_buffer); } -int track_time, find_time; - /* Returns 1 if the subframe is synchronized in time, 0 otherwise */ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE_MAX_PORTS]) { int ret = SRSLTE_ERROR_INVALID_INPUTS; @@ -697,7 +699,7 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE return SRSLTE_ERROR; } } - if (q->cfo_correct_enable) { + if (q->cfo_correct_enable_track) { for (int i = 0; i < q->nof_rx_antennas; i++) { srslte_cfo_correct(&q->file_cfo_correct, input_buffer[i], @@ -718,14 +720,18 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE return SRSLTE_ERROR; } int n; - struct timeval t[3]; switch (q->state) { case SF_FIND: - gettimeofday(&t[1], NULL); + // Correct CFO before PSS/SSS find using the sync object corrector (initialized for 1 ms) + if (q->cfo_correct_enable_find) { + for (int i=0;inof_rx_antennas;i++) { + srslte_cfo_correct(&q->strack.cfo_corr_frame, + input_buffer[i], + input_buffer[i], + -q->cfo_current_value/q->fft_size); + } + } n = srslte_sync_find(&q->sfind, input_buffer[0], 0, &q->peak_idx); - gettimeofday(&t[2], NULL); - get_time_interval(t); - find_time = t[0].tv_usec; switch(n) { case SRSLTE_SYNC_ERROR: ret = SRSLTE_ERROR; @@ -758,7 +764,7 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE q->sf_idx = (q->sf_idx + q->nof_recv_sf) % 10; // Correct CFO before PSS/SSS tracking using the sync object corrector (initialized for 1 ms) - if (q->cfo_correct_enable) { + if (q->cfo_correct_enable_track) { for (int i=0;inof_rx_antennas;i++) { srslte_cfo_correct(&q->strack.cfo_corr_frame, input_buffer[i], @@ -780,14 +786,9 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE /* Track PSS/SSS around the expected PSS position * In tracking phase, the subframe carrying the PSS is always the last one of the frame */ - track_idx = 0; - gettimeofday(&t[1], NULL); - int n = srslte_sync_find(&q->strack, input_buffer[0], + n = srslte_sync_find(&q->strack, input_buffer[0], q->frame_len - q->sf_len/2 - q->fft_size - q->strack.max_offset/2, &track_idx); - gettimeofday(&t[2], NULL); - get_time_interval(t); - track_time = t[0].tv_usec; switch(n) { case SRSLTE_SYNC_ERROR: diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index 6c7ff7717..2d6dd93b7 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -95,7 +95,7 @@ private: void reset(); void radio_error(); bool wait_radio_reset(); - void set_ue_sync_opts(srslte_ue_sync_t *q); + void set_ue_sync_opts(srslte_ue_sync_t *q, float cfo); void run_thread(); void set_sampling_rate(); diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 4f70999dd..75f6ae36c 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -182,7 +182,7 @@ void phch_recv::set_time_adv_sec(float _time_adv_sec) } } -void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q) +void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q, float cfo) { if (worker_com->args->cfo_integer_enabled) { srslte_ue_sync_set_cfo_i_enable(q, true); @@ -198,6 +198,14 @@ void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q) q->strack.pss.chest_on_filter = worker_com->args->sic_pss_enabled; + // Disable CP based CFO estimation during find + if (cfo != 0) { + q->cfo_current_value = cfo/15000; + q->cfo_is_copied = true; + q->cfo_correct_enable_find = true; + srslte_sync_set_cfo_cp_enable(&q->sfind, false, 0); + } + int time_correct_period = worker_com->args->time_correct_period; if (time_correct_period > 0) { srslte_ue_sync_set_sample_offset_correct_period(q, time_correct_period); @@ -238,7 +246,7 @@ bool phch_recv::set_cell() { } // Set options defined in expert section - set_ue_sync_opts(&ue_sync); + set_ue_sync_opts(&ue_sync, search_p.get_last_cfo()); // Reset ue_sync and set CFO/gain from search procedure srslte_ue_sync_reset(&ue_sync); @@ -774,11 +782,7 @@ void phch_recv::search::init(cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h, srslte_ue_cellsearch_set_nof_valid_frames(&cs, 2); // Set options defined in expert section - p->set_ue_sync_opts(&cs.ue_sync); - - if (p->do_agc) { - srslte_ue_sync_start_agc(&cs.ue_sync, callback_set_rx_gain, 40); - } + p->set_ue_sync_opts(&cs.ue_sync, 0); force_N_id_2 = -1; } @@ -859,10 +863,11 @@ phch_recv::search::ret_code phch_recv::search::run(srslte_cell_t *cell) } // Set options defined in expert section - p->set_ue_sync_opts(&ue_mib_sync.ue_sync); + p->set_ue_sync_opts(&ue_mib_sync.ue_sync, cfo); + // Start AGC after initial cell search if (p->do_agc) { - srslte_ue_sync_start_agc(&ue_mib_sync.ue_sync, callback_set_rx_gain, srslte_agc_get_gain(&cs.ue_sync.agc)); + srslte_ue_sync_start_agc(&ue_mib_sync.ue_sync, callback_set_rx_gain, p->radio_h->get_rx_gain()); } srslte_ue_sync_reset(&ue_mib_sync.ue_sync); @@ -1211,7 +1216,6 @@ void phch_recv::scell_recv::init(srslte::log *log_h, bool sic_pss_enabled) // Configure FIND object behaviour (this configuration is always the same) srslte_sync_set_cfo_ema_alpha(&sync_find, 1.0); srslte_sync_set_cfo_i_enable(&sync_find, false); - srslte_sync_set_cfo_cp_enable(&sync_find, false); srslte_sync_set_cfo_pss_enable(&sync_find, true); srslte_sync_set_pss_filt_enable(&sync_find, true); srslte_sync_set_sss_eq_enable(&sync_find, true); From 68537b76d66b4f6319a6640d42fd378e6b05c4fc Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 18 Dec 2017 15:39:24 +0100 Subject: [PATCH 218/242] fix compilation issue on ARM --- lib/src/phy/fec/turbodecoder.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/phy/fec/turbodecoder.c b/lib/src/phy/fec/turbodecoder.c index 7803fde1b..54a0ed109 100644 --- a/lib/src/phy/fec/turbodecoder.c +++ b/lib/src/phy/fec/turbodecoder.c @@ -95,7 +95,7 @@ void srslte_tdec_iteration_par(srslte_tdec_t * h, int16_t* input[SRSLTE_TDEC_MAX #ifdef LV_HAVE_SSE srslte_tdec_simd_iteration(&h->tdec_simd, input, long_cb); #else - srslte_vec_convert_if(input[0], h->input_conv, 0.01, 3*long_cb+12); + srslte_vec_convert_if(input[0], 0.01, h->input_conv, 3*long_cb+12); srslte_tdec_gen_iteration(&h->tdec_gen, h->input_conv, long_cb); #endif } @@ -156,7 +156,7 @@ int srslte_tdec_run_all_par(srslte_tdec_t * h, int16_t * input[SRSLTE_TDEC_MAX_N #ifdef LV_HAVE_SSE return srslte_tdec_simd_run_all(&h->tdec_simd, input, output, nof_iterations, long_cb); #else - srslte_vec_convert_if(input[0], h->input_conv, 0.01, 3*long_cb+12); + srslte_vec_convert_if(input[0], 0.01, h->input_conv, 3*long_cb+12); return srslte_tdec_gen_run_all(&h->tdec_gen, h->input_conv, output[0], nof_iterations, long_cb); #endif } From c54cb02efd1962729d7a1a6c41fd43af1174e990 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Mon, 18 Dec 2017 16:35:21 +0100 Subject: [PATCH 219/242] Increased REF BW CFO loop --- lib/include/srslte/phy/ue/ue_sync.h | 2 +- srsue/src/phy/phch_recv.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/include/srslte/phy/ue/ue_sync.h b/lib/include/srslte/phy/ue/ue_sync.h index ff863c3f9..233b87b11 100644 --- a/lib/include/srslte/phy/ue/ue_sync.h +++ b/lib/include/srslte/phy/ue/ue_sync.h @@ -64,7 +64,7 @@ #define DEFAULT_CFO_BW_PSS 0.05 #define DEFAULT_CFO_PSS_MIN 400 // typical bias of PSS estimation. -#define DEFAULT_CFO_BW_REF 0.01 +#define DEFAULT_CFO_BW_REF 0.08 #define DEFAULT_CFO_REF_MIN 0 // typical bias of REF estimation #define DEFAULT_CFO_REF_MAX DEFAULT_CFO_PSS_MIN // Maximum detection offset of REF based estimation diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 75f6ae36c..b75a37b2e 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -647,7 +647,7 @@ void phch_recv::run_thread() case 1: if (last_worker) { - Warning("SF: cfo=%7.1f Hz, ref=%f Hz, pss=%f Hz\n", + Warning("SF: cfo_tot=%7.1f Hz, ref=%f Hz, pss=%f Hz\n", srslte_ue_sync_get_cfo(&ue_sync), 15000*last_worker->get_ref_cfo(), 15000*ue_sync.strack.cfo_pss_mean); From 1b1301101c8a200e5d9943789271933605e1d9a1 Mon Sep 17 00:00:00 2001 From: yagoda Date: Mon, 18 Dec 2017 19:04:47 +0000 Subject: [PATCH 220/242] adding support for phy(C level) logging to file --- lib/examples/pdsch_enodeb.c | 2 +- lib/examples/pdsch_ue.c | 2 +- lib/include/srslte/phy/common/phy_logger.h | 59 ++++++++++++++++++++++ lib/include/srslte/phy/utils/debug.h | 21 +++++--- lib/include/srslte/srslte.h | 1 + lib/src/phy/common/phy_logger.c | 59 ++++++++++++++++++++++ lib/src/phy/utils/debug.c | 1 + srsue/hdr/phy/phch_recv.h | 2 +- srsue/src/phy/phch_recv.cc | 26 +++++++++- 9 files changed, 162 insertions(+), 11 deletions(-) create mode 100644 lib/include/srslte/phy/common/phy_logger.h create mode 100644 lib/src/phy/common/phy_logger.c diff --git a/lib/examples/pdsch_enodeb.c b/lib/examples/pdsch_enodeb.c index fa5483003..60d9c581f 100644 --- a/lib/examples/pdsch_enodeb.c +++ b/lib/examples/pdsch_enodeb.c @@ -700,7 +700,7 @@ int main(int argc, char **argv) { uint32_t sfn; srslte_refsignal_t csr_refs; srslte_refsignal_t mbsfn_refs; - + srslte_is_example = 1; srslte_debug_handle_crash(argc, argv); #ifdef DISABLE_RF diff --git a/lib/examples/pdsch_ue.c b/lib/examples/pdsch_ue.c index 032ef5c47..20f5151c3 100644 --- a/lib/examples/pdsch_ue.c +++ b/lib/examples/pdsch_ue.c @@ -352,7 +352,7 @@ int main(int argc, char **argv) { uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; int sfn_offset; float cfo = 0; - + srslte_is_example = 1; srslte_debug_handle_crash(argc, argv); parse_args(&prog_args, argc, argv); diff --git a/lib/include/srslte/phy/common/phy_logger.h b/lib/include/srslte/phy/common/phy_logger.h new file mode 100644 index 000000000..d02efbb47 --- /dev/null +++ b/lib/include/srslte/phy/common/phy_logger.h @@ -0,0 +1,59 @@ +/** + * + * \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/. + * + */ + +/****************************************************************************** + * File: phy_logger.h + * Description: Interface for logging output + *****************************************************************************/ + +#ifndef PHY_LOGGER_H +#define PHY_LOGGER_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif // __cplusplus +typedef enum {LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_ERROR} phy_logger_level_t; + +typedef void (*phy_log_handler_t)(phy_logger_level_t log_level, void *ctx, char *str); + +void srslte_phy_log_register_handler(void *ctx, phy_log_handler_t handler); + + void srslte_phy_log_print(phy_logger_level_t log_level, const char *format, ...); + +#ifdef __cplusplus +} +#endif // C++ + +#endif // LOGGER_H diff --git a/lib/include/srslte/phy/utils/debug.h b/lib/include/srslte/phy/utils/debug.h index 9405d0865..ec7fbbba1 100644 --- a/lib/include/srslte/phy/utils/debug.h +++ b/lib/include/srslte/phy/utils/debug.h @@ -37,7 +37,7 @@ #include #include "srslte/config.h" - +#include "srslte/srslte.h" #define SRSLTE_VERBOSE_DEBUG 2 #define SRSLTE_VERBOSE_INFO 1 #define SRSLTE_VERBOSE_NONE 0 @@ -48,6 +48,7 @@ SRSLTE_API void get_time_interval(struct timeval * tdata); #define SRSLTE_DEBUG_ENABLED 1 SRSLTE_API extern int srslte_verbose; +SRSLTE_API extern int srslte_is_example; #define SRSLTE_VERBOSE_ISINFO() (srslte_verbose>=SRSLTE_VERBOSE_INFO) #define SRSLTE_VERBOSE_ISDEBUG() (srslte_verbose>=SRSLTE_VERBOSE_DEBUG) @@ -57,17 +58,23 @@ SRSLTE_API extern int srslte_verbose; #define PRINT_INFO srslte_verbose=SRSLTE_VERBOSE_INFO #define PRINT_NONE srslte_verbose=SRSLTE_VERBOSE_NONE -#define DEBUG(_fmt, ...) if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG) \ - fprintf(stdout, "[DEBUG]: " _fmt, ##__VA_ARGS__) +#define DEBUG(_fmt, ...) if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && srslte_is_example)\ + { fprintf(stdout, "[DEBUG]: " _fmt, ##__VA_ARGS__); }\ + else{ srslte_phy_log_print(LOG_LEVEL_DEBUG, _fmt, ##__VA_ARGS__); } -#define INFO(_fmt, ...) if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO) \ - fprintf(stdout, "[INFO]: " _fmt, ##__VA_ARGS__) +#define INFO(_fmt, ...) if (SRSLTE_DEBUG_ENABLED && ((srslte_verbose >= SRSLTE_VERBOSE_INFO)) && srslte_is_example)\ + { fprintf(stdout, "[INFO]: " _fmt, ##__VA_ARGS__); }\ + else{ srslte_phy_log_print(LOG_LEVEL_INFO, _fmt, ##__VA_ARGS__); } #if CMAKE_BUILD_TYPE==Debug /* In debug mode, it prints out the */ -#define ERROR(_fmt, ...) fprintf(stderr, "\e[31m%s.%d: " _fmt "\e[0m\n", __FILE__, __LINE__, ##__VA_ARGS__) +#define ERROR(_fmt, ...) if (srslte_is_example)\ + { fprintf(stderr, "\e[31m%s.%d: " _fmt "\e[0m\n", __FILE__, __LINE__, ##__VA_ARGS__);}\ + else {srslte_phy_log_print(LOG_LEVEL_ERROR, _fmt, ##__VA_ARGS__);} // #else -#define ERROR(_fmt, ...) fprintf(stderr, "[ERROR in %s]:" _fmt "\n", __FUNCTION__, ##__VA_ARGS__) +#define ERROR(_fmt, ...) if (srslte_is_example)\ + { fprintf(stderr, "[ERROR in %s]:" _fmt "\n", __FUNCTION__, ##__VA_ARGS__);}\ + else{srslte_phy_log_print(LOG_LEVEL_ERROR, _fmt, ##__VA_ARGS__);} // #endif /* CMAKE_BUILD_TYPE==Debug */ void srslte_debug_handle_crash(int argc, char **argv); diff --git a/lib/include/srslte/srslte.h b/lib/include/srslte/srslte.h index f4806b36d..36af629d7 100644 --- a/lib/include/srslte/srslte.h +++ b/lib/include/srslte/srslte.h @@ -48,6 +48,7 @@ #include "srslte/phy/common/timestamp.h" #include "srslte/phy/common/sequence.h" #include "srslte/phy/common/phy_common.h" +#include "srslte/phy/common/phy_logger.h" #include "srslte/phy/ch_estimation/chest_ul.h" #include "srslte/phy/ch_estimation/chest_dl.h" diff --git a/lib/src/phy/common/phy_logger.c b/lib/src/phy/common/phy_logger.c new file mode 100644 index 000000000..a2597961e --- /dev/null +++ b/lib/src/phy/common/phy_logger.c @@ -0,0 +1,59 @@ +/** + * + * \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 +#include +#include +#include +#include "srslte/phy/common/phy_logger.h" +/********************************************************************* + Functions for external logging +*********************************************************************/ +static phy_log_handler_t phy_log_handler; +static void *callback_ctx = NULL; + +void srslte_phy_log_register_handler(void *ctx, phy_log_handler_t handler) { + phy_log_handler = handler; + callback_ctx = ctx; +} + + void srslte_phy_log_print(phy_logger_level_t log_level, const char *format, ...) { + va_list args; + va_start(args, format); + if (phy_log_handler) { + char *args_msg = NULL; + if(vasprintf(&args_msg, format, args) > 0) { + phy_log_handler(log_level, callback_ctx, args_msg); + } + if (args_msg) { + free(args_msg); + } + } + va_end(args); +} \ No newline at end of file diff --git a/lib/src/phy/utils/debug.c b/lib/src/phy/utils/debug.c index 7cb9c0f11..59f55c0a8 100644 --- a/lib/src/phy/utils/debug.c +++ b/lib/src/phy/utils/debug.c @@ -34,6 +34,7 @@ #include "srslte/version.h" int srslte_verbose = 0; +int srslte_is_example = 0; void get_time_interval(struct timeval * tdata) { diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index 2d6dd93b7..d42966634 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -58,7 +58,7 @@ public: void set_earfcn(std::vector earfcn); void force_freq(float dl_freq, float ul_freq); - + void srslte_phy_logger(phy_logger_level_t log_level, char *str); void reset_sync(); void cell_search_start(); void cell_search_stop(); diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index b75a37b2e..5db5ce65a 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -46,6 +46,30 @@ double callback_set_rx_gain(void *h, double gain) { return ((phch_recv*) h)->set_rx_gain(gain); } +static void srslte_phy_handler(phy_logger_level_t log_level, void *ctx, char *str) { + phch_recv *r = (phch_recv *) ctx; + r->srslte_phy_logger(log_level, str); +} + +void phch_recv::srslte_phy_logger(phy_logger_level_t log_level, char *str) { + if (log_h) { + switch(log_level){ + case LOG_LEVEL_INFO: + log_h->info("[PHY_LAYER]: %s", str); + break; + case LOG_LEVEL_DEBUG: + log_h->debug("[PHY_LAYER]: %s", str); + break; + case LOG_LEVEL_ERROR: + log_h->error("[PHY_LAYER]: %s", str); + break; + default: + break; + } + } else { + printf("[PHY_LAYER]: %s\n", str); + } +} phch_recv::phch_recv() { dl_freq = -1; @@ -94,7 +118,7 @@ void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_ma intra_freq_meas.init(worker_com, rrc, log_h); reset(); - + srslte_phy_log_register_handler(this, srslte_phy_handler); // Start main thread if (sync_cpu_affinity < 0) { start(prio); From 23718aebad9a3d18eb48bf4345d1534f6ee87061 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 19 Dec 2017 18:15:10 +0100 Subject: [PATCH 221/242] Forced kill of UE and ENB by typing ctrl +c multiple times --- srsenb/src/main.cc | 6 ++++++ srsue/src/main.cc | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 8cef32af3..c2b08307b 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -318,12 +318,18 @@ void parse_args(all_args_t *args, int argc, char* argv[]) { } } +static int sigcnt = 0; static bool running = true; static bool do_metrics = false; void sig_int_handler(int signo) { + sigcnt++; running = false; + printf("Stopping srsENB... Press Ctrl+C %d more times to force stop\n", 10-sigcnt); + if (sigcnt >= 10) { + exit(-1); + } } void *input_loop(void *m) diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 7a117dd6b..f2b6a8ebb 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -380,12 +380,18 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { } } +static int sigcnt = 0; static bool running = true; static bool do_metrics = false; metrics_stdout metrics_screen; void sig_int_handler(int signo) { + sigcnt++; running = false; + printf("Stopping srsUE... Press Ctrl+C %d more times to force stop\n", 10-sigcnt); + if (sigcnt >= 10) { + exit(-1); + } } void *input_loop(void *m) { From 37ee5505e908c3094516e2972518556cce9aaf81 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 19 Dec 2017 21:25:55 +0100 Subject: [PATCH 222/242] Removed unused log_line() functions. Added DCI info string --- lib/include/srslte/common/log.h | 16 +++-- lib/include/srslte/common/log_filter.h | 5 -- lib/include/srslte/phy/phch/dci.h | 9 +++ lib/src/common/log_filter.cc | 86 ++++---------------------- lib/src/common/pdu_queue.cc | 8 +-- lib/src/phy/phch/dci.c | 65 +++++++++++++++++++ srsenb/src/mac/mac.cc | 8 +-- srsenb/src/mac/scheduler.cc | 8 +-- srsenb/src/mac/scheduler_harq.cc | 8 +-- srsenb/src/mac/scheduler_metric.cc | 8 +-- srsenb/src/mac/scheduler_ue.cc | 8 +-- srsenb/src/mac/ue.cc | 8 +-- srsenb/src/phy/phch_common.cc | 8 +-- srsenb/src/phy/phch_worker.cc | 8 +-- srsenb/src/phy/phy.cc | 8 +-- srsenb/src/phy/txrx.cc | 8 +-- srsue/hdr/mac/dl_harq.h | 8 +-- srsue/hdr/mac/ul_harq.h | 8 +-- srsue/src/mac/demux.cc | 8 +-- srsue/src/mac/mac.cc | 8 +-- srsue/src/mac/mux.cc | 8 +-- srsue/src/mac/proc_bsr.cc | 8 +-- srsue/src/mac/proc_phr.cc | 8 +-- srsue/src/mac/proc_ra.cc | 8 +-- srsue/src/mac/proc_sr.cc | 8 +-- srsue/src/phy/phch_common.cc | 8 +-- srsue/src/phy/phch_recv.cc | 8 +-- srsue/src/phy/phch_worker.cc | 8 +-- srsue/src/phy/phy.cc | 8 +-- srsue/src/phy/prach.cc | 8 +-- 30 files changed, 195 insertions(+), 186 deletions(-) diff --git a/lib/include/srslte/common/log.h b/lib/include/srslte/common/log.h index 9bec779df..84278f9e6 100644 --- a/lib/include/srslte/common/log.h +++ b/lib/include/srslte/common/log.h @@ -75,7 +75,14 @@ public: // This function shall be called at the start of every tti for printing tti void step(uint32_t tti_) { tti = tti_; + add_string_en = false; } + + void prepend_string(std::string s) { + add_string_en = true; + add_string_val = s; + } + uint32_t get_tti() { return tti; } @@ -107,18 +114,15 @@ public: virtual void info_hex(uint8_t *hex, int size, std::string message, ...){error("info_hex not implemented.\n");} virtual void debug_hex(uint8_t *hex, int size, std::string message, ...){error("debug_hex not implemented.\n");} - // Same with line and file info - virtual void error_line(std::string file, int line, std::string message, ...){error("error_line not implemented.\n");} - virtual void warning_line(std::string file, int line, std::string message, ...){error("warning_line not implemented.\n");} - virtual void info_line(std::string file, int line, std::string message, ...){error("info_line not implemented.\n");} - virtual void debug_line(std::string file, int line, std::string message, ...){error("debug_line not implemented.\n");} - protected: std::string get_service_name() { return service_name; } uint32_t tti; LOG_LEVEL_ENUM level; int hex_limit; std::string service_name; + + bool add_string_en; + std::string add_string_val; }; } // namespace srslte diff --git a/lib/include/srslte/common/log_filter.h b/lib/include/srslte/common/log_filter.h index 6902b7740..7e4014190 100644 --- a/lib/include/srslte/common/log_filter.h +++ b/lib/include/srslte/common/log_filter.h @@ -68,11 +68,6 @@ public: void info_hex(uint8_t *hex, int size, std::string message, ...); void debug_hex(uint8_t *hex, int size, std::string message, ...); - void error_line(std::string file, int line, std::string message, ...); - void warning_line(std::string file, int line, std::string message, ...); - void info_line(std::string file, int line, std::string message, ...); - void debug_line(std::string file, int line, std::string message, ...); - class time_itf { public: virtual srslte_timestamp_t get_time() = 0; diff --git a/lib/include/srslte/phy/phch/dci.h b/lib/include/srslte/phy/phch/dci.h index 6976a6b24..24a20e552 100644 --- a/lib/include/srslte/phy/phch/dci.h +++ b/lib/include/srslte/phy/phch/dci.h @@ -178,6 +178,15 @@ SRSLTE_API uint32_t srslte_dci_format_sizeof(srslte_dci_format_t format, uint32_t nof_prb, uint32_t nof_ports); +SRSLTE_API uint32_t srslte_dci_dl_info(char *info_str, + uint32_t str_len, + srslte_ra_dl_dci_t *dci_msg, + srslte_dci_format_t format); + +SRSLTE_API uint32_t srslte_dci_ul_info(char *info_str, + uint32_t len, + srslte_ra_ul_dci_t *dci_msg); + // This is for backwards compatibility only for tm1 formats SRSLTE_API uint32_t srslte_dci_format_sizeof_lut(srslte_dci_format_t format, uint32_t nof_prb); diff --git a/lib/src/common/log_filter.cc b/lib/src/common/log_filter.cc index 85380e745..4e2debb93 100644 --- a/lib/src/common/log_filter.cc +++ b/lib/src/common/log_filter.cc @@ -69,8 +69,12 @@ void log_filter::all_log(srslte::LOG_LEVEL_ENUM level, ss << now_time() << " "; ss << "[" <log(s_ptr); - } -} - void log_filter::console(std::string message, ...) { char *args_msg; va_list args; @@ -228,58 +216,6 @@ void log_filter::debug_hex(uint8_t *hex, int size, std::string message, ...) { } } -void log_filter::error_line(std::string file, int line, std::string message, ...) -{ - if (level >= LOG_LEVEL_ERROR) { - char *args_msg; - va_list args; - va_start(args, message); - if(vasprintf(&args_msg, message.c_str(), args) > 0) - all_log_line(LOG_LEVEL_ERROR, tti, file, line, args_msg); - va_end(args); - free(args_msg); - } -} - -void log_filter::warning_line(std::string file, int line, std::string message, ...) -{ - if (level >= LOG_LEVEL_WARNING) { - char *args_msg; - va_list args; - va_start(args, message); - if(vasprintf(&args_msg, message.c_str(), args) > 0) - all_log_line(LOG_LEVEL_WARNING, tti, file, line, args_msg); - va_end(args); - free(args_msg); - } -} - -void log_filter::info_line(std::string file, int line, std::string message, ...) -{ - if (level >= LOG_LEVEL_INFO) { - char *args_msg; - va_list args; - va_start(args, message); - if(vasprintf(&args_msg, message.c_str(), args) > 0) - all_log_line(LOG_LEVEL_INFO, tti, file, line, args_msg); - va_end(args); - free(args_msg); - } -} - -void log_filter::debug_line(std::string file, int line, std::string message, ...) -{ - if (level >= LOG_LEVEL_DEBUG) { - char *args_msg; - va_list args; - va_start(args, message); - if(vasprintf(&args_msg, message.c_str(), args) > 0) - all_log_line(LOG_LEVEL_DEBUG, tti, file, line, args_msg); - va_end(args); - free(args_msg); - } -} - void log_filter::set_time_src(time_itf *source, time_format_t format) { this->time_src = source; this->time_format = format; diff --git a/lib/src/common/pdu_queue.cc b/lib/src/common/pdu_queue.cc index 6b4c8bfd9..3a116e641 100644 --- a/lib/src/common/pdu_queue.cc +++ b/lib/src/common/pdu_queue.cc @@ -25,10 +25,10 @@ */ -#define Error(fmt, ...) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) log_h->debug(fmt, ##__VA_ARGS__) #include "srslte/common/pdu_queue.h" diff --git a/lib/src/phy/phch/dci.c b/lib/src/phy/phch/dci.c index 3ce4cd6ae..5274cc932 100644 --- a/lib/src/phy/phch/dci.c +++ b/lib/src/phy/phch/dci.c @@ -360,6 +360,71 @@ uint32_t dci_format2B_sizeof(uint32_t nof_prb, uint32_t nof_ports) { } +uint32_t srslte_dci_dl_info(char *info_str, uint32_t len, srslte_ra_dl_dci_t *dci_msg, srslte_dci_format_t format) +{ + int n = 0; + + switch(dci_msg->alloc_type) { + case SRSLTE_RA_ALLOC_TYPE0: + n += snprintf(&info_str[n], len-n, "ra_type0={rbg_mask=0x%x}, ", dci_msg->type0_alloc.rbg_bitmask); + break; + case SRSLTE_RA_ALLOC_TYPE1: + n += snprintf(&info_str[n], len-n, "ra_type1={vrb_mask=0x%x, rbg_subset=%d, shift=%d}, ", + dci_msg->type1_alloc.vrb_bitmask, dci_msg->type1_alloc.rbg_subset, dci_msg->type1_alloc.shift); + break; + case SRSLTE_RA_ALLOC_TYPE2: + n += snprintf(&info_str[n], len-n, "ra_type2={riv=0x%x, rb=(%d,%d), mode=%s", + dci_msg->type2_alloc.riv, + dci_msg->type2_alloc.RB_start, dci_msg->type2_alloc.RB_start+dci_msg->type2_alloc.L_crb-1, + dci_msg->type2_alloc.mode==SRSLTE_RA_TYPE2_LOC?"local":"dist"); + if (dci_msg->type2_alloc.mode==SRSLTE_RA_TYPE2_LOC) { + n += snprintf(&info_str[n], len-n, "ngap=%s, nprb1a=%d", + dci_msg->type2_alloc.n_gap==SRSLTE_RA_TYPE2_NG1?"ng1":"ng2", + dci_msg->type2_alloc.n_prb1a==SRSLTE_RA_TYPE2_NPRB1A_2?2:3); + } + n += snprintf(&info_str[n], len-n, "}, "); + break; + } + n += snprintf(&info_str[n], len-n, "pid=%d, ", dci_msg->harq_process); + + if (dci_msg->tb_en[0]) { + n += snprintf(&info_str[n], len-n, "CW0={mcs=%d, rv=%d, ndi=%d}, ", dci_msg->mcs_idx, dci_msg->rv_idx, dci_msg->ndi); + } + if (dci_msg->tb_en[1]) { + n += snprintf(&info_str[n], len-n, "CW1={mcs=%d, rv=%d, ndi=%d}, ", dci_msg->mcs_idx_1, dci_msg->rv_idx_1, dci_msg->ndi_1); + } + + if (format == SRSLTE_DCI_FORMAT1 || format == SRSLTE_DCI_FORMAT1A || format == SRSLTE_DCI_FORMAT1B) { + n += snprintf(&info_str[n], len-n, "tpc_pucch=%d, ", dci_msg->tpc_pucch); + } + if (format == SRSLTE_DCI_FORMAT2 || format == SRSLTE_DCI_FORMAT2A || format == SRSLTE_DCI_FORMAT2B) { + n += snprintf(&info_str[n], len-n, "tb_swap=%d, pinfo=%d", dci_msg->tb_cw_swap, dci_msg->pinfo); + } + return n; +} + +uint32_t srslte_dci_ul_info(char *info_str, uint32_t len, srslte_ra_ul_dci_t *dci_msg) +{ + int n = 0; + + n += snprintf(&info_str[n], len-n, "riv=0x%x, rb=(%d,%d), ", dci_msg->type2_alloc.riv, + dci_msg->type2_alloc.RB_start, dci_msg->type2_alloc.RB_start+dci_msg->type2_alloc.L_crb-1); + + switch(dci_msg->freq_hop_fl) { + case SRSLTE_RA_PUSCH_HOP_DISABLED: + n += snprintf(&info_str[n], len-n, "freq_hop=n/a, "); + break; + default: + n += snprintf(&info_str[n], len-n, "freq_hop=%d, ", dci_msg->freq_hop_fl); + break; + } + n += snprintf(&info_str[n], len-n, "mcs=%d, rv=%d, ndi=%d, ", dci_msg->mcs_idx, dci_msg->rv_idx, dci_msg->ndi); + n += snprintf(&info_str[n], len-n, "tpc_pusch=%d, dmrs_cs=%d, cqi_req=%s", + dci_msg->tpc_pusch, dci_msg->n_dmrs, dci_msg->cqi_request?"yes":"no"); + + return n; +} + uint32_t srslte_dci_format_sizeof(srslte_dci_format_t format, uint32_t nof_prb, uint32_t nof_ports) { switch (format) { case SRSLTE_DCI_FORMAT0: diff --git a/srsenb/src/mac/mac.cc b/srsenb/src/mac/mac.cc index 80c5e1ddf..4e706cfc7 100644 --- a/srsenb/src/mac/mac.cc +++ b/srsenb/src/mac/mac.cc @@ -24,10 +24,10 @@ * */ -#define Error(fmt, ...) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) log_h->debug(fmt, ##__VA_ARGS__) #include #include diff --git a/srsenb/src/mac/scheduler.cc b/srsenb/src/mac/scheduler.cc index 8d216bba0..5a0da1015 100644 --- a/srsenb/src/mac/scheduler.cc +++ b/srsenb/src/mac/scheduler.cc @@ -5,10 +5,10 @@ #include "srslte/common/pdu.h" #include "mac/scheduler.h" -#define Error(fmt, ...) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) log_h->debug(fmt, ##__VA_ARGS__) namespace srsenb { diff --git a/srsenb/src/mac/scheduler_harq.cc b/srsenb/src/mac/scheduler_harq.cc index 6c97e6f14..a10fb562f 100644 --- a/srsenb/src/mac/scheduler_harq.cc +++ b/srsenb/src/mac/scheduler_harq.cc @@ -30,10 +30,10 @@ #include "srslte/common/pdu.h" #include "mac/scheduler.h" -#define Error(fmt, ...) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) log_h->debug(fmt, ##__VA_ARGS__) namespace srsenb { diff --git a/srsenb/src/mac/scheduler_metric.cc b/srsenb/src/mac/scheduler_metric.cc index 4e03d396c..60a299c04 100644 --- a/srsenb/src/mac/scheduler_metric.cc +++ b/srsenb/src/mac/scheduler_metric.cc @@ -28,10 +28,10 @@ #include "mac/scheduler_harq.h" #include "mac/scheduler_metric.h" -#define Error(fmt, ...) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) log_h->debug(fmt, ##__VA_ARGS__) namespace srsenb { diff --git a/srsenb/src/mac/scheduler_ue.cc b/srsenb/src/mac/scheduler_ue.cc index 84c8f8760..5adee6e43 100644 --- a/srsenb/src/mac/scheduler_ue.cc +++ b/srsenb/src/mac/scheduler_ue.cc @@ -31,10 +31,10 @@ #include "mac/scheduler_ue.h" #include "mac/scheduler.h" -#define Error(fmt, ...) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) log_h->debug(fmt, ##__VA_ARGS__) /****************************************************** * UE class * diff --git a/srsenb/src/mac/ue.cc b/srsenb/src/mac/ue.cc index d41afaf73..03bf13e33 100644 --- a/srsenb/src/mac/ue.cc +++ b/srsenb/src/mac/ue.cc @@ -30,10 +30,10 @@ #include "srslte/interfaces/enb_interfaces.h" #include "mac/ue.h" -#define Error(fmt, ...) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) log_h->debug(fmt, ##__VA_ARGS__) namespace srsenb { diff --git a/srsenb/src/phy/phch_common.cc b/srsenb/src/phy/phch_common.cc index 87184321c..c732f76dc 100644 --- a/srsenb/src/phy/phch_common.cc +++ b/srsenb/src/phy/phch_common.cc @@ -31,10 +31,10 @@ #include -#define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug(fmt, ##__VA_ARGS__) using namespace std; diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index 7d8cbd570..790fa9542 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -31,10 +31,10 @@ #include "phy/phch_worker.h" -#define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug(fmt, ##__VA_ARGS__) using namespace std; diff --git a/srsenb/src/phy/phy.cc b/srsenb/src/phy/phy.cc index 4f8c5fb4d..7aa965291 100644 --- a/srsenb/src/phy/phy.cc +++ b/srsenb/src/phy/phy.cc @@ -36,10 +36,10 @@ #include "srslte/common/log.h" #include "phy/phy.h" -#define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug(fmt, ##__VA_ARGS__) using namespace std; diff --git a/srsenb/src/phy/txrx.cc b/srsenb/src/phy/txrx.cc index acedd36c3..396069b45 100644 --- a/srsenb/src/phy/txrx.cc +++ b/srsenb/src/phy/txrx.cc @@ -32,10 +32,10 @@ #include "phy/txrx.h" #include "phy/phch_worker.h" -#define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug(fmt, ##__VA_ARGS__) using namespace std; diff --git a/srsue/hdr/mac/dl_harq.h b/srsue/hdr/mac/dl_harq.h index 46c3fb0d0..9a7f66f47 100644 --- a/srsue/hdr/mac/dl_harq.h +++ b/srsue/hdr/mac/dl_harq.h @@ -27,10 +27,10 @@ #ifndef DL_HARQ_H #define DL_HARQ_H -#define Error(fmt, ...) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) log_h->debug(fmt, ##__VA_ARGS__) #include "srslte/common/log.h" #include "srslte/common/timers.h" diff --git a/srsue/hdr/mac/ul_harq.h b/srsue/hdr/mac/ul_harq.h index bd38fca97..5b33be1ec 100644 --- a/srsue/hdr/mac/ul_harq.h +++ b/srsue/hdr/mac/ul_harq.h @@ -27,10 +27,10 @@ #ifndef ULHARQ_H #define ULHARQ_H -#define Error(fmt, ...) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) log_h->debug(fmt, ##__VA_ARGS__) #include "srslte/interfaces/ue_interfaces.h" #include "srslte/common/log.h" diff --git a/srsue/src/mac/demux.cc b/srsue/src/mac/demux.cc index 171e7bf45..71be1ffc1 100644 --- a/srsue/src/mac/demux.cc +++ b/srsue/src/mac/demux.cc @@ -25,10 +25,10 @@ */ -#define Error(fmt, ...) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) log_h->debug(fmt, ##__VA_ARGS__) #include "mac/mac.h" #include "mac/demux.h" diff --git a/srsue/src/mac/mac.cc b/srsue/src/mac/mac.cc index 86b644b8d..daa82d1cb 100644 --- a/srsue/src/mac/mac.cc +++ b/srsue/src/mac/mac.cc @@ -24,10 +24,10 @@ * */ -#define Error(fmt, ...) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) log_h->debug(fmt, ##__VA_ARGS__) #include #include diff --git a/srsue/src/mac/mux.cc b/srsue/src/mac/mux.cc index e6e136d2e..ba2b45209 100644 --- a/srsue/src/mac/mux.cc +++ b/srsue/src/mac/mux.cc @@ -24,10 +24,10 @@ * */ -#define Error(fmt, ...) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) log_h->debug(fmt, ##__VA_ARGS__) #include "mac/mux.h" #include "mac/mac.h" diff --git a/srsue/src/mac/proc_bsr.cc b/srsue/src/mac/proc_bsr.cc index 43694c1bc..f68b6eee8 100644 --- a/srsue/src/mac/proc_bsr.cc +++ b/srsue/src/mac/proc_bsr.cc @@ -24,10 +24,10 @@ * */ -#define Error(fmt, ...) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) log_h->debug(fmt, ##__VA_ARGS__) #include "mac/proc_bsr.h" #include "mac/mac.h" diff --git a/srsue/src/mac/proc_phr.cc b/srsue/src/mac/proc_phr.cc index ead0bf153..54c1ec1ce 100644 --- a/srsue/src/mac/proc_phr.cc +++ b/srsue/src/mac/proc_phr.cc @@ -24,10 +24,10 @@ * */ -#define Error(fmt, ...) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) log_h->debug(fmt, ##__VA_ARGS__) #include "mac/proc_phr.h" #include "mac/mac.h" diff --git a/srsue/src/mac/proc_ra.cc b/srsue/src/mac/proc_ra.cc index 0a1855c80..d9a3e0d4d 100644 --- a/srsue/src/mac/proc_ra.cc +++ b/srsue/src/mac/proc_ra.cc @@ -24,10 +24,10 @@ * */ -#define Error(fmt, ...) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) log_h->debug(fmt, ##__VA_ARGS__) #include #include diff --git a/srsue/src/mac/proc_sr.cc b/srsue/src/mac/proc_sr.cc index afd2b7b5a..cb31a1c6d 100644 --- a/srsue/src/mac/proc_sr.cc +++ b/srsue/src/mac/proc_sr.cc @@ -24,10 +24,10 @@ * */ -#define Error(fmt, ...) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) log_h->debug(fmt, ##__VA_ARGS__) #include "mac/proc_sr.h" diff --git a/srsue/src/phy/phch_common.cc b/srsue/src/phy/phch_common.cc index 59db2f546..b9138100b 100644 --- a/srsue/src/phy/phch_common.cc +++ b/srsue/src/phy/phch_common.cc @@ -29,10 +29,10 @@ #include "srslte/srslte.h" #include "phy/phch_common.h" -#define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug(fmt, ##__VA_ARGS__) namespace srsue { diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index b75a37b2e..f653aba33 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -31,10 +31,10 @@ #include "phy/phch_worker.h" #include "phy/phch_recv.h" -#define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug(fmt, ##__VA_ARGS__) namespace srsue { diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 116507ddc..c2496dd53 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -31,10 +31,10 @@ #include "srslte/interfaces/ue_interfaces.h" #include "srslte/asn1/liblte_rrc.h" -#define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug(fmt, ##__VA_ARGS__) /* This is to visualize the channel response */ diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 689426b2a..d40129ff4 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -38,10 +38,10 @@ #include "srslte/common/log.h" #include "phy/phy.h" -#define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug(fmt, ##__VA_ARGS__) diff --git a/srsue/src/phy/prach.cc b/srsue/src/phy/prach.cc index 182a66aa7..498ea1c6a 100644 --- a/srsue/src/phy/prach.cc +++ b/srsue/src/phy/prach.cc @@ -34,10 +34,10 @@ #include "phy/phy.h" #include "srslte/interfaces/ue_interfaces.h" -#define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Error(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->error(fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->warning(fmt, ##__VA_ARGS__) +#define Info(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->info(fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) if (SRSLTE_DEBUG_ENABLED) log_h->debug(fmt, ##__VA_ARGS__) namespace srsue { From dfda8edc049b1abcacc45e985ff94103ba3f14ae Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 20 Dec 2017 10:01:57 +0100 Subject: [PATCH 223/242] Minor changes to log --- lib/include/srslte/common/log.h | 14 ++++++++++ lib/include/srslte/phy/phch/dci.h | 4 ++- lib/src/common/log_filter.cc | 20 +++++++++++--- lib/src/phy/phch/dci.c | 46 ++++++++++++++++++++++++------- 4 files changed, 69 insertions(+), 15 deletions(-) diff --git a/lib/include/srslte/common/log.h b/lib/include/srslte/common/log.h index 84278f9e6..6520b43da 100644 --- a/lib/include/srslte/common/log.h +++ b/lib/include/srslte/common/log.h @@ -54,6 +54,12 @@ static const char log_level_text[LOG_LEVEL_N_ITEMS][16] = {"None ", "Info ", "Debug "}; +static const char log_level_text_short[LOG_LEVEL_N_ITEMS][16] = {"[-]", + "[E]", + "[W]", + "[I]", + "[D]"}; + class log { public: @@ -100,6 +106,12 @@ public: int get_hex_limit() { return hex_limit; } + void set_log_level_short(bool enable) { + level_text_short = enable; + } + void show_layer(bool enable) { + show_layer_en = enable; + } // Pure virtual methods for logging virtual void console(std::string message, ...) = 0; @@ -121,6 +133,8 @@ protected: int hex_limit; std::string service_name; + bool show_layer_en; + bool level_text_short; bool add_string_en; std::string add_string_val; }; diff --git a/lib/include/srslte/phy/phch/dci.h b/lib/include/srslte/phy/phch/dci.h index 24a20e552..79a79c4df 100644 --- a/lib/include/srslte/phy/phch/dci.h +++ b/lib/include/srslte/phy/phch/dci.h @@ -137,7 +137,9 @@ SRSLTE_API srslte_dci_format_t srslte_dci_format_from_string(char *str); SRSLTE_API char* srslte_dci_format_string(srslte_dci_format_t format); -SRSLTE_API int srslte_dci_location_set(srslte_dci_location_t *c, +SRSLTE_API char* srslte_dci_format_string_short(srslte_dci_format_t format); + +SRSLTE_API int srslte_dci_location_set(srslte_dci_location_t *c, uint32_t L, uint32_t nCCE); diff --git a/lib/src/common/log_filter.cc b/lib/src/common/log_filter.cc index 4e2debb93..5879f49a8 100644 --- a/lib/src/common/log_filter.cc +++ b/lib/src/common/log_filter.cc @@ -67,8 +67,14 @@ void log_filter::all_log(srslte::LOG_LEVEL_ENUM level, std::stringstream ss; ss << now_time() << " "; - ss << "[" <alloc_type) { case SRSLTE_RA_ALLOC_TYPE0: - n += snprintf(&info_str[n], len-n, "ra_type0={rbg_mask=0x%x}, ", dci_msg->type0_alloc.rbg_bitmask); + n += snprintf(&info_str[n], len-n, "type0={rbg=0x%x}, ", dci_msg->type0_alloc.rbg_bitmask); break; case SRSLTE_RA_ALLOC_TYPE1: - n += snprintf(&info_str[n], len-n, "ra_type1={vrb_mask=0x%x, rbg_subset=%d, shift=%d}, ", + n += snprintf(&info_str[n], len-n, "type1={vrb=0x%x, rbg_s=%d, sh=%d}, ", dci_msg->type1_alloc.vrb_bitmask, dci_msg->type1_alloc.rbg_subset, dci_msg->type1_alloc.shift); break; case SRSLTE_RA_ALLOC_TYPE2: - n += snprintf(&info_str[n], len-n, "ra_type2={riv=0x%x, rb=(%d,%d), mode=%s", + n += snprintf(&info_str[n], len-n, "type2={riv=%d, rb=(%d,%d), mode=%s", dci_msg->type2_alloc.riv, dci_msg->type2_alloc.RB_start, dci_msg->type2_alloc.RB_start+dci_msg->type2_alloc.L_crb-1, dci_msg->type2_alloc.mode==SRSLTE_RA_TYPE2_LOC?"local":"dist"); @@ -388,17 +388,17 @@ uint32_t srslte_dci_dl_info(char *info_str, uint32_t len, srslte_ra_dl_dci_t *dc n += snprintf(&info_str[n], len-n, "pid=%d, ", dci_msg->harq_process); if (dci_msg->tb_en[0]) { - n += snprintf(&info_str[n], len-n, "CW0={mcs=%d, rv=%d, ndi=%d}, ", dci_msg->mcs_idx, dci_msg->rv_idx, dci_msg->ndi); + n += snprintf(&info_str[n], len-n, "TB0={mcs=%d, rv=%d, ndi=%d}, ", dci_msg->mcs_idx, dci_msg->rv_idx, dci_msg->ndi); } if (dci_msg->tb_en[1]) { - n += snprintf(&info_str[n], len-n, "CW1={mcs=%d, rv=%d, ndi=%d}, ", dci_msg->mcs_idx_1, dci_msg->rv_idx_1, dci_msg->ndi_1); + n += snprintf(&info_str[n], len-n, "TB1={mcs=%d, rv=%d, ndi=%d}, ", dci_msg->mcs_idx_1, dci_msg->rv_idx_1, dci_msg->ndi_1); } if (format == SRSLTE_DCI_FORMAT1 || format == SRSLTE_DCI_FORMAT1A || format == SRSLTE_DCI_FORMAT1B) { n += snprintf(&info_str[n], len-n, "tpc_pucch=%d, ", dci_msg->tpc_pucch); } if (format == SRSLTE_DCI_FORMAT2 || format == SRSLTE_DCI_FORMAT2A || format == SRSLTE_DCI_FORMAT2B) { - n += snprintf(&info_str[n], len-n, "tb_swap=%d, pinfo=%d", dci_msg->tb_cw_swap, dci_msg->pinfo); + n += snprintf(&info_str[n], len-n, "tb_sw=%d, pinfo=%d", dci_msg->tb_cw_swap, dci_msg->pinfo); } return n; } @@ -407,19 +407,19 @@ uint32_t srslte_dci_ul_info(char *info_str, uint32_t len, srslte_ra_ul_dci_t *dc { int n = 0; - n += snprintf(&info_str[n], len-n, "riv=0x%x, rb=(%d,%d), ", dci_msg->type2_alloc.riv, + n += snprintf(&info_str[n], len-n, "riv=%d, rb=(%d,%d), ", dci_msg->type2_alloc.riv, dci_msg->type2_alloc.RB_start, dci_msg->type2_alloc.RB_start+dci_msg->type2_alloc.L_crb-1); switch(dci_msg->freq_hop_fl) { case SRSLTE_RA_PUSCH_HOP_DISABLED: - n += snprintf(&info_str[n], len-n, "freq_hop=n/a, "); + n += snprintf(&info_str[n], len-n, "f_h=n/a, "); break; default: - n += snprintf(&info_str[n], len-n, "freq_hop=%d, ", dci_msg->freq_hop_fl); + n += snprintf(&info_str[n], len-n, "f_h=%d, ", dci_msg->freq_hop_fl); break; } n += snprintf(&info_str[n], len-n, "mcs=%d, rv=%d, ndi=%d, ", dci_msg->mcs_idx, dci_msg->rv_idx, dci_msg->ndi); - n += snprintf(&info_str[n], len-n, "tpc_pusch=%d, dmrs_cs=%d, cqi_req=%s", + n += snprintf(&info_str[n], len-n, "tpc_pusch=%d, dmrs_cs=%d, cqi=%s", dci_msg->tpc_pusch, dci_msg->n_dmrs, dci_msg->cqi_request?"yes":"no"); return n; @@ -1367,6 +1367,32 @@ char* srslte_dci_format_string(srslte_dci_format_t format) { } } + +char* srslte_dci_format_string_short(srslte_dci_format_t format) { + switch (format) { + case SRSLTE_DCI_FORMAT0: + return " 0"; + case SRSLTE_DCI_FORMAT1: + return " 1"; + case SRSLTE_DCI_FORMAT1A: + return "1A"; + case SRSLTE_DCI_FORMAT1B: + return "1B"; + case SRSLTE_DCI_FORMAT1C: + return "1C"; + case SRSLTE_DCI_FORMAT1D: + return "1D"; + case SRSLTE_DCI_FORMAT2: + return " 2"; + case SRSLTE_DCI_FORMAT2A: + return "2A"; + case SRSLTE_DCI_FORMAT2B: + return "2B"; + default: + return "N/A"; // fatal error + } +} + void srslte_dci_msg_type_fprint(FILE *f, srslte_dci_msg_type_t type) { switch (type.type) { case SRSLTE_DCI_MSG_TYPE_PUSCH_SCHED: From ba7d4ca3a4a4d917bc5a273a7f8a9db2bea02e21 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 20 Dec 2017 10:37:36 +0100 Subject: [PATCH 224/242] Added API to access port/ant chest values --- .../srslte/phy/ch_estimation/chest_dl.h | 18 ++++++++++++++- lib/src/phy/ch_estimation/chest_dl.c | 22 +++++++++++++++---- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/lib/include/srslte/phy/ch_estimation/chest_dl.h b/lib/include/srslte/phy/ch_estimation/chest_dl.h index 5bfc1d165..a7956fb10 100644 --- a/lib/include/srslte/phy/ch_estimation/chest_dl.h +++ b/lib/include/srslte/phy/ch_estimation/chest_dl.h @@ -157,16 +157,32 @@ SRSLTE_API void srslte_chest_dl_cfo_estimate_enable(srslte_chest_dl_t *q, SRSLTE_API void srslte_chest_dl_average_subframe(srslte_chest_dl_t *q, bool enable); -SRSLTE_API float srslte_chest_dl_get_noise_estimate(srslte_chest_dl_t *q); +SRSLTE_API float srslte_chest_dl_get_noise_estimate(srslte_chest_dl_t *q); + +SRSLTE_API float srslte_chest_dl_get_noise_estimate_ant_port(srslte_chest_dl_t *q, + uint32_t ant_idx, + uint32_t port_idx); SRSLTE_API float srslte_chest_dl_get_cfo(srslte_chest_dl_t *q); SRSLTE_API float srslte_chest_dl_get_snr(srslte_chest_dl_t *q); +SRSLTE_API float srslte_chest_dl_get_snr_ant_port(srslte_chest_dl_t *q, + uint32_t ant_idx, + uint32_t port_idx); + SRSLTE_API float srslte_chest_dl_get_rssi(srslte_chest_dl_t *q); SRSLTE_API float srslte_chest_dl_get_rsrq(srslte_chest_dl_t *q); +SRSLTE_API float srslte_chest_dl_get_rsrq_ant_port(srslte_chest_dl_t *q, + uint32_t ant_idx, + uint32_t port); + +SRSLTE_API float srslte_chest_dl_get_rsrp_ant_port(srslte_chest_dl_t *q, + uint32_t ant_idx, + uint32_t port); + SRSLTE_API float srslte_chest_dl_get_rsrp_port(srslte_chest_dl_t *q, uint32_t port); diff --git a/lib/src/phy/ch_estimation/chest_dl.c b/lib/src/phy/ch_estimation/chest_dl.c index 3814fb6fb..510f33a23 100644 --- a/lib/src/phy/ch_estimation/chest_dl.c +++ b/lib/src/phy/ch_estimation/chest_dl.c @@ -498,10 +498,7 @@ void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, ui uint32_t npilots = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id); float energy = cabsf(srslte_vec_acc_cc(q->pilot_estimates, npilots)/npilots); q->rsrp[rxant_id][port_id] = energy*energy; - if (port_id == 0) { - /* compute rssi only for port 0 */ - q->rssi[rxant_id][port_id] = srslte_chest_dl_rssi(q, input, port_id); - } + q->rssi[rxant_id][port_id] = srslte_chest_dl_rssi(q, input, port_id); } int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id, uint32_t rxant_id) @@ -599,6 +596,10 @@ float srslte_chest_dl_get_noise_estimate(srslte_chest_dl_t *q) { return n/q->last_nof_antennas; } +float srslte_chest_dl_get_noise_estimate_ant_port(srslte_chest_dl_t *q, uint32_t ant_idx, uint32_t port_idx) { + return q->noise_estimate[ant_idx][port_idx]; +} + float srslte_chest_dl_get_snr(srslte_chest_dl_t *q) { #ifdef FREQ_SEL_SNR int nref=SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, 0); @@ -608,6 +609,11 @@ float srslte_chest_dl_get_snr(srslte_chest_dl_t *q) { #endif } + +float srslte_chest_dl_get_snr_ant_port(srslte_chest_dl_t *q, uint32_t ant_idx, uint32_t port_idx) { + return srslte_chest_dl_get_rsrp_ant_port(q, ant_idx, port_idx)/srslte_chest_dl_get_noise_estimate_ant_port(q, ant_idx, port_idx); +} + float srslte_chest_dl_get_rssi(srslte_chest_dl_t *q) { float n = 0; for (int i=0;ilast_nof_antennas;i++) { @@ -628,6 +634,14 @@ float srslte_chest_dl_get_rsrq(srslte_chest_dl_t *q) { } +float srslte_chest_dl_get_rsrq_ant_port(srslte_chest_dl_t *q, uint32_t ant_idx, uint32_t port_idx) { + return q->cell.nof_prb*q->rsrp[ant_idx][port_idx] / q->rssi[ant_idx][port_idx]; +} + +float srslte_chest_dl_get_rsrp_ant_port(srslte_chest_dl_t *q, uint32_t ant_idx, uint32_t port) { + return q->rsrp[ant_idx][port]; +} + float srslte_chest_dl_get_rsrp_port(srslte_chest_dl_t *q, uint32_t port) { float n = 0; for (int i = 0; i < q->last_nof_antennas; i++) { From 821d5595c59660119a9bb0cd3f0351df3c5a6172 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 20 Dec 2017 12:35:28 +0100 Subject: [PATCH 225/242] Fixed AVX compilation --- lib/include/srslte/phy/utils/simd.h | 4 ++-- lib/src/phy/phch/dci.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/include/srslte/phy/utils/simd.h b/lib/include/srslte/phy/utils/simd.h index 226e2ecae..7ea203290 100644 --- a/lib/include/srslte/phy/utils/simd.h +++ b/lib/include/srslte/phy/utils/simd.h @@ -56,7 +56,7 @@ /* * AVX Macros */ -#ifdef LV_HAVE_AVX2 +#ifdef LV_HAVE_AVX #define _MM256_MULJ_PS(X) _mm256_permute_ps(_MM256_CONJ_PS(X), 0b10110001) #define _MM256_CONJ_PS(X) (_mm256_xor_ps(X, _mm256_set_ps(-0.0f, 0.0f, -0.0f, 0.0f, -0.0f, 0.0f, -0.0f, 0.0f))) @@ -72,7 +72,7 @@ #define _MM256_PROD_PS(a, b) _mm256_addsub_ps(_mm256_mul_ps(a,_mm256_moveldup_ps(b)),\ _mm256_mul_ps(_mm256_shuffle_ps(a,a,0xB1),_mm256_movehdup_ps(b))) #endif /* LV_HAVE_FMA */ -#endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX */ /* diff --git a/lib/src/phy/phch/dci.c b/lib/src/phy/phch/dci.c index 106c061d6..806713e9f 100644 --- a/lib/src/phy/phch/dci.c +++ b/lib/src/phy/phch/dci.c @@ -1371,9 +1371,9 @@ char* srslte_dci_format_string(srslte_dci_format_t format) { char* srslte_dci_format_string_short(srslte_dci_format_t format) { switch (format) { case SRSLTE_DCI_FORMAT0: - return " 0"; + return "0"; case SRSLTE_DCI_FORMAT1: - return " 1"; + return "1"; case SRSLTE_DCI_FORMAT1A: return "1A"; case SRSLTE_DCI_FORMAT1B: @@ -1383,7 +1383,7 @@ char* srslte_dci_format_string_short(srslte_dci_format_t format) { case SRSLTE_DCI_FORMAT1D: return "1D"; case SRSLTE_DCI_FORMAT2: - return " 2"; + return "2"; case SRSLTE_DCI_FORMAT2A: return "2A"; case SRSLTE_DCI_FORMAT2B: From 33c35d575d5df2f76f6242b6993db555ecaf4c62 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 20 Dec 2017 13:47:49 +0100 Subject: [PATCH 226/242] Save last PHICH correlation --- lib/include/srslte/phy/ue/ue_dl.h | 4 +++- lib/src/phy/ue/ue_dl.c | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/include/srslte/phy/ue/ue_dl.h b/lib/include/srslte/phy/ue/ue_dl.h index 02341c08d..6974a0b99 100644 --- a/lib/include/srslte/phy/ue/ue_dl.h +++ b/lib/include/srslte/phy/ue/ue_dl.h @@ -126,7 +126,9 @@ typedef struct SRSLTE_API { srslte_dci_msg_t pending_ul_dci_msg; uint16_t pending_ul_dci_rnti; - float sample_offset; + float sample_offset; + + float last_phich_corr; }srslte_ue_dl_t; /* This function shall be called just after the initial synchronization */ diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index 4183016e0..348d0bdb6 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -973,6 +973,7 @@ bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t n_pr srslte_phich_ngroups(&q->phich), srslte_phich_nsf(&q->phich)); if (!srslte_phich_decode(&q->phich, q->sf_symbols_m, q->ce_m, 0, ngroup, nseq, sf_idx, &ack_bit, &distance)) { + q->last_phich_corr = distance; INFO("Decoded PHICH %d with distance %f\n", ack_bit, distance); } else { fprintf(stderr, "Error decoding PHICH\n"); From 968a503d93efb0578dea922b49fc0080e1a4b663 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 20 Dec 2017 14:12:20 +0100 Subject: [PATCH 227/242] Fixed segfault in metrics hub --- lib/include/srslte/common/metrics_hub.h | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/include/srslte/common/metrics_hub.h b/lib/include/srslte/common/metrics_hub.h index a9b77d5f6..ca6d0beac 100644 --- a/lib/include/srslte/common/metrics_hub.h +++ b/lib/include/srslte/common/metrics_hub.h @@ -54,7 +54,6 @@ private: void run_period() { if (m) { metrics_t metric; - bzero(&metric, sizeof(metrics_t)); m->get_metrics(metric); for (uint32_t i=0;iset_metrics(metric); From 23afd44a7dfedc130e2e745a21a884dd4bb78700 Mon Sep 17 00:00:00 2001 From: yagoda Date: Wed, 20 Dec 2017 14:57:22 +0000 Subject: [PATCH 228/242] modifications to enable phy lib logging --- lib/examples/pdsch_enodeb.c | 2 +- lib/examples/pdsch_ue.c | 2 +- lib/include/srslte/common/log.h | 4 +-- lib/include/srslte/phy/utils/debug.h | 12 ++++----- lib/src/phy/utils/debug.c | 2 +- srsue/hdr/phy/phch_recv.h | 5 ++-- srsue/hdr/phy/phch_worker.h | 3 ++- srsue/hdr/phy/phy.h | 3 ++- srsue/hdr/ue_base.h | 1 + srsue/src/main.cc | 4 +++ srsue/src/phy/phch_recv.cc | 30 ++++----------------- srsue/src/phy/phch_worker.cc | 8 +++++- srsue/src/phy/phy.cc | 39 +++++++++++++++++++++++++--- srsue/src/ue.cc | 12 ++++++++- srsue/ue.conf.example | 1 + 15 files changed, 82 insertions(+), 46 deletions(-) diff --git a/lib/examples/pdsch_enodeb.c b/lib/examples/pdsch_enodeb.c index 60d9c581f..dafff03b9 100644 --- a/lib/examples/pdsch_enodeb.c +++ b/lib/examples/pdsch_enodeb.c @@ -700,7 +700,7 @@ int main(int argc, char **argv) { uint32_t sfn; srslte_refsignal_t csr_refs; srslte_refsignal_t mbsfn_refs; - srslte_is_example = 1; + srslte_debug_handle_crash(argc, argv); #ifdef DISABLE_RF diff --git a/lib/examples/pdsch_ue.c b/lib/examples/pdsch_ue.c index 20f5151c3..2b267efde 100644 --- a/lib/examples/pdsch_ue.c +++ b/lib/examples/pdsch_ue.c @@ -352,7 +352,7 @@ int main(int argc, char **argv) { uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; int sfn_offset; float cfo = 0; - srslte_is_example = 1; + srslte_debug_handle_crash(argc, argv); parse_args(&prog_args, argc, argv); diff --git a/lib/include/srslte/common/log.h b/lib/include/srslte/common/log.h index 9bec779df..6508376e5 100644 --- a/lib/include/srslte/common/log.h +++ b/lib/include/srslte/common/log.h @@ -112,9 +112,9 @@ public: virtual void warning_line(std::string file, int line, std::string message, ...){error("warning_line not implemented.\n");} virtual void info_line(std::string file, int line, std::string message, ...){error("info_line not implemented.\n");} virtual void debug_line(std::string file, int line, std::string message, ...){error("debug_line not implemented.\n");} - -protected: std::string get_service_name() { return service_name; } +protected: + uint32_t tti; LOG_LEVEL_ENUM level; int hex_limit; diff --git a/lib/include/srslte/phy/utils/debug.h b/lib/include/srslte/phy/utils/debug.h index ec7fbbba1..ec4dc220c 100644 --- a/lib/include/srslte/phy/utils/debug.h +++ b/lib/include/srslte/phy/utils/debug.h @@ -48,7 +48,7 @@ SRSLTE_API void get_time_interval(struct timeval * tdata); #define SRSLTE_DEBUG_ENABLED 1 SRSLTE_API extern int srslte_verbose; -SRSLTE_API extern int srslte_is_example; +SRSLTE_API extern int handler_registered; #define SRSLTE_VERBOSE_ISINFO() (srslte_verbose>=SRSLTE_VERBOSE_INFO) #define SRSLTE_VERBOSE_ISDEBUG() (srslte_verbose>=SRSLTE_VERBOSE_DEBUG) @@ -58,21 +58,21 @@ SRSLTE_API extern int srslte_is_example; #define PRINT_INFO srslte_verbose=SRSLTE_VERBOSE_INFO #define PRINT_NONE srslte_verbose=SRSLTE_VERBOSE_NONE -#define DEBUG(_fmt, ...) if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && srslte_is_example)\ +#define DEBUG(_fmt, ...) if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered)\ { fprintf(stdout, "[DEBUG]: " _fmt, ##__VA_ARGS__); }\ - else{ srslte_phy_log_print(LOG_LEVEL_DEBUG, _fmt, ##__VA_ARGS__); } + else{ srslte_phy_log_print(LOG_LEVEL_DEBUG, _fmt, ##__VA_ARGS__); } -#define INFO(_fmt, ...) if (SRSLTE_DEBUG_ENABLED && ((srslte_verbose >= SRSLTE_VERBOSE_INFO)) && srslte_is_example)\ +#define INFO(_fmt, ...) if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO && !handler_registered) \ { fprintf(stdout, "[INFO]: " _fmt, ##__VA_ARGS__); }\ else{ srslte_phy_log_print(LOG_LEVEL_INFO, _fmt, ##__VA_ARGS__); } #if CMAKE_BUILD_TYPE==Debug /* In debug mode, it prints out the */ -#define ERROR(_fmt, ...) if (srslte_is_example)\ +#define ERROR(_fmt, ...) if (!handler_registered)\ { fprintf(stderr, "\e[31m%s.%d: " _fmt "\e[0m\n", __FILE__, __LINE__, ##__VA_ARGS__);}\ else {srslte_phy_log_print(LOG_LEVEL_ERROR, _fmt, ##__VA_ARGS__);} // #else -#define ERROR(_fmt, ...) if (srslte_is_example)\ +#define ERROR(_fmt, ...) if (!handler_registered)\ { fprintf(stderr, "[ERROR in %s]:" _fmt "\n", __FUNCTION__, ##__VA_ARGS__);}\ else{srslte_phy_log_print(LOG_LEVEL_ERROR, _fmt, ##__VA_ARGS__);} // #endif /* CMAKE_BUILD_TYPE==Debug */ diff --git a/lib/src/phy/utils/debug.c b/lib/src/phy/utils/debug.c index 59f55c0a8..4b65e8d6d 100644 --- a/lib/src/phy/utils/debug.c +++ b/lib/src/phy/utils/debug.c @@ -34,7 +34,7 @@ #include "srslte/version.h" int srslte_verbose = 0; -int srslte_is_example = 0; +int handler_registered = 0; void get_time_interval(struct timeval * tdata) { diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index d42966634..ed4bd706a 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -52,13 +52,13 @@ public: ~phch_recv(); void init(srslte::radio_multi* radio_handler, mac_interface_phy *mac,rrc_interface_phy *rrc, prach *prach_buffer, srslte::thread_pool *_workers_pool, - phch_common *_worker_com, srslte::log* _log_h, uint32_t nof_rx_antennas, uint32_t prio, int sync_cpu_affinity = -1); + phch_common *_worker_com, srslte::log* _log_h, srslte::log *_log_phy_lib_h, uint32_t nof_rx_antennas, uint32_t prio, int sync_cpu_affinity = -1); void stop(); void set_agc_enable(bool enable); void set_earfcn(std::vector earfcn); void force_freq(float dl_freq, float ul_freq); - void srslte_phy_logger(phy_logger_level_t log_level, char *str); + void reset_sync(); void cell_search_start(); void cell_search_stop(); @@ -275,6 +275,7 @@ private: mac_interface_phy *mac; rrc_interface_phy *rrc; srslte::log *log_h; + srslte::log *log_phy_lib_h; srslte::thread_pool *workers_pool; srslte::radio_multi *radio_h; phch_common *worker_com; diff --git a/srsue/hdr/phy/phch_worker.h b/srsue/hdr/phy/phch_worker.h index a63f84b4a..e1d943880 100644 --- a/srsue/hdr/phy/phch_worker.h +++ b/srsue/hdr/phy/phch_worker.h @@ -45,7 +45,7 @@ public: ~phch_worker(); void reset(); void set_common(phch_common *phy); - bool init(uint32_t max_prb, srslte::log *log, chest_feedback_itf *chest_loop); + bool init(uint32_t max_prb, srslte::log *log, srslte::log *log_phy_lib_h, chest_feedback_itf *chest_loop); bool set_cell(srslte_cell_t cell); @@ -117,6 +117,7 @@ private: /* Common objects */ phch_common *phy; srslte::log *log_h; + srslte::log *log_phy_lib_h; chest_feedback_itf *chest_loop; srslte_cell_t cell; bool mem_initiated; diff --git a/srsue/hdr/phy/phy.h b/srsue/hdr/phy/phy.h index adc2abdca..5a1ac14a7 100644 --- a/srsue/hdr/phy/phy.h +++ b/srsue/hdr/phy/phy.h @@ -64,7 +64,7 @@ public: void set_agc_enable(bool enabled); void get_metrics(phy_metrics_t &m); - + void srslte_phy_logger(phy_logger_level_t log_level, char *str); static uint32_t tti_to_SFN(uint32_t tti); @@ -160,6 +160,7 @@ private: srslte::radio_multi *radio_handler; std::vector log_vec; srslte::log *log_h; + srslte::log *log_phy_lib_h; srsue::mac_interface_phy *mac; srsue::rrc_interface_phy *rrc; diff --git a/srsue/hdr/ue_base.h b/srsue/hdr/ue_base.h index 8e5ce22a9..0b28dfeb6 100644 --- a/srsue/hdr/ue_base.h +++ b/srsue/hdr/ue_base.h @@ -81,6 +81,7 @@ typedef struct { typedef struct { std::string phy_level; + std::string phy_lib_level; std::string mac_level; std::string rlc_level; std::string pdcp_level; diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 7a117dd6b..e716866eb 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -98,6 +98,7 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { ("gui.enable", bpo::value(&args->gui.enable)->default_value(false), "Enable GUI plots") ("log.phy_level", bpo::value(&args->log.phy_level), "PHY log level") + ("log.phy_lib_level", bpo::value(&args->log.phy_lib_level), "PHY lib log level") ("log.phy_hex_limit", bpo::value(&args->log.phy_hex_limit), "PHY log hex dump limit") ("log.mac_level", bpo::value(&args->log.mac_level), "MAC log level") ("log.mac_hex_limit", bpo::value(&args->log.mac_hex_limit), "MAC log hex dump limit") @@ -327,6 +328,9 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { if (!vm.count("log.phy_level")) { args->log.phy_level = args->log.all_level; } + if (!vm.count("log.phy_lib_level")) { + args->log.phy_lib_level = args->log.all_level; + } if (!vm.count("log.mac_level")) { args->log.mac_level = args->log.all_level; } diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 5db5ce65a..a974d9ed3 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -46,30 +46,7 @@ double callback_set_rx_gain(void *h, double gain) { return ((phch_recv*) h)->set_rx_gain(gain); } -static void srslte_phy_handler(phy_logger_level_t log_level, void *ctx, char *str) { - phch_recv *r = (phch_recv *) ctx; - r->srslte_phy_logger(log_level, str); -} -void phch_recv::srslte_phy_logger(phy_logger_level_t log_level, char *str) { - if (log_h) { - switch(log_level){ - case LOG_LEVEL_INFO: - log_h->info("[PHY_LAYER]: %s", str); - break; - case LOG_LEVEL_DEBUG: - log_h->debug("[PHY_LAYER]: %s", str); - break; - case LOG_LEVEL_ERROR: - log_h->error("[PHY_LAYER]: %s", str); - break; - default: - break; - } - } else { - printf("[PHY_LAYER]: %s\n", str); - } -} phch_recv::phch_recv() { dl_freq = -1; @@ -81,11 +58,12 @@ phch_recv::phch_recv() { void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_mac, rrc_interface_phy *_rrc, prach *_prach_buffer, srslte::thread_pool *_workers_pool, - phch_common *_worker_com, srslte::log *_log_h, uint32_t nof_rx_antennas_, uint32_t prio, + phch_common *_worker_com, srslte::log *_log_h, srslte::log *_log_phy_lib_h, uint32_t nof_rx_antennas_, uint32_t prio, int sync_cpu_affinity) { radio_h = _radio_handler; log_h = _log_h; + log_phy_lib_h = _log_phy_lib_h; mac = _mac; rrc = _rrc; workers_pool = _workers_pool; @@ -118,7 +96,7 @@ void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_ma intra_freq_meas.init(worker_com, rrc, log_h); reset(); - srslte_phy_log_register_handler(this, srslte_phy_handler); + // Start main thread if (sync_cpu_affinity < 0) { start(prio); @@ -585,6 +563,8 @@ void phch_recv::run_thread() } log_h->step(tti); + log_phy_lib_h->step(tti); + sf_idx = tti%10; switch (phy_state) { diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 116507ddc..e196d58e1 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -107,9 +107,10 @@ void phch_worker::set_common(phch_common* phy_) phy = phy_; } -bool phch_worker::init(uint32_t max_prb, srslte::log *log_h, chest_feedback_itf *chest_loop) +bool phch_worker::init(uint32_t max_prb, srslte::log *log_h, srslte::log *log_phy_lib_h , chest_feedback_itf *chest_loop) { this->log_h = log_h; + this->log_phy_lib_h = log_phy_lib_h; this->chest_loop = chest_loop; // ue_sync in phy.cc requires a buffer for 3 subframes @@ -173,6 +174,11 @@ void phch_worker::set_tti(uint32_t tti_, uint32_t tx_tti_) tti = tti_; tx_tti = tx_tti_; log_h->step(tti); + printf("tti\n"); + printf("out : %s", log_phy_lib_h->get_service_name()); + log_phy_lib_h->step(tti); + + } void phch_worker::set_cfo(float cfo_) diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 689426b2a..4a8f99d44 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -56,6 +56,31 @@ phy::phy() : workers_pool(MAX_WORKERS), { } +static void srslte_phy_handler(phy_logger_level_t log_level, void *ctx, char *str) { + phy *r = (phy *) ctx; + r->srslte_phy_logger(log_level, str); +} + +void phy::srslte_phy_logger(phy_logger_level_t log_level, char *str) { + if (log_phy_lib_h) { + switch(log_level){ + case LOG_LEVEL_INFO: + log_phy_lib_h->info(" %s", str); + break; + case LOG_LEVEL_DEBUG: + log_phy_lib_h->debug(" %s", str); + break; + case LOG_LEVEL_ERROR: + log_phy_lib_h->error(" %s", str); + break; + default: + break; + } + } else { + printf("[PHY_LIB]: %s\n", str); + } +} + void phy::set_default_args(phy_args_t *args) { args->nof_rx_ant = 1; @@ -105,7 +130,9 @@ bool phy::init(srslte::radio_multi* radio_handler, mac_interface_phy *mac, rrc_i this->radio_handler = radio_handler; this->mac = mac; this->rrc = rrc; - + + + if (!phy_args) { args = &default_args; set_default_args(args); @@ -118,7 +145,11 @@ bool phy::init(srslte::radio_multi* radio_handler, mac_interface_phy *mac, rrc_i } nof_workers = args->nof_phy_threads; - + + this->log_phy_lib_h = (srslte::log*) log_vec[nof_workers]; + srslte_phy_log_register_handler(this, srslte_phy_handler); + + initiated = false; start(); return true; @@ -133,12 +164,12 @@ void phy::run_thread() { // Add workers to workers pool and start threads for (uint32_t i=0;iworker_cpu_mask); } // Warning this must be initialized after all workers have been added to the pool - sf_recv.init(radio_handler, mac, rrc, &prach_buffer, &workers_pool, &workers_common, log_h, args->nof_rx_ant, SF_RECV_THREAD_PRIO, args->sync_cpu_affinity); + sf_recv.init(radio_handler, mac, rrc, &prach_buffer, &workers_pool, &workers_common, log_h, log_phy_lib_h, args->nof_rx_ant, SF_RECV_THREAD_PRIO, args->sync_cpu_affinity); // Disable UL signal pregeneration until the attachment enable_pregen_signals(false); diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index 2edf0fed5..8f10a5bfc 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -84,6 +84,16 @@ bool ue::init(all_args_t *args_) for (int i=0;iexpert.phy.nof_phy_threads;i++) { ((srslte::log_filter*) phy_log[i])->set_level(level(args->log.phy_level)); } + + /* here we add a log layer to handle logging from the phy library*/ + srslte::log_filter *lib_log = new srslte::log_filter; + char tmp[16]; + sprintf(tmp, "PHY_LIB"); + lib_log->init(tmp, logger, true); + phy_log.push_back((void*) lib_log); + ((srslte::log_filter*) phy_log[args->expert.phy.nof_phy_threads])->set_level(level(args->log.phy_lib_level)); + + mac_log.set_level(level(args->log.mac_level)); rlc_log.set_level(level(args->log.rlc_level)); pdcp_log.set_level(level(args->log.pdcp_level)); @@ -92,7 +102,7 @@ bool ue::init(all_args_t *args_) gw_log.set_level(level(args->log.gw_level)); usim_log.set_level(level(args->log.usim_level)); - for (int i=0;iexpert.phy.nof_phy_threads;i++) { + for (int i=0;iexpert.phy.nof_phy_threads + 1;i++) { ((srslte::log_filter*) phy_log[i])->set_hex_limit(args->log.phy_hex_limit); } mac_log.set_hex_limit(args->log.mac_hex_limit); diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index 17e133bb9..7c096a268 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -73,6 +73,7 @@ nas_filename = /tmp/nas.pcap ##################################################################### [log] all_level = info +phy_lib_level = none all_hex_limit = 32 filename = /tmp/ue.log From 318afbd8b4f933f026764172ee2d295aa72468bf Mon Sep 17 00:00:00 2001 From: yagoda Date: Wed, 20 Dec 2017 15:07:00 +0000 Subject: [PATCH 229/242] minor fixes to phy logging --- lib/include/srslte/common/log.h | 4 ++-- lib/src/phy/common/phy_logger.c | 2 ++ srsue/src/phy/phch_worker.cc | 2 -- srsue/src/phy/phy.cc | 6 +----- 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/lib/include/srslte/common/log.h b/lib/include/srslte/common/log.h index 6508376e5..d4169f3e5 100644 --- a/lib/include/srslte/common/log.h +++ b/lib/include/srslte/common/log.h @@ -112,9 +112,9 @@ public: virtual void warning_line(std::string file, int line, std::string message, ...){error("warning_line not implemented.\n");} virtual void info_line(std::string file, int line, std::string message, ...){error("info_line not implemented.\n");} virtual void debug_line(std::string file, int line, std::string message, ...){error("debug_line not implemented.\n");} - std::string get_service_name() { return service_name; } -protected: +protected: + std::string get_service_name() { return service_name; } uint32_t tti; LOG_LEVEL_ENUM level; int hex_limit; diff --git a/lib/src/phy/common/phy_logger.c b/lib/src/phy/common/phy_logger.c index a2597961e..09393236a 100644 --- a/lib/src/phy/common/phy_logger.c +++ b/lib/src/phy/common/phy_logger.c @@ -31,6 +31,7 @@ #include #include #include +#include "srslte/srslte.h" #include "srslte/phy/common/phy_logger.h" /********************************************************************* Functions for external logging @@ -41,6 +42,7 @@ static void *callback_ctx = NULL; void srslte_phy_log_register_handler(void *ctx, phy_log_handler_t handler) { phy_log_handler = handler; callback_ctx = ctx; + handler_registered++; } void srslte_phy_log_print(phy_logger_level_t log_level, const char *format, ...) { diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index e196d58e1..cb2d68098 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -174,8 +174,6 @@ void phch_worker::set_tti(uint32_t tti_, uint32_t tx_tti_) tti = tti_; tx_tti = tx_tti_; log_h->step(tti); - printf("tti\n"); - printf("out : %s", log_phy_lib_h->get_service_name()); log_phy_lib_h->step(tti); diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 4a8f99d44..da46982a2 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -130,9 +130,7 @@ bool phy::init(srslte::radio_multi* radio_handler, mac_interface_phy *mac, rrc_i this->radio_handler = radio_handler; this->mac = mac; this->rrc = rrc; - - - + if (!phy_args) { args = &default_args; set_default_args(args); @@ -145,11 +143,9 @@ bool phy::init(srslte::radio_multi* radio_handler, mac_interface_phy *mac, rrc_i } nof_workers = args->nof_phy_threads; - this->log_phy_lib_h = (srslte::log*) log_vec[nof_workers]; srslte_phy_log_register_handler(this, srslte_phy_handler); - initiated = false; start(); return true; From c6ab02f3f45aae961ec7315895a183ad609b6cd9 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 21 Dec 2017 11:26:05 +0100 Subject: [PATCH 230/242] Minor changes to logging --- lib/include/srslte/common/log.h | 2 ++ lib/src/phy/phch/dci.c | 2 +- srsue/src/phy/phch_recv.cc | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/include/srslte/common/log.h b/lib/include/srslte/common/log.h index 6520b43da..71f47d197 100644 --- a/lib/include/srslte/common/log.h +++ b/lib/include/srslte/common/log.h @@ -69,6 +69,7 @@ public: tti = 0; level = LOG_LEVEL_NONE; hex_limit = 0; + show_layer_en = true; } log(std::string service_name_) { @@ -76,6 +77,7 @@ public: tti = 0; level = LOG_LEVEL_NONE; hex_limit = 0; + show_layer_en = true; } // This function shall be called at the start of every tti for printing tti diff --git a/lib/src/phy/phch/dci.c b/lib/src/phy/phch/dci.c index 806713e9f..97ea9a40b 100644 --- a/lib/src/phy/phch/dci.c +++ b/lib/src/phy/phch/dci.c @@ -378,7 +378,7 @@ uint32_t srslte_dci_dl_info(char *info_str, uint32_t len, srslte_ra_dl_dci_t *dc dci_msg->type2_alloc.RB_start, dci_msg->type2_alloc.RB_start+dci_msg->type2_alloc.L_crb-1, dci_msg->type2_alloc.mode==SRSLTE_RA_TYPE2_LOC?"local":"dist"); if (dci_msg->type2_alloc.mode==SRSLTE_RA_TYPE2_LOC) { - n += snprintf(&info_str[n], len-n, "ngap=%s, nprb1a=%d", + n += snprintf(&info_str[n], len-n, ", ngap=%s, nprb1a=%d", dci_msg->type2_alloc.n_gap==SRSLTE_RA_TYPE2_NG1?"ng1":"ng2", dci_msg->type2_alloc.n_prb1a==SRSLTE_RA_TYPE2_NPRB1A_2?2:3); } diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index f653aba33..03adc67ff 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -647,7 +647,7 @@ void phch_recv::run_thread() case 1: if (last_worker) { - Warning("SF: cfo_tot=%7.1f Hz, ref=%f Hz, pss=%f Hz\n", + Debug("SF: cfo_tot=%7.1f Hz, ref=%f Hz, pss=%f Hz\n", srslte_ue_sync_get_cfo(&ue_sync), 15000*last_worker->get_ref_cfo(), 15000*ue_sync.strack.cfo_pss_mean); From 143bec18e3018fef5f0538b02cb05792d7621b52 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 21 Dec 2017 11:40:57 +0100 Subject: [PATCH 231/242] fixed compilation --- lib/src/phy/ch_estimation/test/CMakeLists.txt | 4 ++-- lib/src/phy/phch/pdsch.c | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/src/phy/ch_estimation/test/CMakeLists.txt b/lib/src/phy/ch_estimation/test/CMakeLists.txt index 8e1208ef5..c02c39043 100644 --- a/lib/src/phy/ch_estimation/test/CMakeLists.txt +++ b/lib/src/phy/ch_estimation/test/CMakeLists.txt @@ -39,10 +39,10 @@ add_test(chest_test_dl_cellid2 chest_test_dl -c 2 -r 50) ######################################################################## add_executable(chest_test_ul chest_test_ul.c) -target_link_libraries(chest_test_ul srslte_phy) +target_link_libraries(chest_test_ul srslte_phy srslte_common) add_executable(refsignal_ul_test_all refsignal_ul_test.c) -target_link_libraries(refsignal_ul_test_all srslte_phy) +target_link_libraries(refsignal_ul_test_all srslte_phy srslte_common) add_test(chest_test_ul_cellid0 chest_test_ul -c 0 -r 50) add_test(chest_test_ul_cellid1 chest_test_ul -c 1 -r 50) diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index 07249fb54..70ef9d008 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -702,6 +702,7 @@ int srslte_pdsch_decode(srslte_pdsch_t *q, // Pre-decoder if (srslte_predecoding_type(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, pdsch_scaling, noise_estimate)<0) { + printf("Error predecoding\n"); return -1; } From a08c6620286729fb2fb4f68c5d9071fc714f01af Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 29 Dec 2017 00:23:53 +0100 Subject: [PATCH 232/242] Per-antenna SNR --- lib/include/srslte/phy/ch_estimation/chest_dl.h | 4 ---- lib/src/phy/ch_estimation/chest_dl.c | 14 ++++++++------ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/lib/include/srslte/phy/ch_estimation/chest_dl.h b/lib/include/srslte/phy/ch_estimation/chest_dl.h index a7956fb10..0bd6e9afe 100644 --- a/lib/include/srslte/phy/ch_estimation/chest_dl.h +++ b/lib/include/srslte/phy/ch_estimation/chest_dl.h @@ -159,10 +159,6 @@ SRSLTE_API void srslte_chest_dl_average_subframe(srslte_chest_dl_t *q, SRSLTE_API float srslte_chest_dl_get_noise_estimate(srslte_chest_dl_t *q); -SRSLTE_API float srslte_chest_dl_get_noise_estimate_ant_port(srslte_chest_dl_t *q, - uint32_t ant_idx, - uint32_t port_idx); - SRSLTE_API float srslte_chest_dl_get_cfo(srslte_chest_dl_t *q); SRSLTE_API float srslte_chest_dl_get_snr(srslte_chest_dl_t *q); diff --git a/lib/src/phy/ch_estimation/chest_dl.c b/lib/src/phy/ch_estimation/chest_dl.c index 510f33a23..113870cc9 100644 --- a/lib/src/phy/ch_estimation/chest_dl.c +++ b/lib/src/phy/ch_estimation/chest_dl.c @@ -596,22 +596,24 @@ float srslte_chest_dl_get_noise_estimate(srslte_chest_dl_t *q) { return n/q->last_nof_antennas; } -float srslte_chest_dl_get_noise_estimate_ant_port(srslte_chest_dl_t *q, uint32_t ant_idx, uint32_t port_idx) { - return q->noise_estimate[ant_idx][port_idx]; -} - float srslte_chest_dl_get_snr(srslte_chest_dl_t *q) { #ifdef FREQ_SEL_SNR int nref=SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, 0); return srslte_vec_acc_ff(q->snr_vector, nref)/nref; #else - return srslte_chest_dl_get_rsrp(q)/srslte_chest_dl_get_noise_estimate(q); + float rsrp = 0; + for (int i=0;ilast_nof_antennas;i++) { + for (int j=0;jcell.nof_ports;j++) { + rsrp += q->rsrp[i][j]/q->cell.nof_ports; + } + } + return rsrp/srslte_chest_dl_get_noise_estimate(q); #endif } float srslte_chest_dl_get_snr_ant_port(srslte_chest_dl_t *q, uint32_t ant_idx, uint32_t port_idx) { - return srslte_chest_dl_get_rsrp_ant_port(q, ant_idx, port_idx)/srslte_chest_dl_get_noise_estimate_ant_port(q, ant_idx, port_idx); + return srslte_chest_dl_get_rsrp_ant_port(q, ant_idx, port_idx)/srslte_chest_dl_get_noise_estimate(q); } float srslte_chest_dl_get_rssi(srslte_chest_dl_t *q) { From e867184aa34801862fa05dde749abb26de0f907c Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 29 Dec 2017 00:25:08 +0100 Subject: [PATCH 233/242] Default sched policy for prio=-2 threads --- lib/src/common/threads.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/src/common/threads.c b/lib/src/common/threads.c index ec730d5de..0533aa1b6 100644 --- a/lib/src/common/threads.c +++ b/lib/src/common/threads.c @@ -51,6 +51,8 @@ bool threads_new_rt_cpu(pthread_t *thread, void *(*start_routine) (void*), void pthread_attr_t attr; struct sched_param param; cpu_set_t cpuset; + bool attr_enable = false; + if (prio_offset >= 0) { param.sched_priority = sched_get_priority_max(SCHED_FIFO) - prio_offset; pthread_attr_init(&attr); @@ -64,6 +66,21 @@ bool threads_new_rt_cpu(pthread_t *thread, void *(*start_routine) (void*), void perror("pthread_attr_setschedparam"); fprintf(stderr, "Error not enough privileges to set Scheduling priority\n"); } + attr_enable = true; + } else if (prio_offset == -2) { + param.sched_priority = 0; + pthread_attr_init(&attr); + if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED)) { + perror("pthread_attr_setinheritsched"); + } + if (pthread_attr_setschedpolicy(&attr, SCHED_OTHER)) { + perror("pthread_attr_setschedpolicy"); + } + if (pthread_attr_setschedparam(&attr, ¶m)) { + perror("pthread_attr_setschedparam"); + fprintf(stderr, "Error not enough privileges to set Scheduling priority\n"); + } + attr_enable = true; } if(cpu > 0) { if(cpu > 50) { @@ -86,7 +103,7 @@ bool threads_new_rt_cpu(pthread_t *thread, void *(*start_routine) (void*), void } } - int err = pthread_create(thread, prio_offset >= 0 ? &attr : NULL, start_routine, arg); + int err = pthread_create(thread, attr_enable ? &attr : NULL, start_routine, arg); if (err) { if (EPERM == err) { perror("Warning: Failed to create thread with real-time priority. Creating it with normal priority"); @@ -102,7 +119,7 @@ bool threads_new_rt_cpu(pthread_t *thread, void *(*start_routine) (void*), void } else { ret = true; } - if (prio_offset >= 0) { + if (attr_enable) { pthread_attr_destroy(&attr); } return ret; From be880e16f4e048f6e3f1e4ea31ecb5105a541423 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 29 Dec 2017 00:25:31 +0100 Subject: [PATCH 234/242] Do not include srslte.h in debug --- lib/include/srslte/phy/utils/debug.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/include/srslte/phy/utils/debug.h b/lib/include/srslte/phy/utils/debug.h index ec4dc220c..52290ca11 100644 --- a/lib/include/srslte/phy/utils/debug.h +++ b/lib/include/srslte/phy/utils/debug.h @@ -37,7 +37,8 @@ #include #include "srslte/config.h" -#include "srslte/srslte.h" +#include "srslte/phy/common/phy_logger.h" + #define SRSLTE_VERBOSE_DEBUG 2 #define SRSLTE_VERBOSE_INFO 1 #define SRSLTE_VERBOSE_NONE 0 From 03da3dadceaa5f7ecde8670638e44ea773263ab0 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 29 Dec 2017 00:26:01 +0100 Subject: [PATCH 235/242] Minor edits in dci info string --- lib/src/phy/phch/dci.c | 4 ++-- lib/src/phy/phch/ra.c | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/src/phy/phch/dci.c b/lib/src/phy/phch/dci.c index 97ea9a40b..9a92508bc 100644 --- a/lib/src/phy/phch/dci.c +++ b/lib/src/phy/phch/dci.c @@ -398,7 +398,7 @@ uint32_t srslte_dci_dl_info(char *info_str, uint32_t len, srslte_ra_dl_dci_t *dc n += snprintf(&info_str[n], len-n, "tpc_pucch=%d, ", dci_msg->tpc_pucch); } if (format == SRSLTE_DCI_FORMAT2 || format == SRSLTE_DCI_FORMAT2A || format == SRSLTE_DCI_FORMAT2B) { - n += snprintf(&info_str[n], len-n, "tb_sw=%d, pinfo=%d", dci_msg->tb_cw_swap, dci_msg->pinfo); + n += snprintf(&info_str[n], len-n, "tb_sw=%d, pinfo=%d, ", dci_msg->tb_cw_swap, dci_msg->pinfo); } return n; } @@ -419,7 +419,7 @@ uint32_t srslte_dci_ul_info(char *info_str, uint32_t len, srslte_ra_ul_dci_t *dc break; } n += snprintf(&info_str[n], len-n, "mcs=%d, rv=%d, ndi=%d, ", dci_msg->mcs_idx, dci_msg->rv_idx, dci_msg->ndi); - n += snprintf(&info_str[n], len-n, "tpc_pusch=%d, dmrs_cs=%d, cqi=%s", + n += snprintf(&info_str[n], len-n, "tpc_pusch=%d, dmrs_cs=%d, cqi=%s, ", dci_msg->tpc_pusch, dci_msg->n_dmrs, dci_msg->cqi_request?"yes":"no"); return n; diff --git a/lib/src/phy/phch/ra.c b/lib/src/phy/phch/ra.c index 1f6ac7a18..e1eaa5de2 100644 --- a/lib/src/phy/phch/ra.c +++ b/lib/src/phy/phch/ra.c @@ -240,7 +240,6 @@ int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci, uint32_t nof_prb, uint32_ grant->Qm = srslte_mod_bits_x_symbol(grant->mcs.mod); } else { - printf("Error computing UL PRB allocation\n"); return SRSLTE_ERROR; } return SRSLTE_SUCCESS; From bbc5fad1cfd4c50bbb2e585ed0f98a4fa5c22036 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 29 Dec 2017 19:21:36 +0100 Subject: [PATCH 236/242] Possible fix to RSSI bug by scoping rssi_sensor variable to local function --- lib/src/phy/rf/rf_uhd_imp.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/lib/src/phy/rf/rf_uhd_imp.c b/lib/src/phy/rf/rf_uhd_imp.c index a697f52ff..6b4a3ebcd 100644 --- a/lib/src/phy/rf/rf_uhd_imp.c +++ b/lib/src/phy/rf/rf_uhd_imp.c @@ -50,7 +50,6 @@ typedef struct { double tx_rate; bool dynamic_rate; bool has_rssi; - uhd_sensor_value_handle rssi_value; uint32_t nof_rx_channels; int nof_tx_channels; @@ -281,10 +280,15 @@ bool get_has_rssi(void *h) { float rf_uhd_get_rssi(void *h) { rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; if (handler->has_rssi) { - double val_out; - uhd_usrp_get_rx_sensor(handler->usrp, "rssi", 0, &handler->rssi_value); - uhd_sensor_value_to_realnum(handler->rssi_value, &val_out); - return val_out; + double val_out; + + uhd_sensor_value_handle rssi_value; + uhd_sensor_value_make_from_realnum(&rssi_value, "rssi", 0, "dBm", "%f"); + uhd_usrp_get_rx_sensor(handler->usrp, "rssi", 0, &rssi_value); + uhd_sensor_value_to_realnum(rssi_value, &val_out); + uhd_sensor_value_free(&rssi_value); + + return val_out; } else { return 0.0; } @@ -490,10 +494,7 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels) } handler->has_rssi = get_has_rssi(handler); - if (handler->has_rssi) { - uhd_sensor_value_make_from_realnum(&handler->rssi_value, "rssi", 0, "dBm", "%f"); - } - + size_t channel[4] = {0, 1, 2, 3}; uhd_stream_args_t stream_args = { .cpu_format = "fc32", @@ -570,10 +571,7 @@ int rf_uhd_close(void *h) uhd_rx_metadata_free(&handler->rx_md_first); uhd_rx_metadata_free(&handler->rx_md); uhd_meta_range_free(&handler->rx_gain_range); - if (handler->has_rssi) { - uhd_sensor_value_free(&handler->rssi_value); - } - handler->async_thread_running = false; + handler->async_thread_running = false; pthread_join(handler->async_thread, NULL); uhd_tx_streamer_free(&handler->tx_stream); From ba8a42b92a23617a4ec2d9625fab9f50a7c0bc75 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 2 Jan 2018 13:20:43 +0100 Subject: [PATCH 237/242] Set master clock rate by default for usrp unless x300 is defined --- lib/src/phy/rf/rf_uhd_imp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/phy/rf/rf_uhd_imp.c b/lib/src/phy/rf/rf_uhd_imp.c index 6b4a3ebcd..0d289535e 100644 --- a/lib/src/phy/rf/rf_uhd_imp.c +++ b/lib/src/phy/rf/rf_uhd_imp.c @@ -433,7 +433,7 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_channels) handler->current_master_clock = 184320000; handler->dynamic_rate = false; handler->devname = DEVNAME_X300; - } else if (strstr(args, "type=b200")) { + } else { snprintf(args2, sizeof(args2), "%s,master_clock_rate=30.72e6", args); args = args2; handler->current_master_clock = 30720000; From ba807f1ef3894c4e1e7aed00b41d3f00daa9ffdf Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 2 Jan 2018 13:21:11 +0100 Subject: [PATCH 238/242] DLSCH error when CRC=0x0 --- lib/src/phy/phch/sch.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/src/phy/phch/sch.c b/lib/src/phy/phch/sch.c index 7c1f64dff..b782725eb 100644 --- a/lib/src/phy/phch/sch.c +++ b/lib/src/phy/phch/sch.c @@ -493,11 +493,7 @@ static int decode_tb(srslte_sch_t *q, ((uint32_t) data[cb_segm->tbs/8+1])<<8 | ((uint32_t) data[cb_segm->tbs/8+2]); - if (!par_rx) { - INFO("Warning: Received all-zero transport block\n\n",0); - } - - if (par_rx == par_tx) { + if (par_rx == par_tx && par_rx) { INFO("TB decoded OK\n",0); return SRSLTE_SUCCESS; } else { From 0689e69aadd12a9e7e3fc2f10f8ccf74dfb6fb6d Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 2 Jan 2018 13:21:29 +0100 Subject: [PATCH 239/242] Minor DCI str info edits --- lib/src/phy/phch/dci.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/lib/src/phy/phch/dci.c b/lib/src/phy/phch/dci.c index 9a92508bc..01ad7fb61 100644 --- a/lib/src/phy/phch/dci.c +++ b/lib/src/phy/phch/dci.c @@ -387,11 +387,41 @@ uint32_t srslte_dci_dl_info(char *info_str, uint32_t len, srslte_ra_dl_dci_t *dc } n += snprintf(&info_str[n], len-n, "pid=%d, ", dci_msg->harq_process); + n += snprintf(&info_str[n], len-n, "mcs={"); if (dci_msg->tb_en[0]) { - n += snprintf(&info_str[n], len-n, "TB0={mcs=%d, rv=%d, ndi=%d}, ", dci_msg->mcs_idx, dci_msg->rv_idx, dci_msg->ndi); + n += snprintf(&info_str[n], len-n, "%d", dci_msg->mcs_idx); + if (dci_msg->tb_en[1]) { + n += snprintf(&info_str[n], len-n, ","); + } else { + n += snprintf(&info_str[n], len-n, "}, "); + } + } + if (dci_msg->tb_en[1]) { + n += snprintf(&info_str[n], len - n, "%d}, ", dci_msg->mcs_idx_1); + } + n += snprintf(&info_str[n], len-n, "rv={"); + if (dci_msg->tb_en[0]) { + n += snprintf(&info_str[n], len-n, "%d", dci_msg->rv_idx); + if (dci_msg->tb_en[1]) { + n += snprintf(&info_str[n], len-n, ","); + } else { + n += snprintf(&info_str[n], len-n, "}, "); + } + } + if (dci_msg->tb_en[1]) { + n += snprintf(&info_str[n], len - n, "%d}, ", dci_msg->rv_idx_1); + } + n += snprintf(&info_str[n], len-n, "ndi={"); + if (dci_msg->tb_en[0]) { + n += snprintf(&info_str[n], len-n, "%d", dci_msg->ndi); + if (dci_msg->tb_en[1]) { + n += snprintf(&info_str[n], len-n, ","); + } else { + n += snprintf(&info_str[n], len-n, "}, "); + } } if (dci_msg->tb_en[1]) { - n += snprintf(&info_str[n], len-n, "TB1={mcs=%d, rv=%d, ndi=%d}, ", dci_msg->mcs_idx_1, dci_msg->rv_idx_1, dci_msg->ndi_1); + n += snprintf(&info_str[n], len - n, "%d}, ", dci_msg->ndi_1); } if (format == SRSLTE_DCI_FORMAT1 || format == SRSLTE_DCI_FORMAT1A || format == SRSLTE_DCI_FORMAT1B) { From 5c7ce5a79983e79d59d9d079db2105ee29aedf1e Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 3 Jan 2018 18:06:53 +0100 Subject: [PATCH 240/242] Increased viterbi quantification to maximum --- lib/src/phy/fec/viterbi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/phy/fec/viterbi.c b/lib/src/phy/fec/viterbi.c index a010dfebb..a7b861c23 100644 --- a/lib/src/phy/fec/viterbi.c +++ b/lib/src/phy/fec/viterbi.c @@ -40,7 +40,7 @@ #define TB_ITER 3 -#define DEFAULT_GAIN 100 +#define DEFAULT_GAIN 128 //#undef LV_HAVE_SSE From e4696fec3871ee1ff0e3b05ab66ebc2626fb6643 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 3 Jan 2018 18:07:23 +0100 Subject: [PATCH 241/242] Added ue location calculation for a particular L --- lib/include/srslte/phy/phch/pdcch.h | 10 ++++++- lib/src/phy/phch/pdcch.c | 45 +++++++++++++++++------------ 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/lib/include/srslte/phy/phch/pdcch.h b/lib/include/srslte/phy/phch/pdcch.h index 9bb896b34..0e0e63335 100644 --- a/lib/include/srslte/phy/phch/pdcch.h +++ b/lib/include/srslte/phy/phch/pdcch.h @@ -167,7 +167,15 @@ SRSLTE_API uint32_t srslte_pdcch_ue_locations(srslte_pdcch_t *q, SRSLTE_API uint32_t srslte_pdcch_ue_locations_ncce(uint32_t nof_cce, srslte_dci_location_t *c, uint32_t max_candidates, - uint32_t nsubframe, uint16_t rnti); + uint32_t nsubframe, + uint16_t rnti); + +SRSLTE_API uint32_t srslte_pdcch_ue_locations_ncce_L(uint32_t nof_cce, + srslte_dci_location_t *c, + uint32_t max_candidates, + uint32_t nsubframe, + uint16_t rnti, + int L); /* Function for generation of common search space DCI locations */ SRSLTE_API uint32_t srslte_pdcch_common_locations(srslte_pdcch_t *q, diff --git a/lib/src/phy/phch/pdcch.c b/lib/src/phy/phch/pdcch.c index 58d5bf6db..ca8480bc6 100644 --- a/lib/src/phy/phch/pdcch.c +++ b/lib/src/phy/phch/pdcch.c @@ -218,13 +218,20 @@ uint32_t srslte_pdcch_ue_locations(srslte_pdcch_t *q, srslte_dci_location_t *c, return srslte_pdcch_ue_locations_ncce(q->nof_cce, c, max_candidates, nsubframe, rnti); } + +uint32_t srslte_pdcch_ue_locations_ncce(uint32_t nof_cce, srslte_dci_location_t *c, uint32_t max_candidates, + uint32_t nsubframe, uint16_t rnti) +{ + return srslte_pdcch_ue_locations_ncce_L(nof_cce, c, max_candidates, nsubframe, rnti, -1); +} + /** 36.213 v9.1.1 * Computes up to max_candidates UE-specific candidates for DCI messages and saves them * in the structure pointed by c. * Returns the number of candidates saved in the array c. */ -uint32_t srslte_pdcch_ue_locations_ncce(uint32_t nof_cce, srslte_dci_location_t *c, uint32_t max_candidates, - uint32_t nsubframe, uint16_t rnti) { +uint32_t srslte_pdcch_ue_locations_ncce_L(uint32_t nof_cce, srslte_dci_location_t *c, uint32_t max_candidates, + uint32_t nsubframe, uint16_t rnti, int Ls) { int l; // this must be int because of the for(;;--) loop uint32_t i, k, L, m; @@ -241,24 +248,26 @@ uint32_t srslte_pdcch_ue_locations_ncce(uint32_t nof_cce, srslte_dci_location_t // All aggregation levels from 8 to 1 for (l = 3; l >= 0; l--) { L = (1 << l); - // For all candidates as given in table 9.1.1-1 - for (i = 0; i < nof_candidates[l]; i++) { - if (nof_cce >= L) { - ncce = L * ((Yk + i) % (nof_cce / L)); - // Check if candidate fits in c vector and in CCE region - if (k < max_candidates && ncce + L <= nof_cce) - { - c[k].L = l; - c[k].ncce = ncce; - - DEBUG("UE-specific SS Candidate %d: nCCE: %d, L: %d\n", - k, c[k].ncce, c[k].L); - - k++; - } + if (Ls<0 || Ls==L) { + // For all candidates as given in table 9.1.1-1 + for (i = 0; i < nof_candidates[l]; i++) { + if (nof_cce >= L) { + ncce = L * ((Yk + i) % (nof_cce / L)); + // Check if candidate fits in c vector and in CCE region + if (k < max_candidates && ncce + L <= nof_cce) + { + c[k].L = l; + c[k].ncce = ncce; + + DEBUG("UE-specific SS Candidate %d: nCCE: %d, L: %d\n", + k, c[k].ncce, c[k].L); + + k++; + } + } } } - } + } DEBUG("Initiated %d candidate(s) in the UE-specific search space for C-RNTI: 0x%x, nsubframe=%d, nof_cce=%d\n", k, rnti, nsubframe, nof_cce); From 1fb22621308dbd2bcf68e63ec923d9b82468e19e Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 5 Jan 2018 10:33:39 +0100 Subject: [PATCH 242/242] Revert "Increased viterbi quantification to maximum" This reverts commit 5c7ce5a79983e79d59d9d079db2105ee29aedf1e. --- lib/src/phy/fec/viterbi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/phy/fec/viterbi.c b/lib/src/phy/fec/viterbi.c index a7b861c23..a010dfebb 100644 --- a/lib/src/phy/fec/viterbi.c +++ b/lib/src/phy/fec/viterbi.c @@ -40,7 +40,7 @@ #define TB_ITER 3 -#define DEFAULT_GAIN 128 +#define DEFAULT_GAIN 100 //#undef LV_HAVE_SSE