Merging next into epc branch.

master
Pedro Alvarez 7 years ago
commit 042552491b

@ -55,14 +55,20 @@ 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
########################################################################
option(ENABLE_SRSUE "Build srsUE application" ON)
option(ENABLE_SRSENB "Build srsENB application" ON)
option(ENABLE_SRSEPC "Build srsEPC application" ON)
option(DISABLE_SIMD "disable simd instructions" OFF)
option(ENABLE_VOLK "Enable use of VOLK SIMD library" ON)
option(ENABLE_GUI "Enable GUI (using srsGUI)" ON)
option(ENABLE_BLADERF "Enable BladeRF" ON)
@ -190,21 +196,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
########################################################################
@ -283,6 +274,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 -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")
if(HAVE_SSE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Ofast -funroll-loops")
@ -293,9 +289,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)

@ -8,6 +8,7 @@ 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 <immintrin.h>
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)

@ -1,161 +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_16)
CHECK_FUNCTION_EXISTS_MATH(volk_32f_index_max_32u HAVE_VOLK_MAX_FUNCTION_32)
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_REAL_FUNCTION)
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_index_max_16u HAVE_VOLK_MAX_ABS_FUNCTION_16)
CHECK_FUNCTION_EXISTS_MATH(volk_32fc_index_max_32u HAVE_VOLK_MAX_ABS_FUNCTION_32)
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_IF_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_CONVERT_IF_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_MULT_REAL2_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MULT_REAL2_FUNCTION")
ENDIF()
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_16})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MAX_ABS_FUNCTION_16")
ENDIF()
IF(${HAVE_VOLK_MAX_ABS_FUNCTION_32})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MAX_ABS_FUNCTION_32")
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_REAL_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_DEINTERLEAVE_REAL_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_CONVERT_FI_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_CONVERT_FI_FUNCTION")
ENDIF()
IF(${HAVE_VOLK_MAX_FUNCTION_16})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MAX_FUNCTION_16")
ENDIF()
IF(${HAVE_VOLK_MAX_FUNCTION_32})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MAX_FUNCTION_32")
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_CFC_FUNCTION})
SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_DOTPROD_CFC_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)

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

@ -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);
}
@ -249,7 +251,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 +259,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;
}
@ -272,7 +274,15 @@ int main(int argc, char **argv) {
/* Initialize subframe counter */
sf_cnt = 0;
if (srslte_ofdm_rx_init(&fft, cell.cp, cell.nof_prb)) {
int sf_re = SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);
cf_t *sf_symbols = srslte_vec_malloc(sf_re * sizeof(cf_t));
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
ce[i] = srslte_vec_malloc(sizeof(cf_t) * sf_re);
}
if (srslte_ofdm_rx_init(&fft, cell.cp, sf_buffer[0], sf_symbols, cell.nof_prb)) {
fprintf(stderr, "Error initiating FFT\n");
return -1;
}
@ -285,21 +295,10 @@ int main(int argc, char **argv) {
return -1;
}
int sf_re = SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);
cf_t *sf_symbols = srslte_vec_malloc(sf_re * sizeof(cf_t));
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
ce[i] = srslte_vec_malloc(sizeof(cf_t) * sf_re);
}
srslte_rf_start_rx_stream(&rf);
srslte_rf_start_rx_stream(&rf, false);
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) {
@ -315,7 +314,7 @@ int main(int argc, char **argv) {
case DECODE_MIB:
if (srslte_ue_sync_get_sfidx(&ue_sync) == 0) {
srslte_pbch_decode_reset(&ue_mib.pbch);
n = srslte_ue_mib_decode(&ue_mib, sf_buffer[0], bch_payload, NULL, &sfn_offset);
n = srslte_ue_mib_decode(&ue_mib, bch_payload, NULL, &sfn_offset);
if (n < 0) {
fprintf(stderr, "Error decoding UE MIB\n");
return -1;
@ -330,7 +329,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;
@ -351,7 +350,7 @@ int main(int argc, char **argv) {
if (srslte_ue_sync_get_sfidx(&ue_sync) == 5) {
/* Run FFT for all subframe data */
srslte_ofdm_rx_sf(&fft, sf_buffer[0], sf_symbols);
srslte_ofdm_rx_sf(&fft);
srslte_chest_dl_estimate(&chest, sf_symbols, ce, srslte_ue_sync_get_sfidx(&ue_sync));
@ -367,7 +366,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);
}

@ -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");
@ -219,7 +221,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) {

@ -86,7 +86,7 @@ float rf_amp = 0.8, rf_gain = 70.0, rf_freq = 2400000000;
bool null_file_sink=false;
srslte_filesink_t fsink;
srslte_ofdm_t ifft;
srslte_ofdm_t ifft[SRSLTE_MAX_PORTS];
srslte_ofdm_t ifft_mbsfn;
srslte_pbch_t pbch;
srslte_pcfich_t pcfich;
@ -311,18 +311,21 @@ void base_init() {
}
/* create ifft object */
if (srslte_ofdm_tx_init(&ifft, SRSLTE_CP_NORM, cell.nof_prb)) {
for (i = 0; i < cell.nof_ports; i++) {
if (srslte_ofdm_tx_init(&ifft[i], SRSLTE_CP_NORM, sf_buffer[i], output_buffer[i], cell.nof_prb)) {
fprintf(stderr, "Error creating iFFT object\n");
exit(-1);
}
if (srslte_ofdm_tx_init_mbsfn(&ifft_mbsfn, SRSLTE_CP_EXT, cell.nof_prb)) {
srslte_ofdm_set_normalize(&ifft[i], true);
}
if (srslte_ofdm_tx_init_mbsfn(&ifft_mbsfn, SRSLTE_CP_EXT, sf_buffer[0], output_buffer[0], cell.nof_prb)) {
fprintf(stderr, "Error creating iFFT object\n");
exit(-1);
}
srslte_ofdm_set_non_mbsfn_region(&ifft_mbsfn, 2);
srslte_ofdm_set_normalize(&ifft_mbsfn, true);
srslte_ofdm_set_normalize(&ifft, true);
if (srslte_pbch_init(&pbch)) {
fprintf(stderr, "Error creating PBCH object\n");
@ -413,8 +416,9 @@ void base_free() {
srslte_pmch_free(&pmch);
}
srslte_ofdm_tx_free(&ifft_mbsfn);
srslte_ofdm_tx_free(&ifft);
for (i = 0; i < cell.nof_ports; i++) {
srslte_ofdm_tx_free(&ifft[i]);
}
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (data[i]) {
@ -697,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]);
@ -938,7 +944,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;
@ -977,10 +984,10 @@ int main(int argc, char **argv) {
/* Transform to OFDM symbols */
if(sf_idx != 1 || mbsfn_area_id < 0){
for (i = 0; i < cell.nof_ports; i++) {
srslte_ofdm_tx_sf(&ifft, sf_buffer[i], output_buffer[i]);
srslte_ofdm_tx_sf(&ifft[i]);
}
}else{
srslte_ofdm_tx_sf(&ifft_mbsfn, sf_buffer[0], output_buffer[0]);
srslte_ofdm_tx_sf(&ifft_mbsfn);
}
/* send to file or usrp */

@ -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;
@ -121,6 +123,8 @@ void args_default(prog_args_t *args) {
args->rf_args = "";
args->rf_freq = -1.0;
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;
@ -326,6 +338,7 @@ 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) {
struct timeval t[3];
int ret;
int decimate = 1;
srslte_cell_t cell;
@ -340,6 +353,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++) {
@ -402,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;
@ -510,7 +525,10 @@ int main(int argc, char **argv) {
#endif
}
if (srslte_ue_mib_init(&ue_mib, cell.nof_prb)) {
for (int i=0;i<prog_args.rf_nof_rx_ant;i++) {
sf_buffer[i] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
}
if (srslte_ue_mib_init(&ue_mib, sf_buffer, cell.nof_prb)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
exit(-1);
}
@ -519,7 +537,7 @@ int main(int argc, char **argv) {
exit(-1);
}
if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, prog_args.rf_nof_rx_ant)) {
if (srslte_ue_dl_init(&ue_dl, sf_buffer, cell.nof_prb, prog_args.rf_nof_rx_ant)) {
fprintf(stderr, "Error initiating UE downlink processing module\n");
exit(-1);
}
@ -528,9 +546,15 @@ int main(int argc, char **argv) {
exit(-1);
}
for (int i=0;i<prog_args.rf_nof_rx_ant;i++) {
sf_buffer[i] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
}
// 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);
/* 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);
@ -553,14 +577,14 @@ 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
// 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;
@ -578,10 +602,7 @@ int main(int argc, char **argv) {
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_track = !prog_args.disable_cfo;
srslte_pbch_decode_reset(&ue_mib.pbch);
@ -632,7 +653,7 @@ int main(int argc, char **argv) {
switch (state) {
case DECODE_MIB:
if (sfidx == 0) {
n = srslte_ue_mib_decode(&ue_mib, sf_buffer[0], bch_payload, NULL, &sfn_offset);
n = srslte_ue_mib_decode(&ue_mib, bch_payload, NULL, &sfn_offset);
if (n < 0) {
fprintf(stderr, "Error decoding UE MIB\n");
exit(-1);
@ -656,30 +677,37 @@ 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) {
/* 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);
}
}
}
// 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,
data[0],
sfn*10+srslte_ue_sync_get_sfidx(&ue_sync));
if(n>0){
@ -691,6 +719,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) {
@ -726,14 +756,17 @@ int main(int argc, char **argv) {
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)) {
@ -768,9 +801,9 @@ 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 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 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){
@ -972,7 +1005,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],

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

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

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

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

@ -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);
@ -2721,6 +2724,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);

@ -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,
@ -2681,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;
@ -3926,7 +3930,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
@ -6435,11 +6439,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
// Structs
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{
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,

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

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

@ -44,6 +44,19 @@
#define SRSLTE_N_DRB 8
#define SRSLTE_N_RADIO_BEARERS 11
#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)
#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)
#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
#define SRSLTE_MAX_BUFFER_SIZE_BITS 102048
@ -83,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
*

@ -52,13 +52,11 @@ 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;
// TODO: Support the following configurations

@ -86,6 +86,15 @@ 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);
LIBLTE_ERROR_ENUM liblte_security_generate_nh( uint8_t *k_asme,
uint8_t *sync,
uint8_t *nh);
/*********************************************************************
Name: liblte_security_generate_k_nas
@ -121,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
@ -185,6 +196,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

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

@ -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:
@ -63,6 +69,7 @@ public:
tti = 0;
level = LOG_LEVEL_NONE;
hex_limit = 0;
show_layer_en = true;
}
log(std::string service_name_) {
@ -70,12 +77,20 @@ 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
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;
}
@ -93,6 +108,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;
@ -107,18 +128,17 @@ 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 show_layer_en;
bool level_text_short;
bool add_string_en;
std::string add_string_val;
};
} // namespace srslte

@ -37,6 +37,8 @@
#include <stdarg.h>
#include <string>
#include "srslte/phy/common/timestamp.h"
#include "srslte/common/log.h"
#include "srslte/common/logger.h"
#include "srslte/common/logger_stdout.h"
@ -66,15 +68,25 @@ 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;
};
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);

@ -39,6 +39,9 @@ public:
void enable(bool en);
void open(const char *filename, uint32_t ue_id = 0);
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);

@ -24,15 +24,20 @@ template<typename metrics_t>
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<typename metrics_t>
class metrics_hub : public periodic_thread
{
public:
bool init(metrics_interface<metrics_t> *m_, float report_period_secs=1.0) {
metrics_hub()
:m(NULL)
,report_period_secs(1)
{}
bool init(metrics_interface<metrics_t> *m_, float report_period_secs_=1.0) {
m = m_;
report_period_secs = report_period_secs_;
start_periodic(report_period_secs*1e6);
return true;
}
@ -47,16 +52,17 @@ public:
private:
void run_period() {
if (m) {
metrics_t metric;
bzero(&metric, sizeof(metrics_t));
m->get_metrics(metric);
for (uint32_t i=0;i<listeners.size();i++) {
listeners[i]->set_metrics(metric);
}
}
}
metrics_interface<metrics_t> *m;
std::vector<metrics_listener<metrics_t>*> listeners;
float report_period_secs;
};
} // namespace srslte

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

@ -33,6 +33,7 @@
#include <sys/time.h>
#define MAC_LTE_DLT 147
#define NAS_LTE_DLT 148
/* This structure gets written to the start of the file */
@ -73,28 +74,14 @@ typedef struct pcaprec_hdr_s {
#define M_RNTI 6
#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_SUBFRAME_TAG 0x04
/* 2 bytes, network order */
#define MAC_LTE_FRAME_SUBFRAME_TAG 0x04
#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 */
@ -109,17 +96,20 @@ 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 */
typedef struct NAS_Context_Info_s {
// No Context yet
} 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 =
{
@ -128,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");
@ -143,14 +133,26 @@ 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,
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];
int offset = 0;
unsigned short tmp16;
uint16_t tmp16;
/* Can't write if file wasn't successfully opened */
if (fd == NULL) {
@ -176,9 +178,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;
@ -208,11 +212,39 @@ 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)
/**************************************************************************
* API functions for writing NAS-EPS PCAP files *
**************************************************************************/
/* 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)
{
if(fd)
fclose(fd);
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;
}
#endif /* UEPCAP_H */

@ -76,6 +76,15 @@ 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_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,
@ -114,6 +123,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
*****************************************************************************/

@ -78,24 +78,32 @@ 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;
bool run_enable;
void run_thread() {
if (make_periodic()) {
return;
}
while(1) {
while(run_enable) {
run_period();
if (run_enable) {
wait_period();
}
}
}
int make_periodic() {
int ret = -1;
unsigned int ns;

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

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

@ -44,6 +44,7 @@ class tti_sync_cv : public tti_sync
tti_sync_cv(uint32_t modulus = 10240);
~tti_sync_cv();
void increase();
void increase(uint32_t cnt);
uint32_t wait();
void resync();
void set_producer_cntr(uint32_t producer_cntr);

@ -59,5 +59,6 @@
// cf_t definition
typedef _Complex float cf_t;
typedef _Complex short int c16_t;
#endif // CONFIG_H

@ -64,9 +64,11 @@ 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 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;
@ -93,6 +95,7 @@ public:
class phy_interface_rrc
{
public:
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;
};
@ -111,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;
};
@ -147,6 +151,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

@ -131,13 +131,14 @@ 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;
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 {
@ -225,8 +226,10 @@ 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;
virtual int dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) = 0;
/* UL information */

@ -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,17 @@ 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,
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,
int ncc,
uint8_t *k_rrc_enc,
uint8_t *k_rrc_int,
uint8_t *k_up_enc,
@ -104,6 +118,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;
};
@ -133,7 +148,9 @@ 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;
};
// RRC interface for PHY
@ -144,6 +161,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
@ -156,7 +174,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
@ -167,7 +184,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
@ -175,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
@ -190,14 +205,21 @@ 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;
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 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;
};
// PDCP interface for RLC
@ -216,6 +238,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;
};
@ -227,6 +250,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
@ -415,10 +439,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;
};
@ -446,11 +474,21 @@ typedef struct {
std::string snr_estim_alg;
bool cfo_integer_enabled;
float cfo_correct_tol_hz;
float cfo_pss_ema;
float cfo_ref_ema;
float cfo_loop_bw_pss;
float cfo_loop_bw_ref;
float cfo_loop_ref_min;
float cfo_loop_pss_tol;
uint32_t cfo_loop_pss_conv;
uint32_t cfo_ref_mask;
bool average_subframe_enabled;
int time_correct_period;
bool sfo_correct_disable;
std::string sss_algorithm;
float estimator_fil_w;
bool rssi_sensor_enabled;
bool sic_pss_enabled;
} phy_args_t;
@ -520,7 +558,10 @@ 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 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;
@ -528,11 +569,17 @@ 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;
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;

@ -68,6 +68,7 @@ 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];
@ -82,6 +83,10 @@ 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];
@ -91,6 +96,7 @@ typedef struct {
srslte_chest_dl_noise_alg_t noise_alg;
int last_nof_antennas;
bool average_subframe;
} srslte_chest_dl_t;
@ -144,14 +150,35 @@ 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_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_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);

@ -101,8 +101,8 @@ typedef enum {SRSLTE_SF_NORM, SRSLTE_SF_MBSFN} srslte_sf_t;
#define SRSLTE_CP_ISEXT(cp) (cp==SRSLTE_CP_EXT)
#define SRSLTE_CP_NSYMB(cp) (SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_NORM_NSYMB:SRSLTE_CP_EXT_NSYMB)
#define SRSLTE_CP_LEN(symbol_sz, c) ((int) ceil((((float) (c)*(symbol_sz))/2048)))
#define SRSLTE_CP_LEN_NORM(symbol, symbol_sz) ((symbol==0)?SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_NORM_0_LEN):SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_NORM_LEN))
#define SRSLTE_CP_LEN(symbol_sz, c) ((int) ceilf((((float) (c)*(symbol_sz))/2048.0f)))
#define SRSLTE_CP_LEN_NORM(symbol, symbol_sz) (((symbol)==0)?SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_NORM_0_LEN):SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_NORM_LEN))
#define SRSLTE_CP_LEN_EXT(symbol_sz) (SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_EXT_LEN))
#define SRSLTE_SLOT_LEN(symbol_sz) (symbol_sz*15/2)
@ -197,7 +197,8 @@ typedef enum SRSLTE_API {
SRSLTE_MOD_BPSK = 0,
SRSLTE_MOD_QPSK,
SRSLTE_MOD_16QAM,
SRSLTE_MOD_64QAM
SRSLTE_MOD_64QAM,
SRSLTE_MOD_LAST
} srslte_mod_t;
typedef struct SRSLTE_API {
@ -300,6 +301,7 @@ SRSLTE_API int srslte_str2mimotype(char *mimo_type_str,
SRSLTE_API char *srslte_mimotype2str(srslte_mimo_type_t mimo_type);
/* Returns the interval tti1-tti2 mod 10240 */
SRSLTE_API uint32_t srslte_tti_interval(uint32_t tti1,
uint32_t tti2);

@ -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 <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <sys/types.h>
#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

@ -63,6 +63,7 @@ typedef struct SRSLTE_API {
void *in; // Input buffer
void *out; // Output buffer
void *p; // DFT plan
bool is_guru;
bool forward; // Forward transform?
bool mirror; // Shift negative and positive frequencies?
bool db; // Provide output in dB?
@ -85,6 +86,17 @@ SRSLTE_API int srslte_dft_plan_c(srslte_dft_plan_t *plan,
int dft_points,
srslte_dft_dir_t dir);
SRSLTE_API int srslte_dft_plan_guru_c(srslte_dft_plan_t *plan,
int dft_points,
srslte_dft_dir_t dir,
cf_t *in_buffer,
cf_t *out_buffer,
int istride,
int ostride,
int how_many,
int idist,
int odist);
SRSLTE_API int srslte_dft_plan_r(srslte_dft_plan_t *plan,
int dft_points,
srslte_dft_dir_t dir);
@ -92,6 +104,16 @@ SRSLTE_API int srslte_dft_plan_r(srslte_dft_plan_t *plan,
SRSLTE_API int srslte_dft_replan(srslte_dft_plan_t *plan,
const int new_dft_points);
SRSLTE_API int srslte_dft_replan_guru_c(srslte_dft_plan_t *plan,
const int new_dft_points,
cf_t *in_buffer,
cf_t *out_buffer,
int istride,
int ostride,
int how_many,
int idist,
int odist);
SRSLTE_API int srslte_dft_replan_c(srslte_dft_plan_t *plan,
int new_dft_points);
@ -118,19 +140,21 @@ 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,
const void *in,
void *out);
SRSLTE_API void srslte_dft_run_c_zerocopy(srslte_dft_plan_t *plan,
cf_t *in,
const cf_t *in,
cf_t *out);
SRSLTE_API void srslte_dft_run_c(srslte_dft_plan_t *plan,
cf_t *in,
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_

@ -47,14 +47,18 @@
/* This is common for both directions */
typedef struct SRSLTE_API{
srslte_dft_plan_t fft_plan;
srslte_dft_plan_t fft_plan_sf[2];
uint32_t max_prb;
uint32_t nof_symbols;
uint32_t symbol_sz;
uint32_t nof_guards;
uint32_t nof_re;
uint32_t slot_sz;
uint32_t sf_sz;
srslte_cp_t cp;
cf_t *tmp; // for removing zero padding
cf_t *in_buffer;
cf_t *out_buffer;
bool mbsfn_subframe;
uint32_t mbsfn_guard_len;
@ -69,12 +73,16 @@ typedef struct SRSLTE_API{
SRSLTE_API int srslte_ofdm_init_(srslte_ofdm_t *q,
srslte_cp_t cp,
cf_t *in_buffer,
cf_t *out_buffer,
int symbol_sz,
int nof_prb,
srslte_dft_dir_t dir);
SRSLTE_API int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q,
srslte_cp_t cp,
cf_t *in_buffer,
cf_t *out_buffer,
int symbol_sz,
int nof_prb,
srslte_dft_dir_t dir,
@ -82,12 +90,14 @@ SRSLTE_API int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q,
SRSLTE_API int srslte_ofdm_rx_init_mbsfn(srslte_ofdm_t *q,
srslte_cp_t cp_type,
cf_t *in_buffer,
cf_t *out_buffer,
uint32_t nof_prb);
SRSLTE_API int srslte_ofdm_rx_init(srslte_ofdm_t *q,
srslte_cp_t cp_type,
cf_t *in_buffer,
cf_t *out_buffer,
uint32_t max_prb);
SRSLTE_API int srslte_ofdm_tx_set_prb(srslte_ofdm_t *q,
@ -101,38 +111,42 @@ SRSLTE_API int srslte_ofdm_rx_set_prb(srslte_ofdm_t *q,
SRSLTE_API void srslte_ofdm_rx_free(srslte_ofdm_t *q);
SRSLTE_API void srslte_ofdm_rx_slot(srslte_ofdm_t *q,
cf_t *input,
cf_t *output);
int slot_in_sf);
SRSLTE_API void srslte_ofdm_rx_sf(srslte_ofdm_t *q,
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,
cf_t *out_buffer,
uint32_t nof_prb);
SRSLTE_API int srslte_ofdm_tx_init_mbsfn(srslte_ofdm_t *q,
srslte_cp_t cp,
cf_t *in_buffer,
cf_t *out_buffer,
uint32_t nof_prb);
SRSLTE_API void srslte_ofdm_tx_free(srslte_ofdm_t *q);
SRSLTE_API void srslte_ofdm_tx_slot(srslte_ofdm_t *q,
cf_t *input,
cf_t *output);
int slot_in_sf);
SRSLTE_API void srslte_ofdm_tx_slot_mbsfn(srslte_ofdm_t *q,
cf_t *input,
cf_t *output);
SRSLTE_API void srslte_ofdm_tx_sf(srslte_ofdm_t *q,
cf_t *input,
cf_t *output);
SRSLTE_API void srslte_ofdm_tx_sf(srslte_ofdm_t *q);
SRSLTE_API int srslte_ofdm_set_freq_shift(srslte_ofdm_t *q,
float freq_shift);

@ -68,7 +68,7 @@ typedef struct SRSLTE_API {
cf_t *sf_symbols[SRSLTE_MAX_PORTS];
cf_t *slot1_symbols[SRSLTE_MAX_PORTS];
srslte_ofdm_t ifft;
srslte_ofdm_t ifft[SRSLTE_MAX_PORTS];
srslte_pbch_t pbch;
srslte_pcfich_t pcfich;
srslte_regs_t regs;
@ -95,10 +95,11 @@ 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 *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 {
@ -110,6 +111,7 @@ typedef struct {
/* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_enb_dl_init(srslte_enb_dl_t *q,
cf_t *out_buffer[SRSLTE_MAX_PORTS],
uint32_t max_prb);
SRSLTE_API void srslte_enb_dl_free(srslte_enb_dl_t *q);
@ -146,8 +148,7 @@ SRSLTE_API void srslte_enb_dl_put_phich(srslte_enb_dl_t *q,
SRSLTE_API void srslte_enb_dl_put_base(srslte_enb_dl_t *q,
uint32_t tti);
SRSLTE_API void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q,
cf_t *signal_buffer);
SRSLTE_API void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q);
SRSLTE_API int srslte_enb_dl_add_rnti(srslte_enb_dl_t *q,
uint16_t rnti);
@ -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,

@ -101,6 +101,7 @@ typedef struct {
/* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_enb_ul_init(srslte_enb_ul_t *q,
cf_t *in_buffer,
uint32_t max_prb);
SRSLTE_API void srslte_enb_ul_free(srslte_enb_ul_t *q);
@ -124,8 +125,7 @@ SRSLTE_API int srslte_enb_ul_cfg_ue(srslte_enb_ul_t *q, uint16_t rnti,
srslte_refsignal_srs_cfg_t *srs_cfg);
SRSLTE_API void srslte_enb_ul_fft(srslte_enb_ul_t *q,
cf_t *signal_buffer);
SRSLTE_API void srslte_enb_ul_fft(srslte_enb_ul_t *q);
SRSLTE_API int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q,
uint16_t rnti,
@ -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);

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

@ -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,33 +88,27 @@ 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);
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],
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,
@ -118,6 +117,7 @@ SRSLTE_API int srslte_predecoding_type_multi(cf_t *y[SRSLTE_MAX_PORTS],
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],

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

@ -137,6 +137,8 @@ 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 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);
@ -178,6 +180,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);

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

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

@ -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;
@ -48,6 +55,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

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

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

@ -103,13 +103,11 @@ typedef struct SRSLTE_API {
bool prb_idx[2][SRSLTE_MAX_PRB];
uint32_t nof_prb;
uint32_t Qm[SRSLTE_MAX_CODEWORDS];
uint32_t Qm2[SRSLTE_MAX_CODEWORDS];
srslte_ra_mcs_t mcs[SRSLTE_MAX_CODEWORDS];
srslte_ra_mcs_t mcs2[SRSLTE_MAX_CODEWORDS];
uint32_t nof_tb;
srslte_sf_t sf_type;
bool tb_en[SRSLTE_MAX_CODEWORDS];
uint32_t pinfo;
bool tb_cw_swap;
} srslte_ra_dl_grant_t;
#define SRSLTE_RA_DL_GRANT_NOF_TB(G) ((((G)->tb_en[0])?1:0)+(((G)->tb_en[1])?1:0))
@ -226,8 +224,7 @@ SRSLTE_API uint32_t srslte_ra_dl_grant_nof_re(srslte_ra_dl_grant_t *grant,
SRSLTE_API int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci,
uint32_t nof_prb,
uint32_t n_rb_ho,
srslte_ra_ul_grant_t *grant,
uint32_t harq_pid);
srslte_ra_ul_grant_t *grant);
SRSLTE_API void srslte_ra_ul_grant_to_nbits(srslte_ra_ul_grant_t *grant,
srslte_cp_t cp,

@ -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 {
@ -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;
@ -95,6 +96,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,
@ -130,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_uci_bit_t *ri_bits,
bool is_ri);
SRSLTE_API int srslte_uci_decode_ri(srslte_pusch_cfg_t *cfg,
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 *ri_bits,
uint8_t *data);
srslte_uci_bit_t *ack_ri_bits,
uint8_t data[2],
uint32_t nof_bits,
bool is_ri);
#endif

@ -38,10 +38,13 @@
#define RESAMPLE_ARB_
#include <stdint.h>
#include <stdbool.h>
#include <complex.h>
#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,

@ -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);
uint32_t nof_channels);
SRSLTE_API const char *srslte_rf_name(srslte_rf_t *h);
@ -95,7 +91,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);

@ -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 {
@ -66,7 +63,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);

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

@ -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,9 +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_ABS_SQUARE // If enabled, compute abs square, otherwise computes absolute value only
#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
@ -71,8 +69,6 @@
/* 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;
@ -89,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;
@ -97,36 +94,57 @@ typedef struct SRSLTE_API {
float ema_alpha;
float *conv_output_avg;
float peak_value;
}srslte_pss_synch_t;
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];
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_reset(srslte_pss_t *q);
SRSLTE_API void srslte_pss_filter_enable(srslte_pss_t *q,
bool enable);
SRSLTE_API void srslte_pss_sic(srslte_pss_t *q,
cf_t *input);
SRSLTE_API void srslte_pss_synch_reset(srslte_pss_synch_t *q);
SRSLTE_API void srslte_pss_filter(srslte_pss_t *q,
const cf_t *input,
cf_t *output);
SRSLTE_API int srslte_pss_generate(cf_t *signal,
uint32_t N_id_2);
@ -141,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,
cf_t *input,
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,
cf_t *input,
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,
cf_t *pss_recv);
SRSLTE_API float srslte_pss_cfo_compute(srslte_pss_t* q,
const cf_t *pss_recv);
#endif // PSS_

@ -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,11 +104,11 @@ 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,
cf_t *input,
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],
uint32_t *m0,
@ -116,41 +116,41 @@ 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,
cf_t *input,
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,
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_m0m1_diff(srslte_sss_t *q,
const cf_t *input,
uint32_t *m0,
float *m0_value,
uint32_t *m1,
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_

@ -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;
@ -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,33 @@ 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;
float cfo_pss_mean;
int cfo_i_value;
float cfo_ema_alpha;
uint32_t cfo_cp_nsymbols;
srslte_cfo_t cfo_corr_frame;
srslte_cfo_t cfo_corr_symbol;
bool sss_channel_equalize;
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 +151,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 +185,42 @@ 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_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);
/* 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);
/* Set integer CFO */
SRSLTE_API void srslte_sync_set_cfo_i(srslte_sync_t *q,
int cfo_i);
/* 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);
SRSLTE_API void srslte_sync_set_cfo_enable(srslte_sync_t *q,
/* 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,
uint32_t nof_symbols);
SRSLTE_API void srslte_sync_set_cfo_pss_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,20 +228,14 @@ 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);
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);
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);

@ -80,7 +80,7 @@ typedef struct SRSLTE_API {
srslte_pmch_t pmch;
srslte_phich_t phich;
srslte_regs_t regs;
srslte_ofdm_t fft;
srslte_ofdm_t fft[SRSLTE_MAX_PORTS];
srslte_ofdm_t fft_mbsfn;
srslte_chest_dl_t chest;
@ -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;
@ -124,10 +127,13 @@ typedef struct SRSLTE_API {
uint16_t pending_ul_dci_rnti;
float sample_offset;
float last_phich_corr;
}srslte_ue_dl_t;
/* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_ue_dl_init(srslte_ue_dl_t *q,
cf_t *input[SRSLTE_MAX_PORTS],
uint32_t max_prb,
uint32_t nof_rx_antennas);
@ -137,18 +143,20 @@ 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 *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 *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,
SRSLTE_API int srslte_ue_dl_decode_estimate(srslte_ue_dl_t *q,
uint32_t sf_idx,
uint32_t *cfi);
@ -191,14 +199,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,
@ -212,7 +218,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);
@ -243,6 +248,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,

@ -79,6 +79,7 @@ typedef struct SRSLTE_API {
} srslte_ue_mib_t;
SRSLTE_API int srslte_ue_mib_init(srslte_ue_mib_t *q,
cf_t *in_buffer[SRSLTE_MAX_PORTS],
uint32_t max_prb);
SRSLTE_API void srslte_ue_mib_free(srslte_ue_mib_t *q);
@ -89,7 +90,6 @@ SRSLTE_API int srslte_ue_mib_set_cell(srslte_ue_mib_t * q,
SRSLTE_API void srslte_ue_mib_reset(srslte_ue_mib_t * q);
SRSLTE_API int srslte_ue_mib_decode(srslte_ue_mib_t * q,
cf_t *input,
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN],
uint32_t *nof_tx_ports,
int *sfn_offset);

@ -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.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
#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
@ -110,7 +120,20 @@ typedef struct SRSLTE_API {
uint32_t sf_idx;
bool decode_sss_on_track;
bool correct_cfo;
bool cfo_is_copied;
bool cfo_correct_enable_track;
bool cfo_correct_enable_find;
float cfo_current_value;
float cfo_loop_bw_pss;
float cfo_loop_bw_ref;
float cfo_pss_min;
float cfo_ref_min;
float cfo_ref_max;
uint32_t pss_stable_cnt;
uint32_t pss_stable_timeout;
bool pss_is_stable;
uint32_t peak_idx;
int next_rf_sample_offset;
@ -165,6 +188,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);
@ -184,13 +211,24 @@ SRSLTE_API int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q,
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_cfo_i_detec_en(srslte_ue_sync_t *q,
bool enable);
SRSLTE_API 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_timeout);
SRSLTE_API void srslte_ue_sync_reset(srslte_ue_sync_t *q);
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);
SRSLTE_API void srslte_ue_sync_set_N_id_2(srslte_ue_sync_t *q,
uint32_t N_id_2);
@ -198,8 +236,6 @@ SRSLTE_API void srslte_ue_sync_set_N_id_2(srslte_ue_sync_t *q,
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);
@ -215,8 +251,5 @@ SRSLTE_API void srslte_ue_sync_get_last_timestamp(srslte_ue_sync_t *q,
srslte_timestamp_t *timestamp);
#endif // SYNC_FRAME_

@ -108,6 +108,7 @@ typedef struct SRSLTE_API {
/* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_ue_ul_init(srslte_ue_ul_t *q,
cf_t *out_buffer,
uint32_t max_prb);
SRSLTE_API void srslte_ue_ul_free(srslte_ue_ul_t *q);

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

@ -67,17 +67,17 @@ 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,
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,
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);

@ -37,6 +37,7 @@
#include <stdio.h>
#include "srslte/config.h"
#include "srslte/phy/common/phy_logger.h"
#define SRSLTE_VERBOSE_DEBUG 2
#define SRSLTE_VERBOSE_INFO 1
@ -48,6 +49,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 handler_registered;
#define SRSLTE_VERBOSE_ISINFO() (srslte_verbose>=SRSLTE_VERBOSE_INFO)
#define SRSLTE_VERBOSE_ISDEBUG() (srslte_verbose>=SRSLTE_VERBOSE_DEBUG)
@ -57,17 +59,25 @@ 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 && !handler_registered)\
{ 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 && !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, ...) fprintf(stderr, "%s.%d: " _fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#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, ...) fprintf(stderr, "[ERROR in %s]:" _fmt "\n", __FUNCTION__, ##__VA_ARGS__)
#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 */
void srslte_debug_handle_crash(int argc, char **argv);
#endif // DEBUG_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);
@ -66,7 +60,6 @@ SRSLTE_API float srslte_mat_2x2_cn(cf_t h00,
#ifdef LV_HAVE_SSE
#include <smmintrin.h>
/* SSE implementation for complex reciprocal */
SRSLTE_API __m128 srslte_mat_cf_recip_sse(__m128 a);
@ -90,8 +83,6 @@ SRSLTE_API void srslte_mat_2x2_mmse_sse(__m128 y0, __m128 y1,
#ifdef LV_HAVE_AVX
#include <immintrin.h>
/* AVX implementation for complex reciprocal */
SRSLTE_API __m256 srslte_mat_cf_recip_avx(__m256 a);

@ -20,15 +20,18 @@ 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);
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);

File diff suppressed because it is too large Load Diff

@ -53,130 +53,102 @@ 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, const uint32_t len);
/** 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);
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_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_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);
/* 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);
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_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);
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);
/* 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_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_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(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(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(short *x, short *y, short *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, 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_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 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);
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);
/* argument of each vector element */
SRSLTE_API void srslte_vec_arg_cf(cf_t *x, float *arg, 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
}

@ -35,32 +35,99 @@ extern "C" {
#include <stdint.h>
#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_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_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);
/*SIMD Logical operations*/
SRSLTE_API void srslte_vec_xor_bbb_simd(const int8_t *x, const int8_t *y, int8_t *z, int len);
SRSLTE_API void srslte_vec_sum_sss_avx2(short *x, short *y, short *z, uint32_t len);
/* SIMD Basic vector math */
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_sse(short *x, short *y, short *z, uint32_t len);
SRSLTE_API void srslte_vec_sub_sss_simd(const int16_t *x, const 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(const float *x, int len);
SRSLTE_API void srslte_vec_prod_sss_sse(short *x, short *y, short *z, uint32_t len);
SRSLTE_API cf_t srslte_vec_acc_cc_simd(const cf_t *x, int len);
SRSLTE_API void srslte_vec_prod_sss_avx2(short *x, short *y, short *z, uint32_t 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(const float *x, const float *y, float *z, int len);
SRSLTE_API void srslte_vec_sc_div2_sss_sse(short *x, int n_rightshift, short *z, uint32_t 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_div2_sss_avx2(short *x, int k, short *z, uint32_t 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_lut_sss_sse(short *x, unsigned short *lut, short *y, uint32_t len);
SRSLTE_API void srslte_vec_sc_prod_ccc_simd(const cf_t *x, const cf_t h, cf_t *z, const int len);
SRSLTE_API void srslte_vec_convert_fi_sse(float *x, int16_t *z, float scale, uint32_t len);
/* SIMD Vector Product */
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(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(const int16_t *x, const int16_t *y, int16_t *z, const 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(const float *x, const float *y, float *z, const 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(const cf_t *x, const cf_t *y, cf_t *z, const int len);
/* SIMD Division */
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(const cf_t *x, const float *y, cf_t *z, const 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(const cf_t *x, const cf_t *y, const 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(const c16_t *x, const c16_t *y, const 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(const cf_t *x, float *z, const 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(const short *x, const unsigned short *lut, short *y, const 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(const cf_t *src, cf_t *dst, int len);
/* SIMD Find Max functions */
SRSLTE_API uint32_t srslte_vec_max_fi_simd(const float *x, const int len);
SRSLTE_API uint32_t srslte_vec_max_ci_simd(const cf_t *x, const int len);
SRSLTE_API void srslte_vec_sc_prod_cfc_avx(const cf_t *x,const float h,cf_t *y,const uint32_t len);
#ifdef __cplusplus
}
#endif

@ -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);
@ -117,7 +118,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);
@ -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];

@ -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"
@ -47,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"

@ -54,14 +54,21 @@ 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());
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 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);
// RLC interface
void write_pdu(uint32_t lcid, byte_buffer_t *sdu);

@ -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,16 +71,20 @@ public:
srslte::log *log_,
uint32_t lcid_,
srslte_pdcp_config_t cfg_);
void stop();
void reset();
void reestablish();
bool is_active();
// 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
void write_pdu(byte_buffer_t *pdu);
@ -90,26 +97,46 @@ 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;
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;
void integrity_generate(uint8_t *key_128,
void integrity_generate(uint8_t *msg,
uint32_t msg_len,
uint8_t *mac);
bool integrity_verify(uint8_t *msg,
uint32_t count,
uint8_t rb_id,
uint8_t direction,
uint8_t *msg,
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();
uint8_t get_bearer_id(uint8_t lcid);
};
/****************************************************************************

@ -64,7 +64,8 @@ public:
// PDCP interface
void write_sdu(uint32_t lcid, byte_buffer_t *sdu);
std::string get_rb_name(uint32_t lcid);
bool rb_is_um(uint32_t lcid);
// MAC interface
uint32_t get_buffer_state(uint32_t lcid);
@ -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);

@ -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();
@ -163,6 +164,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();

@ -56,6 +56,7 @@ public:
void configure(srslte_rlc_config_t cnfg);
void reset();
void reestablish();
void stop();
void empty_queue();
bool active();

@ -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;
@ -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)
@ -5518,6 +5544,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 +5559,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++;

@ -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; i<cgi_info->n_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; i<cgi_info->n_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; i<meas_report->meas_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; i<meas_report->meas_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);

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

@ -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
*******************************************************************************/
@ -298,6 +462,71 @@ 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);
}
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
@ -682,6 +911,183 @@ 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 < (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);
out[4 * i + 3] = msg[4 * i + 3] ^ ((ks[i] & 0xFF));
}
// Process last bytes
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);
}
// 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 +1649,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);
}
}

@ -38,6 +38,8 @@ namespace srslte{
log_filter::log_filter()
{
do_tti = false;
time_src = NULL;
time_format = TIME;
}
log_filter::log_filter(std::string layer)
@ -65,10 +67,20 @@ void log_filter::all_log(srslte::LOG_LEVEL_ENUM level,
std::stringstream ss;
ss << now_time() << " ";
if (show_layer_en) {
ss << "[" <<get_service_name() << "] ";
}
if (level_text_short) {
ss << log_level_text_short[level] << " ";
} else {
ss << log_level_text[level] << " ";
if(do_tti)
}
if(do_tti) {
ss << "[" << std::setfill('0') << std::setw(5) << tti << "] ";
}
if (add_string_en) {
ss << add_string_val << " ";
}
ss << msg;
str_ptr s_ptr(new std::string(ss.str()));
@ -86,11 +98,22 @@ void log_filter::all_log(srslte::LOG_LEVEL_ENUM level,
std::stringstream ss;
ss << now_time() << " ";
if (show_layer_en) {
ss << "[" <<get_service_name() << "] ";
}
if (level_text_short) {
ss << log_level_text_short[level] << " ";
} else {
ss << log_level_text[level] << " ";
if(do_tti)
}
if(do_tti) {
ss << "[" << std::setfill('0') << std::setw(5) << tti << "] ";
}
if (add_string_en) {
ss << add_string_val << " ";
}
ss << msg;
if (msg[strlen(msg)-1] != '\n') {
@ -105,27 +128,6 @@ void log_filter::all_log(srslte::LOG_LEVEL_ENUM level,
}
}
void log_filter::all_log_line(srslte::LOG_LEVEL_ENUM level,
uint32_t tti,
std::string file,
int line,
char *msg)
{
if(logger_h) {
std::stringstream ss;
ss << now_time() << " ";
ss << "[" <<get_service_name() << "] ";
ss << log_level_text[level] << " ";
if(do_tti)
ss << "[" << std::setfill('0') << std::setw(5) << tti << "] ";
ss << msg;
str_ptr s_ptr(new std::string(ss.str()));
logger_h->log(s_ptr);
}
}
void log_filter::console(std::string message, ...) {
char *args_msg;
va_list args;
@ -226,60 +228,11 @@ 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::set_time_src(time_itf *source, time_format_t format) {
this->time_src = source;
this->time_format = format;
}
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);
}
}
std::string log_filter::now_time()
{
struct timeval rawtime;
@ -287,13 +240,32 @@ std::string log_filter::now_time()
char buffer[64];
char us[16];
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);
}

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

@ -40,14 +40,18 @@ 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;
pcap_file = LTE_PCAP_Open(MAC_LTE_DLT, filename);
this->ue_id = ue_id;
enable_write = true;
}
void mac_pcap::close()
{
fprintf(stdout, "Saving PCAP file\n");
MAC_LTE_PCAP_Close(pcap_file);
fprintf(stdout, "Saving MAC PCAP file\n");
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,
@ -65,7 +69,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);
}
}
}

@ -0,0 +1,35 @@
#include <stdint.h>
#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 = 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");
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) {
LTE_PCAP_NAS_WritePDU(pcap_file, &context, pdu, pdu_len_bytes);
}
}
}
}

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

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

@ -61,6 +61,26 @@ 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_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,
@ -146,6 +166,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
*****************************************************************************/

@ -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, &param)) {
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;

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

@ -57,9 +57,5 @@ set(srslte_srcs $<TARGET_OBJECTS:srslte_agc>
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})

@ -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,10 +125,10 @@ 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);
q->gain = pow(10, gain_uhd_db/10);

@ -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);
@ -306,8 +318,12 @@ static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t
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;l<nsymbols;l++) {
if (ch_mode == SRSLTE_SF_MBSFN) {
if (l == 0) {
fidx_offset = srslte_refsignal_cs_fidx(q->cell, l, port_id, 0);
@ -329,6 +345,12 @@ static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t
}
/* Now interpolate in the time domain between symbols */
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);
@ -360,6 +382,7 @@ static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t
}
}
}
}
void srslte_chest_dl_set_smooth_filter(srslte_chest_dl_t *q, float *filter, uint32_t filter_len) {
@ -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;l<nsymbols;l++) {
srslte_vec_sum_ccc(&input[l*nref], input, input, nref);
}
srslte_vec_sc_prod_cfc(input, 1.0/((float) nsymbols), input, nref);
nsymbols = 1;
}
// Average in the frequency domain
for (int l=0;l<nsymbols;l++) {
srslte_conv_same_cf(&input[l*nref], q->smooth_filter, &output[l*nref], nref, q->smooth_filter_len);
@ -410,7 +442,35 @@ 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_cfo_estimate[i*npilots/4],
npilots/4);
}
// Average all angles
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;
}
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 (q->cfo_estimate_enable && ((1<<sf_idx) & q->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)) {
@ -435,12 +495,11 @@ 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));
if (port_id == 0) {
/* compute rssi only for port 0 */
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;
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)
{
@ -451,6 +510,7 @@ 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;
@ -474,10 +534,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_id<nof_rx_antennas;rxant_id++) {
@ -517,7 +573,20 @@ int srslte_chest_dl_estimate_multi_mbsfn(srslte_chest_dl_t *q, cf_t *input[SRSLT
return SRSLTE_SUCCESS;
}
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)
{
q->cfo_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;
@ -532,10 +601,21 @@ float srslte_chest_dl_get_snr(srslte_chest_dl_t *q) {
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;i<q->last_nof_antennas;i++) {
for (int j=0;j<q->cell.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(q);
}
float srslte_chest_dl_get_rssi(srslte_chest_dl_t *q) {
float n = 0;
for (int i=0;i<q->last_nof_antennas;i++) {
@ -556,6 +636,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++) {

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

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

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

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

@ -0,0 +1,61 @@
/**
*
* \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 <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <sys/types.h>
#include <stdarg.h>
#include "srslte/srslte.h"
#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;
handler_registered++;
}
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);
}

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

Loading…
Cancel
Save