Merge branch 'next'

master
Andre Puschmann 7 years ago
commit 4bbcfaa1dc

@ -42,6 +42,8 @@ include(SRSLTEPackage) #setup cpack
include(CTest) include(CTest)
set(CTEST_MEMORYCHECK_COMMAND valgrind) set(CTEST_MEMORYCHECK_COMMAND valgrind)
set(CTEST_MEMORYCHECK_COMMAND_OPTIONS "--trace-children=yes --leak-check=full" )
configure_file( configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/CTestCustom.cmake.in" "${CMAKE_CURRENT_SOURCE_DIR}/CTestCustom.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake" "${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake"
@ -74,28 +76,62 @@ set(GCC_ARCH native CACHE STRING "GCC compile for specific architecture.")
######################################################################## ########################################################################
# Find dependencies # Find dependencies
######################################################################## ########################################################################
# Threads
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
# FFT
find_package(MKL)
if(MKL_FOUND)
include_directories(${MKL_INCLUDE_DIRS})
link_directories(${MKL_LIBRARY_DIRS})
set(FFT_LIBRARIES "${MKL_STATIC_LIBRARIES}") # Static by default
else(MKL_FOUND)
find_package(FFTW3F REQUIRED)
if(FFTW3F_FOUND)
include_directories(${FFTW3F_INCLUDE_DIRS})
link_directories(${FFTW3F_LIBRARY_DIRS})
if(BUILD_STATIC)
set(FFT_LIBRARIES "${FFTW3F_STATIC_LIBRARIES}")
else(BUILD_STATIC)
set(FFT_LIBRARIES "${FFTW3F_LIBRARIES}")
endif(BUILD_STATIC)
endif(FFTW3F_FOUND)
endif(MKL_FOUND)
# Crypto
find_package(Polarssl) find_package(Polarssl)
if (POLARSSL_FOUND) if (POLARSSL_FOUND)
set(SEC_INCLUDE_DIRS "${POLARSSL_INCLUDE_DIRS}") set(SEC_INCLUDE_DIRS "${POLARSSL_INCLUDE_DIRS}")
if(BUILD_STATIC)
set(SEC_LIBRARIES "${POLARSSL_STATIC_LIBRARIES}")
else(BUILD_STATIC)
set(SEC_LIBRARIES "${POLARSSL_LIBRARIES}") set(SEC_LIBRARIES "${POLARSSL_LIBRARIES}")
endif(BUILD_STATIC)
add_definitions(-DHAVE_POLARSSL) add_definitions(-DHAVE_POLARSSL)
else(POLARSSL_FOUND) else(POLARSSL_FOUND)
find_package(MbedTLS REQUIRED) find_package(MbedTLS REQUIRED)
if (MBEDTLS_FOUND) if (MBEDTLS_FOUND)
set(SEC_INCLUDE_DIRS "${MBEDTLS_INCLUDE_DIRS}") set(SEC_INCLUDE_DIRS "${MBEDTLS_INCLUDE_DIRS}")
if(BUILD_STATIC)
set(SEC_LIBRARIES "${MBEDTLS_STATIC_LIBRARIES}")
else(BUILD_STATIC)
set(SEC_LIBRARIES "${MBEDTLS_LIBRARIES}") set(SEC_LIBRARIES "${MBEDTLS_LIBRARIES}")
endif(BUILD_STATIC)
add_definitions(-DHAVE_MBEDTLS) add_definitions(-DHAVE_MBEDTLS)
else(MBEDTLS_FOUND)
message(FATAL_ERROR "Either PolarSSL or mbedTLS are required to build srsLTE")
endif (MBEDTLS_FOUND) endif (MBEDTLS_FOUND)
endif(POLARSSL_FOUND) endif(POLARSSL_FOUND)
# UHD
find_package(UHD) find_package(UHD)
if(UHD_FOUND) if(UHD_FOUND)
include_directories(${UHD_INCLUDE_DIRS}) include_directories(${UHD_INCLUDE_DIRS})
link_directories(${UHD_LIBRARY_DIRS}) link_directories(${UHD_LIBRARY_DIRS})
endif(UHD_FOUND) endif(UHD_FOUND)
# BladeRF
if(ENABLE_BLADERF) if(ENABLE_BLADERF)
find_package(bladeRF) find_package(bladeRF)
if(BLADERF_FOUND) if(BLADERF_FOUND)
@ -104,6 +140,7 @@ if(ENABLE_BLADERF)
endif(BLADERF_FOUND) endif(BLADERF_FOUND)
endif(ENABLE_BLADERF) endif(ENABLE_BLADERF)
# Soapy
find_package(SoapySDR) find_package(SoapySDR)
if(SOAPYSDR_FOUND) if(SOAPYSDR_FOUND)
include_directories(${SOAPYSDR_INCLUDE_DIRS}) include_directories(${SOAPYSDR_INCLUDE_DIRS})
@ -117,8 +154,12 @@ else(BLADERF_FOUND OR UHD_FOUND OR SOAPYSDR_FOUND)
add_definitions(-DDISABLE_RF) add_definitions(-DDISABLE_RF)
endif(BLADERF_FOUND OR UHD_FOUND OR SOAPYSDR_FOUND) endif(BLADERF_FOUND OR UHD_FOUND OR SOAPYSDR_FOUND)
# Boost
if(ENABLE_SRSUE OR ENABLE_SRSENB) if(ENABLE_SRSUE OR ENABLE_SRSENB)
# Find Boost if(BUILD_STATIC)
set(Boost_USE_STATIC_LIBS ON)
endif(BUILD_STATIC)
set(BOOST_REQUIRED_COMPONENTS set(BOOST_REQUIRED_COMPONENTS
program_options program_options
system system
@ -138,7 +179,7 @@ if(ENABLE_SRSUE OR ENABLE_SRSENB)
find_package(Boost "1.35" COMPONENTS ${BOOST_REQUIRED_COMPONENTS}) find_package(Boost "1.35" COMPONENTS ${BOOST_REQUIRED_COMPONENTS})
endif(ENABLE_SRSUE OR ENABLE_SRSENB) endif(ENABLE_SRSUE OR ENABLE_SRSENB)
# srsGUI
if(ENABLE_GUI) if(ENABLE_GUI)
find_package(SRSGUI) find_package(SRSGUI)
if(SRSGUI_FOUND) if(SRSGUI_FOUND)
@ -148,6 +189,7 @@ if(ENABLE_GUI)
endif(SRSGUI_FOUND) endif(SRSGUI_FOUND)
endif(ENABLE_GUI) endif(ENABLE_GUI)
# VOLK
include(CheckFunctionExistsMath) include(CheckFunctionExistsMath)
if(ENABLE_VOLK) if(ENABLE_VOLK)
find_package(Volk) find_package(Volk)
@ -162,7 +204,6 @@ else(ENABLE_VOLK)
message(STATUS "VOLK library disabled") message(STATUS "VOLK library disabled")
endif(ENABLE_VOLK) endif(ENABLE_VOLK)
######################################################################## ########################################################################
# Install Dirs # Install Dirs
######################################################################## ########################################################################

@ -7,7 +7,7 @@ SET(CTEST_CUSTOM_MEMCHECK_IGNORE
realplot_test realplot_test
complexplot_test complexplot_test
# Ignore these to, they take too lonk # Ignore these to, they take too long
fft_normal fft_normal
fft_extened fft_extened
chest_test_all_cellids chest_test_all_cellids

@ -15,11 +15,12 @@ srsLTE is released under the AGPLv3 license and uses software from the OpenLTE p
Common Features Common Features
--------------- ---------------
* LTE Release 8 compliant * LTE Release 8 compliant (with selected features of Release 9)
* FDD configuration * FDD configuration
* Tested bandwidths: 1.4, 3, 5, 10, 15 and 20 MHz * Tested bandwidths: 1.4, 3, 5, 10, 15 and 20 MHz
* Transmission mode 1 (single antenna) and 2 (transmit diversity) * Transmission mode 1 (single antenna), 2 (transmit diversity), 3 (transmit diversity/CCD) and 4 (closed-loop spatial multiplexing)
* Frequency-based ZF and MMSE equalizer * Frequency-based ZF and MMSE equalizer
* Evolved multimedia broadcast and multicast service (eMBMS)
* Highly optimized Turbo Decoder available in Intel SSE4.1/AVX (+100 Mbps) and standard C (+25 Mbps) * Highly optimized Turbo Decoder available in Intel SSE4.1/AVX (+100 Mbps) and standard C (+25 Mbps)
* MAC, RLC, PDCP, RRC, NAS, S1AP and GW layers * MAC, RLC, PDCP, RRC, NAS, S1AP and GW layers
* Detailed log system with per-layer log levels and hex dumps * Detailed log system with per-layer log levels and hex dumps
@ -33,6 +34,7 @@ srsUE Features
* Cell search and synchronization procedure for the UE * Cell search and synchronization procedure for the UE
* Soft USIM supporting Milenage and XOR authentication * Soft USIM supporting Milenage and XOR authentication
* Virtual network interface *tun_srsue* created upon network attach * Virtual network interface *tun_srsue* created upon network attach
* +100 Mbps DL in 20 MHz MIMO TM4 configuration in i7 Quad-Core CPU.
* 75 Mbps DL in 20 MHz SISO configuration in i7 Quad-Core CPU. * 75 Mbps DL in 20 MHz SISO configuration in i7 Quad-Core CPU.
* 36 Mbps DL in 10 MHz SISO configuration in i5 Dual-Core CPU. * 36 Mbps DL in 10 MHz SISO configuration in i5 Dual-Core CPU.
@ -65,13 +67,14 @@ We have tested the following hardware:
* USRP B210 * USRP B210
* USRP X300 * USRP X300
* bladeRF * bladeRF
* limeSDR * limeSDR (currently, only the PHY-layer examples, i.e., pdsch_enodeb/ue are supported)
Build Instructions Build Instructions
------------------ ------------------
* Mandatory requirements: * Mandatory requirements:
* Common: * Common:
* cmake https://cmake.org/
* libfftw http://www.fftw.org/ * libfftw http://www.fftw.org/
* PolarSSL/mbedTLS https://tls.mbed.org * PolarSSL/mbedTLS https://tls.mbed.org
* srsUE: * srsUE:
@ -83,7 +86,7 @@ Build Instructions
For example, on Ubuntu 17.04, one can install the required libraries with: For example, on Ubuntu 17.04, one can install the required libraries with:
``` ```
sudo apt-get install libfftw3-dev libmbedtls-dev libboost-all-dev libconfig++-dev libsctp-dev sudo apt-get install cmake libfftw3-dev libmbedtls-dev libboost-all-dev libconfig++-dev libsctp-dev
``` ```
Note that depending on your flavor and version of Linux, the actual package names may be different. Note that depending on your flavor and version of Linux, the actual package names may be different.

@ -15,6 +15,12 @@ find_path(FFTW3F_INCLUDE_DIR
PATHS /usr/local/include PATHS /usr/local/include
/usr/include ) /usr/include )
find_library(FFTW3F_STATIC_LIBRARY
NAMES fftw3f.a libfftw3f.a libfftw3f-3.a
HINTS ${PC_FFTW3F_LIBDIR} ${PC_FFTW3F_LIBRARY_DIRS} $ENV{FFTW3_DIR}/lib
PATHS /usr/local/lib
/usr/lib)
find_library(FFTW3F_LIBRARY find_library(FFTW3F_LIBRARY
NAMES fftw3f libfftw3f libfftw3f-3 NAMES fftw3f libfftw3f libfftw3f-3
HINTS ${PC_FFTW3F_LIBDIR} ${PC_FFTW3F_LIBRARY_DIRS} $ENV{FFTW3_DIR}/lib HINTS ${PC_FFTW3F_LIBDIR} ${PC_FFTW3F_LIBRARY_DIRS} $ENV{FFTW3_DIR}/lib
@ -22,12 +28,17 @@ find_library(FFTW3F_LIBRARY
/usr/lib) /usr/lib)
set(FFTW3F_LIBRARIES ${FFTW3F_LIBRARY} ) set(FFTW3F_LIBRARIES ${FFTW3F_LIBRARY} )
set(FFTW3F_STATIC_LIBRARIES ${FFTW3F_STATIC_LIBRARY} )
set(FFTW3F_INCLUDE_DIRS ${FFTW3F_INCLUDE_DIR} ) set(FFTW3F_INCLUDE_DIRS ${FFTW3F_INCLUDE_DIR} )
message(STATUS "FFTW3F LIBRARIES: " ${FFTW3F_LIBRARIES})
message(STATUS "FFTW3F STATIC LIBRARIES: " ${FFTW3F_STATIC_LIBRARIES})
message(STATUS "FFTW3F INCLUDE DIRS: " ${FFTW3F_INCLUDE_DIRS})
include(FindPackageHandleStandardArgs) include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set FFTW3F_FOUND to TRUE # handle the QUIETLY and REQUIRED arguments and set FFTW3F_FOUND to TRUE
# if all listed variables are TRUE # if all listed variables are TRUE
find_package_handle_standard_args(fftw3f DEFAULT_MSG find_package_handle_standard_args(fftw3f DEFAULT_MSG
FFTW3F_LIBRARY FFTW3F_INCLUDE_DIR) FFTW3F_LIBRARY FFTW3F_STATIC_LIBRARY FFTW3F_INCLUDE_DIR)
mark_as_advanced(FFTW3F_INCLUDE_DIR FFTW3F_LIBRARY ) mark_as_advanced(FFTW3F_INCLUDE_DIR FFTW3F_STATIC_LIBRARY FFTW3F_LIBRARY )

@ -32,9 +32,23 @@ FIND_LIBRARY(
/usr/lib64 /usr/lib64
) )
FIND_LIBRARY(
MBEDTLS_STATIC_LIBRARIES
NAMES libmbedcrypto.a
HINTS $ENV{MBEDTLS_DIR}/lib
${PC_MBEDTLS_LIBDIR}
${CMAKE_INSTALL_PREFIX}/lib
${CMAKE_INSTALL_PREFIX}/lib64
PATHS /usr/local/lib
/usr/local/lib64
/usr/lib
/usr/lib64
)
message(STATUS "MBEDTLS LIBRARIES: " ${MBEDTLS_LIBRARIES}) message(STATUS "MBEDTLS LIBRARIES: " ${MBEDTLS_LIBRARIES})
message(STATUS "MBEDTLS STATIC LIBRARIES: " ${MBEDTLS_STATIC_LIBRARIES})
message(STATUS "MBEDTLS INCLUDE DIRS: " ${MBEDTLS_INCLUDE_DIRS}) message(STATUS "MBEDTLS INCLUDE DIRS: " ${MBEDTLS_INCLUDE_DIRS})
INCLUDE(FindPackageHandleStandardArgs) INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(MBEDTLS DEFAULT_MSG MBEDTLS_LIBRARIES MBEDTLS_INCLUDE_DIRS) FIND_PACKAGE_HANDLE_STANDARD_ARGS(MBEDTLS DEFAULT_MSG MBEDTLS_LIBRARIES MBEDTLS_INCLUDE_DIRS)
MARK_AS_ADVANCED(MBEDTLS_LIBRARIES MBEDTLS_INCLUDE_DIRS) MARK_AS_ADVANCED(MBEDTLS_LIBRARIES MBEDTLS_STATIC_LIBRARIES MBEDTLS_INCLUDE_DIRS)

@ -31,9 +31,23 @@ FIND_LIBRARY(
/usr/lib64 /usr/lib64
) )
FIND_LIBRARY(
POLARSSL_STATIC_LIBRARIES
NAMES libpolarssl.a
HINTS $ENV{POLARSSL_DIR}/lib
${PC_POLARSSL_LIBDIR}
${CMAKE_INSTALL_PREFIX}/lib
${CMAKE_INSTALL_PREFIX}/lib64
PATHS /usr/local/lib
/usr/local/lib64
/usr/lib
/usr/lib64
)
message(STATUS "POLARSSL LIBRARIES: " ${POLARSSL_LIBRARIES}) message(STATUS "POLARSSL LIBRARIES: " ${POLARSSL_LIBRARIES})
message(STATUS "POLARSSL STATIC LIBRARIES: " ${POLARSSL_STATIC_LIBRARIES})
message(STATUS "POLARSSL INCLUDE DIRS: " ${POLARSSL_INCLUDE_DIRS}) message(STATUS "POLARSSL INCLUDE DIRS: " ${POLARSSL_INCLUDE_DIRS})
INCLUDE(FindPackageHandleStandardArgs) INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(POLARSSL DEFAULT_MSG POLARSSL_LIBRARIES POLARSSL_INCLUDE_DIRS) FIND_PACKAGE_HANDLE_STANDARD_ARGS(POLARSSL DEFAULT_MSG POLARSSL_LIBRARIES POLARSSL_INCLUDE_DIRS)
MARK_AS_ADVANCED(POLARSSL_LIBRARIES POLARSSL_INCLUDE_DIRS) MARK_AS_ADVANCED(POLARSSL_STATIC_LIBRARIES POLARSSL_LIBRARIES POLARSSL_INCLUDE_DIRS)

@ -7,6 +7,7 @@ include(CheckCSourceRuns)
option(ENABLE_SSE "Enable compile-time SSE4.1 support." ON) option(ENABLE_SSE "Enable compile-time SSE4.1 support." ON)
option(ENABLE_AVX "Enable compile-time AVX support." ON) option(ENABLE_AVX "Enable compile-time AVX support." ON)
option(ENABLE_AVX2 "Enable compile-time AVX2 support." ON) option(ENABLE_AVX2 "Enable compile-time AVX2 support." ON)
option(ENABLE_FMA "Enable compile-time FMA support." ON)
if (ENABLE_SSE) if (ENABLE_SSE)
# #
@ -99,6 +100,41 @@ if (ENABLE_SSE)
endif() endif()
endif() endif()
if (ENABLE_FMA)
#
# Check compiler for AVX intrinsics
#
if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG )
set(CMAKE_REQUIRED_FLAGS "-mfma")
check_c_source_runs("
#include <immintrin.h>
int main()
{
__m256 a, b, c, r;
const float src[8] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f };
float dst[8];
a = _mm256_loadu_ps( src );
b = _mm256_loadu_ps( src );
c = _mm256_loadu_ps( src );
r = _mm256_fmadd_ps( a, b, c );
_mm256_storeu_ps( dst, r );
int i = 0;
for( i = 0; i < 8; i++ ){
if( ( src[i] * src[i] + src[i] ) != dst[i] ){
return -1;
}
}
return 0;
}"
HAVE_FMA)
endif()
if (HAVE_FMA)
message(STATUS "FMA is enabled - target CPU must support it")
endif()
endif()
endif() endif()
mark_as_advanced(HAVE_SSE, HAVE_AVX, HAVE_AVX2) mark_as_advanced(HAVE_SSE, HAVE_AVX, HAVE_AVX2, HAVE_FMA)

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

@ -18,7 +18,7 @@
# and at http://www.gnu.org/licenses/. # and at http://www.gnu.org/licenses/.
# #
SET(SRSLTE_VERSION_MAJOR 002) SET(SRSLTE_VERSION_MAJOR 17)
SET(SRSLTE_VERSION_MINOR 000) SET(SRSLTE_VERSION_MINOR 9)
SET(SRSLTE_VERSION_PATCH 000) SET(SRSLTE_VERSION_PATCH 0)
SET(SRSLTE_VERSION_STRING "${SRSLTE_VERSION_MAJOR}.${SRSLTE_VERSION_MINOR}.${SRSLTE_VERSION_PATCH}") SET(SRSLTE_VERSION_STRING "${SRSLTE_VERSION_MAJOR}.${SRSLTE_VERSION_MINOR}.${SRSLTE_VERSION_PATCH}")

@ -118,7 +118,7 @@ int parse_args(prog_args_t *args, int argc, char **argv) {
/**********************************************************************/ /**********************************************************************/
/* TODO: Do something with the output data */ /* TODO: Do something with the output data */
uint8_t data[1000000]; uint8_t *data[SRSLTE_MAX_CODEWORDS];
bool go_exit = false; bool go_exit = false;
void sig_int_handler(int signo) void sig_int_handler(int signo)
@ -161,6 +161,7 @@ int main(int argc, char **argv) {
float rssi_utra=0,rssi=0, rsrp=0, rsrq=0, snr=0; float rssi_utra=0,rssi=0, rsrp=0, rsrq=0, snr=0;
cf_t *ce[SRSLTE_MAX_PORTS]; cf_t *ce[SRSLTE_MAX_PORTS];
float cfo = 0; float cfo = 0;
bool acks[SRSLTE_MAX_CODEWORDS] = {false};
if (parse_args(&prog_args, argc, argv)) { if (parse_args(&prog_args, argc, argv)) {
exit(-1); exit(-1);
@ -183,6 +184,9 @@ int main(int argc, char **argv) {
} }
sf_buffer[0] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(100)); sf_buffer[0] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(100));
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
data[i] = srslte_vec_malloc(sizeof(uint8_t) * 1500*8);
}
sigset_t sigset; sigset_t sigset;
sigemptyset(&sigset); sigemptyset(&sigset);
@ -237,15 +241,27 @@ int main(int argc, char **argv) {
srslte_rf_stop_rx_stream(&rf); srslte_rf_stop_rx_stream(&rf);
srslte_rf_flush_buffer(&rf); srslte_rf_flush_buffer(&rf);
if (srslte_ue_sync_init_multi(&ue_sync, cell, srslte_rf_recv_wrapper, 1, (void*) &rf)) { if (srslte_ue_sync_init_multi(&ue_sync, cell.nof_prb, cell.id==1000, srslte_rf_recv_wrapper, 1, (void*) &rf)) {
fprintf(stderr, "Error initiating ue_sync\n");
return -1;
}
if (srslte_ue_sync_set_cell(&ue_sync, cell)) {
fprintf(stderr, "Error initiating ue_sync\n"); fprintf(stderr, "Error initiating ue_sync\n");
return -1; return -1;
} }
if (srslte_ue_dl_init_multi(&ue_dl, cell, 1)) { if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, 1)) {
fprintf(stderr, "Error initiating UE downlink processing module\n"); fprintf(stderr, "Error initiating UE downlink processing module\n");
return -1; return -1;
} }
if (srslte_ue_mib_init(&ue_mib, cell)) { if (srslte_ue_dl_set_cell(&ue_dl, cell)) {
fprintf(stderr, "Error initiating UE downlink processing module\n");
return -1;
}
if (srslte_ue_mib_init(&ue_mib, cell.nof_prb)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
return -1;
}
if (srslte_ue_mib_set_cell(&ue_mib, cell)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n"); fprintf(stderr, "Error initaiting UE MIB decoder\n");
return -1; return -1;
} }
@ -260,7 +276,11 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error initiating FFT\n"); fprintf(stderr, "Error initiating FFT\n");
return -1; return -1;
} }
if (srslte_chest_dl_init(&chest, cell)) { if (srslte_chest_dl_init(&chest, cell.nof_prb)) {
fprintf(stderr, "Error initiating channel estimator\n");
return -1;
}
if (srslte_chest_dl_set_cell(&chest, cell)) {
fprintf(stderr, "Error initiating channel estimator\n"); fprintf(stderr, "Error initiating channel estimator\n");
return -1; return -1;
} }
@ -310,19 +330,18 @@ int main(int argc, char **argv) {
case DECODE_SIB: case DECODE_SIB:
/* We are looking for SI Blocks, search only in appropiate places */ /* We are looking for SI Blocks, search only in appropiate places */
if ((srslte_ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%2)==0)) { if ((srslte_ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%2)==0)) {
n = srslte_ue_dl_decode_multi(&ue_dl, sf_buffer, data, sfn*10+srslte_ue_sync_get_sfidx(&ue_sync)); n = srslte_ue_dl_decode(&ue_dl, sf_buffer, data, 0, sfn*10+srslte_ue_sync_get_sfidx(&ue_sync), acks);
if (n < 0) { if (n < 0) {
fprintf(stderr, "Error decoding UE DL\n");fflush(stdout); fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);
return -1; return -1;
} else if (n == 0) { } else if (n == 0) {
printf("CFO: %+6.4f kHz, SFO: %+6.4f kHz, NOI: %.2f, PDCCH-Det: %.3f\r", printf("CFO: %+6.4f kHz, SFO: %+6.4f kHz, PDCCH-Det: %.3f\r",
srslte_ue_sync_get_cfo(&ue_sync)/1000, srslte_ue_sync_get_sfo(&ue_sync)/1000, srslte_ue_sync_get_cfo(&ue_sync)/1000, srslte_ue_sync_get_sfo(&ue_sync)/1000,
srslte_sch_average_noi(&ue_dl.pdsch.dl_sch),
(float) ue_dl.nof_detected/nof_trials); (float) ue_dl.nof_detected/nof_trials);
nof_trials++; nof_trials++;
} else { } else {
printf("Decoded SIB1. Payload: "); printf("Decoded SIB1. Payload: ");
srslte_vec_fprint_byte(stdout, data, n/8);; srslte_vec_fprint_byte(stdout, data[0], n/8);;
state = MEASURE; state = MEASURE;
} }
} }
@ -386,6 +405,12 @@ int main(int argc, char **argv) {
sf_cnt++; sf_cnt++;
} // Main loop } // Main loop
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (data[i]) {
free(data[i]);
}
}
srslte_ue_sync_free(&ue_sync); srslte_ue_sync_free(&ue_sync);
srslte_rf_close(&rf); srslte_rf_close(&rf);
printf("\nBye\n"); printf("\nBye\n");

@ -188,6 +188,18 @@ int main(int argc, char **argv) {
sigprocmask(SIG_UNBLOCK, &sigset, NULL); sigprocmask(SIG_UNBLOCK, &sigset, NULL);
signal(SIGINT, sig_int_handler); signal(SIGINT, sig_int_handler);
if (srslte_ue_cellsearch_init_multi(&cs, cell_detect_config.max_frames_pss, srslte_rf_recv_wrapper, 1, (void*) &rf)) {
fprintf(stderr, "Error initiating UE cell detect\n");
exit(-1);
}
if (cell_detect_config.max_frames_pss) {
srslte_ue_cellsearch_set_nof_valid_frames(&cs, cell_detect_config.nof_valid_pss_frames);
}
if (cell_detect_config.init_agc) {
srslte_ue_sync_start_agc(&cs.ue_sync, srslte_rf_set_rx_gain_wrapper, cell_detect_config.init_agc);
}
for (freq=0;freq<nof_freqs && !go_exit;freq++) { for (freq=0;freq<nof_freqs && !go_exit;freq++) {
/* set rf_freq */ /* set rf_freq */
@ -204,25 +216,12 @@ int main(int argc, char **argv) {
bzero(found_cells, 3*sizeof(srslte_ue_cellsearch_result_t)); bzero(found_cells, 3*sizeof(srslte_ue_cellsearch_result_t));
if (srslte_ue_cellsearch_init_multi(&cs, cell_detect_config.max_frames_pss, srslte_rf_recv_wrapper, 1, (void*) &rf)) {
fprintf(stderr, "Error initiating UE cell detect\n");
exit(-1);
}
if (cell_detect_config.max_frames_pss) {
srslte_ue_cellsearch_set_nof_valid_frames(&cs, cell_detect_config.nof_valid_pss_frames);
}
if (cell_detect_config.init_agc) {
srslte_ue_sync_start_agc(&cs.ue_sync, srslte_rf_set_rx_gain_wrapper, cell_detect_config.init_agc);
}
INFO("Setting sampling frequency %.2f MHz for PSS search\n", SRSLTE_CS_SAMP_FREQ/1000000); INFO("Setting sampling frequency %.2f MHz for PSS search\n", SRSLTE_CS_SAMP_FREQ/1000000);
srslte_rf_set_rx_srate(&rf, SRSLTE_CS_SAMP_FREQ); srslte_rf_set_rx_srate(&rf, SRSLTE_CS_SAMP_FREQ);
INFO("Starting receiver...\n", 0); INFO("Starting receiver...\n", 0);
srslte_rf_start_rx_stream(&rf); srslte_rf_start_rx_stream(&rf);
n = srslte_ue_cellsearch_scan(&cs, found_cells, NULL); n = srslte_ue_cellsearch_scan(&cs, found_cells, NULL);
srslte_ue_cellsearch_free(&cs);
if (n < 0) { if (n < 0) {
fprintf(stderr, "Error searching cell\n"); fprintf(stderr, "Error searching cell\n");
exit(-1); exit(-1);
@ -269,6 +268,7 @@ int main(int argc, char **argv) {
printf("\nBye\n"); printf("\nBye\n");
srslte_ue_cellsearch_free(&cs);
srslte_rf_close(&rf); srslte_rf_close(&rf);
exit(0); exit(0);
} }

@ -33,15 +33,18 @@
#include <pthread.h> #include <pthread.h>
#include <semaphore.h> #include <semaphore.h>
#include <signal.h> #include <signal.h>
#include <srslte/phy/common/phy_common.h>
#include <srslte/phy/phch/pdsch_cfg.h>
#include "srslte/srslte.h" #include "srslte/srslte.h"
#define UE_CRNTI 0x1234 #define UE_CRNTI 0x1234
#define M_CRNTI 0xFFFD
#ifndef DISABLE_RF #ifndef DISABLE_RF
#include "srslte/phy/rf/rf.h" #include "srslte/phy/rf/rf.h"
#include "srslte/phy/common/phy_common.h"
srslte_rf_t rf; srslte_rf_t rf;
#else #else
#warning Compiling pdsch_ue with no RF support #warning Compiling pdsch_ue with no RF support
@ -59,32 +62,47 @@ srslte_cell_t cell = {
1, // nof_ports 1, // nof_ports
0, // cell_id 0, // cell_id
SRSLTE_CP_NORM, // cyclic prefix SRSLTE_CP_NORM, // cyclic prefix
SRSLTE_PHICH_R_1, // PHICH resources SRSLTE_PHICH_NORM, // PHICH length
SRSLTE_PHICH_NORM // PHICH length SRSLTE_PHICH_R_1 // PHICH resources
}; };
uint16_t c = -1;
int net_port = -1; // -1 generates random dataThat means there is some problem sending samples to the device int net_port = -1; // -1 generates random dataThat means there is some problem sending samples to the device
uint32_t cfi=3; uint32_t cfi = 2;
uint32_t mcs_idx = 1, last_mcs_idx = 1; uint32_t mcs_idx = 1, last_mcs_idx = 1;
int nof_frames = -1; int nof_frames = -1;
char mimo_type_str[32] = "single";
uint32_t nof_tb = 1;
uint32_t multiplex_pmi = 0;
uint32_t multiplex_nof_layers = 1;
int mbsfn_area_id = -1;
char *rf_args = ""; char *rf_args = "";
float rf_amp = 0.8, rf_gain = 70.0, rf_freq = 2400000000; float rf_amp = 0.8, rf_gain = 70.0, rf_freq = 2400000000;
bool null_file_sink=false; bool null_file_sink=false;
srslte_filesink_t fsink; srslte_filesink_t fsink;
srslte_ofdm_t ifft; srslte_ofdm_t ifft;
srslte_ofdm_t ifft_mbsfn;
srslte_pbch_t pbch; srslte_pbch_t pbch;
srslte_pcfich_t pcfich; srslte_pcfich_t pcfich;
srslte_pdcch_t pdcch; srslte_pdcch_t pdcch;
srslte_pdsch_t pdsch; srslte_pdsch_t pdsch;
srslte_pdsch_cfg_t pdsch_cfg; srslte_pdsch_cfg_t pdsch_cfg;
srslte_softbuffer_tx_t softbuffer; srslte_pmch_t pmch;
srslte_pdsch_cfg_t pmch_cfg;
srslte_softbuffer_tx_t *softbuffers[SRSLTE_MAX_CODEWORDS];
srslte_regs_t regs; srslte_regs_t regs;
srslte_ra_dl_dci_t ra_dl; srslte_ra_dl_dci_t ra_dl;
int rvidx[SRSLTE_MAX_CODEWORDS] = {0, 0};
cf_t *sf_buffer[SRSLTE_MAX_PORTS] = {NULL}, *output_buffer [SRSLTE_MAX_PORTS] = {NULL};
cf_t *sf_buffer = NULL, *output_buffer = NULL;
int sf_n_re, sf_n_samples; int sf_n_re, sf_n_samples;
pthread_t net_thread; pthread_t net_thread;
@ -94,12 +112,20 @@ bool net_packet_ready = false;
srslte_netsource_t net_source; srslte_netsource_t net_source;
srslte_netsink_t net_sink; srslte_netsink_t net_sink;
int prbset_num = 1, last_prbset_num = 1; int prbset_num = 1, last_prbset_num = 1;
int prbset_orig = 0; int prbset_orig = 0;
//#define DATA_BUFF_SZ 1024*128
//uint8_t data[8*DATA_BUFF_SZ], data2[DATA_BUFF_SZ];
//uint8_t data_tmp[DATA_BUFF_SZ];
#define DATA_BUFF_SZ 1024*1024
uint8_t *data[2], data2[DATA_BUFF_SZ];
uint8_t data_tmp[DATA_BUFF_SZ];
void usage(char *prog) { void usage(char *prog) {
printf("Usage: %s [agmfoncvpu]\n", prog); printf("Usage: %s [agmfoncvpuxb]\n", prog);
#ifndef DISABLE_RF #ifndef DISABLE_RF
printf("\t-a RF args [Default %s]\n", rf_args); printf("\t-a RF args [Default %s]\n", rf_args);
printf("\t-l RF amplitude [Default %.2f]\n", rf_amp); printf("\t-l RF amplitude [Default %.2f]\n", rf_amp);
@ -113,13 +139,20 @@ void usage(char *prog) {
printf("\t-n number of frames [Default %d]\n", nof_frames); printf("\t-n number of frames [Default %d]\n", nof_frames);
printf("\t-c cell id [Default %d]\n", cell.id); printf("\t-c cell id [Default %d]\n", cell.id);
printf("\t-p nof_prb [Default %d]\n", cell.nof_prb); printf("\t-p nof_prb [Default %d]\n", cell.nof_prb);
printf("\t-M MBSFN area id [Default %d]\n", mbsfn_area_id);
printf("\t-x Transmission mode[single|diversity|cdd|multiplex] [Default %s]\n", mimo_type_str);
printf("\t-b Precoding Matrix Index (multiplex mode only)* [Default %d]\n", multiplex_pmi);
printf("\t-w Number of codewords/layers (multiplex mode only)* [Default %d]\n", multiplex_nof_layers);
printf("\t-u listen TCP port for input data (-1 is random) [Default %d]\n", net_port); printf("\t-u listen TCP port for input data (-1 is random) [Default %d]\n", net_port);
printf("\t-v [set srslte_verbose to debug, default none]\n"); printf("\t-v [set srslte_verbose to debug, default none]\n");
printf("\n");
printf("\t*: See 3GPP 36.212 Table 5.3.3.1.5-4 for more information\n");
} }
void parse_args(int argc, char **argv) { void parse_args(int argc, char **argv) {
int opt; int opt;
while ((opt = getopt(argc, argv, "aglfmoncpvu")) != -1) { while ((opt = getopt(argc, argv, "aglfmoncpvutxbwM")) != -1) {
switch (opt) { switch (opt) {
case 'a': case 'a':
rf_args = argv[optind]; rf_args = argv[optind];
@ -151,6 +184,18 @@ void parse_args(int argc, char **argv) {
case 'c': case 'c':
cell.id = atoi(argv[optind]); cell.id = atoi(argv[optind]);
break; break;
case 'x':
strncpy(mimo_type_str, argv[optind], 32);
break;
case 'b':
multiplex_pmi = (uint32_t) atoi(argv[optind]);
break;
case 'w':
multiplex_nof_layers = (uint32_t) atoi(argv[optind]);
break;
case 'M':
mbsfn_area_id = atoi(argv[optind]);
break;
case 'v': case 'v':
srslte_verbose++; srslte_verbose++;
break; break;
@ -168,18 +213,62 @@ void parse_args(int argc, char **argv) {
} }
void base_init() { void base_init() {
int i;
/* Select transmission mode */
if (srslte_str2mimotype(mimo_type_str, &pdsch_cfg.mimo_type)) {
ERROR("Wrong transmission mode! Allowed modes: single, diversity, cdd and multiplex");
exit(-1);
}
/* Configure cell and PDSCH in function of the transmission mode */
switch(pdsch_cfg.mimo_type) {
case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA:
cell.nof_ports = 1;
break;
case SRSLTE_MIMO_TYPE_TX_DIVERSITY:
cell.nof_ports = 2;
break;
case SRSLTE_MIMO_TYPE_CDD:
cell.nof_ports = 2;
break;
case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX:
cell.nof_ports = 2;
break;
default:
ERROR("Transmission mode not implemented.");
exit(-1);
}
/* Allocate memory */
for(i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
data[i] = srslte_vec_malloc(sizeof(uint8_t) * SOFTBUFFER_SIZE);
if (!data[i]) {
perror("malloc");
exit(-1);
}
bzero(data[i], sizeof(uint8_t) * SOFTBUFFER_SIZE);
}
/* init memory */ /* init memory */
sf_buffer = srslte_vec_malloc(sizeof(cf_t) * sf_n_re); for (i = 0; i < SRSLTE_MAX_PORTS; i++) {
if (!sf_buffer) { sf_buffer[i] = srslte_vec_malloc(sizeof(cf_t) * sf_n_re);
if (!sf_buffer[i]) {
perror("malloc"); perror("malloc");
exit(-1); exit(-1);
} }
output_buffer = srslte_vec_malloc(sizeof(cf_t) * sf_n_samples); }
if (!output_buffer) {
for (i = 0; i < SRSLTE_MAX_PORTS; i++) {
output_buffer[i] = srslte_vec_malloc(sizeof(cf_t) * sf_n_samples);
if (!output_buffer[i]) {
perror("malloc"); perror("malloc");
exit(-1); exit(-1);
} }
bzero(output_buffer[i], sizeof(cf_t) * sf_n_samples);
}
/* open file or USRP */ /* open file or USRP */
if (output_file_name) { if (output_file_name) {
if (strcmp(output_file_name, "NULL")) { if (strcmp(output_file_name, "NULL")) {
@ -194,7 +283,7 @@ void base_init() {
} else { } else {
#ifndef DISABLE_RF #ifndef DISABLE_RF
printf("Opening RF device...\n"); printf("Opening RF device...\n");
if (srslte_rf_open(&rf, rf_args)) { if (srslte_rf_open_multi(&rf, rf_args, cell.nof_ports)) {
fprintf(stderr, "Error opening rf\n"); fprintf(stderr, "Error opening rf\n");
exit(-1); exit(-1);
} }
@ -226,18 +315,36 @@ void base_init() {
fprintf(stderr, "Error creating iFFT object\n"); fprintf(stderr, "Error creating iFFT object\n");
exit(-1); exit(-1);
} }
if (srslte_ofdm_tx_init_mbsfn(&ifft_mbsfn, SRSLTE_CP_EXT, 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); srslte_ofdm_set_normalize(&ifft, true);
if (srslte_pbch_init(&pbch, cell)) {
if (srslte_pbch_init(&pbch)) {
fprintf(stderr, "Error creating PBCH object\n"); fprintf(stderr, "Error creating PBCH object\n");
exit(-1); exit(-1);
} }
if (srslte_pbch_set_cell(&pbch, cell)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
if (srslte_regs_init(&regs, cell)) { if (srslte_regs_init(&regs, cell)) {
fprintf(stderr, "Error initiating regs\n"); fprintf(stderr, "Error initiating regs\n");
exit(-1); exit(-1);
} }
if (srslte_pcfich_init(&pcfich, 1)) {
if (srslte_pcfich_init(&pcfich, &regs, cell)) { fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
if (srslte_pcfich_set_cell(&pcfich, &regs, cell)) {
fprintf(stderr, "Error creating PBCH object\n"); fprintf(stderr, "Error creating PBCH object\n");
exit(-1); exit(-1);
} }
@ -247,39 +354,82 @@ void base_init() {
exit(-1); exit(-1);
} }
if (srslte_pdcch_init(&pdcch, &regs, cell)) { if (srslte_pdcch_init_enb(&pdcch, cell.nof_prb)) {
fprintf(stderr, "Error creating PDCCH object\n");
exit(-1);
}
if (srslte_pdcch_set_cell(&pdcch, &regs, cell)) {
fprintf(stderr, "Error creating PDCCH object\n"); fprintf(stderr, "Error creating PDCCH object\n");
exit(-1); exit(-1);
} }
if (srslte_pdsch_init(&pdsch, cell)) { if (srslte_pdsch_init_enb(&pdsch, cell.nof_prb)) {
fprintf(stderr, "Error creating PDSCH object\n");
exit(-1);
}
if (srslte_pdsch_set_cell(&pdsch, cell)) {
fprintf(stderr, "Error creating PDSCH object\n"); fprintf(stderr, "Error creating PDSCH object\n");
exit(-1); exit(-1);
} }
srslte_pdsch_set_rnti(&pdsch, UE_CRNTI); srslte_pdsch_set_rnti(&pdsch, UE_CRNTI);
if (srslte_softbuffer_tx_init(&softbuffer, cell.nof_prb)) {
if(mbsfn_area_id > -1){
if (srslte_pmch_init(&pmch, cell.nof_prb)) {
fprintf(stderr, "Error creating PMCH object\n");
}
srslte_pmch_set_area_id(&pmch, mbsfn_area_id);
}
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
softbuffers[i] = calloc(sizeof(srslte_softbuffer_tx_t), 1);
if (!softbuffers[i]) {
fprintf(stderr, "Error allocating soft buffer\n");
exit(-1);
}
if (srslte_softbuffer_tx_init(softbuffers[i], cell.nof_prb)) {
fprintf(stderr, "Error initiating soft buffer\n"); fprintf(stderr, "Error initiating soft buffer\n");
exit(-1); exit(-1);
} }
}
} }
void base_free() {
srslte_softbuffer_tx_free(&softbuffer); void base_free() {
int i;
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
srslte_softbuffer_tx_free(softbuffers[i]);
if (softbuffers[i]) {
free(softbuffers[i]);
}
}
srslte_pdsch_free(&pdsch); srslte_pdsch_free(&pdsch);
srslte_pdcch_free(&pdcch); srslte_pdcch_free(&pdcch);
srslte_regs_free(&regs); srslte_regs_free(&regs);
srslte_pbch_free(&pbch); srslte_pbch_free(&pbch);
if(mbsfn_area_id > -1){
srslte_pmch_free(&pmch);
}
srslte_ofdm_tx_free(&ifft_mbsfn);
srslte_ofdm_tx_free(&ifft); srslte_ofdm_tx_free(&ifft);
if (sf_buffer) {
free(sf_buffer); for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (data[i]) {
free(data[i]);
}
}
for (i = 0; i < SRSLTE_MAX_PORTS; i++) {
if (sf_buffer[i]) {
free(sf_buffer[i]);
}
if (output_buffer[i]) {
free(output_buffer[i]);
} }
if (output_buffer) {
free(output_buffer);
} }
if (output_file_name) { if (output_file_name) {
if (!null_file_sink) { if (!null_file_sink) {
@ -333,22 +483,65 @@ uint32_t prbset_to_bitmask() {
int update_radl() { int update_radl() {
/* Configure cell and PDSCH in function of the transmission mode */
switch(pdsch_cfg.mimo_type) {
case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA:
pdsch_cfg.nof_layers = 1;
nof_tb = 1;
break;
case SRSLTE_MIMO_TYPE_TX_DIVERSITY:
pdsch_cfg.nof_layers = 2;
nof_tb = 1;
break;
case SRSLTE_MIMO_TYPE_CDD:
pdsch_cfg.nof_layers = 2;
nof_tb = 2;
break;
case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX:
pdsch_cfg.nof_layers = multiplex_nof_layers;
nof_tb = multiplex_nof_layers;
break;
default:
ERROR("Transmission mode not implemented.");
exit(-1);
}
bzero(&ra_dl, sizeof(srslte_ra_dl_dci_t)); bzero(&ra_dl, sizeof(srslte_ra_dl_dci_t));
ra_dl.harq_process = 0; ra_dl.harq_process = 0;
ra_dl.mcs_idx = mcs_idx; ra_dl.mcs_idx = mcs_idx;
ra_dl.ndi = 0; ra_dl.ndi = 0;
ra_dl.rv_idx = 0; ra_dl.rv_idx = rvidx[0];
ra_dl.alloc_type = SRSLTE_RA_ALLOC_TYPE0; ra_dl.alloc_type = SRSLTE_RA_ALLOC_TYPE0;
ra_dl.type0_alloc.rbg_bitmask = prbset_to_bitmask(); ra_dl.type0_alloc.rbg_bitmask = prbset_to_bitmask();
ra_dl.tb_en[0] = 1; ra_dl.tb_en[0] = 1;
if (nof_tb > 1) {
ra_dl.mcs_idx_1 = mcs_idx;
ra_dl.ndi_1 = 0;
ra_dl.rv_idx_1 = rvidx[1];
ra_dl.tb_en[1] = 1;
}
srslte_ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb); srslte_ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb);
srslte_ra_dl_grant_t dummy_grant; srslte_ra_dl_grant_t dummy_grant;
srslte_ra_nbits_t dummy_nbits; srslte_ra_nbits_t dummy_nbits;
srslte_ra_dl_dci_to_grant(&ra_dl, cell.nof_prb, UE_CRNTI, &dummy_grant); srslte_ra_dl_dci_to_grant(&ra_dl, cell.nof_prb, UE_CRNTI, &dummy_grant);
srslte_ra_dl_grant_to_nbits(&dummy_grant, cfi, cell, 0, &dummy_nbits); srslte_ra_dl_grant_to_nbits(&dummy_grant, cfi, cell, 0, &dummy_nbits);
srslte_ra_dl_grant_fprint(stdout, &dummy_grant); srslte_ra_dl_grant_fprint(stdout, &dummy_grant);
printf("Type new MCS index and press Enter: "); fflush(stdout); dummy_grant.sf_type = SRSLTE_SF_NORM;
if (pdsch_cfg.mimo_type != SRSLTE_MIMO_TYPE_SINGLE_ANTENNA) {
printf("\nTransmission mode key table:\n");
printf(" Mode | 1TB | 2TB |\n");
printf("----------+---------+-----+\n");
printf("Diversity | x | |\n");
printf(" CDD | | z |\n");
printf("Multiplex | q,w,e,r | a,s |\n");
printf("\n");
printf("Type new MCS index (0-28) or mode key and press Enter: ");
} else {
printf("Type new MCS index (0-28) and press Enter: ");
}
fflush(stdout);
return 0; return 0;
} }
@ -390,9 +583,48 @@ int update_control() {
break; break;
} }
} else { } else {
switch (input[0]) {
case 'q':
pdsch_cfg.mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
multiplex_pmi = 0;
multiplex_nof_layers = 1;
break;
case 'w':
pdsch_cfg.mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
multiplex_pmi = 1;
multiplex_nof_layers = 1;
break;
case 'e':
pdsch_cfg.mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
multiplex_pmi = 2;
multiplex_nof_layers = 1;
break;
case 'r':
pdsch_cfg.mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
multiplex_pmi = 3;
multiplex_nof_layers = 1;
break;
case 'a':
pdsch_cfg.mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
multiplex_pmi = 0;
multiplex_nof_layers = 2;
break;
case 's':
pdsch_cfg.mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
multiplex_pmi = 1;
multiplex_nof_layers = 2;
break;
case 'z':
pdsch_cfg.mimo_type = SRSLTE_MIMO_TYPE_CDD;
break;
case 'x':
pdsch_cfg.mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
break;
default:
last_mcs_idx = mcs_idx; last_mcs_idx = mcs_idx;
mcs_idx = atoi(input); mcs_idx = atoi(input);
} }
}
bzero(input,sizeof(input)); bzero(input,sizeof(input));
if (update_radl()) { if (update_radl()) {
printf("Trying with last known MCS index\n"); printf("Trying with last known MCS index\n");
@ -411,9 +643,6 @@ int update_control() {
} }
} }
#define DATA_BUFF_SZ 1024*128
uint8_t data[8*DATA_BUFF_SZ], data2[DATA_BUFF_SZ];
uint8_t data_tmp[DATA_BUFF_SZ];
/** Function run in a separate thread to receive UDP data */ /** Function run in a separate thread to receive UDP data */
void *net_thread_fnc(void *arg) { void *net_thread_fnc(void *arg) {
@ -423,14 +652,16 @@ void *net_thread_fnc(void *arg) {
do { do {
n = srslte_netsource_read(&net_source, &data2[rpm], DATA_BUFF_SZ-rpm); n = srslte_netsource_read(&net_source, &data2[rpm], DATA_BUFF_SZ-rpm);
if (n > 0) { if (n > 0) {
int nbytes = 1+(pdsch_cfg.grant.mcs.tbs-1)/8; // FIXME: I assume that both transport blocks have same size in case of 2 tb are active
int nbytes = 1 + (pdsch_cfg.grant.mcs[0].tbs + pdsch_cfg.grant.mcs[1].tbs - 1) / 8;
rpm += n; rpm += n;
INFO("received %d bytes. rpm=%d/%d\n",n,rpm,nbytes); INFO("received %d bytes. rpm=%d/%d\n",n,rpm,nbytes);
wpm = 0; wpm = 0;
while (rpm >= nbytes) { while (rpm >= nbytes) {
// wait for packet to be transmitted // wait for packet to be transmitted
sem_wait(&net_sem); sem_wait(&net_sem);
memcpy(data, &data2[wpm], nbytes); memcpy(data[0], &data2[wpm], nbytes / (size_t) 2);
memcpy(data[1], &data2[wpm], nbytes / (size_t) 2);
INFO("Sent %d/%d bytes ready\n", nbytes, rpm); INFO("Sent %d/%d bytes ready\n", nbytes, rpm);
rpm -= nbytes; rpm -= nbytes;
wpm += nbytes; wpm += nbytes;
@ -450,6 +681,7 @@ void *net_thread_fnc(void *arg) {
return NULL; return NULL;
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
int nf=0, sf_idx=0, N_id_2=0; int nf=0, sf_idx=0, N_id_2=0;
cf_t pss_signal[SRSLTE_PSS_LEN]; cf_t pss_signal[SRSLTE_PSS_LEN];
@ -462,7 +694,8 @@ int main(int argc, char **argv) {
srslte_dci_msg_t dci_msg; srslte_dci_msg_t dci_msg;
srslte_dci_location_t locations[SRSLTE_NSUBFRAMES_X_FRAME][30]; srslte_dci_location_t locations[SRSLTE_NSUBFRAMES_X_FRAME][30];
uint32_t sfn; uint32_t sfn;
srslte_chest_dl_t est; srslte_refsignal_t csr_refs;
srslte_refsignal_t mbsfn_refs;
#ifdef DISABLE_RF #ifdef DISABLE_RF
if (argc < 3) { if (argc < 3) {
@ -491,17 +724,31 @@ int main(int argc, char **argv) {
srslte_pss_generate(pss_signal, N_id_2); srslte_pss_generate(pss_signal, N_id_2);
srslte_sss_generate(sss_signal0, sss_signal5, cell.id); srslte_sss_generate(sss_signal0, sss_signal5, cell.id);
/* Generate CRS signals */
if (srslte_chest_dl_init(&est, cell)) { /* Generate reference signals */
if(srslte_refsignal_cs_init(&csr_refs, cell.nof_prb)) {
fprintf(stderr, "Error initializing equalizer\n"); fprintf(stderr, "Error initializing equalizer\n");
exit(-1); exit(-1);
} }
if(mbsfn_area_id > -1) {
if(srslte_refsignal_mbsfn_init(&mbsfn_refs, cell, mbsfn_area_id)) {
fprintf(stderr, "Error initializing equalizer\n");
exit(-1);
}
}
if(srslte_refsignal_cs_set_cell(&csr_refs, cell)){
fprintf(stderr, "Error setting cell\n");
exit(-1);
}
for (i = 0; i < SRSLTE_MAX_PORTS; i++) { // now there's only 1 port
sf_symbols[i] = sf_buffer; for (i = 0; i < SRSLTE_MAX_PORTS; i++) {
slot1_symbols[i] = &sf_buffer[SRSLTE_SLOT_LEN_RE(cell.nof_prb, cell.cp)]; sf_symbols[i] = sf_buffer[i%cell.nof_ports];
slot1_symbols[i] = &sf_buffer[i%cell.nof_ports][SRSLTE_SLOT_LEN_RE(cell.nof_prb, cell.cp)];
} }
#ifndef DISABLE_RF #ifndef DISABLE_RF
@ -550,13 +797,15 @@ int main(int argc, char **argv) {
/* Initiate valid DCI locations */ /* Initiate valid DCI locations */
for (i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) { for (i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
srslte_pdcch_ue_locations(&pdcch, locations[i], 30, i, cfi, UE_CRNTI); srslte_pdcch_ue_locations(&pdcch, locations[i], 30, i, cfi, UE_CRNTI);
} }
nf = 0; nf = 0;
bool send_data = false; bool send_data = false;
srslte_softbuffer_tx_reset(&softbuffer); for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
srslte_softbuffer_tx_reset(softbuffers[i]);
}
#ifndef DISABLE_RF #ifndef DISABLE_RF
bool start_of_burst = true; bool start_of_burst = true;
@ -564,15 +813,28 @@ int main(int argc, char **argv) {
while ((nf < nof_frames || nof_frames == -1) && !go_exit) { while ((nf < nof_frames || nof_frames == -1) && !go_exit) {
for (sf_idx = 0; sf_idx < SRSLTE_NSUBFRAMES_X_FRAME && (nf < nof_frames || nof_frames == -1); sf_idx++) { for (sf_idx = 0; sf_idx < SRSLTE_NSUBFRAMES_X_FRAME && (nf < nof_frames || nof_frames == -1); sf_idx++) {
bzero(sf_buffer, sizeof(cf_t) * sf_n_re); /* Set Antenna port resource elements to zero */
bzero(sf_symbols[0], sizeof(cf_t) * sf_n_re);
if (sf_idx == 0 || sf_idx == 5) { if (sf_idx == 0 || sf_idx == 5) {
srslte_pss_put_slot(pss_signal, sf_buffer, cell.nof_prb, SRSLTE_CP_NORM); srslte_pss_put_slot(pss_signal, sf_symbols[0], cell.nof_prb, SRSLTE_CP_NORM);
srslte_sss_put_slot(sf_idx ? sss_signal5 : sss_signal0, sf_buffer, cell.nof_prb, srslte_sss_put_slot(sf_idx ? sss_signal5 : sss_signal0, sf_symbols[0], cell.nof_prb,
SRSLTE_CP_NORM); SRSLTE_CP_NORM);
} }
srslte_refsignal_cs_put_sf(cell, 0, est.csr_signal.pilots[0][sf_idx], sf_buffer); /* Copy zeros, SSS, PSS into the rest of antenna ports */
for (i = 1; i < cell.nof_ports; i++) {
memcpy(sf_symbols[i], sf_symbols[0], sizeof(cf_t) * sf_n_re);
}
if(sf_idx == 1 && mbsfn_area_id > -1){
srslte_refsignal_mbsfn_put_sf(cell, 0,csr_refs.pilots[0][sf_idx], mbsfn_refs.pilots[0][sf_idx], sf_symbols[0]);
} else {
for (i = 0; i < cell.nof_ports; i++) {
srslte_refsignal_cs_put_sf(cell, (uint32_t) i, csr_refs.pilots[i / 2][sf_idx], sf_symbols[i]);
}
}
srslte_pbch_mib_pack(&cell, sfn, bch_payload); srslte_pbch_mib_pack(&cell, sfn, bch_payload);
if (sf_idx == 0) { if (sf_idx == 0) {
@ -593,9 +855,13 @@ int main(int argc, char **argv) {
INFO("Transmitting packet\n",0); INFO("Transmitting packet\n",0);
} }
} else { } else {
INFO("SF: %d, Generating %d random bits\n", sf_idx, pdsch_cfg.grant.mcs.tbs); INFO("SF: %d, Generating %d random bits\n", sf_idx, pdsch_cfg.grant.mcs[0].tbs + pdsch_cfg.grant.mcs[1].tbs);
for (i=0;i<pdsch_cfg.grant.mcs.tbs/8;i++) { for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
data[i] = rand()%256; if (pdsch_cfg.grant.tb_en[tb]) {
for (i = 0; i < pdsch_cfg.grant.mcs[tb].tbs / 8; i++) {
data[tb][i] = (uint8_t) rand();
}
}
} }
/* Uncomment this to transmit on sf 0 and 5 only */ /* Uncomment this to transmit on sf 0 and 5 only */
if (sf_idx != 0 && sf_idx != 5) { if (sf_idx != 0 && sf_idx != 5) {
@ -606,10 +872,31 @@ int main(int argc, char **argv) {
} }
if (send_data) { if (send_data) {
if(sf_idx != 1 || mbsfn_area_id < 0) { // PDCCH + PDSCH
srslte_dci_format_t dci_format;
switch(pdsch_cfg.mimo_type) {
case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA:
dci_format = SRSLTE_DCI_FORMAT1;
break;
case SRSLTE_MIMO_TYPE_TX_DIVERSITY:
case SRSLTE_MIMO_TYPE_CDD:
dci_format = SRSLTE_DCI_FORMAT2A;
break;
case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX:
dci_format = SRSLTE_DCI_FORMAT2;
if (multiplex_nof_layers == 1) {
ra_dl.pinfo = (uint8_t) (multiplex_pmi + 1);
} else {
ra_dl.pinfo = (uint8_t) multiplex_pmi;
}
break;
default:
fprintf(stderr, "Wrong MIMO configuration\n");
exit(SRSLTE_ERROR);
}
/* Encode PDCCH */ /* Encode PDCCH */
INFO("Putting DCI to location: n=%d, L=%d\n", locations[sf_idx][0].ncce, locations[sf_idx][0].L); INFO("Putting DCI to location: n=%d, L=%d\n", locations[sf_idx][0].ncce, locations[sf_idx][0].L);
srslte_dci_msg_pack_pdsch(&ra_dl, SRSLTE_DCI_FORMAT1, &dci_msg, cell.nof_prb, cell.nof_ports, false); srslte_dci_msg_pack_pdsch(&ra_dl, dci_format, &dci_msg, cell.nof_prb, cell.nof_ports, false);
if (srslte_pdcch_encode(&pdcch, &dci_msg, locations[sf_idx][0], UE_CRNTI, sf_symbols, sf_idx, cfi)) { if (srslte_pdcch_encode(&pdcch, &dci_msg, locations[sf_idx][0], UE_CRNTI, sf_symbols, sf_idx, cfi)) {
fprintf(stderr, "Error encoding DCI message\n"); fprintf(stderr, "Error encoding DCI message\n");
exit(-1); exit(-1);
@ -618,20 +905,66 @@ int main(int argc, char **argv) {
/* Configure pdsch_cfg parameters */ /* Configure pdsch_cfg parameters */
srslte_ra_dl_grant_t grant; srslte_ra_dl_grant_t grant;
srslte_ra_dl_dci_to_grant(&ra_dl, cell.nof_prb, UE_CRNTI, &grant); srslte_ra_dl_dci_to_grant(&ra_dl, cell.nof_prb, UE_CRNTI, &grant);
if (srslte_pdsch_cfg(&pdsch_cfg, cell, &grant, cfi, sf_idx, 0)) { if (srslte_pdsch_cfg_mimo(&pdsch_cfg, cell, &grant, cfi, sf_idx, rvidx, pdsch_cfg.mimo_type, multiplex_pmi)) {
fprintf(stderr, "Error configuring PDSCH\n"); fprintf(stderr, "Error configuring PDSCH\n");
exit(-1); exit(-1);
} }
/* Encode PDSCH */ /* Encode PDSCH */
if (srslte_pdsch_encode(&pdsch, &pdsch_cfg, &softbuffer, data, UE_CRNTI, sf_symbols)) { if (srslte_pdsch_encode(&pdsch, &pdsch_cfg, softbuffers, data, UE_CRNTI, sf_symbols)) {
fprintf(stderr, "Error encoding PDSCH\n");
exit(-1);
}
if (net_port > 0 && net_packet_ready) {
if (null_file_sink) {
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
srslte_bit_pack_vector(data[tb], data_tmp, pdsch_cfg.grant.mcs[tb].tbs);
if (srslte_netsink_write(&net_sink, data_tmp, 1 + (pdsch_cfg.grant.mcs[tb].tbs - 1) / 8) < 0) {
fprintf(stderr, "Error sending data through UDP socket\n");
}
}
}
net_packet_ready = false;
sem_post(&net_sem);
}
}else{ // We're sending MCH on subframe 1 - PDCCH + PMCH
/* Encode PDCCH */
INFO("Putting DCI to location: n=%d, L=%d\n", locations[sf_idx][0].ncce, locations[sf_idx][0].L);
srslte_dci_msg_pack_pdsch(&ra_dl, SRSLTE_DCI_FORMAT1, &dci_msg, cell.nof_prb, cell.nof_ports, false);
if (srslte_pdcch_encode(&pdcch, &dci_msg, locations[sf_idx][0], M_CRNTI, sf_symbols, sf_idx, cfi)) {
fprintf(stderr, "Error encoding DCI message\n");
exit(-1);
}
/* Configure pmch_cfg parameters */
srslte_ra_dl_grant_t grant;
grant.nof_tb = 1;
grant.mcs[0].idx = 2;
grant.mcs[0].mod = SRSLTE_MOD_QPSK;
grant.nof_prb = cell.nof_prb;
grant.sf_type = SRSLTE_SF_MBSFN;
grant.Qm[0] = srslte_mod_bits_x_symbol(grant.mcs[0].mod);
srslte_dl_fill_ra_mcs(&grant.mcs[0], cell.nof_prb);
for(int i = 0; i < 2; i++){
for(int j = 0; j < grant.nof_prb; j++){
grant.prb_idx[i][j] = true;
}
}
if (srslte_pmch_cfg(&pmch_cfg, cell, &grant, cfi, sf_idx)) {
fprintf(stderr, "Error configuring PMCH\n");
exit(-1);
}
/* Encode PMCH */
if (srslte_pmch_encode(&pmch, &pmch_cfg, softbuffers[0], data[0], mbsfn_area_id, sf_symbols)) {
fprintf(stderr, "Error encoding PDSCH\n"); fprintf(stderr, "Error encoding PDSCH\n");
exit(-1); exit(-1);
} }
if (net_port > 0 && net_packet_ready) { if (net_port > 0 && net_packet_ready) {
if (null_file_sink) { if (null_file_sink) {
srslte_bit_pack_vector(data, data_tmp, pdsch_cfg.grant.mcs.tbs); srslte_bit_pack_vector(data[0], data_tmp, pmch_cfg.grant.mcs[0].tbs);
if (srslte_netsink_write(&net_sink, data_tmp, 1+(pdsch_cfg.grant.mcs.tbs-1)/8) < 0) { if (srslte_netsink_write(&net_sink, data_tmp, 1+(pmch_cfg.grant.mcs[0].tbs-1)/8) < 0) {
fprintf(stderr, "Error sending data through UDP socket\n"); fprintf(stderr, "Error sending data through UDP socket\n");
} }
} }
@ -639,22 +972,30 @@ int main(int argc, char **argv) {
sem_post(&net_sem); sem_post(&net_sem);
} }
} }
}
/* Transform to OFDM symbols */ /* Transform to OFDM symbols */
srslte_ofdm_tx_sf(&ifft, sf_buffer, output_buffer); 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]);
}
}else{
srslte_ofdm_tx_sf(&ifft_mbsfn, sf_buffer[0], output_buffer[0]);
}
/* send to file or usrp */ /* send to file or usrp */
if (output_file_name) { if (output_file_name) {
if (!null_file_sink) { if (!null_file_sink) {
srslte_filesink_write(&fsink, output_buffer, sf_n_samples); srslte_filesink_write_multi(&fsink, (void**) output_buffer, sf_n_samples, cell.nof_ports);
} }
usleep(1000); usleep(1000);
} else { } else {
#ifndef DISABLE_RF #ifndef DISABLE_RF
// FIXME
float norm_factor = (float) cell.nof_prb/15/sqrtf(pdsch_cfg.grant.nof_prb); float norm_factor = (float) cell.nof_prb/15/sqrtf(pdsch_cfg.grant.nof_prb);
srslte_vec_sc_prod_cfc(output_buffer, rf_amp*norm_factor, output_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb)); for (i = 0; i < cell.nof_ports; i++) {
srslte_rf_send2(&rf, output_buffer, sf_n_samples, true, start_of_burst, false); srslte_vec_sc_prod_cfc(output_buffer[i], rf_amp * norm_factor, output_buffer[i], SRSLTE_SF_LEN_PRB(cell.nof_prb));
}
srslte_rf_send_multi(&rf, (void**) output_buffer, sf_n_samples, true, start_of_burst, false);
start_of_burst=false; start_of_burst=false;
#endif #endif
} }

@ -36,7 +36,8 @@
#include <signal.h> #include <signal.h>
#include <pthread.h> #include <pthread.h>
#include <semaphore.h> #include <semaphore.h>
#include <srslte/phy/common/phy_common.h>
#include "srslte/phy/io/filesink.h"
#include "srslte/srslte.h" #include "srslte/srslte.h"
#define ENABLE_AGC_DEFAULT #define ENABLE_AGC_DEFAULT
@ -66,7 +67,7 @@ sem_t plot_sem;
uint32_t plot_sf_idx=0; uint32_t plot_sf_idx=0;
bool plot_track = true; bool plot_track = true;
#endif #endif
char *output_file_name;
#define PRINT_CHANGE_SCHEDULIGN #define PRINT_CHANGE_SCHEDULIGN
//#define CORRECT_SAMPLE_OFFSET //#define CORRECT_SAMPLE_OFFSET
@ -98,6 +99,9 @@ typedef struct {
int net_port_signal; int net_port_signal;
char *net_address_signal; char *net_address_signal;
int decimate; int decimate;
int32_t mbsfn_area_id;
uint8_t non_mbsfn_region;
int verbose;
}prog_args_t; }prog_args_t;
void args_default(prog_args_t *args) { void args_default(prog_args_t *args) {
@ -128,10 +132,12 @@ void args_default(prog_args_t *args) {
args->net_address_signal = "127.0.0.1"; args->net_address_signal = "127.0.0.1";
args->decimate = 0; args->decimate = 0;
args->cpu_affinity = -1; args->cpu_affinity = -1;
args->mbsfn_area_id = -1;
args->non_mbsfn_region = 2;
} }
void usage(prog_args_t *args, char *prog) { void usage(prog_args_t *args, char *prog) {
printf("Usage: %s [agpPoOcildDnruv] -f rx_frequency (in Hz) | -i input_file\n", prog); printf("Usage: %s [agpPoOcildDnruMNv] -f rx_frequency (in Hz) | -i input_file\n", prog);
#ifndef DISABLE_RF #ifndef DISABLE_RF
printf("\t-a RF args [Default %s]\n", args->rf_args); 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); printf("\t-A Number of RX antennas [Default %d]\n", args->rf_nof_rx_ant);
@ -165,13 +171,15 @@ void usage(prog_args_t *args, char *prog) {
printf("\t-S remote UDP address to send input signal [Default %s]\n", args->net_address_signal); printf("\t-S remote UDP address to send input signal [Default %s]\n", args->net_address_signal);
printf("\t-u remote TCP port to send data (-1 does nothing with it) [Default %d]\n", args->net_port); printf("\t-u remote TCP port to send data (-1 does nothing with it) [Default %d]\n", args->net_port);
printf("\t-U remote TCP address to send data [Default %s]\n", args->net_address); printf("\t-U remote TCP address to send data [Default %s]\n", args->net_address);
printf("\t-M MBSFN area id [Default %d]\n", args->mbsfn_area_id);
printf("\t-N Non-MBSFN region [Default %d]\n", args->non_mbsfn_region);
printf("\t-v [set srslte_verbose to debug, default none]\n"); printf("\t-v [set srslte_verbose to debug, default none]\n");
} }
void parse_args(prog_args_t *args, int argc, char **argv) { void parse_args(prog_args_t *args, int argc, char **argv) {
int opt; int opt;
args_default(args); args_default(args);
while ((opt = getopt(argc, argv, "aAoglipPcOCtdDnvrfuUsSZy")) != -1) { while ((opt = getopt(argc, argv, "aAoglipPcOCtdDnvrfuUsSZyWMN")) != -1) {
switch (opt) { switch (opt) {
case 'i': case 'i':
args->input_file_name = argv[optind]; args->input_file_name = argv[optind];
@ -238,6 +246,7 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
break; break;
case 'v': case 'v':
srslte_verbose++; srslte_verbose++;
args->verbose = srslte_verbose;
break; break;
case 'Z': case 'Z':
args->decimate = atoi(argv[optind]); args->decimate = atoi(argv[optind]);
@ -245,6 +254,15 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
case 'y': case 'y':
args->cpu_affinity = atoi(argv[optind]); args->cpu_affinity = atoi(argv[optind]);
break; break;
case 'W':
output_file_name = argv[optind];
break;
case 'M':
args->mbsfn_area_id = atoi(argv[optind]);
break;
case 'N':
args->non_mbsfn_region = atoi(argv[optind]);
break;
default: default:
usage(args, argv[0]); usage(args, argv[0]);
exit(-1); exit(-1);
@ -258,7 +276,7 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
/**********************************************************************/ /**********************************************************************/
/* TODO: Do something with the output data */ /* TODO: Do something with the output data */
uint8_t data[20000]; uint8_t *data[SRSLTE_MAX_CODEWORDS];
bool go_exit = false; bool go_exit = false;
void sig_int_handler(int signo) void sig_int_handler(int signo)
@ -266,10 +284,13 @@ void sig_int_handler(int signo)
printf("SIGINT received. Exiting...\n"); printf("SIGINT received. Exiting...\n");
if (signo == SIGINT) { if (signo == SIGINT) {
go_exit = true; go_exit = true;
} else if (signo == SIGSEGV) {
exit(1);
} }
} }
cf_t *sf_buffer[2] = {NULL, NULL}; cf_t *sf_buffer[SRSLTE_MAX_PORTS] = {NULL};
#ifndef DISABLE_RF #ifndef DISABLE_RF
int srslte_rf_recv_wrapper(void *h, cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *t) { int srslte_rf_recv_wrapper(void *h, cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *t) {
@ -297,6 +318,12 @@ prog_args_t prog_args;
uint32_t sfn = 0; // system frame number uint32_t sfn = 0; // system frame number
srslte_netsink_t net_sink, net_sink_signal; srslte_netsink_t net_sink, net_sink_signal;
/* Useful macros for printing lines which will disappear */
#define PRINT_LINE_INIT() int this_nof_lines = 0; static int prev_nof_lines = 0
#define PRINT_LINE(_fmt, ...) printf("\033[K" _fmt "\n", ##__VA_ARGS__); this_nof_lines++
#define PRINT_LINE_RESET_CURSOR() printf("\033[%dA", this_nof_lines); prev_nof_lines = this_nof_lines
#define PRINT_LINE_ADVANCE_CURSOR() printf("\033[%dB", prev_nof_lines + 1)
int main(int argc, char **argv) { int main(int argc, char **argv) {
int ret; int ret;
@ -304,17 +331,26 @@ int main(int argc, char **argv) {
srslte_cell_t cell; srslte_cell_t cell;
int64_t sf_cnt; int64_t sf_cnt;
srslte_ue_mib_t ue_mib; srslte_ue_mib_t ue_mib;
#ifndef DISABLE_RF #ifndef DISABLE_RF
srslte_rf_t rf; srslte_rf_t rf;
#endif #endif
uint32_t nof_trials = 0; uint32_t nof_trials = 0;
int n;
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
int sfn_offset; int sfn_offset;
float cfo = 0; float cfo = 0;
parse_args(&prog_args, argc, argv); parse_args(&prog_args, argc, argv);
for (int i = 0; i< SRSLTE_MAX_CODEWORDS; i++) {
data[i] = srslte_vec_malloc(sizeof(uint8_t)*1500*8);
if (!data[i]) {
ERROR("Allocating data");
go_exit = true;
}
}
if(prog_args.cpu_affinity > -1) { if(prog_args.cpu_affinity > -1) {
cpu_set_t cpuset; cpu_set_t cpuset;
@ -379,10 +415,11 @@ int main(int argc, char **argv) {
srslte_rf_set_master_clock_rate(&rf, 30.72e6); srslte_rf_set_master_clock_rate(&rf, 30.72e6);
/* set receiver frequency */ /* set receiver frequency */
printf("Tunning receiver to %.3f MHz\n", prog_args.rf_freq/1000000); printf("Tunning receiver to %.3f MHz\n", (prog_args.rf_freq + prog_args.file_offset_freq)/1000000);
srslte_rf_set_rx_freq(&rf, prog_args.rf_freq); srslte_rf_set_rx_freq(&rf, prog_args.rf_freq + prog_args.file_offset_freq);
srslte_rf_rx_wait_lo_locked(&rf); srslte_rf_rx_wait_lo_locked(&rf);
uint32_t ntrial=0; uint32_t ntrial=0;
do { do {
ret = rf_search_and_decode_mib(&rf, prog_args.rf_nof_rx_ant, &cell_detect_config, prog_args.force_N_id_2, &cell, &cfo); ret = rf_search_and_decode_mib(&rf, prog_args.rf_nof_rx_ant, &cell_detect_config, prog_args.force_N_id_2, &cell, &cfo);
@ -435,8 +472,8 @@ int main(int argc, char **argv) {
cell.nof_ports = prog_args.file_nof_ports; cell.nof_ports = prog_args.file_nof_ports;
cell.nof_prb = prog_args.file_nof_prb; cell.nof_prb = prog_args.file_nof_prb;
if (srslte_ue_sync_init_file(&ue_sync, prog_args.file_nof_prb, if (srslte_ue_sync_init_file_multi(&ue_sync, prog_args.file_nof_prb,
prog_args.input_file_name, prog_args.file_offset_time, prog_args.file_offset_freq)) { prog_args.input_file_name, prog_args.file_offset_time, prog_args.file_offset_freq, prog_args.rf_nof_rx_ant)) {
fprintf(stderr, "Error initiating ue_sync\n"); fprintf(stderr, "Error initiating ue_sync\n");
exit(-1); exit(-1);
} }
@ -455,19 +492,38 @@ int main(int argc, char **argv) {
//ue_sync.decimate = prog_args.decimate; //ue_sync.decimate = prog_args.decimate;
} }
} }
if (srslte_ue_sync_init_multi_decim(&ue_sync, cell, srslte_rf_recv_wrapper, prog_args.rf_nof_rx_ant, (void*) &rf,decimate)) { if (srslte_ue_sync_init_multi_decim(&ue_sync,
cell.nof_prb,
cell.id==1000,
srslte_rf_recv_wrapper,
prog_args.rf_nof_rx_ant,
(void*) &rf,decimate))
{
fprintf(stderr, "Error initiating ue_sync\n");
exit(-1);
}
if (srslte_ue_sync_set_cell(&ue_sync, cell))
{
fprintf(stderr, "Error initiating ue_sync\n"); fprintf(stderr, "Error initiating ue_sync\n");
exit(-1); exit(-1);
} }
#endif #endif
} }
if (srslte_ue_mib_init(&ue_mib, cell)) { if (srslte_ue_mib_init(&ue_mib, cell.nof_prb)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
exit(-1);
}
if (srslte_ue_mib_set_cell(&ue_mib, cell)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n"); fprintf(stderr, "Error initaiting UE MIB decoder\n");
exit(-1); exit(-1);
} }
if (srslte_ue_dl_init_multi(&ue_dl, cell, prog_args.rf_nof_rx_ant)) { // This is the User RNTI if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, prog_args.rf_nof_rx_ant)) {
fprintf(stderr, "Error initiating UE downlink processing module\n");
exit(-1);
}
if (srslte_ue_dl_set_cell(&ue_dl, cell)) {
fprintf(stderr, "Error initiating UE downlink processing module\n"); fprintf(stderr, "Error initiating UE downlink processing module\n");
exit(-1); exit(-1);
} }
@ -479,6 +535,11 @@ int main(int argc, char **argv) {
/* Configure downlink receiver for the SI-RNTI since will be the only one we'll use */ /* 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); srslte_ue_dl_set_rnti(&ue_dl, prog_args.rnti);
/* Configure MBSFN area id and non-MBSFN Region */
if (prog_args.mbsfn_area_id > -1) {
srslte_ue_dl_set_mbsfn_area_id(&ue_dl, prog_args.mbsfn_area_id);
srslte_ue_dl_set_non_mbsfn_region(&ue_dl, prog_args.non_mbsfn_region);
}
/* Initialize subframe counter */ /* Initialize subframe counter */
sf_cnt = 0; sf_cnt = 0;
@ -498,9 +559,15 @@ int main(int argc, char **argv) {
// Variables for measurements // Variables for measurements
uint32_t nframes=0; uint32_t nframes=0;
float rsrp=0.0, rsrq=0.0, noise=0.0; uint8_t ri = 0, pmi = 0;
float rsrp0=0.0, rsrp1=0.0, rsrq=0.0, noise=0.0, enodebrate = 0.0, uerate = 0.0,
sinr[SRSLTE_MAX_LAYERS][SRSLTE_MAX_CODEBOOKS], cn = 0.0;
bool decode_pdsch = false; bool decode_pdsch = false;
for (int i = 0; i < SRSLTE_MAX_LAYERS; i++) {
bzero(sinr[i], sizeof(float)*SRSLTE_MAX_CODEBOOKS);
}
#ifndef DISABLE_RF #ifndef DISABLE_RF
if (prog_args.rf_gain < 0) { if (prog_args.rf_gain < 0) {
srslte_ue_sync_start_agc(&ue_sync, srslte_rf_set_rx_gain_th_wrapper_, cell_detect_config.init_agc); srslte_ue_sync_start_agc(&ue_sync, srslte_rf_set_rx_gain_th_wrapper_, cell_detect_config.init_agc);
@ -521,6 +588,31 @@ int main(int argc, char **argv) {
INFO("\nEntering main loop...\n\n", 0); INFO("\nEntering main loop...\n\n", 0);
/* Main loop */ /* Main loop */
while (!go_exit && (sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1)) { while (!go_exit && (sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1)) {
bool acks [SRSLTE_MAX_CODEWORDS] = {false};
char input[128];
PRINT_LINE_INIT();
fd_set set;
FD_ZERO(&set);
FD_SET(0, &set);
struct timeval to;
to.tv_sec = 0;
to.tv_usec = 0;
/* Set default verbose level */
srslte_verbose = prog_args.verbose;
int n = select(1, &set, NULL, NULL, &to);
if (n == 1) {
/* If a new line is detected set verbose level to Debug */
if (fgets(input, sizeof(input), stdin)) {
srslte_verbose = SRSLTE_VERBOSE_DEBUG;
ue_dl.pkt_errors = 0;
ue_dl.pkts_total = 0;
ue_dl.nof_detected = 0;
nof_trials = 0;
}
}
ret = srslte_ue_sync_zerocopy_multi(&ue_sync, sf_buffer); ret = srslte_ue_sync_zerocopy_multi(&ue_sync, sf_buffer);
if (ret < 0) { if (ret < 0) {
@ -534,9 +626,12 @@ int main(int argc, char **argv) {
/* srslte_ue_sync_get_buffer returns 1 if successfully read 1 aligned subframe */ /* srslte_ue_sync_get_buffer returns 1 if successfully read 1 aligned subframe */
if (ret == 1) { if (ret == 1) {
uint32_t sfidx = srslte_ue_sync_get_sfidx(&ue_sync);
switch (state) { switch (state) {
case DECODE_MIB: case DECODE_MIB:
if (srslte_ue_sync_get_sfidx(&ue_sync) == 0) { 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, sf_buffer[0], bch_payload, NULL, &sfn_offset);
if (n < 0) { if (n < 0) {
fprintf(stderr, "Error decoding UE MIB\n"); fprintf(stderr, "Error decoding UE MIB\n");
@ -555,28 +650,64 @@ int main(int argc, char **argv) {
decode_pdsch = true; decode_pdsch = true;
} else { } else {
/* We are looking for SIB1 Blocks, search only in appropiate places */ /* We are looking for SIB1 Blocks, search only in appropiate places */
if ((srslte_ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%2)==0)) { if ((sfidx == 5 && (sfn%2)==0) || sfidx == 1) {
decode_pdsch = true; decode_pdsch = true;
} else { } else {
decode_pdsch = false; decode_pdsch = false;
} }
} }
if (decode_pdsch) { if (decode_pdsch) {
INFO("Attempting DL decode SFN=%d\n", sfn); if(sfidx != 1 || prog_args.mbsfn_area_id < 0){ // Not an MBSFN subframe
n = srslte_ue_dl_decode_multi(&ue_dl, 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);
} 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),
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),
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),
acks);
}
}
}
}else{ // MBSFN subframe
n = srslte_ue_dl_decode_mbsfn(&ue_dl,
sf_buffer, sf_buffer,
data, data[0],
sfn*10+srslte_ue_sync_get_sfidx(&ue_sync)); sfn*10+srslte_ue_sync_get_sfidx(&ue_sync));
if(n>0){
if(output_file_name){
//srslte_filesink_init(&sink, output_file_name, SRSLTE_BYTE_BIN);
// srslte_filesink_write(&sink, data, n);
//srslte_filesink_free(&sink);
}
INFO("mbsfn PDU size is %d\n", n);
}
}
if (n < 0) { if (n < 0) {
// fprintf(stderr, "Error decoding UE DL\n");fflush(stdout); // fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);
} else if (n > 0) { } else if (n > 0) {
/* Send data if socket active */ /* Send data if socket active */
if (prog_args.net_port > 0) { if (prog_args.net_port > 0) {
srslte_netsink_write(&net_sink, data, 1+(n-1)/8); if(sfidx == 1) {
srslte_netsink_write(&net_sink, data[0], 1+(n-1)/8);
} else {
// FIXME: UDP Data transmission does not work
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
if (ue_dl.pdsch_cfg.grant.tb_en[tb]) {
srslte_netsink_write(&net_sink, data[tb], 1 + (ue_dl.pdsch_cfg.grant.mcs[tb].tbs - 1) / 8);
}
}
}
} }
#ifdef PRINT_CHANGE_SCHEDULIGN #ifdef PRINT_CHANGE_SCHEDULIGN
if (ue_dl.dl_dci.mcs_idx != old_dl_dci.mcs_idx || if (ue_dl.dl_dci.mcs_idx != old_dl_dci.mcs_idx ||
memcmp(&ue_dl.dl_dci.type0_alloc, &old_dl_dci.type0_alloc, sizeof(srslte_ra_type0_t)) || memcmp(&ue_dl.dl_dci.type0_alloc, &old_dl_dci.type0_alloc, sizeof(srslte_ra_type0_t)) ||
@ -595,9 +726,15 @@ int main(int argc, char **argv) {
nof_trials++; nof_trials++;
rsrq = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrq(&ue_dl.chest), rsrq, 0.1);
rsrp = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp(&ue_dl.chest), rsrp, 0.05); rsrq = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrq(&ue_dl.chest), rsrq, 0.1f);
noise = SRSLTE_VEC_EMA(srslte_chest_dl_get_noise_estimate(&ue_dl.chest), noise, 0.05); 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);
nframes++; nframes++;
if (isnan(rsrq)) { if (isnan(rsrq)) {
rsrq = 0; rsrq = 0;
@ -605,43 +742,104 @@ int main(int argc, char **argv) {
if (isnan(noise)) { if (isnan(noise)) {
noise = 0; noise = 0;
} }
if (isnan(rsrp)) { if (isnan(rsrp0)) {
rsrp = 0; rsrp0 = 0;
}
if (isnan(rsrp1)) {
rsrp1 = 0;
} }
} }
// Plot and Printf // Plot and Printf
if (srslte_ue_sync_get_sfidx(&ue_sync) == 5) { if (sfidx == 5) {
float gain = prog_args.rf_gain; float gain = prog_args.rf_gain;
if (gain < 0) { if (gain < 0) {
gain = 10*log10(srslte_agc_get_gain(&ue_sync.agc)); gain = 10*log10(srslte_agc_get_gain(&ue_sync.agc));
} }
printf("CFO: %+6.2f kHz, "
"SNR: %4.1f dB, "
"PDCCH-Miss: %5.2f%%, PDSCH-BLER: %5.2f%%\r",
srslte_ue_sync_get_cfo(&ue_sync)/1000, /* Print transmission scheme */
10*log10(rsrp/noise), if (ue_dl.pdsch_cfg.mimo_type == SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX) {
100*(1-(float) ue_dl.nof_detected/nof_trials), PRINT_LINE(" Tx scheme: %s (codebook_idx=%d)", srslte_mimotype2str(ue_dl.pdsch_cfg.mimo_type),
(float) 100*ue_dl.pkt_errors/ue_dl.pkts_total); ue_dl.pdsch_cfg.codebook_idx);
} else {
PRINT_LINE(" Tx scheme: %s", srslte_mimotype2str(ue_dl.pdsch_cfg.mimo_type));
}
/* 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(" 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(" 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){
PRINT_LINE(" PMCH-BLER: %5.2f%%", (float) 100 * ue_dl.pmch_pkt_errors/ue_dl.pmch_pkts_total);
}
PRINT_LINE(" TB 0: mcs=%d; tbs=%d", ue_dl.pdsch_cfg.grant.mcs[0].idx,
ue_dl.pdsch_cfg.grant.mcs[0].tbs);
PRINT_LINE(" TB 1: mcs=%d; tbs=%d", ue_dl.pdsch_cfg.grant.mcs[1].idx,
ue_dl.pdsch_cfg.grant.mcs[1].tbs);
/* MIMO: if tx and rx antennas are bigger than 1 */
if (cell.nof_ports > 1 && ue_dl.pdsch.nof_rx_antennas > 1) {
/* Compute condition number */
srslte_ue_dl_ri_select(&ue_dl, NULL, &cn);
/* Print condition number */
PRINT_LINE(" κ: %.1f dB (Condition number, 0 dB => Best)", cn);
}
PRINT_LINE("");
/* Spatial multiplex only */
if (ue_dl.pdsch_cfg.mimo_type == SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX) {
/* Compute Rank Indicator (RI) and Precoding Matrix Indicator (PMI) */
srslte_ue_dl_ri_pmi_select(&ue_dl, &ri, &pmi, NULL);
for (uint32_t nl = 0; nl < SRSLTE_MAX_LAYERS; nl++) {
for (uint32_t cb = 0; cb < SRSLTE_MAX_CODEBOOKS; cb++) {
sinr[nl][cb] = SRSLTE_VEC_EMA(ue_dl.sinr[nl][cb], sinr[nl][cb], 0.5f);
}
}
/* Print Multiplex stats */
PRINT_LINE("SINR (dB) Vs RI and PMI:");
PRINT_LINE(" | RI | 1 | 2 |");
PRINT_LINE(" -------+-------+-------+");
PRINT_LINE(" P | 0 | %5.2f%c| %5.2f%c|", 10 * log10(sinr[0][0]), (ri == 1 && pmi == 0) ? '*' : ' ',
10 * log10(sinr[1][0]), (ri == 2 && pmi == 0) ? '*' : ' ');
PRINT_LINE(" M | 1 | %5.2f%c| %5.2f%c|", 10 * log10(sinr[0][1]), (ri == 1 && pmi == 1) ? '*' : ' ',
10 * log10(sinr[1][1]), (ri == 2 && pmi == 1) ? '*' : ' ');
PRINT_LINE(" I | 2 | %5.2f%c|-------+ ", 10 * log10(sinr[0][2]), (ri == 1 && pmi == 2) ? '*' : ' ');
PRINT_LINE(" | 3 | %5.2f%c| ", 10 * log10(sinr[0][3]), (ri == 1 && pmi == 3) ? '*' : ' ');
PRINT_LINE("");
}
PRINT_LINE("Press enter maximum printing debug log of 1 subframe.");
PRINT_LINE("");
PRINT_LINE_RESET_CURSOR();
} }
break; break;
} }
if (srslte_ue_sync_get_sfidx(&ue_sync) == 9) { if (sfidx == 9) {
sfn++; sfn++;
if (sfn == 1024) { if (sfn == 1024) {
sfn = 0; sfn = 0;
printf("\n"); PRINT_LINE_ADVANCE_CURSOR();
ue_dl.pdsch_pkt_errors = 0;
ue_dl.pdsch_pkts_total = 0;
/*
ue_dl.pkt_errors = 0; ue_dl.pkt_errors = 0;
ue_dl.pkts_total = 0; ue_dl.pkts_total = 0;
ue_dl.nof_detected = 0; ue_dl.nof_detected = 0;
nof_trials = 0; nof_trials = 0;
*/
} }
} }
#ifndef DISABLE_GRAPHICS #ifndef DISABLE_GRAPHICS
if (!prog_args.disable_plots) { if (!prog_args.disable_plots) {
if ((sfn%4) == 0 && decode_pdsch) { if ((sfn%3) == 0 && decode_pdsch) {
plot_sf_idx = srslte_ue_sync_get_sfidx(&ue_sync); plot_sf_idx = srslte_ue_sync_get_sfidx(&ue_sync);
plot_track = true; plot_track = true;
sem_post(&plot_sem); sem_post(&plot_sem);
@ -674,6 +872,16 @@ int main(int argc, char **argv) {
#endif #endif
srslte_ue_dl_free(&ue_dl); srslte_ue_dl_free(&ue_dl);
srslte_ue_sync_free(&ue_sync); srslte_ue_sync_free(&ue_sync);
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (data[i]) {
free(data[i]);
}
}
for (int i = 0; i < prog_args.rf_nof_rx_ant; i++) {
if (sf_buffer[i]) {
free(sf_buffer[i]);
}
}
#ifndef DISABLE_RF #ifndef DISABLE_RF
if (!prog_args.input_file_name) { if (!prog_args.input_file_name) {
@ -681,6 +889,7 @@ int main(int argc, char **argv) {
srslte_rf_close(&rf); srslte_rf_close(&rf);
} }
#endif #endif
printf("\nBye\n"); printf("\nBye\n");
exit(0); exit(0);
} }
@ -742,7 +951,7 @@ void *plot_thread_run(void *arg) {
while(1) { while(1) {
sem_wait(&plot_sem); sem_wait(&plot_sem);
uint32_t nof_symbols = ue_dl.pdsch_cfg.nbits.nof_re; uint32_t nof_symbols = ue_dl.pdsch_cfg.nbits[0].nof_re;
if (!prog_args.disable_plots_except_constellation) { if (!prog_args.disable_plots_except_constellation) {
for (i = 0; i < nof_re; i++) { for (i = 0; i < nof_re; i++) {
tmp_plot[i] = 20 * log10f(cabsf(ue_dl.sf_symbols[i])); tmp_plot[i] = 20 * log10f(cabsf(ue_dl.sf_symbols[i]));
@ -784,7 +993,7 @@ void *plot_thread_run(void *arg) {
plot_scatter_setNewData(&pscatequal_pdcch, ue_dl.pdcch.d, 36*ue_dl.pdcch.nof_cce); plot_scatter_setNewData(&pscatequal_pdcch, ue_dl.pdcch.d, 36*ue_dl.pdcch.nof_cce);
} }
plot_scatter_setNewData(&pscatequal, ue_dl.pdsch.d, nof_symbols); plot_scatter_setNewData(&pscatequal, ue_dl.pdsch.d[0], nof_symbols);
if (plot_sf_idx == 1) { if (plot_sf_idx == 1) {
if (prog_args.net_port_signal > 0) { if (prog_args.net_port_signal > 0) {

@ -44,6 +44,7 @@ char *output_file_name;
char *rf_args=""; char *rf_args="";
float rf_gain=40.0, rf_freq=-1.0, rf_rate=0.96e6; float rf_gain=40.0, rf_freq=-1.0, rf_rate=0.96e6;
int nof_samples = -1; int nof_samples = -1;
int nof_rx_antennas = 1;
void int_handler(int dummy) { void int_handler(int dummy) {
keep_running = false; keep_running = false;
@ -55,12 +56,13 @@ void usage(char *prog) {
printf("\t-g RF Gain [Default %.2f dB]\n", rf_gain); printf("\t-g RF Gain [Default %.2f dB]\n", rf_gain);
printf("\t-r RF Rate [Default %.6f Hz]\n", rf_rate); printf("\t-r RF Rate [Default %.6f Hz]\n", rf_rate);
printf("\t-n nof_samples [Default %d]\n", nof_samples); printf("\t-n nof_samples [Default %d]\n", nof_samples);
printf("\t-A nof_rx_antennas [Default %d]\n", nof_rx_antennas);
printf("\t-v srslte_verbose\n"); printf("\t-v srslte_verbose\n");
} }
void parse_args(int argc, char **argv) { void parse_args(int argc, char **argv) {
int opt; int opt;
while ((opt = getopt(argc, argv, "agrnvfo")) != -1) { while ((opt = getopt(argc, argv, "agrnvfoA")) != -1) {
switch (opt) { switch (opt) {
case 'o': case 'o':
output_file_name = argv[optind]; output_file_name = argv[optind];
@ -80,6 +82,9 @@ void parse_args(int argc, char **argv) {
case 'n': case 'n':
nof_samples = atoi(argv[optind]); nof_samples = atoi(argv[optind]);
break; break;
case 'A':
nof_rx_antennas = atoi(argv[optind]);
break;
case 'v': case 'v':
srslte_verbose++; srslte_verbose++;
break; break;
@ -95,11 +100,11 @@ void parse_args(int argc, char **argv) {
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
cf_t *buffer; cf_t *buffer[SRSLTE_MAX_PORTS];
int sample_count, n; int sample_count, n;
srslte_rf_t rf; srslte_rf_t rf;
srslte_filesink_t sink; srslte_filesink_t sink;
int32_t buflen; uint32_t buflen;
signal(SIGINT, int_handler); signal(SIGINT, int_handler);
@ -108,16 +113,18 @@ int main(int argc, char **argv) {
buflen = 4800; buflen = 4800;
sample_count = 0; sample_count = 0;
buffer = malloc(sizeof(cf_t) * buflen); for (int i = 0; i < nof_rx_antennas; i++) {
if (!buffer) { buffer[i] = malloc(sizeof(cf_t) * buflen);
if (!buffer[i]) {
perror("malloc"); perror("malloc");
exit(-1); exit(-1);
} }
}
srslte_filesink_init(&sink, output_file_name, SRSLTE_COMPLEX_FLOAT_BIN); srslte_filesink_init(&sink, output_file_name, SRSLTE_COMPLEX_FLOAT_BIN);
printf("Opening RF device...\n"); printf("Opening RF device...\n");
if (srslte_rf_open(&rf, rf_args)) { if (srslte_rf_open_multi(&rf, rf_args, nof_rx_antennas)) {
fprintf(stderr, "Error opening rf\n"); fprintf(stderr, "Error opening rf\n");
exit(-1); exit(-1);
} }
@ -151,18 +158,23 @@ int main(int argc, char **argv) {
while((sample_count < nof_samples || nof_samples == -1) while((sample_count < nof_samples || nof_samples == -1)
&& keep_running){ && keep_running){
n = srslte_rf_recv(&rf, buffer, buflen, 1); n = srslte_rf_recv_with_time_multi(&rf, (void**) buffer, buflen, true, NULL, NULL);
if (n < 0) { if (n < 0) {
fprintf(stderr, "Error receiving samples\n"); fprintf(stderr, "Error receiving samples\n");
exit(-1); exit(-1);
} }
srslte_filesink_write(&sink, buffer, buflen); srslte_filesink_write_multi(&sink, (void**) buffer, buflen, nof_rx_antennas);
sample_count += buflen; sample_count += buflen;
} }
for (int i = 0; i < nof_rx_antennas; i++) {
if (buffer[i]) {
free(buffer[i]);
}
}
srslte_filesink_free(&sink); srslte_filesink_free(&sink);
free(buffer);
srslte_rf_close(&rf); srslte_rf_close(&rf);
printf("Ok - wrote %d samples\n", sample_count); printf("Ok - wrote %d samples\n", sample_count);

@ -45,6 +45,7 @@ float rf_gain=60.0, rf_freq=-1.0;
int nof_prb = 6; int nof_prb = 6;
int nof_subframes = -1; int nof_subframes = -1;
int N_id_2 = -1; int N_id_2 = -1;
uint32_t nof_rx_antennas = 1;
void int_handler(int dummy) { void int_handler(int dummy) {
keep_running = false; keep_running = false;
@ -56,12 +57,13 @@ void usage(char *prog) {
printf("\t-g RF Gain [Default %.2f dB]\n", rf_gain); printf("\t-g RF Gain [Default %.2f dB]\n", rf_gain);
printf("\t-p nof_prb [Default %d]\n", nof_prb); printf("\t-p nof_prb [Default %d]\n", nof_prb);
printf("\t-n nof_subframes [Default %d]\n", nof_subframes); printf("\t-n nof_subframes [Default %d]\n", nof_subframes);
printf("\t-A nof_rx_antennas [Default %d]\n", nof_rx_antennas);
printf("\t-v verbose\n"); printf("\t-v verbose\n");
} }
void parse_args(int argc, char **argv) { void parse_args(int argc, char **argv) {
int opt; int opt;
while ((opt = getopt(argc, argv, "agpnvfol")) != -1) { while ((opt = getopt(argc, argv, "agpnvfolA")) != -1) {
switch (opt) { switch (opt) {
case 'o': case 'o':
output_file_name = argv[optind]; output_file_name = argv[optind];
@ -84,6 +86,9 @@ void parse_args(int argc, char **argv) {
case 'l': case 'l':
N_id_2 = atoi(argv[optind]); N_id_2 = atoi(argv[optind]);
break; break;
case 'A':
nof_rx_antennas = (uint32_t) atoi(argv[optind]);
break;
case 'v': case 'v':
srslte_verbose++; srslte_verbose++;
break; break;
@ -100,7 +105,7 @@ void parse_args(int argc, char **argv) {
int srslte_rf_recv_wrapper(void *h, cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *t) { int srslte_rf_recv_wrapper(void *h, cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *t) {
DEBUG(" ---- Receive %d samples ---- \n", nsamples); DEBUG(" ---- Receive %d samples ---- \n", nsamples);
return srslte_rf_recv(h, data[0], nsamples, 1); return srslte_rf_recv_with_time_multi(h, (void**) data, nsamples, true, NULL, NULL);
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
@ -118,13 +123,15 @@ int main(int argc, char **argv) {
srslte_filesink_init(&sink, output_file_name, SRSLTE_COMPLEX_FLOAT_BIN); srslte_filesink_init(&sink, output_file_name, SRSLTE_COMPLEX_FLOAT_BIN);
printf("Opening RF device...\n"); printf("Opening RF device...\n");
if (srslte_rf_open(&rf, rf_args)) { if (srslte_rf_open_multi(&rf, rf_args, nof_rx_antennas)) {
fprintf(stderr, "Error opening rf\n"); fprintf(stderr, "Error opening rf\n");
exit(-1); exit(-1);
} }
srslte_rf_set_master_clock_rate(&rf, 30.72e6); srslte_rf_set_master_clock_rate(&rf, 30.72e6);
buffer[0] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(100)); for (int i = 0; i< SRSLTE_MAX_PORTS; i++) {
buffer[i] = srslte_vec_malloc(3 * sizeof(cf_t) * SRSLTE_SF_LEN_PRB(100));
}
sigset_t sigset; sigset_t sigset;
sigemptyset(&sigset); sigemptyset(&sigset);
@ -158,7 +165,11 @@ int main(int argc, char **argv) {
cell.nof_prb = nof_prb; cell.nof_prb = nof_prb;
cell.nof_ports = 1; cell.nof_ports = 1;
if (srslte_ue_sync_init_multi(&ue_sync, cell, srslte_rf_recv_wrapper, 1, (void*) &rf)) { if (srslte_ue_sync_init_multi(&ue_sync, cell.nof_prb, cell.id==1000, srslte_rf_recv_wrapper, nof_rx_antennas, (void*) &rf)) {
fprintf(stderr, "Error initiating ue_sync\n");
exit(-1);
}
if (srslte_ue_sync_set_cell(&ue_sync, cell)) {
fprintf(stderr, "Error initiating ue_sync\n"); fprintf(stderr, "Error initiating ue_sync\n");
exit(-1); exit(-1);
} }
@ -181,7 +192,7 @@ int main(int argc, char **argv) {
} }
} else { } else {
printf("Writing to file %6d subframes...\r", subframe_count); printf("Writing to file %6d subframes...\r", subframe_count);
srslte_filesink_write(&sink, buffer[0], SRSLTE_SF_LEN_PRB(nof_prb)); srslte_filesink_write_multi(&sink, (void**) buffer, SRSLTE_SF_LEN_PRB(nof_prb),nof_rx_antennas);
subframe_count++; subframe_count++;
} }
} }
@ -196,6 +207,12 @@ int main(int argc, char **argv) {
srslte_rf_close(&rf); srslte_rf_close(&rf);
srslte_ue_sync_free(&ue_sync); srslte_ue_sync_free(&ue_sync);
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
if (buffer[i]) {
free(buffer[i]);
}
}
printf("Ok - wrote %d subframes\n", subframe_count); printf("Ok - wrote %d subframes\n", subframe_count);
exit(0); exit(0);
} }

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

@ -156,6 +156,9 @@ public:
return pool->allocate(debug_name); return pool->allocate(debug_name);
} }
void deallocate(byte_buffer_t *b) { void deallocate(byte_buffer_t *b) {
if(!b) {
return;
}
b->reset(); b->reset();
pool->deallocate(b); pool->deallocate(b);
} }

@ -50,7 +50,7 @@
#define SRSLTE_MAX_BUFFER_SIZE_BYTES 12756 #define SRSLTE_MAX_BUFFER_SIZE_BYTES 12756
#define SRSLTE_BUFFER_HEADER_OFFSET 1024 #define SRSLTE_BUFFER_HEADER_OFFSET 1024
#define SRSLTE_BUFFER_POOL_LOG_ENABLED //#define SRSLTE_BUFFER_POOL_LOG_ENABLED
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED #ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
#define pool_allocate (pool->allocate(__FUNCTION__)) #define pool_allocate (pool->allocate(__FUNCTION__))
@ -83,32 +83,6 @@ static const char error_text[ERROR_N_ITEMS][20] = { "None",
"Can't start", "Can't start",
"Already started"}; "Already started"};
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_N_ITEMS,
}rb_id_t;
static const char rb_id_text[RB_ID_N_ITEMS][20] = { "SRB0",
"SRB1",
"SRB2",
"DRB1",
"DRB2",
"DRB3",
"DRB4",
"DRB5",
"DRB6",
"DRB7",
"DRB8"};
/****************************************************************************** /******************************************************************************
* Byte and Bit buffers * Byte and Bit buffers
* *

@ -28,17 +28,52 @@
#define INTERFACE_COMMON_H #define INTERFACE_COMMON_H
#include "srslte/common/timers.h" #include "srslte/common/timers.h"
#include "srslte/common/security.h"
#include "srslte/asn1/liblte_rrc.h"
namespace srslte { namespace srslte {
class srslte_nas_config_t
{
public:
srslte_nas_config_t(uint32_t lcid_ = 0)
:lcid(lcid_)
{}
uint32_t lcid;
};
class srslte_pdcp_config_t
{
public:
srslte_pdcp_config_t(bool is_control_ = false, bool is_data_ = false, uint8_t direction_ = SECURITY_DIRECTION_UPLINK)
: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
// bool do_rohc;
};
class mac_interface_timers class mac_interface_timers
{ {
public: public:
/* Timer services with ms resolution. /* Timer services with ms resolution.
* timer_id must be lower than MAC_NOF_UPPER_TIMERS * timer_id must be lower than MAC_NOF_UPPER_TIMERS
*/ */
virtual timers::timer* get(uint32_t timer_id) = 0; virtual timers::timer* timer_get(uint32_t timer_id) = 0;
virtual uint32_t get_unique_id() = 0; virtual void timer_release_id(uint32_t timer_id) = 0;
virtual uint32_t timer_get_unique_id() = 0;
}; };
class read_pdu_interface class read_pdu_interface

@ -38,15 +38,19 @@
#include <stdarg.h> #include <stdarg.h>
#include <string> #include <string>
#include "srslte/common/log.h" #include "srslte/common/log.h"
#include "logger.h" #include "srslte/common/logger.h"
#include "srslte/common/logger_stdout.h"
namespace srslte { namespace srslte {
typedef std::string* str_ptr;
class log_filter : public srslte::log class log_filter : public srslte::log
{ {
public: public:
log_filter(); log_filter();
log_filter(std::string layer);
log_filter(std::string layer, logger *logger_, bool tti=false); log_filter(std::string layer, logger *logger_, bool tti=false);
void init(std::string layer, logger *logger_, bool tti=false); void init(std::string layer, logger *logger_, bool tti=false);
@ -71,6 +75,8 @@ private:
logger *logger_h; logger *logger_h;
bool do_tti; bool do_tti;
logger_stdout def_logger_stdout;
void all_log(srslte::LOG_LEVEL_ENUM level, uint32_t tti, char *msg); void all_log(srslte::LOG_LEVEL_ENUM level, uint32_t tti, char *msg);
void all_log(srslte::LOG_LEVEL_ENUM level, uint32_t tti, char *msg, uint8_t *hex, int size); void all_log(srslte::LOG_LEVEL_ENUM level, uint32_t tti, char *msg, uint8_t *hex, int size);
void all_log_line(srslte::LOG_LEVEL_ENUM level, uint32_t tti, std::string file, int line, char *msg); void all_log_line(srslte::LOG_LEVEL_ENUM level, uint32_t tti, std::string file, int line, char *msg);

@ -1,82 +0,0 @@
/**
*
* \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: log_stout.h
*
* Description: Logging service through standard output. Inherits log interface
*
* Reference:
*****************************************************************************/
#ifndef LOGSTDOUT_H
#define LOGSTDOUT_H
#include <stdarg.h>
#include <string>
#include "srslte/common/log.h"
namespace srslte {
class log_stdout : public log
{
public:
log_stdout(std::string service_name_) : log(service_name_) { }
void console(std::string message, ...);
void error(std::string message, ...);
void warning(std::string message, ...);
void info(std::string message, ...);
void debug(std::string message, ...);
// Same with hex dump
void error_hex(uint8_t *hex, int size, std::string message, ...);
void warning_hex(uint8_t *hex, int size, std::string message, ...);
void info_hex(uint8_t *hex, int size, std::string message, ...);
void debug_hex(uint8_t *hex, int size, std::string message, ...);
// Same with line and file info
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, ...);
private:
void printlog(srslte::LOG_LEVEL_ENUM level, uint32_t tti, std::string file, int line, std::string message, va_list args);
void printlog(srslte::LOG_LEVEL_ENUM level, uint32_t tti, std::string message, va_list args);
void all_log(srslte::LOG_LEVEL_ENUM level, uint32_t tti, char *msg);
void all_log(srslte::LOG_LEVEL_ENUM level, uint32_t tti, char *msg, uint8_t *hex, int size);
void all_log_line(srslte::LOG_LEVEL_ENUM level, uint32_t tti, std::string file, int line, char *msg);
std::string now_time();
std::string hex_string(uint8_t *hex, int size);
};
}
#endif

@ -26,49 +26,23 @@
/****************************************************************************** /******************************************************************************
* File: logger.h * File: logger.h
* Description: Common log object. Maintains a queue of log messages * Description: Interface for logging output
* and runs a thread to read messages and write to file.
* Multiple producers, single consumer. If full, producers
* increase queue size. If empty, consumer blocks.
*****************************************************************************/ *****************************************************************************/
#ifndef LOGGER_H #ifndef LOGGER_H
#define LOGGER_H #define LOGGER_H
#include <stdio.h> #include <stdio.h>
#include <deque>
#include <string> #include <string>
#include "srslte/common/threads.h"
namespace srslte { namespace srslte {
typedef std::string* str_ptr; class logger
class logger : public thread
{ {
public: public:
logger(); virtual void log(std::string *msg) = 0;
logger(std::string file);
~logger();
void init(std::string file);
void log(const char *msg);
void log(str_ptr msg);
private:
void run_thread();
void flush();
FILE* logfile;
bool inited;
bool not_done;
std::string filename;
pthread_cond_t not_empty;
pthread_cond_t not_full;
pthread_mutex_t mutex;
pthread_t thread;
std::deque<str_ptr> buffer;
}; };
} // namespace srsue } // namespace srslte
#endif // LOGGER_H #endif // LOGGER_H

@ -0,0 +1,76 @@
/**
*
* \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: logger_file.h
* Description: Common log object. Maintains a queue of log messages
* and runs a thread to read messages and write to file.
* Multiple producers, single consumer. If full, producers
* increase queue size. If empty, consumer blocks.
*****************************************************************************/
#ifndef LOGGER_FILE_H
#define LOGGER_FILE_H
#include <stdio.h>
#include <deque>
#include <string>
#include "srslte/common/logger.h"
#include "srslte/common/threads.h"
namespace srslte {
typedef std::string* str_ptr;
class logger_file : public thread, public logger
{
public:
logger_file();
logger_file(std::string file);
~logger_file();
void init(std::string file);
// Implementation of log_out
void log(str_ptr msg);
void log(const char *msg);
private:
void run_thread();
void flush();
FILE* logfile;
bool inited;
bool not_done;
std::string filename;
pthread_cond_t not_empty;
pthread_cond_t not_full;
pthread_mutex_t mutex;
pthread_t thread;
std::deque<str_ptr> buffer;
};
} // namespace srsue
#endif // LOGGER_H

@ -0,0 +1,51 @@
/**
*
* \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: logger_stdout.h
* Description: Interface for logging output
*****************************************************************************/
#ifndef LOGGER_STDOUT_H
#define LOGGER_STDOUT_H
#include <stdio.h>
#include <string>
#include "srslte/common/logger.h"
namespace srslte {
class logger_stdout : public logger
{
public:
void log(std::string *msg) {
fprintf(stdout, "%s", msg->c_str());
}
};
} // namespace srslte
#endif // LOGGER_H

@ -24,7 +24,7 @@ template<typename metrics_t>
class metrics_listener class metrics_listener
{ {
public: public:
virtual void set_metrics(metrics_t &m) = 0; virtual void set_metrics(metrics_t &m, float report_period_secs=1.0) = 0;
}; };
template<typename metrics_t> template<typename metrics_t>
@ -34,9 +34,11 @@ public:
bool init(metrics_interface<metrics_t> *m_, float report_period_secs=1.0) { bool init(metrics_interface<metrics_t> *m_, float report_period_secs=1.0) {
m = m_; m = m_;
start_periodic(report_period_secs*1e6); start_periodic(report_period_secs*1e6);
return true;
} }
void stop() { void stop() {
thread_cancel(); thread_cancel();
wait_thread_finish();
} }
void add_listener(metrics_listener<metrics_t> *listener) { void add_listener(metrics_listener<metrics_t> *listener) {
@ -46,8 +48,9 @@ public:
private: private:
void run_period() { void run_period() {
metrics_t metric; metrics_t metric;
bzero(&metric, sizeof(metrics_t));
m->get_metrics(metric); m->get_metrics(metric);
for (int i=0;i<listeners.size();i++) { for (uint32_t i=0;i<listeners.size();i++) {
listeners[i]->set_metrics(metric); listeners[i]->set_metrics(metric);
} }
} }

@ -97,11 +97,13 @@ public:
bool running; bool running;
}; };
timers(uint32_t nof_timers_) : timer_list(nof_timers_) { timers(uint32_t nof_timers_) : timer_list(nof_timers_),used_timers(nof_timers_) {
nof_timers = nof_timers_; nof_timers = nof_timers_;
next_timer = 0; next_timer = 0;
nof_used_timers = 0;
for (uint32_t i=0;i<nof_timers;i++) { for (uint32_t i=0;i<nof_timers;i++) {
timer_list[i].id = i; timer_list[i].id = i;
used_timers[i] = false;
} }
} }
@ -133,17 +135,36 @@ public:
return NULL; return NULL;
} }
} }
void release_id(uint32_t i) {
if (nof_used_timers > 0 && i < nof_timers) {
used_timers[i] = false;
nof_used_timers--;
} else {
fprintf(stderr, "Error releasing timer: nof_used_timers=%d, nof_timers=%d\n", nof_used_timers, nof_timers);
}
}
uint32_t get_unique_id() { uint32_t get_unique_id() {
if (next_timer == nof_timers){ if (nof_used_timers >= nof_timers) {
printf("No more unique timer ids (Only %d timers available)\n", nof_timers); fprintf(stderr, "Error getting unique timer id: no more timers available\n");
next_timer = 0; return 0;
} else {
while(used_timers[next_timer]) {
next_timer++;
if (next_timer >= nof_timers) {
next_timer=0;
}
}
used_timers[next_timer] = true;
nof_used_timers++;
return next_timer;
} }
return next_timer++;
} }
private: private:
uint32_t nof_timers;
uint32_t next_timer; uint32_t next_timer;
uint32_t nof_used_timers;
uint32_t nof_timers;
std::vector<timer> timer_list; std::vector<timer> timer_list;
std::vector<bool> used_timers;
}; };
} // namespace srslte } // namespace srslte

@ -28,7 +28,9 @@
#include "srslte/common/common.h" #include "srslte/common/common.h"
#include "srslte/common/security.h" #include "srslte/common/security.h"
#include "srslte/common/interfaces_common.h"
#include "srslte/interfaces/sched_interface.h" #include "srslte/interfaces/sched_interface.h"
#include "srslte/upper/rlc_interface.h"
#include "srslte/asn1/liblte_rrc.h" #include "srslte/asn1/liblte_rrc.h"
#include "srslte/asn1/liblte_s1ap.h" #include "srslte/asn1/liblte_s1ap.h"
@ -156,7 +158,7 @@ public:
virtual void add_user(uint16_t rnti) = 0; virtual void add_user(uint16_t rnti) = 0;
virtual void rem_user(uint16_t rnti) = 0; virtual void rem_user(uint16_t rnti) = 0;
virtual void add_bearer(uint16_t rnti, uint32_t lcid) = 0; virtual void add_bearer(uint16_t rnti, uint32_t lcid) = 0;
virtual void add_bearer(uint16_t rnti, uint32_t lcid, LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg) = 0; virtual void add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_rlc_config_t cnfg) = 0;
}; };
// PDCP interface for GTPU // PDCP interface for GTPU
@ -174,7 +176,7 @@ public:
virtual void add_user(uint16_t rnti) = 0; virtual void add_user(uint16_t rnti) = 0;
virtual void rem_user(uint16_t rnti) = 0; virtual void rem_user(uint16_t rnti) = 0;
virtual void write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t *sdu) = 0; virtual void write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t *sdu) = 0;
virtual void add_bearer(uint16_t rnti, uint32_t lcid, LIBLTE_RRC_PDCP_CONFIG_STRUCT *cnfg=NULL) = 0; virtual void add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_pdcp_config_t cnfg) = 0;
virtual void config_security(uint16_t rnti, virtual void config_security(uint16_t rnti,
uint32_t lcid, uint32_t lcid,
uint8_t *k_rrc_enc_, uint8_t *k_rrc_enc_,
@ -242,7 +244,7 @@ public:
class gtpu_interface_rrc class gtpu_interface_rrc
{ {
public: public:
virtual void add_bearer(uint16_t rnti, uint32_t lcid, uint32_t teid_out, uint32_t *teid_in) = 0; virtual void add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, uint32_t *teid_in) = 0;
virtual void rem_bearer(uint16_t rnti, uint32_t lcid) = 0; virtual void rem_bearer(uint16_t rnti, uint32_t lcid) = 0;
virtual void rem_user(uint16_t rnti) = 0; virtual void rem_user(uint16_t rnti) = 0;
}; };

@ -32,7 +32,7 @@
#include "upper/common_enb.h" #include "upper/common_enb.h"
#include "upper/s1ap_metrics.h" #include "upper/s1ap_metrics.h"
#include "upper/rrc_metrics.h" #include "upper/rrc_metrics.h"
#include "srslte/upper/gw_metrics.h" #include "../../../../srsue/hdr/upper/gw_metrics.h"
#include "srslte/upper/rlc_metrics.h" #include "srslte/upper/rlc_metrics.h"
#include "mac/mac_metrics.h" #include "mac/mac_metrics.h"
#include "phy/phy_metrics.h" #include "phy/phy_metrics.h"

@ -95,6 +95,7 @@ public:
int priority; int priority;
int bsd; int bsd;
int pbr; int pbr;
int group;
enum {IDLE = 0, UL, DL, BOTH} direction; enum {IDLE = 0, UL, DL, BOTH} direction;
} ue_bearer_cfg_t; } ue_bearer_cfg_t;
@ -231,7 +232,7 @@ public:
/* UL information */ /* UL information */
virtual int ul_crc_info(uint32_t tti, uint16_t rnti, bool crc) = 0; virtual int ul_crc_info(uint32_t tti, uint16_t rnti, bool crc) = 0;
virtual int ul_sr_info(uint32_t tti, uint16_t rnti) = 0; virtual int ul_sr_info(uint32_t tti, uint16_t rnti) = 0;
virtual int ul_bsr(uint16_t rnti, uint32_t lcid, uint32_t bsr) = 0; virtual int ul_bsr(uint16_t rnti, uint32_t lcid, uint32_t bsr, bool set_value = true) = 0;
virtual int ul_recv_len(uint16_t rnti, uint32_t lcid, uint32_t len) = 0; virtual int ul_recv_len(uint16_t rnti, uint32_t lcid, uint32_t len) = 0;
virtual int ul_phr(uint16_t rnti, int phr) = 0; virtual int ul_phr(uint16_t rnti, int phr) = 0;
virtual int ul_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi, uint32_t ul_ch_code) = 0; virtual int ul_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi, uint32_t ul_ch_code) = 0;

@ -39,6 +39,7 @@
#include "srslte/common/interfaces_common.h" #include "srslte/common/interfaces_common.h"
#include "srslte/common/common.h" #include "srslte/common/common.h"
#include "srslte/common/security.h" #include "srslte/common/security.h"
#include "srslte/upper/rlc_interface.h"
namespace srsue { namespace srsue {
@ -97,26 +98,49 @@ class nas_interface_rrc
{ {
public: public:
virtual bool is_attached() = 0; virtual bool is_attached() = 0;
virtual bool is_attaching() = 0;
virtual void notify_connection_setup() = 0; virtual void notify_connection_setup() = 0;
virtual void write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu) = 0; virtual void write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu) = 0;
virtual uint32_t get_ul_count() = 0; virtual uint32_t get_ul_count() = 0;
virtual bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) = 0; virtual bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) = 0;
virtual void plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) = 0;
};
// NAS interface for UE
class nas_interface_ue
{
public:
virtual void attach_request() = 0;
virtual void deattach_request() = 0;
};
// NAS interface for UE
class nas_interface_gw
{
public:
virtual void attach_request() = 0;
}; };
// RRC interface for MAC // RRC interface for MAC
class rrc_interface_mac class rrc_interface_mac_common
{ {
public: public:
virtual void release_pucch_srs() = 0;
virtual void ra_problem() = 0; virtual void ra_problem() = 0;
}; };
class rrc_interface_mac : public rrc_interface_mac_common
{
public:
virtual void release_pucch_srs() = 0;
};
// RRC interface for PHY // RRC interface for PHY
class rrc_interface_phy class rrc_interface_phy
{ {
public: public:
virtual void in_sync() = 0; virtual void in_sync() = 0;
virtual void out_of_sync() = 0; virtual void out_of_sync() = 0;
virtual void cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) = 0;
}; };
// RRC interface for NAS // RRC interface for NAS
@ -127,15 +151,9 @@ public:
virtual uint16_t get_mcc() = 0; virtual uint16_t get_mcc() = 0;
virtual uint16_t get_mnc() = 0; virtual uint16_t get_mnc() = 0;
virtual void enable_capabilities() = 0; virtual void enable_capabilities() = 0;
}; virtual void plmn_search() = 0;
virtual void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) = 0;
// RRC interface for GW virtual std::string get_rb_name(uint32_t lcid) = 0;
class rrc_interface_gw
{
public:
virtual bool rrc_connected() = 0;
virtual void rrc_connect() = 0;
virtual bool have_drb() = 0;
}; };
// RRC interface for PDCP // RRC interface for PDCP
@ -146,6 +164,7 @@ public:
virtual void write_pdu_bcch_bch(srslte::byte_buffer_t *pdu) = 0; 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_bcch_dlsch(srslte::byte_buffer_t *pdu) = 0;
virtual void write_pdu_pcch(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 // RRC interface for RLC
@ -153,6 +172,7 @@ class rrc_interface_rlc
{ {
public: public:
virtual void max_retx_attempted() = 0; virtual void max_retx_attempted() = 0;
virtual std::string get_rb_name(uint32_t lcid) = 0;
}; };
// PDCP interface for GW // PDCP interface for GW
@ -160,6 +180,7 @@ class pdcp_interface_gw
{ {
public: public:
virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu) = 0; virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu) = 0;
virtual bool is_drb_enabled(uint32_t lcid) = 0;
}; };
// PDCP interface for RRC // PDCP interface for RRC
@ -168,7 +189,7 @@ class pdcp_interface_rrc
public: public:
virtual void reset() = 0; virtual void reset() = 0;
virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu) = 0; virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu) = 0;
virtual void add_bearer(uint32_t lcid, LIBLTE_RRC_PDCP_CONFIG_STRUCT *cnfg=NULL) = 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, virtual void config_security(uint32_t lcid,
uint8_t *k_rrc_enc_, uint8_t *k_rrc_enc_,
uint8_t *k_rrc_int_, uint8_t *k_rrc_int_,
@ -193,7 +214,7 @@ class rlc_interface_rrc
public: public:
virtual void reset() = 0; virtual void reset() = 0;
virtual void add_bearer(uint32_t lcid) = 0; virtual void add_bearer(uint32_t lcid) = 0;
virtual void add_bearer(uint32_t lcid, LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg) = 0; virtual void add_bearer(uint32_t lcid, srslte::srslte_rlc_config_t cnfg) = 0;
}; };
// RLC interface for PDCP // RLC interface for PDCP
@ -230,6 +251,31 @@ public:
}; };
//BSR interface for MUX
class bsr_interface_mux
{
public:
typedef enum {
LONG_BSR,
SHORT_BSR,
TRUNC_BSR
} bsr_format_t;
typedef struct {
bsr_format_t format;
uint32_t buff_size[4];
} bsr_t;
/* MUX calls BSR to check if it can fit a BSR into PDU */
virtual bool need_to_send_bsr_on_ul_grant(uint32_t grant_size, bsr_t *bsr) = 0;
/* MUX calls BSR to let it generate a padding BSR if there is space in PDU */
virtual bool generate_padding_bsr(uint32_t nof_padding_bytes, bsr_t *bsr) = 0;
/* MAX calls BSR to set the Tx TTI */
virtual void set_tx_tti(uint32_t tti) = 0;
};
/** MAC interface /** MAC interface
* *
@ -243,10 +289,12 @@ public:
uint32_t pid; uint32_t pid;
uint32_t tti; uint32_t tti;
uint32_t last_tti; uint32_t last_tti;
bool ndi; bool ndi[SRSLTE_MAX_CODEWORDS];
bool last_ndi; bool last_ndi[SRSLTE_MAX_CODEWORDS];
uint32_t n_bytes; uint32_t n_bytes[SRSLTE_MAX_CODEWORDS];
int rv; int rv[SRSLTE_MAX_CODEWORDS];
bool tb_en[SRSLTE_MAX_CODEWORDS];
bool tb_cw_swap;
uint16_t rnti; uint16_t rnti;
bool is_from_rar; bool is_from_rar;
bool is_sps_release; bool is_sps_release;
@ -256,28 +304,29 @@ public:
} mac_grant_t; } mac_grant_t;
typedef struct { typedef struct {
bool decode_enabled; bool decode_enabled[SRSLTE_MAX_TB];
int rv; int rv[SRSLTE_MAX_TB];
uint16_t rnti; uint16_t rnti;
bool generate_ack; bool generate_ack;
bool default_ack; bool default_ack[SRSLTE_MAX_TB];
// If non-null, called after tb_decoded_ok to determine if ack needs to be sent // If non-null, called after tb_decoded_ok to determine if ack needs to be sent
bool (*generate_ack_callback)(void*); bool (*generate_ack_callback)(void*);
void *generate_ack_callback_arg; void *generate_ack_callback_arg;
uint8_t *payload_ptr; uint8_t *payload_ptr[SRSLTE_MAX_TB];
srslte_softbuffer_rx_t *softbuffer; srslte_softbuffer_rx_t *softbuffers[SRSLTE_MAX_TB];
srslte_phy_grant_t phy_grant; srslte_phy_grant_t phy_grant;
} tb_action_dl_t; } tb_action_dl_t;
typedef struct { typedef struct {
bool tx_enabled; bool tx_enabled;
bool expect_ack; bool expect_ack;
uint32_t rv; uint32_t rv[SRSLTE_MAX_TB];
uint16_t rnti; uint16_t rnti;
uint32_t current_tx_nb; uint32_t current_tx_nb;
srslte_softbuffer_tx_t *softbuffer; int32_t tti_offset; // relative offset between grant and UL tx/HARQ rx
srslte_softbuffer_tx_t *softbuffers;
srslte_phy_grant_t phy_grant; srslte_phy_grant_t phy_grant;
uint8_t *payload_ptr; uint8_t *payload_ptr[SRSLTE_MAX_TB];
} tb_action_ul_t; } tb_action_ul_t;
/* Indicate reception of UL grant. /* Indicate reception of UL grant.
@ -294,7 +343,7 @@ public:
virtual void new_grant_dl(mac_grant_t grant, tb_action_dl_t *action) = 0; virtual void new_grant_dl(mac_grant_t grant, tb_action_dl_t *action) = 0;
/* Indicate successfull decoding of PDSCH TB. */ /* Indicate successfull decoding of PDSCH TB. */
virtual void tb_decoded(bool ack, srslte_rnti_type_t rnti_type, uint32_t harq_pid) = 0; virtual void tb_decoded(bool ack, uint32_t tb_idx, srslte_rnti_type_t rnti_type, uint32_t harq_pid) = 0;
/* Indicate successfull decoding of BCH TB through PBCH */ /* Indicate successfull decoding of BCH TB through PBCH */
virtual void bch_decoded_ok(uint8_t *payload, uint32_t len) = 0; virtual void bch_decoded_ok(uint8_t *payload, uint32_t len) = 0;
@ -309,9 +358,27 @@ public:
}; };
/* Interface RRC -> MAC shared between different RATs */
class mac_interface_rrc_common
{
public:
// Class to handle UE specific RNTIs between RRC and MAC
typedef struct {
uint16_t crnti;
uint16_t temp_rnti;
uint16_t tpc_rnti;
uint16_t sps_rnti;
uint64_t contention_id;
} ue_rnti_t;
typedef struct {
uint32_t max_harq_msg3_tx;
uint32_t max_harq_tx;
} ul_harq_params_t;
};
/* Interface RRC -> MAC */ /* Interface RRC -> MAC */
class mac_interface_rrc class mac_interface_rrc : public mac_interface_rrc_common
{ {
public: public:
@ -319,19 +386,10 @@ public:
LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT main; LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT main;
LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT rach; LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT rach;
LIBLTE_RRC_SCHEDULING_REQUEST_CONFIG_STRUCT sr; LIBLTE_RRC_SCHEDULING_REQUEST_CONFIG_STRUCT sr;
ul_harq_params_t ul_harq_params;
uint32_t prach_config_index; uint32_t prach_config_index;
} mac_cfg_t; } mac_cfg_t;
// Class to handle UE specific RNTIs between RRC and MAC
typedef struct {
uint16_t crnti;
uint16_t temp_rnti;
uint16_t tpc_rnti;
uint16_t sps_rnti;
uint64_t contention_id;
} ue_rnti_t;
/* Instructs the MAC to start receiving BCCH */ /* Instructs the MAC to start receiving BCCH */
virtual void bcch_start_rx() = 0; virtual void bcch_start_rx() = 0;
virtual void bcch_stop_rx() = 0; virtual void bcch_stop_rx() = 0;
@ -392,27 +450,17 @@ typedef struct {
bool rssi_sensor_enabled; bool rssi_sensor_enabled;
} phy_args_t; } phy_args_t;
/* Interface MAC -> PHY */
class phy_interface_mac /* RAT agnostic Interface MAC -> PHY */
class phy_interface_mac_common
{ {
public: public:
/* Configure PRACH using parameters written by RRC */
virtual void configure_prach_params() = 0;
/* Start synchronization with strongest cell in the current carrier frequency */ /* Start synchronization with strongest cell in the current carrier frequency */
virtual void sync_start() = 0; virtual bool sync_status() = 0;
virtual void sync_stop() = 0;
/* Sets a C-RNTI allowing the PHY to pregenerate signals if necessary */ /* Sets a C-RNTI allowing the PHY to pregenerate signals if necessary */
virtual void set_crnti(uint16_t rnti) = 0; virtual void set_crnti(uint16_t rnti) = 0;
virtual void prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm) = 0;
virtual int prach_tx_tti() = 0;
/* Indicates the transmission of a SR signal in the next opportunity */
virtual void sr_send() = 0;
virtual int sr_last_tx_tti() = 0;
/* Time advance commands */ /* Time advance commands */
virtual void set_timeadv_rar(uint32_t ta_cmd) = 0; virtual void set_timeadv_rar(uint32_t ta_cmd) = 0;
virtual void set_timeadv(uint32_t ta_cmd) = 0; virtual void set_timeadv(uint32_t ta_cmd) = 0;
@ -420,17 +468,31 @@ public:
/* Sets RAR grant payload */ /* Sets RAR grant payload */
virtual void set_rar_grant(uint32_t tti, uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN]) = 0; virtual void set_rar_grant(uint32_t tti, uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN]) = 0;
/* Instruct the PHY to decode PDCCH with the CRC scrambled with given RNTI */
virtual void pdcch_ul_search(srslte_rnti_type_t rnti_type, uint16_t rnti, int tti_start = -1, int tti_end = -1) = 0;
virtual void pdcch_dl_search(srslte_rnti_type_t rnti_type, uint16_t rnti, int tti_start = -1, int tti_end = -1) = 0;
virtual void pdcch_ul_search_reset() = 0;
virtual void pdcch_dl_search_reset() = 0;
virtual uint32_t get_current_tti() = 0; virtual uint32_t get_current_tti() = 0;
virtual float get_phr() = 0; virtual float get_phr() = 0;
virtual float get_pathloss_db() = 0; virtual float get_pathloss_db() = 0;
};
/* Interface MAC -> PHY */
class phy_interface_mac : public phy_interface_mac_common
{
public:
/* Configure PRACH using parameters written by RRC */
virtual void configure_prach_params() = 0;
virtual void prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm) = 0;
virtual int prach_tx_tti() = 0;
/* Indicates the transmission of a SR signal in the next opportunity */
virtual void sr_send() = 0;
virtual int sr_last_tx_tti() = 0;
/* Instruct the PHY to decode PDCCH with the CRC scrambled with given RNTI */
virtual void pdcch_ul_search(srslte_rnti_type_t rnti_type, uint16_t rnti, int tti_start = -1, int tti_end = -1) = 0;
virtual void pdcch_dl_search(srslte_rnti_type_t rnti_type, uint16_t rnti, int tti_start = -1, int tti_end = -1) = 0;
virtual void pdcch_ul_search_reset() = 0;
virtual void pdcch_dl_search_reset() = 0;
}; };
class phy_interface_rrc class phy_interface_rrc
@ -463,16 +525,21 @@ public:
virtual void set_config_tdd(LIBLTE_RRC_TDD_CONFIG_STRUCT *tdd) = 0; virtual void set_config_tdd(LIBLTE_RRC_TDD_CONFIG_STRUCT *tdd) = 0;
virtual void set_config_64qam_en(bool enable) = 0; virtual void set_config_64qam_en(bool enable) = 0;
/* Cell search and selection procedures */
virtual void cell_search_start() = 0;
virtual void cell_search_stop() = 0;
virtual void cell_search_next() = 0;
virtual bool cell_select(uint32_t earfcn, srslte_cell_t cell) = 0;
/* Is the PHY downlink synchronized? */ /* Is the PHY downlink synchronized? */
virtual bool status_is_sync() = 0; virtual bool sync_status() = 0;
virtual void sync_reset() = 0;
/* Configure UL using parameters written with set_param() */ /* Configure UL using parameters written with set_param() */
virtual void configure_ul_params(bool pregen_disabled = false) = 0; virtual void configure_ul_params(bool pregen_disabled = false) = 0;
virtual void reset() = 0; virtual void reset() = 0;
virtual void resync_sfn() = 0;
}; };

@ -60,7 +60,10 @@ typedef enum {
typedef struct { typedef struct {
srslte_cell_t cell; srslte_cell_t cell;
srslte_refsignal_cs_t csr_signal; srslte_refsignal_t csr_refs;
srslte_refsignal_t **mbsfn_refs;
cf_t *pilot_estimates; cf_t *pilot_estimates;
cf_t *pilot_estimates_average; cf_t *pilot_estimates_average;
cf_t *pilot_recv_signal; cf_t *pilot_recv_signal;
@ -75,7 +78,7 @@ typedef struct {
srslte_interp_linsrslte_vec_t srslte_interp_linvec; srslte_interp_linsrslte_vec_t srslte_interp_linvec;
srslte_interp_lin_t srslte_interp_lin; srslte_interp_lin_t srslte_interp_lin;
srslte_interp_lin_t srslte_interp_lin_mbsfn;
float rssi[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; float rssi[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
float rsrp[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; float rsrp[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
float noise_estimate[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; float noise_estimate[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
@ -92,10 +95,17 @@ typedef struct {
SRSLTE_API int srslte_chest_dl_init(srslte_chest_dl_t *q, SRSLTE_API int srslte_chest_dl_init(srslte_chest_dl_t *q,
srslte_cell_t cell); uint32_t max_prb);
SRSLTE_API void srslte_chest_dl_free(srslte_chest_dl_t *q); SRSLTE_API void srslte_chest_dl_free(srslte_chest_dl_t *q);
SRSLTE_API int srslte_chest_dl_set_mbsfn_area_id(srslte_chest_dl_t *q,
uint16_t mbsfn_area_id);
SRSLTE_API int srslte_chest_dl_set_cell(srslte_chest_dl_t *q,
srslte_cell_t cell);
SRSLTE_API void srslte_chest_dl_set_smooth_filter(srslte_chest_dl_t *q, SRSLTE_API void srslte_chest_dl_set_smooth_filter(srslte_chest_dl_t *q,
float *filter, float *filter,
uint32_t filter_len); uint32_t filter_len);
@ -106,6 +116,8 @@ SRSLTE_API void srslte_chest_dl_set_smooth_filter3_coeff(srslte_chest_dl_t* q,
SRSLTE_API void srslte_chest_dl_set_noise_alg(srslte_chest_dl_t *q, SRSLTE_API void srslte_chest_dl_set_noise_alg(srslte_chest_dl_t *q,
srslte_chest_dl_noise_alg_t noise_estimation_alg); srslte_chest_dl_noise_alg_t noise_estimation_alg);
SRSLTE_API int srslte_chest_dl_estimate_multi(srslte_chest_dl_t *q, SRSLTE_API int srslte_chest_dl_estimate_multi(srslte_chest_dl_t *q,
cf_t *input[SRSLTE_MAX_PORTS], cf_t *input[SRSLTE_MAX_PORTS],
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
@ -117,6 +129,14 @@ SRSLTE_API int srslte_chest_dl_estimate(srslte_chest_dl_t *q,
cf_t *ce[SRSLTE_MAX_PORTS], cf_t *ce[SRSLTE_MAX_PORTS],
uint32_t sf_idx); uint32_t sf_idx);
SRSLTE_API int srslte_chest_dl_estimate_multi_mbsfn(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,
uint16_t mbsfn_area_id);
SRSLTE_API int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, SRSLTE_API int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q,
cf_t *input, cf_t *input,
cf_t *ce, cf_t *ce,
@ -132,6 +152,9 @@ 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(srslte_chest_dl_t *q);
SRSLTE_API float srslte_chest_dl_get_rsrp_port(srslte_chest_dl_t *q,
uint32_t port);
SRSLTE_API float srslte_chest_dl_get_rsrp(srslte_chest_dl_t *q); SRSLTE_API float srslte_chest_dl_get_rsrp(srslte_chest_dl_t *q);
#endif #endif

@ -77,10 +77,14 @@ typedef struct {
SRSLTE_API int srslte_chest_ul_init(srslte_chest_ul_t *q, SRSLTE_API int srslte_chest_ul_init(srslte_chest_ul_t *q,
srslte_cell_t cell); uint32_t max_prb);
SRSLTE_API void srslte_chest_ul_free(srslte_chest_ul_t *q); SRSLTE_API void srslte_chest_ul_free(srslte_chest_ul_t *q);
SRSLTE_API int srslte_chest_ul_set_cell(srslte_chest_ul_t *q,
srslte_cell_t cell);
SRSLTE_API void srslte_chest_ul_set_cfg(srslte_chest_ul_t *q, SRSLTE_API void srslte_chest_ul_set_cfg(srslte_chest_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg, srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
srslte_pucch_cfg_t *pucch_cfg, srslte_pucch_cfg_t *pucch_cfg,

@ -40,22 +40,34 @@
// Number of references in a subframe: there are 2 symbols for port_id=0,1 x 2 slots x 2 refs per prb // Number of references in a subframe: there are 2 symbols for port_id=0,1 x 2 slots x 2 refs per prb
#define SRSLTE_REFSIGNAL_NUM_SF(nof_prb, port_id) (((port_id)<2?8:4)*(nof_prb)) #define SRSLTE_REFSIGNAL_NUM_SF(nof_prb, port_id) (((port_id)<2?8:4)*(nof_prb))
#define SRSLTE_REFSIGNAL_NUM_SF_MBSFN(nof_prb, port_id) ((2 + 18)*(nof_prb))
#define SRSLTE_REFSIGNAL_MAX_NUM_SF(nof_prb) SRSLTE_REFSIGNAL_NUM_SF(nof_prb, 0) #define SRSLTE_REFSIGNAL_MAX_NUM_SF(nof_prb) SRSLTE_REFSIGNAL_NUM_SF(nof_prb, 0)
#define SRSLTE_REFSIGNAL_MAX_NUM_SF_MBSFN(nof_prb) SRSLTE_REFSIGNAL_NUM_SF_MBSFN(nof_prb,0)
#define SRSLTE_REFSIGNAL_PILOT_IDX(i,l,cell) (2*cell.nof_prb*(l)+(i)) #define SRSLTE_REFSIGNAL_PILOT_IDX(i,l,cell) (2*cell.nof_prb*(l)+(i))
#define SRSLTE_REFSIGNAL_PILOT_IDX_MBSFN(i,l,cell) ((6*cell.nof_prb*(l)+(i)))
/** Cell-Specific Reference Signal */ /** Cell-Specific Reference Signal */
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
srslte_cell_t cell; srslte_cell_t cell;
cf_t *pilots[2][SRSLTE_NSUBFRAMES_X_FRAME]; // Saves the reference signal per subframe for ports 0,1 and ports 2,3 cf_t *pilots[2][SRSLTE_NSUBFRAMES_X_FRAME]; // Saves the reference signal per subframe for ports 0,1 and ports 2,3
} srslte_refsignal_cs_t; srslte_sf_t type;
uint16_t mbsfn_area_id;
} srslte_refsignal_t;
SRSLTE_API int srslte_refsignal_cs_init(srslte_refsignal_t *q,
uint32_t max_prb);
SRSLTE_API int srslte_refsignal_cs_init(srslte_refsignal_cs_t *q, SRSLTE_API int srslte_refsignal_cs_set_cell(srslte_refsignal_t * q,
srslte_cell_t cell); srslte_cell_t cell);
SRSLTE_API void srslte_refsignal_cs_free(srslte_refsignal_cs_t *q); SRSLTE_API void srslte_refsignal_free(srslte_refsignal_t *q);
SRSLTE_API int srslte_refsignal_cs_put_sf(srslte_cell_t cell, SRSLTE_API int srslte_refsignal_cs_put_sf(srslte_cell_t cell,
uint32_t port_id, uint32_t port_id,
@ -81,4 +93,29 @@ SRSLTE_API uint32_t srslte_refsignal_cs_v(uint32_t port_id,
SRSLTE_API uint32_t srslte_refsignal_cs_nof_symbols(uint32_t port_id); SRSLTE_API uint32_t srslte_refsignal_cs_nof_symbols(uint32_t port_id);
SRSLTE_API int srslte_refsignal_mbsfn_init(srslte_refsignal_t *q, srslte_cell_t cell,
uint16_t mbsfn_area_id);
SRSLTE_API int srslte_refsignal_mbsfn_get_sf(srslte_cell_t cell,
uint32_t port_id,
cf_t *sf_symbols,
cf_t *pilots);
SRSLTE_API uint32_t srslte_refsignal_mbsfn_nsymbol(uint32_t l);
SRSLTE_API uint32_t srslte_refsignal_mbsfn_fidx(uint32_t l);
SRSLTE_API uint32_t srslte_refsignal_mbsfn_nof_symbols();
SRSLTE_API int srslte_refsignal_mbsfn_put_sf(srslte_cell_t cell,
uint32_t port_id,
cf_t *cs_pilots,
cf_t *mbsfn_pilots,
cf_t *sf_symbols);
SRSLTE_API int srslte_refsignal_mbsfn_gen_seq(srslte_refsignal_t * q,
srslte_cell_t cell,
uint32_t N_mbsfn_id);
#endif #endif

@ -94,6 +94,9 @@ typedef struct {
} srslte_refsignal_srs_pregen_t; } srslte_refsignal_srs_pregen_t;
SRSLTE_API int srslte_refsignal_ul_init(srslte_refsignal_ul_t *q, SRSLTE_API int srslte_refsignal_ul_init(srslte_refsignal_ul_t *q,
uint32_t max_prb);
SRSLTE_API int srslte_refsignal_ul_set_cell(srslte_refsignal_ul_t *q,
srslte_cell_t cell); srslte_cell_t cell);
SRSLTE_API void srslte_refsignal_ul_free(srslte_refsignal_ul_t *q); SRSLTE_API void srslte_refsignal_ul_free(srslte_refsignal_ul_t *q);
@ -117,6 +120,10 @@ SRSLTE_API bool srslte_refsignal_dmrs_pusch_cfg_isvalid(srslte_refsignal_ul_t *q
srslte_refsignal_dmrs_pusch_cfg_t *cfg, srslte_refsignal_dmrs_pusch_cfg_t *cfg,
uint32_t nof_prb); uint32_t nof_prb);
SRSLTE_API int srslte_refsignal_dmrs_pusch_pregen_init(srslte_refsignal_ul_t *q,
srslte_refsignal_ul_dmrs_pregen_t *pregen,
uint32_t max_prb);
SRSLTE_API int srslte_refsignal_dmrs_pusch_pregen(srslte_refsignal_ul_t *q, SRSLTE_API int srslte_refsignal_dmrs_pusch_pregen(srslte_refsignal_ul_t *q,
srslte_refsignal_ul_dmrs_pregen_t *pregen); srslte_refsignal_ul_dmrs_pregen_t *pregen);

@ -52,13 +52,22 @@
#define SRSLTE_MAX_PORTS 4 #define SRSLTE_MAX_PORTS 4
#define SRSLTE_MAX_LAYERS 4 #define SRSLTE_MAX_LAYERS 4
#define SRSLTE_MAX_CODEWORDS 2 #define SRSLTE_MAX_CODEWORDS 2
#define SRSLTE_MAX_TB SRSLTE_MAX_CODEWORDS
#define SRSLTE_MAX_CODEBLOCKS 32
#define SRSLTE_MAX_CODEBOOKS 4
#define SRSLTE_LTE_CRC24A 0x1864CFB #define SRSLTE_LTE_CRC24A 0x1864CFB
#define SRSLTE_LTE_CRC24B 0X1800063 #define SRSLTE_LTE_CRC24B 0X1800063
#define SRSLTE_LTE_CRC16 0x11021 #define SRSLTE_LTE_CRC16 0x11021
#define SRSLTE_LTE_CRC8 0x19B #define SRSLTE_LTE_CRC8 0x19B
#define SRSLTE_MAX_MBSFN_AREA_IDS 256
#define SRSLTE_PMCH_RV 0
typedef enum {SRSLTE_CP_NORM, SRSLTE_CP_EXT} srslte_cp_t; typedef enum {SRSLTE_CP_NORM, SRSLTE_CP_EXT} srslte_cp_t;
typedef enum {SRSLTE_SF_NORM, SRSLTE_SF_MBSFN} srslte_sf_t;
#define SRSLTE_CRNTI_START 0x000B #define SRSLTE_CRNTI_START 0x000B
@ -125,6 +134,13 @@ typedef enum {SRSLTE_CP_NORM, SRSLTE_CP_EXT} srslte_cp_t;
|| l == SRSLTE_CP_NSYMB(cp) - 3) || l == SRSLTE_CP_NSYMB(cp) - 3)
#define SRSLTE_SYMBOL_HAS_REF_MBSFN(l, s) ((l == 2 && s == 0) || (l == 0 && s == 1) || (l == 4 && s == 1))
#define SRSLTE_NON_MBSFN_REGION_GUARD_LENGTH(non_mbsfn_region,symbol_sz) ((non_mbsfn_region == 1)?(SRSLTE_CP_LEN_EXT(symbol_sz) - SRSLTE_CP_LEN_NORM(0, symbol_sz)):(2*SRSLTE_CP_LEN_EXT(symbol_sz) - SRSLTE_CP_LEN_NORM(0, symbol_sz)- SRSLTE_CP_LEN_NORM(1, symbol_sz)))
#define SRSLTE_NOF_LTE_BANDS 38 #define SRSLTE_NOF_LTE_BANDS 38
#define SRSLTE_DEFAULT_MAX_FRAMES_PBCH 500 #define SRSLTE_DEFAULT_MAX_FRAMES_PBCH 500
@ -146,12 +162,13 @@ typedef enum SRSLTE_API {
} srslte_phich_resources_t; } srslte_phich_resources_t;
typedef enum { typedef enum {
SRSLTE_RNTI_USER = 0, SRSLTE_RNTI_USER = 0, /* Cell RNTI */
SRSLTE_RNTI_SI, SRSLTE_RNTI_SI, /* System Information RNTI */
SRSLTE_RNTI_RAR, SRSLTE_RNTI_RAR, /* Random Access RNTI */
SRSLTE_RNTI_TEMP, SRSLTE_RNTI_TEMP, /* Temporary C-RNTI */
SRSLTE_RNTI_SPS, SRSLTE_RNTI_SPS, /* Semi-Persistent Scheduling C-RNTI */
SRSLTE_RNTI_PCH, SRSLTE_RNTI_PCH, /* Paging RNTI */
SRSLTE_RNTI_MBSFN,
SRSLTE_RNTI_NOF_TYPES SRSLTE_RNTI_NOF_TYPES
} srslte_rnti_type_t; } srslte_rnti_type_t;
@ -171,6 +188,11 @@ typedef enum SRSLTE_API {
SRSLTE_MIMO_TYPE_CDD SRSLTE_MIMO_TYPE_CDD
} srslte_mimo_type_t; } srslte_mimo_type_t;
typedef enum SRSLTE_API {
SRSLTE_MIMO_DECODER_ZF,
SRSLTE_MIMO_DECODER_MMSE
} srslte_mimo_decoder_t;
typedef enum SRSLTE_API { typedef enum SRSLTE_API {
SRSLTE_MOD_BPSK = 0, SRSLTE_MOD_BPSK = 0,
SRSLTE_MOD_QPSK, SRSLTE_MOD_QPSK,
@ -240,8 +262,13 @@ SRSLTE_API uint32_t srslte_N_ta_new_rar(uint32_t ta);
SRSLTE_API uint32_t srslte_N_ta_new(uint32_t N_ta_old, SRSLTE_API uint32_t srslte_N_ta_new(uint32_t N_ta_old,
uint32_t ta); uint32_t ta);
SRSLTE_API float srslte_coderate(uint32_t tbs,
uint32_t nof_re);
SRSLTE_API char *srslte_cp_string(srslte_cp_t cp); SRSLTE_API char *srslte_cp_string(srslte_cp_t cp);
SRSLTE_API srslte_mod_t srslte_str2mod (char * mod_str);
SRSLTE_API char *srslte_mod_string(srslte_mod_t mod); SRSLTE_API char *srslte_mod_string(srslte_mod_t mod);
SRSLTE_API uint32_t srslte_mod_bits_x_symbol(srslte_mod_t mod); SRSLTE_API uint32_t srslte_mod_bits_x_symbol(srslte_mod_t mod);
@ -271,6 +298,8 @@ SRSLTE_API int srslte_band_get_fd_region(enum band_geographical_area region,
SRSLTE_API int srslte_str2mimotype(char *mimo_type_str, SRSLTE_API int srslte_str2mimotype(char *mimo_type_str,
srslte_mimo_type_t *type); srslte_mimo_type_t *type);
SRSLTE_API char *srslte_mimotype2str(srslte_mimo_type_t mimo_type);
SRSLTE_API uint32_t srslte_tti_interval(uint32_t tti1, SRSLTE_API uint32_t srslte_tti_interval(uint32_t tti1,
uint32_t tti2); uint32_t tti2);

@ -44,7 +44,8 @@ typedef struct SRSLTE_API {
uint8_t *c_bytes; uint8_t *c_bytes;
float *c_float; float *c_float;
short *c_short; short *c_short;
uint32_t len; uint32_t cur_len;
uint32_t max_len;
} srslte_sequence_t; } srslte_sequence_t;
SRSLTE_API int srslte_sequence_init(srslte_sequence_t *q, uint32_t len); SRSLTE_API int srslte_sequence_init(srslte_sequence_t *q, uint32_t len);
@ -55,7 +56,8 @@ SRSLTE_API int srslte_sequence_LTE_pr(srslte_sequence_t *q,
uint32_t len, uint32_t len,
uint32_t seed); uint32_t seed);
SRSLTE_API void srslte_sequence_set_LTE_pr(srslte_sequence_t *q, SRSLTE_API int srslte_sequence_set_LTE_pr(srslte_sequence_t *q,
uint32_t len,
uint32_t seed); uint32_t seed);
SRSLTE_API int srslte_sequence_pbch(srslte_sequence_t *seq, SRSLTE_API int srslte_sequence_pbch(srslte_sequence_t *seq,
@ -92,4 +94,10 @@ SRSLTE_API int srslte_sequence_pucch(srslte_sequence_t *seq,
uint16_t rnti, uint16_t rnti,
uint32_t nslot, uint32_t nslot,
uint32_t cell_id); uint32_t cell_id);
SRSLTE_API int srslte_sequence_pmch(srslte_sequence_t *seq,
uint32_t nslot,
uint32_t mbsfn_id,
uint32_t len);
#endif #endif

@ -58,6 +58,7 @@ typedef enum {
}srslte_dft_dir_t; }srslte_dft_dir_t;
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
int init_size; // DFT length used in the first initialization
int size; // DFT length int size; // DFT length
void *in; // Input buffer void *in; // Input buffer
void *out; // Output buffer void *out; // Output buffer
@ -71,7 +72,9 @@ typedef struct SRSLTE_API {
srslte_dft_mode_t mode; // Complex/Real srslte_dft_mode_t mode; // Complex/Real
}srslte_dft_plan_t; }srslte_dft_plan_t;
/* Create DFT plans */ SRSLTE_API void srslte_dft_load();
SRSLTE_API void srslte_dft_exit();
SRSLTE_API int srslte_dft_plan(srslte_dft_plan_t *plan, SRSLTE_API int srslte_dft_plan(srslte_dft_plan_t *plan,
int dft_points, int dft_points,
@ -86,6 +89,16 @@ SRSLTE_API int srslte_dft_plan_r(srslte_dft_plan_t *plan,
int dft_points, int dft_points,
srslte_dft_dir_t dir); srslte_dft_dir_t dir);
SRSLTE_API int srslte_dft_replan(srslte_dft_plan_t *plan,
const int new_dft_points);
SRSLTE_API int srslte_dft_replan_c(srslte_dft_plan_t *plan,
int new_dft_points);
SRSLTE_API int srslte_dft_replan_r(srslte_dft_plan_t *plan,
int new_dft_points);
SRSLTE_API void srslte_dft_plan_free(srslte_dft_plan_t *plan); SRSLTE_API void srslte_dft_plan_free(srslte_dft_plan_t *plan);
/* Set options */ /* Set options */

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

@ -47,6 +47,7 @@
/* This is common for both directions */ /* This is common for both directions */
typedef struct SRSLTE_API{ typedef struct SRSLTE_API{
srslte_dft_plan_t fft_plan; srslte_dft_plan_t fft_plan;
uint32_t max_prb;
uint32_t nof_symbols; uint32_t nof_symbols;
uint32_t symbol_sz; uint32_t symbol_sz;
uint32_t nof_guards; uint32_t nof_guards;
@ -55,7 +56,14 @@ typedef struct SRSLTE_API{
srslte_cp_t cp; srslte_cp_t cp;
cf_t *tmp; // for removing zero padding cf_t *tmp; // for removing zero padding
bool mbsfn_subframe;
uint32_t mbsfn_guard_len;
uint32_t nof_symbols_mbsfn;
uint8_t non_mbsfn_region;
bool freq_shift; bool freq_shift;
float freq_shift_f;
cf_t *shift_buffer; cf_t *shift_buffer;
}srslte_ofdm_t; }srslte_ofdm_t;
@ -65,8 +73,29 @@ SRSLTE_API int srslte_ofdm_init_(srslte_ofdm_t *q,
int nof_prb, int nof_prb,
srslte_dft_dir_t dir); srslte_dft_dir_t dir);
SRSLTE_API int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q,
srslte_cp_t cp,
int symbol_sz,
int nof_prb,
srslte_dft_dir_t dir,
srslte_sf_t sf_type);
SRSLTE_API int srslte_ofdm_rx_init_mbsfn(srslte_ofdm_t *q,
srslte_cp_t cp_type,
uint32_t nof_prb);
SRSLTE_API int srslte_ofdm_rx_init(srslte_ofdm_t *q, SRSLTE_API int srslte_ofdm_rx_init(srslte_ofdm_t *q,
srslte_cp_t cp_type, srslte_cp_t cp_type,
uint32_t max_prb);
SRSLTE_API int srslte_ofdm_tx_set_prb(srslte_ofdm_t *q,
srslte_cp_t cp,
uint32_t nof_prb);
SRSLTE_API int srslte_ofdm_rx_set_prb(srslte_ofdm_t *q,
srslte_cp_t cp,
uint32_t nof_prb); uint32_t nof_prb);
SRSLTE_API void srslte_ofdm_rx_free(srslte_ofdm_t *q); SRSLTE_API void srslte_ofdm_rx_free(srslte_ofdm_t *q);
@ -85,12 +114,22 @@ SRSLTE_API int srslte_ofdm_tx_init(srslte_ofdm_t *q,
srslte_cp_t cp_type, srslte_cp_t cp_type,
uint32_t nof_prb); uint32_t nof_prb);
SRSLTE_API int srslte_ofdm_tx_init_mbsfn(srslte_ofdm_t *q,
srslte_cp_t cp,
uint32_t nof_prb);
SRSLTE_API void srslte_ofdm_tx_free(srslte_ofdm_t *q); SRSLTE_API void srslte_ofdm_tx_free(srslte_ofdm_t *q);
SRSLTE_API void srslte_ofdm_tx_slot(srslte_ofdm_t *q, SRSLTE_API void srslte_ofdm_tx_slot(srslte_ofdm_t *q,
cf_t *input, cf_t *input,
cf_t *output); cf_t *output);
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, SRSLTE_API void srslte_ofdm_tx_sf(srslte_ofdm_t *q,
cf_t *input, cf_t *input,
cf_t *output); cf_t *output);
@ -101,4 +140,8 @@ SRSLTE_API int srslte_ofdm_set_freq_shift(srslte_ofdm_t *q,
SRSLTE_API void srslte_ofdm_set_normalize(srslte_ofdm_t *q, SRSLTE_API void srslte_ofdm_set_normalize(srslte_ofdm_t *q,
bool normalize_enable); bool normalize_enable);
SRSLTE_API void srslte_ofdm_set_non_mbsfn_region(srslte_ofdm_t *q,
uint8_t non_mbsfn_region);
#endif #endif

@ -76,7 +76,7 @@ typedef struct SRSLTE_API {
srslte_pdsch_t pdsch; srslte_pdsch_t pdsch;
srslte_phich_t phich; srslte_phich_t phich;
srslte_refsignal_cs_t csr_signal; srslte_refsignal_t csr_signal;
srslte_pdsch_cfg_t pdsch_cfg; srslte_pdsch_cfg_t pdsch_cfg;
srslte_ra_dl_dci_t dl_dci; srslte_ra_dl_dci_t dl_dci;
@ -89,6 +89,8 @@ typedef struct SRSLTE_API {
float tx_amp; float tx_amp;
uint8_t tmp[1024*128];
} srslte_enb_dl_t; } srslte_enb_dl_t;
typedef struct { typedef struct {
@ -108,10 +110,13 @@ typedef struct {
/* This function shall be called just after the initial synchronization */ /* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_enb_dl_init(srslte_enb_dl_t *q, SRSLTE_API int srslte_enb_dl_init(srslte_enb_dl_t *q,
srslte_cell_t cell); uint32_t max_prb);
SRSLTE_API void srslte_enb_dl_free(srslte_enb_dl_t *q); SRSLTE_API void srslte_enb_dl_free(srslte_enb_dl_t *q);
SRSLTE_API int srslte_enb_dl_set_cell(srslte_enb_dl_t *q,
srslte_cell_t cell);
SRSLTE_API void srslte_enb_dl_set_cfi(srslte_enb_dl_t *q, SRSLTE_API void srslte_enb_dl_set_cfi(srslte_enb_dl_t *q,
uint32_t cfi); uint32_t cfi);
@ -152,11 +157,13 @@ SRSLTE_API void srslte_enb_dl_rem_rnti(srslte_enb_dl_t *q,
SRSLTE_API int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q, SRSLTE_API int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q,
srslte_ra_dl_grant_t *grant, srslte_ra_dl_grant_t *grant,
srslte_softbuffer_tx_t *softbuffer, srslte_softbuffer_tx_t *softbuffer[SRSLTE_MAX_CODEWORDS],
uint16_t rnti, uint16_t rnti,
uint32_t rv_idx, int rv_idx[SRSLTE_MAX_CODEWORDS],
uint32_t sf_idx, uint32_t sf_idx,
uint8_t *data); uint8_t *data[SRSLTE_MAX_CODEWORDS],
srslte_mimo_type_t mimo_type,
uint32_t pmi);
SRSLTE_API int srslte_enb_dl_put_pdcch_dl(srslte_enb_dl_t *q, SRSLTE_API int srslte_enb_dl_put_pdcch_dl(srslte_enb_dl_t *q,
srslte_ra_dl_dci_t *grant, srslte_ra_dl_dci_t *grant,
@ -171,5 +178,12 @@ SRSLTE_API int srslte_enb_dl_put_pdcch_ul(srslte_enb_dl_t *q,
uint16_t rnti, uint16_t rnti,
uint32_t sf_idx); uint32_t sf_idx);
SRSLTE_API void srslte_enb_dl_save_signal(srslte_enb_dl_t *q,
srslte_softbuffer_tx_t *softbuffer,
uint8_t *data,
uint32_t tti,
uint32_t rv_idx,
uint16_t rnti,
uint32_t cfi);
#endif #endif

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

@ -50,18 +50,14 @@
#define SRSLTE_TCOD_MAX_LEN_CODED (SRSLTE_TCOD_RATE*SRSLTE_TCOD_MAX_LEN_CB+SRSLTE_TCOD_TOTALTAIL) #define SRSLTE_TCOD_MAX_LEN_CODED (SRSLTE_TCOD_RATE*SRSLTE_TCOD_MAX_LEN_CB+SRSLTE_TCOD_TOTALTAIL)
#include "srslte/phy/fec/turbodecoder_gen.h" #include "srslte/phy/fec/turbodecoder_gen.h"
#include "srslte/phy/fec/turbodecoder_simd.h"
#ifdef LV_HAVE_SSE
#include "srslte/phy/fec/turbodecoder_sse.h"
#endif
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
#ifdef LV_HAVE_SSE
srslte_tdec_sse_t tdec_sse;
#else
float *input_conv; float *input_conv;
union {
srslte_tdec_simd_t tdec_simd;
srslte_tdec_gen_t tdec_gen; srslte_tdec_gen_t tdec_gen;
#endif };
} srslte_tdec_t; } srslte_tdec_t;
SRSLTE_API int srslte_tdec_init(srslte_tdec_t * h, SRSLTE_API int srslte_tdec_init(srslte_tdec_t * h,
@ -69,7 +65,16 @@ SRSLTE_API int srslte_tdec_init(srslte_tdec_t * h,
SRSLTE_API void srslte_tdec_free(srslte_tdec_t * h); SRSLTE_API void srslte_tdec_free(srslte_tdec_t * h);
SRSLTE_API int srslte_tdec_reset(srslte_tdec_t * h, uint32_t long_cb); SRSLTE_API int srslte_tdec_reset(srslte_tdec_t * h,
uint32_t long_cb);
SRSLTE_API int srslte_tdec_reset_cb(srslte_tdec_t * h,
uint32_t cb_idx);
SRSLTE_API int srslte_tdec_get_nof_iterations_cb(srslte_tdec_t * h,
uint32_t cb_idx);
SRSLTE_API uint32_t srslte_tdec_get_nof_parallel(srslte_tdec_t * h);
SRSLTE_API void srslte_tdec_iteration(srslte_tdec_t * h, SRSLTE_API void srslte_tdec_iteration(srslte_tdec_t * h,
int16_t* input, int16_t* input,
@ -89,4 +94,27 @@ SRSLTE_API int srslte_tdec_run_all(srslte_tdec_t * h,
uint32_t nof_iterations, uint32_t nof_iterations,
uint32_t long_cb); uint32_t long_cb);
SRSLTE_API void srslte_tdec_iteration_par(srslte_tdec_t * h,
int16_t* input[SRSLTE_TDEC_MAX_NPAR],
uint32_t long_cb);
SRSLTE_API void srslte_tdec_decision_par(srslte_tdec_t * h,
uint8_t *output[SRSLTE_TDEC_MAX_NPAR],
uint32_t long_cb);
SRSLTE_API void srslte_tdec_decision_byte_par(srslte_tdec_t * h,
uint8_t *output[SRSLTE_TDEC_MAX_NPAR],
uint32_t long_cb);
SRSLTE_API void srslte_tdec_decision_byte_par_cb(srslte_tdec_t * h,
uint8_t *output,
uint32_t cb_idx,
uint32_t long_cb);
SRSLTE_API int srslte_tdec_run_all_par(srslte_tdec_t * h,
int16_t * input[SRSLTE_TDEC_MAX_NPAR],
uint8_t *output[SRSLTE_TDEC_MAX_NPAR],
uint32_t nof_iterations,
uint32_t long_cb);
#endif #endif

@ -66,6 +66,8 @@ typedef struct SRSLTE_API {
float *parity; float *parity;
int current_cbidx; int current_cbidx;
uint32_t current_cb_len;
uint32_t n_iter;
srslte_tc_interl_t interleaver[SRSLTE_NOF_TC_CB_SIZES]; srslte_tc_interl_t interleaver[SRSLTE_NOF_TC_CB_SIZES];
} srslte_tdec_gen_t; } srslte_tdec_gen_t;

@ -0,0 +1,122 @@
/**
*
* \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/.
*
*/
/**********************************************************************************************
* File: turbodecoder.h
*
* Description: Turbo Decoder.
* Parallel Concatenated Convolutional Code (PCCC) with two 8-state constituent
* encoders and one turbo code internal interleaver. The coding rate of turbo
* encoder is 1/3.
* MAP_GEN is the MAX-LOG-MAP generic implementation of the decoder.
*
* Reference: 3GPP TS 36.212 version 10.0.0 Release 10 Sec. 5.1.3.2
*********************************************************************************************/
#ifndef TURBODECODER_SSE_
#define TURBODECODER_SSE_
#include "srslte/config.h"
#include "srslte/phy/fec/tc_interl.h"
#include "srslte/phy/fec/cbsegm.h"
// Define maximum number of CB decoded in parallel (2 for AVX2)
#define SRSLTE_TDEC_MAX_NPAR 2
#define SRSLTE_TCOD_RATE 3
#define SRSLTE_TCOD_TOTALTAIL 12
#define SRSLTE_TCOD_MAX_LEN_CB 6144
#define SRSLTE_TCOD_MAX_LEN_CODED (SRSLTE_TCOD_RATE*SRSLTE_TCOD_MAX_LEN_CB+SRSLTE_TCOD_TOTALTAIL)
typedef struct SRSLTE_API {
uint32_t max_long_cb;
uint32_t max_par_cb;
int16_t *alpha;
int16_t *branch;
} map_gen_t;
typedef struct SRSLTE_API {
uint32_t max_long_cb;
uint32_t max_par_cb;
map_gen_t dec;
int16_t *app1[SRSLTE_TDEC_MAX_NPAR];
int16_t *app2[SRSLTE_TDEC_MAX_NPAR];
int16_t *ext1[SRSLTE_TDEC_MAX_NPAR];
int16_t *ext2[SRSLTE_TDEC_MAX_NPAR];
int16_t *syst[SRSLTE_TDEC_MAX_NPAR];
int16_t *parity0[SRSLTE_TDEC_MAX_NPAR];
int16_t *parity1[SRSLTE_TDEC_MAX_NPAR];
int cb_mask;
int current_cbidx;
srslte_tc_interl_t interleaver[SRSLTE_NOF_TC_CB_SIZES];
int n_iter[SRSLTE_TDEC_MAX_NPAR];
} srslte_tdec_simd_t;
SRSLTE_API int srslte_tdec_simd_init(srslte_tdec_simd_t * h,
uint32_t max_par_cb,
uint32_t max_long_cb);
SRSLTE_API void srslte_tdec_simd_free(srslte_tdec_simd_t * h);
SRSLTE_API int srslte_tdec_simd_reset(srslte_tdec_simd_t * h,
uint32_t long_cb);
SRSLTE_API
SRSLTE_API int srslte_tdec_simd_get_nof_iterations_cb(srslte_tdec_simd_t * h,
uint32_t cb_idx);
SRSLTE_API int srslte_tdec_simd_reset_cb(srslte_tdec_simd_t * h,
uint32_t cb_idx);
SRSLTE_API void srslte_tdec_simd_iteration(srslte_tdec_simd_t * h,
int16_t * input[SRSLTE_TDEC_MAX_NPAR],
uint32_t long_cb);
SRSLTE_API void srslte_tdec_simd_decision(srslte_tdec_simd_t * h,
uint8_t *output[SRSLTE_TDEC_MAX_NPAR],
uint32_t long_cb);
SRSLTE_API void srslte_tdec_simd_decision_byte(srslte_tdec_simd_t * h,
uint8_t *output[SRSLTE_TDEC_MAX_NPAR],
uint32_t long_cb);
SRSLTE_API void srslte_tdec_simd_decision_byte_cb(srslte_tdec_simd_t * h,
uint8_t *output,
uint32_t cbidx,
uint32_t long_cb);
SRSLTE_API int srslte_tdec_simd_run_all(srslte_tdec_simd_t * h,
int16_t * input[SRSLTE_TDEC_MAX_NPAR],
uint8_t *output[SRSLTE_TDEC_MAX_NPAR],
uint32_t nof_iterations,
uint32_t long_cb);
#endif

@ -0,0 +1,119 @@
/**
*
* \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/.
*
*/
/**********************************************************************************************
* File: turbodecoder.h
*
* Description: Turbo Decoder.
* Parallel Concatenated Convolutional Code (PCCC) with two 8-state constituent
* encoders and one turbo code internal interleaver. The coding rate of turbo
* encoder is 1/3.
* MAP_GEN is the MAX-LOG-MAP generic implementation of the decoder.
*
* Reference: 3GPP TS 36.212 version 10.0.0 Release 10 Sec. 5.1.3.2
*********************************************************************************************/
#ifndef TURBODECODER_SSE_INTER_
#define TURBODECODER_SSE_INTER_
/** This is an simd inter-frame parallel turbo decoder. Parallizes 8 code-blocks using SSE
* This implementation is currently not functional and not used by the rest of the code
*/
#include "srslte/config.h"
#include "srslte/phy/fec/tc_interl.h"
#include "srslte/phy/fec/cbsegm.h"
#if LV_HAVE_AVX2
#define SRSLTE_TDEC_MAX_NPAR 16
#else
#define SRSLTE_TDEC_MAX_NPAR 8
#endif
typedef struct SRSLTE_API {
int max_long_cb;
int16_t *syst0;
int16_t *parity0;
int16_t *syst1;
int16_t *parity1;
int16_t *llr1;
int16_t *llr2;
int16_t *w;
int16_t *alpha;
uint32_t max_par_cb;
int current_cbidx;
uint32_t current_long_cb;
srslte_tc_interl_t interleaver[SRSLTE_NOF_TC_CB_SIZES];
int n_iter[SRSLTE_TDEC_MAX_NPAR];
} srslte_tdec_simd_inter_t;
SRSLTE_API int srslte_tdec_simd_inter_init(srslte_tdec_simd_inter_t * h,
uint32_t max_par_cb,
uint32_t max_long_cb);
SRSLTE_API void srslte_tdec_simd_inter_free(srslte_tdec_simd_inter_t * h);
SRSLTE_API int srslte_tdec_simd_inter_reset(srslte_tdec_simd_inter_t * h,
uint32_t long_cb);
SRSLTE_API int srslte_tdec_simd_inter_get_nof_iterations_cb(srslte_tdec_simd_inter_t * h,
uint32_t cb_idx);
SRSLTE_API int srslte_tdec_simd_inter_reset_cb(srslte_tdec_simd_inter_t * h,
uint32_t cb_idx);
SRSLTE_API void srslte_tdec_simd_inter_iteration(srslte_tdec_simd_inter_t * h,
int16_t * input[SRSLTE_TDEC_MAX_NPAR],
uint32_t nof_cb,
uint32_t long_cb);
SRSLTE_API void srslte_tdec_simd_inter_decision(srslte_tdec_simd_inter_t * h,
uint8_t *output[SRSLTE_TDEC_MAX_NPAR],
uint32_t nof_cb,
uint32_t long_cb);
SRSLTE_API void srslte_tdec_simd_inter_decision_byte(srslte_tdec_simd_inter_t * h,
uint8_t *output[SRSLTE_TDEC_MAX_NPAR],
uint32_t nof_cb,
uint32_t long_cb);
SRSLTE_API void srslte_tdec_simd_inter_decision_byte_cb(srslte_tdec_simd_inter_t * h,
uint8_t *output,
uint32_t cbidx,
uint32_t long_cb);
SRSLTE_API int srslte_tdec_simd_inter_run_all(srslte_tdec_simd_inter_t * h,
int16_t *input[SRSLTE_TDEC_MAX_NPAR],
uint8_t *output[SRSLTE_TDEC_MAX_NPAR],
uint32_t nof_iterations,
uint32_t nof_cb,
uint32_t long_cb);
#endif

@ -59,4 +59,9 @@ SRSLTE_API int srslte_filesink_write(srslte_filesink_t *q,
void *buffer, void *buffer,
int nsamples); int nsamples);
SRSLTE_API int srslte_filesink_write_multi(srslte_filesink_t *q,
void **buffer,
int nsamples,
int nchannels);
#endif // FILESINK_ #endif // FILESINK_

@ -62,4 +62,9 @@ SRSLTE_API int srslte_filesource_read(srslte_filesource_t *q,
void *buffer, void *buffer,
int nsamples); int nsamples);
SRSLTE_API int srslte_filesource_read_multi(srslte_filesource_t *q,
void **buffer,
int nsamples,
int nof_channels);
#endif // FILESOURCE_ #endif // FILESOURCE_

@ -66,6 +66,7 @@ SRSLTE_API int srslte_precoding_type(cf_t *x[SRSLTE_MAX_LAYERS],
cf_t *y[SRSLTE_MAX_PORTS], cf_t *y[SRSLTE_MAX_PORTS],
int nof_layers, int nof_layers,
int nof_ports, int nof_ports,
int codebook_idx,
int nof_symbols, int nof_symbols,
srslte_mimo_type_t type); srslte_mimo_type_t type);
@ -106,14 +107,31 @@ SRSLTE_API int srslte_predecoding_type(cf_t *y,
srslte_mimo_type_t type, srslte_mimo_type_t type,
float noise_estimate); float noise_estimate);
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_multi(cf_t *y[SRSLTE_MAX_PORTS],
cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
cf_t *x[SRSLTE_MAX_LAYERS], cf_t *x[SRSLTE_MAX_LAYERS],
int nof_rxant, int nof_rxant,
int nof_ports, int nof_ports,
int nof_layers, int nof_layers,
int codebook_idx,
int nof_symbols, int nof_symbols,
srslte_mimo_type_t type, srslte_mimo_type_t type,
float noise_estimate); float noise_estimate);
SRSLTE_API int srslte_precoding_pmi_select(cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
uint32_t nof_symbols,
float noise_estimate,
int nof_layers,
uint32_t *pmi,
float sinr[SRSLTE_MAX_CODEBOOKS]);
SRSLTE_API int srslte_precoding_cn(cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
uint32_t nof_tx_antennas,
uint32_t nof_rx_antennas,
uint32_t nof_symbols,
float *cn);
#endif /* PRECODING_H_ */ #endif /* PRECODING_H_ */

@ -41,10 +41,14 @@
#include "srslte/phy/common/phy_common.h" #include "srslte/phy/common/phy_common.h"
#define SRSLTE_CQI_MAX_BITS 64 #define SRSLTE_CQI_MAX_BITS 64
#define SRSLTE_DIF_CQI_MAX_BITS 3
#define SRSLTE_PMI_MAX_BITS 4
typedef struct { typedef struct {
bool configured; bool configured;
uint32_t pmi_idx; uint32_t pmi_idx;
uint32_t ri_idx;
bool ri_idx_present;
bool simul_cqi_ack; bool simul_cqi_ack;
bool format_is_subband; bool format_is_subband;
uint32_t subband_size; uint32_t subband_size;
@ -139,6 +143,10 @@ SRSLTE_API int srslte_cqi_format2_subband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BIT
SRSLTE_API bool srslte_cqi_send(uint32_t I_cqi_pmi, SRSLTE_API bool srslte_cqi_send(uint32_t I_cqi_pmi,
uint32_t tti); uint32_t tti);
SRSLTE_API bool srslte_ri_send(uint32_t I_cqi_pmi,
uint32_t I_ri,
uint32_t tti);
SRSLTE_API uint8_t srslte_cqi_from_snr(float snr); SRSLTE_API uint8_t srslte_cqi_from_snr(float snr);
SRSLTE_API float srslte_cqi_to_coderate(uint32_t cqi); SRSLTE_API float srslte_cqi_to_coderate(uint32_t cqi);

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

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

@ -64,6 +64,7 @@ typedef struct SRSLTE_API {
uint32_t nof_cce; uint32_t nof_cce;
uint32_t max_bits; uint32_t max_bits;
uint32_t nof_rx_antennas; uint32_t nof_rx_antennas;
bool is_ue;
srslte_regs_t *regs; srslte_regs_t *regs;
@ -84,14 +85,16 @@ typedef struct SRSLTE_API {
} srslte_pdcch_t; } srslte_pdcch_t;
SRSLTE_API int srslte_pdcch_init(srslte_pdcch_t *q, SRSLTE_API int srslte_pdcch_init_ue(srslte_pdcch_t *q,
srslte_regs_t *regs, uint32_t max_prb,
srslte_cell_t cell); uint32_t nof_rx_antennas);
SRSLTE_API int srslte_pdcch_init_multi(srslte_pdcch_t *q, SRSLTE_API int srslte_pdcch_init_enb(srslte_pdcch_t *q,
uint32_t max_prb);
SRSLTE_API int srslte_pdcch_set_cell(srslte_pdcch_t *q,
srslte_regs_t *regs, srslte_regs_t *regs,
srslte_cell_t cell, srslte_cell_t cell);
uint32_t nof_rx_antennas);
SRSLTE_API void srslte_pdcch_free(srslte_pdcch_t *q); SRSLTE_API void srslte_pdcch_free(srslte_pdcch_t *q);

@ -48,7 +48,8 @@
#include "srslte/phy/phch/pdsch_cfg.h" #include "srslte/phy/phch/pdsch_cfg.h"
typedef struct { typedef struct {
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME]; srslte_sequence_t seq[SRSLTE_MAX_CODEWORDS][SRSLTE_NSUBFRAMES_X_FRAME];
uint32_t cell_id;
bool sequence_generated; bool sequence_generated;
} srslte_pdsch_user_t; } srslte_pdsch_user_t;
@ -57,16 +58,20 @@ typedef struct SRSLTE_API {
srslte_cell_t cell; srslte_cell_t cell;
uint32_t nof_rx_antennas; uint32_t nof_rx_antennas;
uint32_t last_nof_iterations[SRSLTE_MAX_CODEWORDS];
uint32_t max_re; uint32_t max_re;
uint16_t ue_rnti;
bool is_ue;
/* buffers */ /* buffers */
// void buffers are shared for tx and rx // void buffers are shared for tx and rx
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; /* Channel estimation (Rx only) */
cf_t *symbols[SRSLTE_MAX_PORTS]; cf_t *symbols[SRSLTE_MAX_PORTS]; /* PDSCH Encoded/Decoded Symbols */
cf_t *x[SRSLTE_MAX_PORTS]; cf_t *x[SRSLTE_MAX_LAYERS]; /* Layer mapped */
cf_t *d; cf_t *d[SRSLTE_MAX_CODEWORDS]; /* Modulated/Demodulated codewords */
void *e; void *e[SRSLTE_MAX_CODEWORDS];
/* tx & rx objects */ /* tx & rx objects */
srslte_modem_table_t mod[4]; srslte_modem_table_t mod[4];
@ -74,62 +79,83 @@ typedef struct SRSLTE_API {
// This is to generate the scrambling seq for multiple CRNTIs // This is to generate the scrambling seq for multiple CRNTIs
srslte_pdsch_user_t **users; srslte_pdsch_user_t **users;
srslte_sequence_t tmp_seq;
srslte_sch_t dl_sch; srslte_sch_t dl_sch;
} srslte_pdsch_t; } srslte_pdsch_t;
SRSLTE_API int srslte_pdsch_init(srslte_pdsch_t *q,
srslte_cell_t cell);
SRSLTE_API int srslte_pdsch_init_multi(srslte_pdsch_t *q, SRSLTE_API int srslte_pdsch_init_ue(srslte_pdsch_t *q,
srslte_cell_t cell, uint32_t max_prb,
uint32_t nof_rx_antennas); uint32_t nof_rx_antennas);
SRSLTE_API int srslte_pdsch_init_enb(srslte_pdsch_t *q,
uint32_t max_prb);
SRSLTE_API void srslte_pdsch_free(srslte_pdsch_t *q); SRSLTE_API void srslte_pdsch_free(srslte_pdsch_t *q);
SRSLTE_API int srslte_pdsch_set_cell(srslte_pdsch_t *q,
srslte_cell_t cell);
SRSLTE_API int srslte_pdsch_set_rnti(srslte_pdsch_t *q, SRSLTE_API int srslte_pdsch_set_rnti(srslte_pdsch_t *q,
uint16_t rnti); uint16_t rnti);
SRSLTE_API void srslte_pdsch_free_rnti(srslte_pdsch_t *q, SRSLTE_API void srslte_pdsch_free_rnti(srslte_pdsch_t *q,
uint16_t rnti); uint16_t rnti);
SRSLTE_API float srslte_pdsch_coderate(uint32_t tbs,
uint32_t nof_re);
SRSLTE_API int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg, SRSLTE_API int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg,
srslte_cell_t cell, srslte_cell_t cell,
srslte_ra_dl_grant_t *grant, srslte_ra_dl_grant_t *grant,
uint32_t cfi, uint32_t cfi,
uint32_t sf_idx, uint32_t sf_idx,
uint32_t rvidx); int rvidx);
SRSLTE_API int srslte_pdsch_cfg_mimo(srslte_pdsch_cfg_t *cfg,
srslte_cell_t cell,
srslte_ra_dl_grant_t *grant,
uint32_t cfi,
uint32_t sf_idx,
int rvidx[SRSLTE_MAX_CODEWORDS],
srslte_mimo_type_t mimo_type,
uint32_t pmi);
SRSLTE_API int srslte_pdsch_encode(srslte_pdsch_t *q, SRSLTE_API int srslte_pdsch_encode(srslte_pdsch_t *q,
srslte_pdsch_cfg_t *cfg, srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffer, srslte_softbuffer_tx_t *softbuffers[SRSLTE_MAX_CODEWORDS],
uint8_t *data, uint8_t *data[SRSLTE_MAX_CODEWORDS],
uint16_t rnti, uint16_t rnti,
cf_t *sf_symbols[SRSLTE_MAX_PORTS]); cf_t *sf_symbols[SRSLTE_MAX_PORTS]);
SRSLTE_API int srslte_pdsch_decode(srslte_pdsch_t *q, SRSLTE_API int srslte_pdsch_decode(srslte_pdsch_t *q,
srslte_pdsch_cfg_t *cfg, srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_rx_t *softbuffer, srslte_softbuffer_rx_t *softbuffers[SRSLTE_MAX_CODEWORDS],
cf_t *sf_symbols, cf_t *sf_symbols[SRSLTE_MAX_PORTS],
cf_t *ce[SRSLTE_MAX_PORTS], cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
float noise_estimate, float noise_estimate,
uint16_t rnti, uint16_t rnti,
uint8_t *data); uint8_t *data[SRSLTE_MAX_CODEWORDS],
bool acks[SRSLTE_MAX_CODEWORDS]);
SRSLTE_API int srslte_pdsch_decode_multi(srslte_pdsch_t *q, SRSLTE_API int srslte_pdsch_pmi_select(srslte_pdsch_t *q,
srslte_pdsch_cfg_t *cfg, srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_rx_t *softbuffer,
cf_t *sf_symbols[SRSLTE_MAX_PORTS],
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
float noise_estimate, float noise_estimate,
uint16_t rnti, uint32_t nof_ce,
uint8_t *data); uint32_t pmi[SRSLTE_MAX_LAYERS],
float sinr[SRSLTE_MAX_LAYERS][SRSLTE_MAX_CODEBOOKS]);
SRSLTE_API int srslte_pdsch_cn_compute(srslte_pdsch_t *q,
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
uint32_t nof_ce,
float *cn);
SRSLTE_API void srslte_pdsch_set_max_noi(srslte_pdsch_t *q,
uint32_t max_iter);
SRSLTE_API float srslte_pdsch_average_noi(srslte_pdsch_t *q); SRSLTE_API float srslte_pdsch_last_noi(srslte_pdsch_t *q);
SRSLTE_API uint32_t srslte_pdsch_last_noi(srslte_pdsch_t *q); SRSLTE_API uint32_t srslte_pdsch_last_noi_cw(srslte_pdsch_t *q,
uint32_t cw_idx);
#endif #endif

@ -40,11 +40,14 @@
#include "srslte/phy/fec/cbsegm.h" #include "srslte/phy/fec/cbsegm.h"
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
srslte_cbsegm_t cb_segm; srslte_cbsegm_t cb_segm[SRSLTE_MAX_CODEWORDS];
srslte_ra_dl_grant_t grant; srslte_ra_dl_grant_t grant;
srslte_ra_nbits_t nbits; srslte_ra_nbits_t nbits[SRSLTE_MAX_CODEWORDS];
uint32_t rv; uint32_t rv[SRSLTE_MAX_CODEWORDS];
uint32_t sf_idx; uint32_t sf_idx;
uint32_t nof_layers;
uint32_t codebook_idx;
srslte_mimo_type_t mimo_type;
} srslte_pdsch_cfg_t; } srslte_pdsch_cfg_t;
#endif #endif

@ -86,16 +86,14 @@ typedef struct SRSLTE_API {
} srslte_phich_t; } srslte_phich_t;
SRSLTE_API int srslte_phich_init(srslte_phich_t *q, SRSLTE_API int srslte_phich_init(srslte_phich_t *q,
srslte_regs_t *regs,
srslte_cell_t cell);
SRSLTE_API int srslte_phich_init_multi(srslte_phich_t *q,
srslte_regs_t *regs,
srslte_cell_t cell,
uint32_t nof_rx_antennas); uint32_t nof_rx_antennas);
SRSLTE_API void srslte_phich_free(srslte_phich_t *q); SRSLTE_API void srslte_phich_free(srslte_phich_t *q);
SRSLTE_API int srslte_phich_set_cell(srslte_phich_t *q,
srslte_regs_t *regs,
srslte_cell_t cell);
SRSLTE_API void srslte_phich_calc(srslte_phich_t *q, SRSLTE_API void srslte_phich_calc(srslte_phich_t *q,
uint32_t n_prb_lowest, uint32_t n_prb_lowest,
uint32_t n_dmrs, uint32_t n_dmrs,
@ -103,16 +101,6 @@ SRSLTE_API void srslte_phich_calc(srslte_phich_t *q,
uint32_t *nseq); uint32_t *nseq);
SRSLTE_API int srslte_phich_decode(srslte_phich_t *q, SRSLTE_API int srslte_phich_decode(srslte_phich_t *q,
cf_t *slot_symbols,
cf_t *ce[SRSLTE_MAX_PORTS],
float noise_estimate,
uint32_t ngroup,
uint32_t nseq,
uint32_t nsubframe,
uint8_t *ack,
float *distance);
SRSLTE_API int srslte_phich_decode_multi(srslte_phich_t *q,
cf_t *slot_symbols[SRSLTE_MAX_PORTS], cf_t *slot_symbols[SRSLTE_MAX_PORTS],
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
float noise_estimate, float noise_estimate,

@ -0,0 +1,152 @@
/**
*
* \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/.
*
*/
/******************************************************************************
* File: pmch.h
*
* Description: Physical multicast channel
*
* Reference: 3GPP TS 36.211 version 10.0.0 Release 10 Sec. 6.5
*****************************************************************************/
#ifndef PMCH_
#define PMCH_
#include "srslte/config.h"
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/mimo/precoding.h"
#include "srslte/phy/mimo/layermap.h"
#include "srslte/phy/modem/mod.h"
#include "srslte/phy/modem/demod_soft.h"
#include "srslte/phy/scrambling/scrambling.h"
#include "srslte/phy/phch/dci.h"
#include "srslte/phy/phch/regs.h"
#include "srslte/phy/phch/sch.h"
#include "srslte/phy/common/sequence.h"
typedef struct {
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
} srslte_pmch_seq_t;
typedef struct SRSLTE_API {
srslte_cbsegm_t cb_segm;
srslte_ra_dl_grant_t grant;
srslte_ra_nbits_t nbits[SRSLTE_MAX_CODEWORDS];
uint32_t sf_idx;
} srslte_pmch_cfg_t;
/* PMCH object */
typedef struct SRSLTE_API {
srslte_cell_t cell;
uint32_t nof_rx_antennas;
uint32_t max_re;
/* buffers */
// void buffers are shared for tx and rx
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
cf_t *symbols[SRSLTE_MAX_PORTS];
cf_t *x[SRSLTE_MAX_PORTS];
cf_t *d;
void *e;
/* tx & rx objects */
srslte_modem_table_t mod[4];
// This is to generate the scrambling seq for multiple MBSFN Area IDs
srslte_pmch_seq_t **seqs;
srslte_sch_t dl_sch;
} srslte_pmch_t;
SRSLTE_API int srslte_pmch_init(srslte_pmch_t *q,
uint32_t max_prb);
SRSLTE_API int srslte_pmch_init_multi(srslte_pmch_t *q,
uint32_t max_prb,
uint32_t nof_rx_antennas);
SRSLTE_API void srslte_pmch_free(srslte_pmch_t *q);
SRSLTE_API int srslte_pmch_set_area_id(srslte_pmch_t *q, uint16_t area_id);
SRSLTE_API void srslte_pmch_free_area_id(srslte_pmch_t *q, uint16_t area_id);
SRSLTE_API int srslte_pmch_get(srslte_pmch_t *q, cf_t *sf_symbols, cf_t *symbols, uint32_t lstart);
SRSLTE_API int srslte_pmch_put(srslte_pmch_t *q, cf_t *symbols, cf_t *sf_symbols, uint32_t lstart);
SRSLTE_API int srslte_pmch_cp(srslte_pmch_t *q, cf_t *input, cf_t *output, uint32_t lstart_grant, bool put);
SRSLTE_API float srslte_pmch_coderate(uint32_t tbs,
uint32_t nof_re);
SRSLTE_API int srslte_pmch_cfg(srslte_pdsch_cfg_t *cfg,
srslte_cell_t cell,
srslte_ra_dl_grant_t *grant,
uint32_t cfi,
uint32_t sf_idx);
SRSLTE_API int srslte_pmch_encode(srslte_pmch_t *q,
srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffer,
uint8_t *data,
uint16_t area_id,
cf_t *sf_symbols[SRSLTE_MAX_PORTS]);
SRSLTE_API int srslte_pmch_decode(srslte_pmch_t *q,
srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_rx_t *softbuffer,
cf_t *sf_symbols,
cf_t *ce[SRSLTE_MAX_PORTS],
float noise_estimate,
uint16_t area_id,
uint8_t *data);
SRSLTE_API int srslte_pmch_decode_multi(srslte_pmch_t *q,
srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_rx_t *softbuffer,
cf_t *sf_symbols[SRSLTE_MAX_PORTS],
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
float noise_estimate,
uint16_t area_id,
uint8_t *data);
SRSLTE_API float srslte_pmch_average_noi(srslte_pmch_t *q);
SRSLTE_API uint32_t srslte_pmch_last_noi(srslte_pmch_t *q);
#endif

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

@ -45,7 +45,7 @@
#define SRSLTE_PUCCH_N_SEQ 12 #define SRSLTE_PUCCH_N_SEQ 12
#define SRSLTE_PUCCH2_NOF_BITS SRSLTE_UCI_CQI_CODED_PUCCH_B #define SRSLTE_PUCCH2_NOF_BITS SRSLTE_UCI_CQI_CODED_PUCCH_B
#define SRSLTE_PUCCH_MAX_BITS SRSLTE_CQI_MAX_BITS #define SRSLTE_PUCCH_MAX_BITS SRSLTE_CQI_MAX_BITS
#define SRSLTE_PUCCH_MAX_SYMBOLS 120 #define SRSLTE_PUCCH_MAX_SYMBOLS 128
typedef enum SRSLTE_API { typedef enum SRSLTE_API {
SRSLTE_PUCCH_FORMAT_1 = 0, SRSLTE_PUCCH_FORMAT_1 = 0,
@ -108,7 +108,6 @@ typedef struct SRSLTE_API {
bool group_hopping_en; bool group_hopping_en;
float threshold_format1; float threshold_format1;
float threshold_format1a;
float last_corr; float last_corr;
uint32_t last_n_prb; uint32_t last_n_prb;
uint32_t last_n_pucch; uint32_t last_n_pucch;
@ -116,18 +115,19 @@ typedef struct SRSLTE_API {
}srslte_pucch_t; }srslte_pucch_t;
SRSLTE_API int srslte_pucch_init(srslte_pucch_t *q, SRSLTE_API int srslte_pucch_init(srslte_pucch_t *q);
srslte_cell_t cell);
SRSLTE_API void srslte_pucch_free(srslte_pucch_t *q); SRSLTE_API void srslte_pucch_free(srslte_pucch_t *q);
SRSLTE_API int srslte_pucch_set_cell(srslte_pucch_t *q,
srslte_cell_t cell);
SRSLTE_API bool srslte_pucch_set_cfg(srslte_pucch_t* q, SRSLTE_API bool srslte_pucch_set_cfg(srslte_pucch_t* q,
srslte_pucch_cfg_t* cfg, srslte_pucch_cfg_t* cfg,
bool group_hopping_en); bool group_hopping_en);
SRSLTE_API void srslte_pucch_set_threshold(srslte_pucch_t *q, SRSLTE_API void srslte_pucch_set_threshold(srslte_pucch_t *q,
float format1, float format1_threshold);
float format1a);
SRSLTE_API int srslte_pucch_set_crnti(srslte_pucch_t *q, SRSLTE_API int srslte_pucch_set_crnti(srslte_pucch_t *q,
uint16_t c_rnti); uint16_t c_rnti);

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

@ -102,13 +102,18 @@ typedef struct SRSLTE_API {
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
bool prb_idx[2][SRSLTE_MAX_PRB]; bool prb_idx[2][SRSLTE_MAX_PRB];
uint32_t nof_prb; uint32_t nof_prb;
uint32_t Qm; uint32_t Qm[SRSLTE_MAX_CODEWORDS];
uint32_t Qm2; uint32_t Qm2[SRSLTE_MAX_CODEWORDS];
srslte_ra_mcs_t mcs; srslte_ra_mcs_t mcs[SRSLTE_MAX_CODEWORDS];
srslte_ra_mcs_t mcs2; srslte_ra_mcs_t mcs2[SRSLTE_MAX_CODEWORDS];
uint32_t nof_tb; uint32_t nof_tb;
srslte_sf_t sf_type;
bool tb_en[SRSLTE_MAX_CODEWORDS];
uint32_t pinfo;
} srslte_ra_dl_grant_t; } srslte_ra_dl_grant_t;
#define SRSLTE_RA_DL_GRANT_NOF_TB(G) ((((G)->tb_en[0])?1:0)+(((G)->tb_en[1])?1:0))
/** Unpacked DCI message for DL grant */ /** Unpacked DCI message for DL grant */
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
@ -207,7 +212,7 @@ SRSLTE_API void srslte_ra_dl_grant_to_nbits(srslte_ra_dl_grant_t *grant,
uint32_t cfi, uint32_t cfi,
srslte_cell_t cell, srslte_cell_t cell,
uint32_t sf_idx, uint32_t sf_idx,
srslte_ra_nbits_t *nbits); srslte_ra_nbits_t nbits[SRSLTE_MAX_CODEWORDS]);
SRSLTE_API uint32_t srslte_ra_dl_approx_nof_re(srslte_cell_t cell, SRSLTE_API uint32_t srslte_ra_dl_approx_nof_re(srslte_cell_t cell,
uint32_t nof_prb, uint32_t nof_prb,
@ -289,4 +294,9 @@ SRSLTE_API void srslte_ra_pusch_fprint(FILE *f,
SRSLTE_API void srslte_ra_ul_grant_fprint(FILE *f, SRSLTE_API void srslte_ra_ul_grant_fprint(FILE *f,
srslte_ra_ul_grant_t *grant); srslte_ra_ul_grant_t *grant);
SRSLTE_API int srslte_dl_fill_ra_mcs_pmch(srslte_ra_mcs_t *mcs, uint32_t nprb);
SRSLTE_API int srslte_dl_fill_ra_mcs(srslte_ra_mcs_t *mcs, uint32_t nprb);
#endif /* RB_ALLOC_H_ */ #endif /* RB_ALLOC_H_ */

@ -58,7 +58,6 @@ typedef struct SRSLTE_API {
uint32_t max_iterations; uint32_t max_iterations;
uint32_t nof_iterations; uint32_t nof_iterations;
float average_nof_iterations;
/* buffers */ /* buffers */
uint8_t *cb_in; uint8_t *cb_in;
@ -77,6 +76,7 @@ typedef struct SRSLTE_API {
srslte_uci_cqi_pusch_t uci_cqi; srslte_uci_cqi_pusch_t uci_cqi;
} srslte_sch_t; } srslte_sch_t;
#include "srslte/phy/phch/pmch.h"
SRSLTE_API int srslte_sch_init(srslte_sch_t *q); SRSLTE_API int srslte_sch_init(srslte_sch_t *q);
@ -86,8 +86,6 @@ SRSLTE_API void srslte_sch_free(srslte_sch_t *q);
SRSLTE_API void srslte_sch_set_max_noi(srslte_sch_t *q, SRSLTE_API void srslte_sch_set_max_noi(srslte_sch_t *q,
uint32_t max_iterations); uint32_t max_iterations);
SRSLTE_API float srslte_sch_average_noi(srslte_sch_t *q);
SRSLTE_API uint32_t srslte_sch_last_noi(srslte_sch_t *q); SRSLTE_API uint32_t srslte_sch_last_noi(srslte_sch_t *q);
SRSLTE_API int srslte_dlsch_encode(srslte_sch_t *q, SRSLTE_API int srslte_dlsch_encode(srslte_sch_t *q,
@ -96,12 +94,26 @@ SRSLTE_API int srslte_dlsch_encode(srslte_sch_t *q,
uint8_t *data, uint8_t *data,
uint8_t *e_bits); uint8_t *e_bits);
SRSLTE_API int srslte_dlsch_encode2(srslte_sch_t *q,
srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffer,
uint8_t *data,
uint8_t *e_bits,
int codeword_idx);
SRSLTE_API int srslte_dlsch_decode(srslte_sch_t *q, SRSLTE_API int srslte_dlsch_decode(srslte_sch_t *q,
srslte_pdsch_cfg_t *cfg, srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_rx_t *softbuffer, srslte_softbuffer_rx_t *softbuffer,
int16_t *e_bits, int16_t *e_bits,
uint8_t *data); uint8_t *data);
SRSLTE_API int srslte_dlsch_decode2(srslte_sch_t *q,
srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_rx_t *softbuffer,
int16_t *e_bits,
uint8_t *data,
int codeword_idx);
SRSLTE_API int srslte_ulsch_encode(srslte_sch_t *q, SRSLTE_API int srslte_ulsch_encode(srslte_sch_t *q,
srslte_pusch_cfg_t *cfg, srslte_pusch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffer, srslte_softbuffer_tx_t *softbuffer,

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

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

@ -200,5 +200,21 @@ SRSLTE_API int srslte_rf_send_timed2(srslte_rf_t *h,
bool is_start_of_burst, bool is_start_of_burst,
bool is_end_of_burst); bool is_end_of_burst);
SRSLTE_API int srslte_rf_send_timed_multi(srslte_rf_t *rf,
void *data[4],
int nsamples,
time_t secs,
double frac_secs,
bool blocking,
bool is_start_of_burst,
bool is_end_of_burst);
SRSLTE_API int srslte_rf_send_multi(srslte_rf_t *rf,
void *data[4],
int nsamples,
bool blocking,
bool is_start_of_burst,
bool is_end_of_burst);
#endif #endif

@ -49,6 +49,7 @@ typedef struct SRSLTE_API {
float last_freq; float last_freq;
float tol; float tol;
int nsamples; int nsamples;
int max_samples;
srslte_cexptab_t tab; srslte_cexptab_t tab;
cf_t *cur_cexp; cf_t *cur_cexp;
}srslte_cfo_t; }srslte_cfo_t;
@ -58,7 +59,7 @@ SRSLTE_API int srslte_cfo_init(srslte_cfo_t *h,
SRSLTE_API void srslte_cfo_free(srslte_cfo_t *h); SRSLTE_API void srslte_cfo_free(srslte_cfo_t *h);
SRSLTE_API int srslte_cfo_realloc(srslte_cfo_t *h, SRSLTE_API int srslte_cfo_resize(srslte_cfo_t *h,
uint32_t samples); uint32_t samples);
SRSLTE_API void srslte_cfo_set_tol(srslte_cfo_t *h, SRSLTE_API void srslte_cfo_set_tol(srslte_cfo_t *h,

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

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

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

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

@ -48,6 +48,7 @@
#include "srslte/phy/phch/pcfich.h" #include "srslte/phy/phch/pcfich.h"
#include "srslte/phy/phch/pdcch.h" #include "srslte/phy/phch/pdcch.h"
#include "srslte/phy/phch/pdsch.h" #include "srslte/phy/phch/pdsch.h"
#include "srslte/phy/phch/pmch.h"
#include "srslte/phy/phch/pdsch_cfg.h" #include "srslte/phy/phch/pdsch_cfg.h"
#include "srslte/phy/phch/phich.h" #include "srslte/phy/phch/phich.h"
#include "srslte/phy/phch/ra.h" #include "srslte/phy/phch/ra.h"
@ -76,15 +77,18 @@ typedef struct SRSLTE_API {
srslte_pcfich_t pcfich; srslte_pcfich_t pcfich;
srslte_pdcch_t pdcch; srslte_pdcch_t pdcch;
srslte_pdsch_t pdsch; srslte_pdsch_t pdsch;
srslte_pmch_t pmch;
srslte_phich_t phich; srslte_phich_t phich;
srslte_regs_t regs; srslte_regs_t regs;
srslte_ofdm_t fft; srslte_ofdm_t fft;
srslte_ofdm_t fft_mbsfn;
srslte_chest_dl_t chest; srslte_chest_dl_t chest;
srslte_cfo_t sfo_correct; srslte_cfo_t sfo_correct;
srslte_pdsch_cfg_t pdsch_cfg; srslte_pdsch_cfg_t pdsch_cfg;
srslte_softbuffer_rx_t softbuffer; srslte_pdsch_cfg_t pmch_cfg;
srslte_softbuffer_rx_t *softbuffers[SRSLTE_MAX_CODEWORDS];
srslte_ra_dl_dci_t dl_dci; srslte_ra_dl_dci_t dl_dci;
srslte_cell_t cell; srslte_cell_t cell;
@ -95,12 +99,22 @@ typedef struct SRSLTE_API {
cf_t *ce[SRSLTE_MAX_PORTS]; // compatibility cf_t *ce[SRSLTE_MAX_PORTS]; // compatibility
cf_t *ce_m[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; cf_t *ce_m[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
/* RI, PMI and SINR for MIMO statistics */
float sinr[SRSLTE_MAX_LAYERS][SRSLTE_MAX_CODEBOOKS];
uint32_t pmi[SRSLTE_MAX_LAYERS];
uint32_t ri;
srslte_dci_format_t dci_format; srslte_dci_format_t dci_format;
uint64_t pkt_errors; uint64_t pkt_errors;
uint64_t pkts_total; uint64_t pkts_total;
uint64_t pdsch_pkt_errors;
uint64_t pdsch_pkts_total;
uint64_t pmch_pkt_errors;
uint64_t pmch_pkts_total;
uint64_t nof_detected; uint64_t nof_detected;
uint16_t current_rnti; uint16_t current_rnti;
uint16_t current_mbsfn_area_id;
dci_blind_search_t current_ss_ue[3][10]; dci_blind_search_t current_ss_ue[3][10];
dci_blind_search_t current_ss_common[3]; dci_blind_search_t current_ss_common[3];
srslte_dci_location_t last_location; srslte_dci_location_t last_location;
@ -114,33 +128,41 @@ typedef struct SRSLTE_API {
/* This function shall be called just after the initial synchronization */ /* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_ue_dl_init(srslte_ue_dl_t *q, SRSLTE_API int srslte_ue_dl_init(srslte_ue_dl_t *q,
srslte_cell_t cell); uint32_t max_prb,
SRSLTE_API int srslte_ue_dl_init_multi(srslte_ue_dl_t *q,
srslte_cell_t cell,
uint32_t nof_rx_antennas); uint32_t nof_rx_antennas);
SRSLTE_API void srslte_ue_dl_free(srslte_ue_dl_t *q); SRSLTE_API void srslte_ue_dl_free(srslte_ue_dl_t *q);
SRSLTE_API int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q, SRSLTE_API int srslte_ue_dl_set_cell(srslte_ue_dl_t *q,
cf_t *input, srslte_cell_t cell);
int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q,
cf_t *input[SRSLTE_MAX_PORTS],
uint32_t sf_idx, uint32_t sf_idx,
uint32_t *cfi); uint32_t *cfi);
SRSLTE_API int srslte_ue_dl_decode_fft_estimate_multi(srslte_ue_dl_t *q, SRSLTE_API int srslte_ue_dl_decode_fft_estimate_mbsfn(srslte_ue_dl_t *q,
cf_t *input[SRSLTE_MAX_PORTS], cf_t *input[SRSLTE_MAX_PORTS],
uint32_t sf_idx, uint32_t sf_idx,
uint32_t *cfi); uint32_t *cfi,
srslte_sf_t sf_type);
SRSLTE_API int srslte_ue_dl_decode_estimate(srslte_ue_dl_t *q, int srslte_ue_dl_decode_estimate(srslte_ue_dl_t *q,
uint32_t sf_idx, uint32_t sf_idx,
uint32_t *cfi); uint32_t *cfi);
SRSLTE_API int srslte_ue_dl_decode_estimate_mbsfn(srslte_ue_dl_t *q,
uint32_t sf_idx,
uint32_t *cfi,
srslte_sf_t sf_type);
SRSLTE_API int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q, SRSLTE_API int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q,
srslte_ra_dl_grant_t *grant, srslte_ra_dl_grant_t *grant,
uint32_t cfi, uint32_t cfi,
uint32_t sf_idx, uint32_t sf_idx,
uint32_t rvidx); int rvidx[SRSLTE_MAX_CODEWORDS],
srslte_mimo_type_t mimo_type);
SRSLTE_API int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t *q, SRSLTE_API int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t *q,
uint32_t cfi, uint32_t cfi,
@ -149,12 +171,14 @@ SRSLTE_API int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t *q,
srslte_dci_msg_t *dci_msg); srslte_dci_msg_t *dci_msg);
SRSLTE_API int srslte_ue_dl_find_dl_dci(srslte_ue_dl_t *q, SRSLTE_API int srslte_ue_dl_find_dl_dci(srslte_ue_dl_t *q,
uint32_t tm,
uint32_t cfi, uint32_t cfi,
uint32_t sf_idx, uint32_t sf_idx,
uint16_t rnti, uint16_t rnti,
srslte_dci_msg_t *dci_msg); srslte_dci_msg_t *dci_msg);
SRSLTE_API int srslte_ue_dl_find_dl_dci_type(srslte_ue_dl_t *q, SRSLTE_API int srslte_ue_dl_find_dl_dci_type(srslte_ue_dl_t *q,
uint32_t tm,
uint32_t cfi, uint32_t cfi,
uint32_t sf_idx, uint32_t sf_idx,
uint16_t rnti, uint16_t rnti,
@ -166,27 +190,41 @@ SRSLTE_API uint32_t srslte_ue_dl_get_ncce(srslte_ue_dl_t *q);
SRSLTE_API void srslte_ue_dl_set_sample_offset(srslte_ue_dl_t * q, SRSLTE_API void srslte_ue_dl_set_sample_offset(srslte_ue_dl_t * q,
float sample_offset); float sample_offset);
SRSLTE_API int srslte_ue_dl_decode(srslte_ue_dl_t * q, SRSLTE_API int srslte_ue_dl_decode(srslte_ue_dl_t *q,
cf_t *input,
uint8_t *data,
uint32_t tti);
SRSLTE_API int srslte_ue_dl_decode_multi(srslte_ue_dl_t * q,
cf_t *input[SRSLTE_MAX_PORTS], cf_t *input[SRSLTE_MAX_PORTS],
uint8_t *data, uint8_t *data[SRSLTE_MAX_CODEWORDS],
uint32_t tti); uint32_t tm,
uint32_t tti,
bool acks[SRSLTE_MAX_CODEWORDS]);
SRSLTE_API int srslte_ue_dl_decode_rnti(srslte_ue_dl_t * q, SRSLTE_API int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q,
cf_t *input, cf_t *input[SRSLTE_MAX_PORTS],
uint8_t *data, uint8_t *data[SRSLTE_MAX_CODEWORDS],
uint32_t tm,
uint32_t tti, uint32_t tti,
uint16_t rnti); uint16_t rnti,
bool acks[SRSLTE_MAX_CODEWORDS]);
SRSLTE_API int srslte_ue_dl_decode_rnti_multi(srslte_ue_dl_t * q, /* Used by example applications - full PMCH decode for a given MBSFN area ID
* srslte_ue_dl_decode_fft_estimate_multi,
* srslte_chest_dl_get_noise_estimate,
* srslte_ue_dl_cfg_grant,
* srslte_pmch_decode_multi
*/
SRSLTE_API int srslte_ue_dl_decode_mbsfn(srslte_ue_dl_t * q,
cf_t *input[SRSLTE_MAX_PORTS], cf_t *input[SRSLTE_MAX_PORTS],
uint8_t *data, uint8_t *data,
uint32_t tti, uint32_t tti);
uint16_t rnti);
SRSLTE_API int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q,
uint8_t *ri,
uint8_t *pmi,
float *current_sinr);
SRSLTE_API int srslte_ue_dl_ri_select(srslte_ue_dl_t *q,
uint8_t *ri,
float *cn);
SRSLTE_API bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q, SRSLTE_API bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q,
uint32_t sf_idx, uint32_t sf_idx,
@ -198,6 +236,15 @@ SRSLTE_API void srslte_ue_dl_reset(srslte_ue_dl_t *q);
SRSLTE_API void srslte_ue_dl_set_rnti(srslte_ue_dl_t *q, SRSLTE_API void srslte_ue_dl_set_rnti(srslte_ue_dl_t *q,
uint16_t rnti); uint16_t rnti);
/* Generate signals if required, store in q->current_mbsfn_area_id */
SRSLTE_API int srslte_ue_dl_set_mbsfn_area_id(srslte_ue_dl_t *q,
uint16_t mbsfn_area_id);
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_save_signal(srslte_ue_dl_t *q, SRSLTE_API void srslte_ue_dl_save_signal(srslte_ue_dl_t *q,
srslte_softbuffer_rx_t *softbuffer, srslte_softbuffer_rx_t *softbuffer,
uint32_t tti, uint32_t tti,

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

@ -70,6 +70,8 @@ typedef struct SRSLTE_API {
srslte_sync_t sfind; srslte_sync_t sfind;
srslte_sync_t strack; srslte_sync_t strack;
uint32_t max_prb;
srslte_agc_t agc; srslte_agc_t agc;
bool do_agc; bool do_agc;
uint32_t agc_period; uint32_t agc_period;
@ -125,18 +127,21 @@ typedef struct SRSLTE_API {
} srslte_ue_sync_t; } srslte_ue_sync_t;
SRSLTE_API int srslte_ue_sync_init(srslte_ue_sync_t *q, SRSLTE_API int srslte_ue_sync_init(srslte_ue_sync_t *q,
srslte_cell_t cell, uint32_t max_prb,
bool search_cell,
int (recv_callback)(void*, void*, uint32_t, srslte_timestamp_t*), int (recv_callback)(void*, void*, uint32_t, srslte_timestamp_t*),
void *stream_handler); void *stream_handler);
SRSLTE_API int srslte_ue_sync_init_multi(srslte_ue_sync_t *q, SRSLTE_API int srslte_ue_sync_init_multi(srslte_ue_sync_t *q,
srslte_cell_t cell, uint32_t max_prb,
bool search_cell,
int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t*), int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t*),
uint32_t nof_rx_antennas, uint32_t nof_rx_antennas,
void *stream_handler); void *stream_handler);
SRSLTE_API int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q, SRSLTE_API int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q,
srslte_cell_t cell, uint32_t max_prb,
bool search_cell,
int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t*), int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t*),
uint32_t nof_rx_antennas, uint32_t nof_rx_antennas,
void *stream_handler, void *stream_handler,
@ -148,8 +153,18 @@ SRSLTE_API int srslte_ue_sync_init_file(srslte_ue_sync_t *q,
int offset_time, int offset_time,
float offset_freq); float offset_freq);
SRSLTE_API int srslte_ue_sync_init_file_multi(srslte_ue_sync_t *q,
uint32_t nof_prb,
char *file_name,
int offset_time,
float offset_freq,
uint32_t nof_rx_ant);
SRSLTE_API void srslte_ue_sync_free(srslte_ue_sync_t *q); SRSLTE_API void srslte_ue_sync_free(srslte_ue_sync_t *q);
SRSLTE_API int srslte_ue_sync_set_cell(srslte_ue_sync_t *q,
srslte_cell_t cell);
SRSLTE_API int srslte_ue_sync_start_agc(srslte_ue_sync_t *q, SRSLTE_API int srslte_ue_sync_start_agc(srslte_ue_sync_t *q,
double (set_gain_callback)(void*, double), double (set_gain_callback)(void*, double),
float init_gain_value); float init_gain_value);
@ -166,6 +181,9 @@ SRSLTE_API int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q,
SRSLTE_API int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, SRSLTE_API int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q,
cf_t *input_buffer[SRSLTE_MAX_PORTS]); cf_t *input_buffer[SRSLTE_MAX_PORTS]);
SRSLTE_API void srslte_ue_sync_set_cfo_tol(srslte_ue_sync_t *q,
float tol);
SRSLTE_API void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q, SRSLTE_API void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q,
float cfo); float cfo);

@ -76,6 +76,7 @@ typedef struct SRSLTE_API {
bool normalize_en; bool normalize_en;
bool cfo_en; bool cfo_en;
float current_cfo_tol;
float current_cfo; float current_cfo;
srslte_pucch_format_t last_pucch_format; srslte_pucch_format_t last_pucch_format;
@ -107,10 +108,16 @@ typedef struct SRSLTE_API {
/* This function shall be called just after the initial synchronization */ /* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_ue_ul_init(srslte_ue_ul_t *q, SRSLTE_API int srslte_ue_ul_init(srslte_ue_ul_t *q,
srslte_cell_t cell); uint32_t max_prb);
SRSLTE_API void srslte_ue_ul_free(srslte_ue_ul_t *q); SRSLTE_API void srslte_ue_ul_free(srslte_ue_ul_t *q);
SRSLTE_API int srslte_ue_ul_set_cell(srslte_ue_ul_t *q,
srslte_cell_t cell);
SRSLTE_API void srslte_ue_ul_set_cfo_tol(srslte_ue_ul_t *q,
float tol);
SRSLTE_API void srslte_ue_ul_set_cfo(srslte_ue_ul_t *q, SRSLTE_API void srslte_ue_ul_set_cfo(srslte_ue_ul_t *q,
float cur_cfo); float cur_cfo);

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

@ -58,10 +58,16 @@ SRSLTE_API extern int srslte_verbose;
#define PRINT_NONE srslte_verbose=SRSLTE_VERBOSE_NONE #define PRINT_NONE srslte_verbose=SRSLTE_VERBOSE_NONE
#define DEBUG(_fmt, ...) if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG) \ #define DEBUG(_fmt, ...) if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG) \
fprintf(stdout, "[DEBUG]: " _fmt, __VA_ARGS__) fprintf(stdout, "[DEBUG]: " _fmt, ##__VA_ARGS__)
#define INFO(_fmt, ...) if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO) \ #define INFO(_fmt, ...) if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO) \
fprintf(stdout, "[INFO]: " _fmt, __VA_ARGS__) fprintf(stdout, "[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__)
#else
#define ERROR(_fmt, ...) fprintf(stderr, "[ERROR in %s]:" _fmt "\n", __FUNCTION__, ##__VA_ARGS__)
#endif /* CMAKE_BUILD_TYPE==Debug */
#endif // DEBUG_H #endif // DEBUG_H

@ -0,0 +1,115 @@
/**
*
* \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 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))
/* Generic implementation for complex reciprocal */
SRSLTE_API cf_t srslte_mat_cf_recip_gen(cf_t a);
/* Generic implementation for 2x2 determinant */
SRSLTE_API cf_t srslte_mat_2x2_det_gen(cf_t a00, cf_t a01, cf_t a10, cf_t a11);
/* Generic implementation for 2x2 Matrix Inversion */
SRSLTE_API void srslte_mat_2x2_inv_gen(cf_t a00, cf_t a01, cf_t a10, cf_t a11,
cf_t *r00, cf_t *r01, cf_t *r10, cf_t *r11);
/* Generic implementation for Zero Forcing (ZF) solver */
SRSLTE_API void srslte_mat_2x2_zf_gen(cf_t y0, cf_t y1,
cf_t h00, cf_t h01, cf_t h10, cf_t h11,
cf_t *x0, cf_t *x1,
float norm);
/* Generic implementation for Minimum Mean Squared Error (MMSE) solver */
SRSLTE_API void srslte_mat_2x2_mmse_gen(cf_t y0, cf_t y1,
cf_t h00, cf_t h01, cf_t h10, cf_t h11,
cf_t *x0, cf_t *x1,
float noise_estimate,
float norm);
SRSLTE_API float srslte_mat_2x2_cn(cf_t h00,
cf_t h01,
cf_t h10,
cf_t h11);
#ifdef LV_HAVE_SSE
#include <smmintrin.h>
/* SSE implementation for complex reciprocal */
SRSLTE_API __m128 srslte_mat_cf_recip_sse(__m128 a);
/* SSE implementation for 2x2 determinant */
SRSLTE_API __m128 srslte_mat_2x2_det_sse(__m128 a00, __m128 a01, __m128 a10, __m128 a11);
/* SSE implementation for Zero Forcing (ZF) solver */
SRSLTE_API void srslte_mat_2x2_zf_sse(__m128 y0, __m128 y1,
__m128 h00, __m128 h01, __m128 h10, __m128 h11,
__m128 *x0, __m128 *x1,
float norm);
/* SSE implementation for Minimum Mean Squared Error (MMSE) solver */
SRSLTE_API void srslte_mat_2x2_mmse_sse(__m128 y0, __m128 y1,
__m128 h00, __m128 h01, __m128 h10, __m128 h11,
__m128 *x0, __m128 *x1,
float noise_estimate, float norm);
#endif /* LV_HAVE_SSE */
#ifdef LV_HAVE_AVX
#include <immintrin.h>
/* AVX implementation for complex reciprocal */
SRSLTE_API __m256 srslte_mat_cf_recip_avx(__m256 a);
/* AVX implementation for 2x2 determinant */
SRSLTE_API __m256 srslte_mat_2x2_det_avx(__m256 a00, __m256 a01, __m256 a10, __m256 a11);
/* AVX implementation for Zero Forcing (ZF) solver */
SRSLTE_API void srslte_mat_2x2_zf_avx(__m256 y0, __m256 y1,
__m256 h00, __m256 h01, __m256 h10, __m256 h11,
__m256 *x0, __m256 *x1,
float norm);
/* AVX implementation for Minimum Mean Squared Error (MMSE) solver */
SRSLTE_API void srslte_mat_2x2_mmse_avx(__m256 y0, __m256 y1,
__m256 h00, __m256 h01, __m256 h10, __m256 h11,
__m256 *x0, __m256 *x1,
float noise_estimate, float norm);
#endif /* LV_HAVE_AVX */
#endif /* SRSLTE_MAT_H */

@ -0,0 +1,81 @@
/**
*
* \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 SRSLTE_SIMD_H_H
#define SRSLTE_SIMD_H_H
/*
* SSE Macros
*/
#ifdef LV_HAVE_SSE
#define _MM_SWAP(X) ((__m128)_mm_shuffle_ps(X, X, _MM_SHUFFLE(2,3,0,1)))
#define _MM_PERM(X) ((__m128)_mm_shuffle_ps(X, X, _MM_SHUFFLE(2,1,3,0)))
#define _MM_MULJ_PS(X) _MM_SWAP(_MM_CONJ_PS(X))
#define _MM_CONJ_PS(X) (_mm_xor_ps(X, _mm_set_ps(-0.0f, 0.0f, -0.0f, 0.0f)))
#define _MM_SQMOD_PS(X) _MM_PERM(_mm_hadd_ps(_mm_mul_ps(X,X), _mm_set_ps(0.0f, 0.0f, 0.0f, 0.0f)))
#define _MM_PROD_PS(a, b) _mm_addsub_ps(_mm_mul_ps(a,_mm_moveldup_ps(b)),_mm_mul_ps(\
_mm_shuffle_ps(a,a,0xB1),_mm_movehdup_ps(b)))
#endif /* LV_HAVE_SSE */
/*
* AVX Macros
*/
#ifdef LV_HAVE_AVX
#define _MM256_MULJ_PS(X) _mm256_permute_ps(_MM256_CONJ_PS(X), 0b10110001)
#define _MM256_CONJ_PS(X) (_mm256_xor_ps(X, _mm256_set_ps(-0.0f, 0.0f, -0.0f, 0.0f, -0.0f, 0.0f, -0.0f, 0.0f)))
#ifdef LV_HAVE_FMA
#define _MM256_SQMOD_PS(A, B) _mm256_permute_ps(_mm256_hadd_ps(_mm256_fmadd_ps(A, A, _mm256_mul_ps(B,B)), \
_mm256_set_ps(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), 0b11011100)
#define _MM256_PROD_PS(a, b) _mm256_fmaddsub_ps(a,_mm256_moveldup_ps(b),\
_mm256_mul_ps(_mm256_shuffle_ps(a,a,0xB1),_mm256_movehdup_ps(b)))
#else
#define _MM256_SQMOD_PS(A, B) _mm256_permute_ps(_mm256_hadd_ps(_mm256_add_ps(_mm256_mul_ps(A,A), _mm256_mul_ps(B,B)), \
_mm256_set_ps(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), 0b11011100)
#define _MM256_PROD_PS(a, b) _mm256_addsub_ps(_mm256_mul_ps(a,_mm256_moveldup_ps(b)),\
_mm256_mul_ps(_mm256_shuffle_ps(a,a,0xB1),_mm256_movehdup_ps(b)))
#endif /* LV_HAVE_FMA */
#endif /* LV_HAVE_AVX */
/*
* AVX extension with FMA Macros
*/
#ifdef LV_HAVE_FMA
#define _MM256_SQMOD_ADD_PS(A, B, C) _mm256_permute_ps(_mm256_hadd_ps(_mm256_fmadd_ps(A, A, _mm256_fmadd_ps(B, B, C)),\
_mm256_set_ps(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)), 0b11011100)
#define _MM256_PROD_ADD_PS(A, B, C) _mm256_fmaddsub_ps(A,_mm256_moveldup_ps(B),\
_mm256_fmaddsub_ps(_mm256_shuffle_ps(A,A,0xB1),_mm256_movehdup_ps(B), C))
#define _MM256_PROD_SUB_PS(A, B, C) _mm256_fmaddsub_ps(A,_mm256_moveldup_ps(B),\
_mm256_fmsubadd_ps(_mm256_shuffle_ps(A,A,0xB1),_mm256_movehdup_ps(B), C))
#endif /* LV_HAVE_FMA */
#endif //SRSLTE_SIMD_H_H

@ -152,6 +152,9 @@ SRSLTE_API void srslte_vec_conj_cc(cf_t *x, cf_t *y, uint32_t len);
/* average vector power */ /* 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(cf_t *x, 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);
/* return the index of the maximum value in the vector */ /* 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_fi(float *x, uint32_t len);
SRSLTE_API uint32_t srslte_vec_max_abs_ci(cf_t *x, uint32_t len); SRSLTE_API uint32_t srslte_vec_max_abs_ci(cf_t *x, uint32_t len);
@ -172,6 +175,9 @@ SRSLTE_API void srslte_vec_abs_square_cf(cf_t *x, float *abs_square, uint32_t le
/* argument of each vector element */ /* 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_arg_cf(cf_t *x, float *arg, uint32_t len);
/* Copy 256 bit aligned vector */
SRSLTE_API void srs_vec_cf_cpy(cf_t *src, cf_t *dst, int len);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

@ -39,22 +39,14 @@ SRSLTE_API int srslte_vec_dot_prod_sss_sse(short *x, short *y, uint32_t len);
SRSLTE_API int srslte_vec_dot_prod_sss_avx2(short *x, short *y, uint32_t len); SRSLTE_API int srslte_vec_dot_prod_sss_avx2(short *x, short *y, uint32_t len);
SRSLTE_API void srslte_vec_sum_sss_sse(short *x, short *y, short *z, uint32_t len); SRSLTE_API void srslte_vec_sum_sss_sse(short *x, short *y, short *z, uint32_t len);
SRSLTE_API void srslte_vec_sum_sss_avx2(short *x, short *y, short *z, uint32_t len); SRSLTE_API void srslte_vec_sum_sss_avx2(short *x, short *y, short *z, uint32_t 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_sse(short *x, short *y, short *z, uint32_t len);
SRSLTE_API void srslte_vec_sub_sss_avx2(short *x, short *y, short *z, uint32_t len); SRSLTE_API void srslte_vec_sub_sss_avx2(short *x, short *y, short *z, uint32_t len);
SRSLTE_API void srslte_vec_prod_sss_sse(short *x, short *y, short *z, uint32_t len); SRSLTE_API void srslte_vec_prod_sss_sse(short *x, short *y, short *z, uint32_t len);
SRSLTE_API void srslte_vec_prod_sss_avx2(short *x, short *y, short *z, uint32_t len); SRSLTE_API void srslte_vec_prod_sss_avx2(short *x, short *y, short *z, uint32_t len);
@ -64,17 +56,11 @@ SRSLTE_API void srslte_vec_sc_div2_sss_sse(short *x, int n_rightshift, short *z,
SRSLTE_API void srslte_vec_sc_div2_sss_avx2(short *x, int k, short *z, uint32_t len); SRSLTE_API void srslte_vec_sc_div2_sss_avx2(short *x, int k, short *z, uint32_t len);
SRSLTE_API void srslte_vec_lut_sss_sse(short *x, unsigned short *lut, short *y, uint32_t len); SRSLTE_API void srslte_vec_lut_sss_sse(short *x, unsigned short *lut, short *y, uint32_t len);
SRSLTE_API void srslte_vec_convert_fi_sse(float *x, int16_t *z, float scale, uint32_t len); SRSLTE_API void srslte_vec_convert_fi_sse(float *x, int16_t *z, float scale, uint32_t len);
SRSLTE_API void srslte_vec_sc_prod_cfc_avx(const cf_t *x,const float h,cf_t *y,const uint32_t len);
SRSLTE_API void srslte_vec_mult_scalar_cf_f_avx( cf_t *z,const cf_t *x,const float h,const uint32_t len);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

@ -57,7 +57,6 @@ namespace srslte {
bzero(&end_of_burst_time, sizeof(srslte_timestamp_t)); bzero(&end_of_burst_time, sizeof(srslte_timestamp_t));
bzero(zeros, burst_preamble_max_samples*sizeof(cf_t)); bzero(zeros, burst_preamble_max_samples*sizeof(cf_t));
sf_len = 0;
burst_preamble_sec = 0; burst_preamble_sec = 0;
is_start_of_burst = false; is_start_of_burst = false;
burst_preamble_samples = 0; burst_preamble_samples = 0;
@ -73,12 +72,11 @@ namespace srslte {
trace_enabled = false; trace_enabled = false;
tti = 0; tti = 0;
agc_enabled = false; agc_enabled = false;
offset = 0;
}; };
bool init(char *args = NULL, char *devname = NULL); bool init(char *args = NULL, char *devname = NULL);
void stop(); void stop();
void reset();
bool start_agc(bool tx_gain_same_rx); bool start_agc(bool tx_gain_same_rx);
void set_burst_preamble(double preamble_us); void set_burst_preamble(double preamble_us);
@ -98,15 +96,16 @@ namespace srslte {
void set_tx_rx_gain_offset(float offset); void set_tx_rx_gain_offset(float offset);
double set_rx_gain_th(float gain); double set_rx_gain_th(float gain);
void set_tx_freq(float freq); void set_freq_offset(double freq);
void set_rx_freq(float freq); void set_tx_freq(double freq);
void set_rx_freq(double freq);
float get_tx_freq(); double get_tx_freq();
float get_rx_freq(); double get_rx_freq();
void set_master_clock_rate(float rate); void set_master_clock_rate(double rate);
void set_tx_srate(float srate); void set_tx_srate(double srate);
void set_rx_srate(float srate); void set_rx_srate(double srate);
float get_tx_gain(); float get_tx_gain();
float get_rx_gain(); float get_rx_gain();
@ -122,9 +121,8 @@ namespace srslte {
void stop_rx(); void stop_rx();
void set_tti(uint32_t tti); void set_tti(uint32_t tti);
void tx_offset(int offset);
void set_tti_len(uint32_t sf_len); bool is_first_of_burst();
uint32_t get_tti_len();
void register_error_handler(srslte_rf_error_handler_t h); void register_error_handler(srslte_rf_error_handler_t h);
@ -158,7 +156,7 @@ namespace srslte {
const static double blade_default_tx_adv_samples = 27; const static double blade_default_tx_adv_samples = 27;
const static double blade_default_tx_adv_offset_sec = 1e-6; const static double blade_default_tx_adv_offset_sec = 1e-6;
float tx_freq, rx_freq; double tx_freq, rx_freq, freq_offset;
trace<uint32_t> tr_local_time; trace<uint32_t> tr_local_time;
trace<uint32_t> tr_usrp_time; trace<uint32_t> tr_usrp_time;
@ -167,8 +165,10 @@ namespace srslte {
bool trace_enabled; bool trace_enabled;
uint32_t tti; uint32_t tti;
bool agc_enabled; bool agc_enabled;
int offset;
uint32_t sf_len; char saved_args[128];
char saved_devname[128];
}; };
} }

@ -46,13 +46,17 @@ public:
srsue::rrc_interface_pdcp *rrc_, srsue::rrc_interface_pdcp *rrc_,
srsue::gw_interface_pdcp *gw_, srsue::gw_interface_pdcp *gw_,
log *pdcp_log_, log *pdcp_log_,
uint32_t lcid_,
uint8_t direction_); uint8_t direction_);
void stop(); void stop();
// GW interface
bool is_drb_enabled(uint32_t lcid);
// RRC interface // RRC interface
void reset(); void reset();
void write_sdu(uint32_t lcid, byte_buffer_t *sdu); void write_sdu(uint32_t lcid, byte_buffer_t *sdu);
void add_bearer(uint32_t lcid, LIBLTE_RRC_PDCP_CONFIG_STRUCT *cnfg = NULL); void add_bearer(uint32_t lcid, srslte_pdcp_config_t cnfg = srslte_pdcp_config_t());
void config_security(uint32_t lcid, void config_security(uint32_t lcid,
uint8_t *k_rrc_enc, uint8_t *k_rrc_enc,
uint8_t *k_rrc_int, uint8_t *k_rrc_int,
@ -66,13 +70,13 @@ public:
void write_pdu_pcch(byte_buffer_t *sdu); void write_pdu_pcch(byte_buffer_t *sdu);
private: private:
log *pdcp_log;
pdcp_entity pdcp_array[SRSLTE_N_RADIO_BEARERS];
srsue::rlc_interface_pdcp *rlc; srsue::rlc_interface_pdcp *rlc;
srsue::rrc_interface_pdcp *rrc; srsue::rrc_interface_pdcp *rrc;
srsue::gw_interface_pdcp *gw; srsue::gw_interface_pdcp *gw;
log *pdcp_log;
pdcp_entity pdcp_array[SRSLTE_N_RADIO_BEARERS];
uint32_t lcid; // default LCID that is maintained active by PDCP instance
uint8_t direction; uint8_t direction;
bool valid_lcid(uint32_t lcid); bool valid_lcid(uint32_t lcid);

@ -67,9 +67,7 @@ public:
srsue::gw_interface_pdcp *gw_, srsue::gw_interface_pdcp *gw_,
srslte::log *log_, srslte::log *log_,
uint32_t lcid_, uint32_t lcid_,
uint8_t direction_, srslte_pdcp_config_t cfg_);
LIBLTE_RRC_PDCP_CONFIG_STRUCT *cnfg = NULL
);
void reset(); void reset();
bool is_active(); bool is_active();
@ -94,12 +92,7 @@ private:
bool active; bool active;
uint32_t lcid; uint32_t lcid;
bool do_security; srslte_pdcp_config_t cfg;
u_int8_t direction;
uint8_t sn_len;
// TODO: Support the following configurations
// bool do_rohc;
uint32_t rx_count; uint32_t rx_count;
uint32_t tx_count; uint32_t tx_count;

@ -34,6 +34,7 @@
#include "srslte/common/msg_queue.h" #include "srslte/common/msg_queue.h"
#include "srslte/upper/rlc_entity.h" #include "srslte/upper/rlc_entity.h"
#include "srslte/upper/rlc_metrics.h" #include "srslte/upper/rlc_metrics.h"
#include "srslte/upper/rlc_common.h"
namespace srslte { namespace srslte {
@ -55,13 +56,15 @@ public:
srsue::rrc_interface_rlc *rrc_, srsue::rrc_interface_rlc *rrc_,
srsue::ue_interface *ue_, srsue::ue_interface *ue_,
log *rlc_log_, log *rlc_log_,
mac_interface_timers *mac_timers_); mac_interface_timers *mac_timers_,
uint32_t lcid_);
void stop(); void stop();
void get_metrics(rlc_metrics_t &m); void get_metrics(rlc_metrics_t &m);
// PDCP interface // PDCP interface
void write_sdu(uint32_t lcid, byte_buffer_t *sdu); void write_sdu(uint32_t lcid, byte_buffer_t *sdu);
std::string get_rb_name(uint32_t lcid);
// MAC interface // MAC interface
uint32_t get_buffer_state(uint32_t lcid); uint32_t get_buffer_state(uint32_t lcid);
@ -74,8 +77,9 @@ public:
// RRC interface // RRC interface
void reset(); void reset();
void empty_queue();
void add_bearer(uint32_t lcid); void add_bearer(uint32_t lcid);
void add_bearer(uint32_t lcid, LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg); void add_bearer(uint32_t lcid, srslte_rlc_config_t cnfg);
private: private:
void reset_metrics(); void reset_metrics();
@ -87,6 +91,7 @@ private:
srslte::mac_interface_timers *mac_timers; srslte::mac_interface_timers *mac_timers;
srsue::ue_interface *ue; srsue::ue_interface *ue;
srslte::rlc_entity rlc_array[SRSLTE_N_RADIO_BEARERS]; srslte::rlc_entity rlc_array[SRSLTE_N_RADIO_BEARERS];
uint32_t default_lcid;
long ul_tput_bytes[SRSLTE_N_RADIO_BEARERS]; long ul_tput_bytes[SRSLTE_N_RADIO_BEARERS];
long dl_tput_bytes[SRSLTE_N_RADIO_BEARERS]; long dl_tput_bytes[SRSLTE_N_RADIO_BEARERS];

@ -76,8 +76,9 @@ public:
srsue::pdcp_interface_rlc *pdcp_, srsue::pdcp_interface_rlc *pdcp_,
srsue::rrc_interface_rlc *rrc_, srsue::rrc_interface_rlc *rrc_,
mac_interface_timers *mac_timers); mac_interface_timers *mac_timers);
void configure(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg); void configure(srslte_rlc_config_t cnfg);
void reset(); void reset();
void stop();
void empty_queue(); void empty_queue();
rlc_mode_t get_mode(); rlc_mode_t get_mode();
@ -128,15 +129,7 @@ private:
* Ref: 3GPP TS 36.322 v10.0.0 Section 7 * Ref: 3GPP TS 36.322 v10.0.0 Section 7
***************************************************************************/ ***************************************************************************/
// TX configs srslte_rlc_am_config_t cfg;
int32_t t_poll_retx; // Poll retx timeout (ms)
int32_t poll_pdu; // Insert poll bit after this many PDUs
int32_t poll_byte; // Insert poll bit after this much data (KB)
uint32_t max_retx_thresh; // Max number of retx
// RX configs
int32_t t_reordering; // Timer used by rx to detect PDU loss (ms)
int32_t t_status_prohibit; // Timer used by rx to prohibit tx of status PDU (ms)
/**************************************************************************** /****************************************************************************
* State variables and counters * State variables and counters

@ -27,6 +27,8 @@
#ifndef RLC_COMMON_H #ifndef RLC_COMMON_H
#define RLC_COMMON_H #define RLC_COMMON_H
#include "srslte/upper/rlc_interface.h"
namespace srslte { namespace srslte {
/**************************************************************************** /****************************************************************************
@ -66,14 +68,6 @@ typedef enum{
static const char rlc_dc_field_text[RLC_DC_FIELD_N_ITEMS][20] = {"Control PDU", static const char rlc_dc_field_text[RLC_DC_FIELD_N_ITEMS][20] = {"Control PDU",
"Data PDU"}; "Data PDU"};
typedef enum{
RLC_UMD_SN_SIZE_5_BITS = 0,
RLC_UMD_SN_SIZE_10_BITS,
RLC_UMD_SN_SIZE_N_ITEMS,
}rlc_umd_sn_size_t;
static const char rlc_umd_sn_size_text[RLC_UMD_SN_SIZE_N_ITEMS][20] = {"5 bits", "10 bits"};
static const uint16_t rlc_umd_sn_size_num[RLC_UMD_SN_SIZE_N_ITEMS] = {5, 10};
// UMD PDU Header // UMD PDU Header
typedef struct{ typedef struct{
uint8_t fi; // Framing info uint8_t fi; // Framing info
@ -162,8 +156,9 @@ public:
srsue::pdcp_interface_rlc *pdcp_, srsue::pdcp_interface_rlc *pdcp_,
srsue::rrc_interface_rlc *rrc_, srsue::rrc_interface_rlc *rrc_,
srslte::mac_interface_timers *mac_timers_) = 0; srslte::mac_interface_timers *mac_timers_) = 0;
virtual void configure(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg) = 0; virtual void configure(srslte_rlc_config_t cnfg) = 0;
virtual void reset() = 0; virtual void reset() = 0;
virtual void stop() = 0;
virtual void empty_queue() = 0; virtual void empty_queue() = 0;
virtual rlc_mode_t get_mode() = 0; virtual rlc_mode_t get_mode() = 0;

@ -54,8 +54,10 @@ public:
srsue::rrc_interface_rlc *rrc_, srsue::rrc_interface_rlc *rrc_,
mac_interface_timers *mac_timers_); mac_interface_timers *mac_timers_);
void configure(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg); void configure(srslte_rlc_config_t cnfg);
void reset(); void reset();
void stop();
void empty_queue();
bool active(); bool active();
rlc_mode_t get_mode(); rlc_mode_t get_mode();

@ -0,0 +1,126 @@
/**
*
* \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/.
*
*/
#ifndef RLC_INTERFACE_H
#define RLC_INTERFACE_H
// for custom constructors
#include "srslte/asn1/liblte_rrc.h"
namespace srslte {
typedef enum{
RLC_UMD_SN_SIZE_5_BITS = 0,
RLC_UMD_SN_SIZE_10_BITS,
RLC_UMD_SN_SIZE_N_ITEMS,
}rlc_umd_sn_size_t;
static const char rlc_umd_sn_size_text[RLC_UMD_SN_SIZE_N_ITEMS][20] = {"5 bits", "10 bits"};
static const uint16_t rlc_umd_sn_size_num[RLC_UMD_SN_SIZE_N_ITEMS] = {5, 10};
typedef struct {
/****************************************************************************
* Configurable parameters
* Ref: 3GPP TS 36.322 v10.0.0 Section 7
***************************************************************************/
// TX configs
int32_t t_poll_retx; // Poll retx timeout (ms)
int32_t poll_pdu; // Insert poll bit after this many PDUs
int32_t poll_byte; // Insert poll bit after this much data (KB)
uint32_t max_retx_thresh; // Max number of retx
// RX configs
int32_t t_reordering; // Timer used by rx to detect PDU loss (ms)
int32_t t_status_prohibit; // Timer used by rx to prohibit tx of status PDU (ms)
} srslte_rlc_am_config_t;
typedef struct {
/****************************************************************************
* Configurable parameters
* Ref: 3GPP TS 36.322 v10.0.0 Section 7
***************************************************************************/
int32_t t_reordering; // Timer used by rx to detect PDU loss (ms)
rlc_umd_sn_size_t tx_sn_field_length; // Number of bits used for tx (UL) sequence number
rlc_umd_sn_size_t rx_sn_field_length; // Number of bits used for rx (DL) sequence number
uint32_t rx_window_size;
uint32_t rx_mod; // Rx counter modulus
uint32_t tx_mod; // Tx counter modulus
} srslte_rlc_um_config_t;
class srslte_rlc_config_t
{
public:
LIBLTE_RRC_RLC_MODE_ENUM rlc_mode;
srslte_rlc_am_config_t am;
srslte_rlc_um_config_t um;
// Constructor based on liblte's RLC config
srslte_rlc_config_t(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg) : rlc_mode(cnfg->rlc_mode), am(), um()
{
switch(rlc_mode)
{
case LIBLTE_RRC_RLC_MODE_AM:
am.t_poll_retx = liblte_rrc_t_poll_retransmit_num[cnfg->ul_am_rlc.t_poll_retx];
am.poll_pdu = liblte_rrc_poll_pdu_num[cnfg->ul_am_rlc.poll_pdu];
am.poll_byte = liblte_rrc_poll_byte_num[cnfg->ul_am_rlc.poll_byte]*1000; // KB
am.max_retx_thresh = liblte_rrc_max_retx_threshold_num[cnfg->ul_am_rlc.max_retx_thresh];
am.t_reordering = liblte_rrc_t_reordering_num[cnfg->dl_am_rlc.t_reordering];
am.t_status_prohibit = liblte_rrc_t_status_prohibit_num[cnfg->dl_am_rlc.t_status_prohibit];
break;
case LIBLTE_RRC_RLC_MODE_UM_BI:
um.t_reordering = liblte_rrc_t_reordering_num[cnfg->dl_um_bi_rlc.t_reordering];
um.rx_sn_field_length = (rlc_umd_sn_size_t)cnfg->dl_um_bi_rlc.sn_field_len;
um.rx_window_size = (RLC_UMD_SN_SIZE_5_BITS == um.rx_sn_field_length) ? 16 : 512;
um.rx_mod = (RLC_UMD_SN_SIZE_5_BITS == um.rx_sn_field_length) ? 32 : 1024;
um.tx_sn_field_length = (rlc_umd_sn_size_t)cnfg->ul_um_bi_rlc.sn_field_len;
um.tx_mod = (RLC_UMD_SN_SIZE_5_BITS == um.tx_sn_field_length) ? 32 : 1024;
break;
case LIBLTE_RRC_RLC_MODE_UM_UNI_UL:
um.tx_sn_field_length = (rlc_umd_sn_size_t)cnfg->ul_um_uni_rlc.sn_field_len;
um.tx_mod = (RLC_UMD_SN_SIZE_5_BITS == um.tx_sn_field_length) ? 32 : 1024;
break;
case LIBLTE_RRC_RLC_MODE_UM_UNI_DL:
um.t_reordering = liblte_rrc_t_reordering_num[cnfg->dl_um_uni_rlc.t_reordering];
um.rx_sn_field_length = (rlc_umd_sn_size_t)cnfg->dl_um_uni_rlc.sn_field_len;
um.rx_window_size = (RLC_UMD_SN_SIZE_5_BITS == um.rx_sn_field_length) ? 16 : 512;
um.rx_mod = (RLC_UMD_SN_SIZE_5_BITS == um.rx_sn_field_length) ? 32 : 1024;
break;
default:
// Handle default case
break;
}
}
};
} // namespace srslte
#endif // RLC_INTERFACE_H

@ -46,8 +46,9 @@ public:
srsue::pdcp_interface_rlc *pdcp_, srsue::pdcp_interface_rlc *pdcp_,
srsue::rrc_interface_rlc *rrc_, srsue::rrc_interface_rlc *rrc_,
mac_interface_timers *mac_timers); mac_interface_timers *mac_timers);
void configure(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg); void configure(srslte_rlc_config_t cnfg);
void reset(); void reset();
void stop();
void empty_queue(); void empty_queue();
rlc_mode_t get_mode(); rlc_mode_t get_mode();

@ -56,8 +56,9 @@ public:
srsue::pdcp_interface_rlc *pdcp_, srsue::pdcp_interface_rlc *pdcp_,
srsue::rrc_interface_rlc *rrc_, srsue::rrc_interface_rlc *rrc_,
mac_interface_timers *mac_timers_); mac_interface_timers *mac_timers_);
void configure(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg); void configure(srslte_rlc_config_t cnfg);
void reset(); void reset();
void stop();
void empty_queue(); void empty_queue();
rlc_mode_t get_mode(); rlc_mode_t get_mode();
@ -92,9 +93,6 @@ private:
// Rx window // Rx window
std::map<uint32_t, rlc_umd_pdu_t> rx_window; std::map<uint32_t, rlc_umd_pdu_t> rx_window;
uint32_t rx_window_size;
uint32_t rx_mod; // Rx counter modulus
uint32_t tx_mod; // Tx counter modulus
// RX SDU buffers // RX SDU buffers
byte_buffer_t *rx_sdu; byte_buffer_t *rx_sdu;
@ -108,9 +106,7 @@ private:
* Ref: 3GPP TS 36.322 v10.0.0 Section 7 * Ref: 3GPP TS 36.322 v10.0.0 Section 7
***************************************************************************/ ***************************************************************************/
int32_t t_reordering; // Timer used by rx to detect PDU loss (ms) srslte_rlc_um_config_t cfg;
rlc_umd_sn_size_t tx_sn_field_length; // Number of bits used for tx (UL) sequence number
rlc_umd_sn_size_t rx_sn_field_length; // Number of bits used for rx (DL) sequence number
/**************************************************************************** /****************************************************************************
* State variables and counters * State variables and counters
@ -129,7 +125,8 @@ private:
* Timers * Timers
* Ref: 3GPP TS 36.322 v10.0.0 Section 7 * Ref: 3GPP TS 36.322 v10.0.0 Section 7
***************************************************************************/ ***************************************************************************/
uint32_t reordering_timeout_id; srslte::timers::timer *reordering_timer;
uint32_t reordering_timer_id;
bool pdu_lost; bool pdu_lost;

@ -40,6 +40,11 @@ log_filter::log_filter()
do_tti = false; do_tti = false;
} }
log_filter::log_filter(std::string layer)
{
init(layer, &def_logger_stdout, tti);
}
log_filter::log_filter(std::string layer, logger *logger_, bool tti) log_filter::log_filter(std::string layer, logger *logger_, bool tti)
{ {
init(layer, logger_, tti); init(layer, logger_, tti);

@ -1,290 +0,0 @@
/**
*
* \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 <iostream>
#include <sstream>
#include <iomanip>
#include <string>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <stdarg.h>
#include <string>
#include "srslte/common/log_stdout.h"
using namespace std;
namespace srslte {
void log_stdout::all_log(srslte::LOG_LEVEL_ENUM level,
uint32_t tti,
char *msg)
{
std::stringstream ss;
ss << now_time() << " ";
ss << "[" <<get_service_name() << "] ";
ss << log_level_text[level] << " ";
ss << "[" << std::setfill('0') << std::setw(5) << tti << "] ";
ss << msg;
cout << ss.str();
}
void log_stdout::all_log(srslte::LOG_LEVEL_ENUM level,
uint32_t tti,
char *msg,
uint8_t *hex,
int size)
{
std::stringstream ss;
ss << now_time() << " ";
ss << "[" <<get_service_name() << "] ";
ss << log_level_text[level] << " ";
ss << "[" << std::setfill('0') << std::setw(5) << tti << "] ";
ss << msg << std::endl;
ss << hex_string(hex, size);
cout << ss.str();
}
void log_stdout::all_log_line(srslte::LOG_LEVEL_ENUM level,
uint32_t tti,
std::string file,
int line,
char *msg)
{
std::stringstream ss;
ss << now_time() << " ";
ss << "[" <<get_service_name() << "] ";
ss << log_level_text[level] << " ";
ss << "[" << std::setfill('0') << std::setw(5) << tti << "] ";
ss << msg;
cout << ss.str();
}
void log_stdout::console(std::string message, ...) {
char *args_msg;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message.c_str(), args) > 0)
printf("%s",args_msg); // Print directly to stdout
va_end(args);
free(args_msg);
}
void log_stdout::error(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(LOG_LEVEL_ERROR, tti, args_msg);
va_end(args);
free(args_msg);
}
}
void log_stdout::warning(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(LOG_LEVEL_WARNING, tti, args_msg);
va_end(args);
free(args_msg);
}
}
void log_stdout::info(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(LOG_LEVEL_INFO, tti, args_msg);
va_end(args);
free(args_msg);
}
}
void log_stdout::debug(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(LOG_LEVEL_DEBUG, tti, args_msg);
va_end(args);
free(args_msg);
}
}
void log_stdout::error_hex(uint8_t *hex, int size, 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(LOG_LEVEL_ERROR, tti, args_msg, hex, size);
va_end(args);
free(args_msg);
}
}
void log_stdout::warning_hex(uint8_t *hex, int size, 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(LOG_LEVEL_WARNING, tti, args_msg, hex, size);
va_end(args);
free(args_msg);
}
}
void log_stdout::info_hex(uint8_t *hex, int size, 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(LOG_LEVEL_INFO, tti, args_msg, hex, size);
va_end(args);
free(args_msg);
}
}
void log_stdout::debug_hex(uint8_t *hex, int size, 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(LOG_LEVEL_DEBUG, tti, args_msg, hex, size);
va_end(args);
free(args_msg);
}
}
void log_stdout::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_stdout::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_stdout::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_stdout::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_stdout::now_time()
{
struct timeval rawtime;
struct tm * timeinfo;
char buffer[64];
char us[16];
gettimeofday(&rawtime, NULL);
timeinfo = localtime(&rawtime.tv_sec);
strftime(buffer,64,"%H:%M:%S",timeinfo);
strcat(buffer,".");
snprintf(us,16,"%ld",rawtime.tv_usec);
strcat(buffer,us);
return std::string(buffer);
}
std::string log_stdout::hex_string(uint8_t *hex, int size)
{
std::stringstream ss;
int c = 0;
ss << std::hex << std::setfill('0');
if(hex_limit >= 0) {
size = (size > hex_limit) ? hex_limit : size;
}
while(c < size) {
ss << " " << std::setw(4) << static_cast<unsigned>(c) << ": ";
int tmp = (size-c < 16) ? size-c : 16;
for(int i=0;i<tmp;i++) {
ss << std::setw(2) << static_cast<unsigned>(hex[c++]) << " ";
}
ss << "\n";
}
return ss.str();
}
}

@ -27,20 +27,20 @@
#define LOG_BUFFER_SIZE 1024*32 #define LOG_BUFFER_SIZE 1024*32
#include "srslte/common/logger.h" #include "srslte/common/logger_file.h"
using namespace std; using namespace std;
namespace srslte{ namespace srslte{
logger::logger() logger_file::logger_file()
:inited(false) :inited(false)
,not_done(true) ,not_done(true)
{} {}
logger::~logger() { logger_file::~logger_file() {
not_done = false; not_done = false;
log("Closing log"); log(new std::string("Closing log"));
if(inited) { if(inited) {
wait_thread_finish(); wait_thread_finish();
flush(); flush();
@ -48,7 +48,7 @@ logger::~logger() {
} }
} }
void logger::init(std::string file) { void logger_file::init(std::string file) {
pthread_mutex_init(&mutex, NULL); pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&not_empty, NULL); pthread_cond_init(&not_empty, NULL);
pthread_cond_init(&not_full, NULL); pthread_cond_init(&not_full, NULL);
@ -61,19 +61,18 @@ void logger::init(std::string file) {
inited = true; inited = true;
} }
void logger::log(const char *msg) { void logger_file::log(const char *msg) {
str_ptr s_ptr(new std::string(msg)); log(new std::string(msg));
log(s_ptr);
} }
void logger::log(str_ptr msg) { void logger_file::log(str_ptr msg) {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
buffer.push_back(msg); buffer.push_back(msg);
pthread_cond_signal(&not_empty); pthread_cond_signal(&not_empty);
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
} }
void logger::run_thread() { void logger_file::run_thread() {
while(not_done) { while(not_done) {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
while(buffer.empty()) { while(buffer.empty()) {
@ -89,7 +88,7 @@ void logger::run_thread() {
} }
} }
void logger::flush() { void logger_file::flush() {
std::deque<str_ptr>::iterator it; std::deque<str_ptr>::iterator it;
for(it=buffer.begin();it!=buffer.end();it++) for(it=buffer.begin();it!=buffer.end();it++)
{ {

@ -33,7 +33,7 @@
// Table 6.1.3.1-1 Buffer size levels for BSR // Table 6.1.3.1-1 Buffer size levels for BSR
static uint32_t btable[64] = { static uint32_t btable[64] = {
0, 5, 10, 12, 14, 17, 19, 22, 26, 31, 36, 42, 49, 57, 67, 78, 91, 107, 125, 146, 171, 200, 234, 274, 321, 376, 440, 515, 603, 706, 826, 967, 1132, 0, 1, 10, 12, 14, 17, 19, 22, 26, 31, 36, 42, 49, 57, 67, 78, 91, 107, 125, 146, 171, 200, 234, 274, 321, 376, 440, 515, 603, 706, 826, 967, 1132,
1326, 1552, 1817, 2127, 2490, 2915, 3413, 3995, 4667, 5476, 6411, 7505, 8787, 10287, 12043, 14099, 16507, 19325, 22624, 26487, 31009, 36304, 1326, 1552, 1817, 2127, 2490, 2915, 3413, 3995, 4667, 5476, 6411, 7505, 8787, 10287, 12043, 14099, 16507, 19325, 22624, 26487, 31009, 36304,
42502, 49759, 58255, 68201, 79846, 93479, 109439, 128125, 150000}; 42502, 49759, 58255, 68201, 79846, 93479, 109439, 128125, 150000};
@ -428,12 +428,16 @@ int sch_subh::get_bsr(uint32_t buff_size[4])
buff_size[2] = (payload[1]&0x0F) << 4 | (payload[1]&0xC0) >> 6; buff_size[2] = (payload[1]&0x0F) << 4 | (payload[1]&0xC0) >> 6;
buff_size[3] = (payload[2]&0x3F); buff_size[3] = (payload[2]&0x3F);
} else { } else {
uint32_t nonzero_lcg = (payload[0]&0xc0) >> 6; nonzero_lcg = (payload[0]&0xc0) >> 6;
buff_size[nonzero_lcg%4] = payload[0]&0x3f; buff_size[nonzero_lcg%4] = payload[0]&0x3f;
} }
for (int i=0;i<4;i++) { for (int i=0;i<4;i++) {
if (buff_size[i]) { if (buff_size[i]) {
buff_size[i] = btable[buff_size[i]%64]; if (buff_size[i]<63) {
buff_size[i] = btable[1+buff_size[i]];
} else {
buff_size[i] = btable[63];
}
} }
} }
return nonzero_lcg; return nonzero_lcg;
@ -515,8 +519,8 @@ bool sch_subh::set_bsr(uint32_t buff_size[4], sch_subh::cetype format)
bool sch_subh::set_c_rnti(uint16_t crnti) bool sch_subh::set_c_rnti(uint16_t crnti)
{ {
if (((sch_pdu*)parent)->has_space_ce(2)) { if (((sch_pdu*)parent)->has_space_ce(2)) {
w_payload_ce[0] = (uint8_t) (crnti&0xff00)>>8; w_payload_ce[0] = (uint8_t) ((crnti&0xff00)>>8);
w_payload_ce[1] = (uint8_t) (crnti&0x00ff); w_payload_ce[1] = (uint8_t) ((crnti&0x00ff));
lcid = CRNTI; lcid = CRNTI;
((sch_pdu*)parent)->update_space_ce(2); ((sch_pdu*)parent)->update_space_ce(2);
nof_bytes = 2; nof_bytes = 2;

@ -66,7 +66,7 @@ uint8_t* pdu_queue::request(uint32_t len)
void pdu_queue::deallocate(uint8_t* pdu) void pdu_queue::deallocate(uint8_t* pdu)
{ {
if (!pool.deallocate((pdu_t*) pdu)) { if (!pool.deallocate((pdu_t*) pdu)) {
log_h->warning("Error deallocating from buffer pool: buffer not created in this pool.\n"); log_h->warning("Error deallocating from buffer pool in deallocate(): buffer not created in this pool.\n");
} }
} }
@ -92,7 +92,7 @@ bool pdu_queue::process_pdus()
callback->process_pdu(pdu->ptr, pdu->len, pdu->tstamp); callback->process_pdu(pdu->ptr, pdu->len, pdu->tstamp);
} }
if (!pool.deallocate(pdu)) { if (!pool.deallocate(pdu)) {
log_h->warning("Error deallocating from buffer pool: buffer not created in this pool.\n"); log_h->warning("Error deallocating from buffer pool in process_pdus(): buffer not created in this pool.\n");
} }
cnt++; cnt++;
have_data = true; have_data = true;

@ -55,32 +55,7 @@ set(srslte_srcs $<TARGET_OBJECTS:srslte_agc>
) )
add_library(srslte_phy STATIC ${srslte_srcs}) add_library(srslte_phy STATIC ${srslte_srcs})
set_target_properties(srslte_phy PROPERTIES target_link_libraries(srslte_phy ${FFT_LIBRARIES})
VERSION ${SRSLTE_VERSION_MAJOR}.${SRSLTE_VERSION_MINOR})
find_package(MKL)
if(MKL_FOUND)
include_directories(${MKL_INCLUDE_DIRS})
link_directories(${MKL_LIBRARY_DIRS})
else(MKL_FOUND)
find_package(FFTW3F REQUIRED)
if(FFTW3F_FOUND)
include_directories(${FFTW3F_INCLUDE_DIRS})
link_directories(${FFTW3F_LIBRARY_DIRS})
endif(FFTW3F_FOUND)
endif(MKL_FOUND)
if(MKL_FOUND)
if(STATIC_MKL)
target_link_libraries(srslte_phy ${MKL_STATIC_LIBRARIES})
else(STATIC_MKL)
target_link_libraries(srslte_phy ${MKL_LIBRARIES})
endif(STATIC_MKL)
else(MKL_FOUND)
target_link_libraries(srslte_phy ${FFTW3F_LIBRARIES})
endif(MKL_FOUND)
if(VOLK_FOUND) if(VOLK_FOUND)
target_link_libraries(srslte_phy ${VOLK_LIBRARIES}) target_link_libraries(srslte_phy ${VOLK_LIBRARIES})

@ -32,6 +32,8 @@
#include <string.h> #include <string.h>
#include <complex.h> #include <complex.h>
#include <math.h> #include <math.h>
#include <srslte/phy/common/phy_common.h>
#include <srslte/srslte.h>
#include "srslte/config.h" #include "srslte/config.h"
@ -72,54 +74,70 @@ static void set_default_filter(srslte_chest_dl_t *q, int filter_len) {
* *
* This object depends on the srslte_refsignal_t object for creating the LTE CSR signal. * This object depends on the srslte_refsignal_t object for creating the LTE CSR signal.
*/ */
int srslte_chest_dl_init(srslte_chest_dl_t *q, uint32_t max_prb)
int srslte_chest_dl_init(srslte_chest_dl_t *q, srslte_cell_t cell)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && if (q != NULL)
srslte_cell_isvalid(&cell))
{ {
bzero(q, sizeof(srslte_chest_dl_t)); bzero(q, sizeof(srslte_chest_dl_t));
ret = srslte_refsignal_cs_init(&q->csr_signal, cell);
ret = srslte_refsignal_cs_init(&q->csr_refs, max_prb);
if (ret != SRSLTE_SUCCESS) { if (ret != SRSLTE_SUCCESS) {
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret); fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
goto clean_exit; goto clean_exit;
} }
q->tmp_noise = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb)); q->mbsfn_refs = calloc(SRSLTE_MAX_MBSFN_AREA_IDS, sizeof(srslte_refsignal_t*));
if (!q->mbsfn_refs) {
fprintf(stderr, "Calloc error initializing mbsfn_refs (%d)\n", ret);
goto clean_exit;
}
int pilot_vec_size;
if(SRSLTE_REFSIGNAL_MAX_NUM_SF_MBSFN(max_prb)>SRSLTE_REFSIGNAL_MAX_NUM_SF(max_prb)) {
pilot_vec_size = SRSLTE_REFSIGNAL_MAX_NUM_SF_MBSFN(max_prb);
}else{
pilot_vec_size = SRSLTE_REFSIGNAL_MAX_NUM_SF(max_prb);
}
q->tmp_noise = srslte_vec_malloc(sizeof(cf_t) * pilot_vec_size);
if (!q->tmp_noise) { if (!q->tmp_noise) {
perror("malloc"); perror("malloc");
goto clean_exit; goto clean_exit;
} }
q->pilot_estimates = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb)); q->pilot_estimates = srslte_vec_malloc(sizeof(cf_t) * pilot_vec_size);
if (!q->pilot_estimates) { if (!q->pilot_estimates) {
perror("malloc"); perror("malloc");
goto clean_exit; goto clean_exit;
} }
q->pilot_estimates_average = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb)); q->pilot_estimates_average = srslte_vec_malloc(sizeof(cf_t) * pilot_vec_size);
if (!q->pilot_estimates_average) { if (!q->pilot_estimates_average) {
perror("malloc"); perror("malloc");
goto clean_exit; goto clean_exit;
} }
q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb)); q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * pilot_vec_size);
if (!q->pilot_recv_signal) { if (!q->pilot_recv_signal) {
perror("malloc"); perror("malloc");
goto clean_exit; goto clean_exit;
} }
if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, SRSLTE_NRE*cell.nof_prb)) { if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, SRSLTE_NRE*max_prb)) {
fprintf(stderr, "Error initializing vector interpolator\n"); fprintf(stderr, "Error initializing vector interpolator\n");
goto clean_exit; goto clean_exit;
} }
if (srslte_interp_linear_init(&q->srslte_interp_lin, 2*cell.nof_prb, SRSLTE_NRE/2)) { if (srslte_interp_linear_init(&q->srslte_interp_lin, 2*max_prb, SRSLTE_NRE/2)) {
fprintf(stderr, "Error initializing interpolator\n"); fprintf(stderr, "Error initializing interpolator\n");
goto clean_exit; goto clean_exit;
} }
if (srslte_pss_generate(q->pss_signal, cell.id%3)) { if (srslte_interp_linear_init(&q->srslte_interp_lin_mbsfn, 6*max_prb, SRSLTE_NRE/6)) {
fprintf(stderr, "Error initializing PSS signal for noise estimation\n"); fprintf(stderr, "Error initializing interpolator\n");
goto clean_exit; goto clean_exit;
} }
@ -128,7 +146,6 @@ int srslte_chest_dl_init(srslte_chest_dl_t *q, srslte_cell_t cell)
q->smooth_filter_len = 3; q->smooth_filter_len = 3;
srslte_chest_dl_set_smooth_filter3_coeff(q, 0.1); srslte_chest_dl_set_smooth_filter3_coeff(q, 0.1);
q->cell = cell;
} }
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
@ -142,14 +159,25 @@ clean_exit:
void srslte_chest_dl_free(srslte_chest_dl_t *q) void srslte_chest_dl_free(srslte_chest_dl_t *q)
{ {
srslte_refsignal_cs_free(&q->csr_signal); int i;
if(&q->csr_refs)
srslte_refsignal_free(&q->csr_refs);
if (q->mbsfn_refs) {
for (i=0; i<SRSLTE_MAX_MBSFN_AREA_IDS; i++) {
if (q->mbsfn_refs[i]) {
srslte_refsignal_free(q->mbsfn_refs[i]);
}
}
free(q->mbsfn_refs);
}
if (q->tmp_noise) { if (q->tmp_noise) {
free(q->tmp_noise); free(q->tmp_noise);
} }
srslte_interp_linear_vector_free(&q->srslte_interp_linvec); 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);
srslte_interp_linear_free(&q->srslte_interp_lin_mbsfn);
if (q->pilot_estimates) { if (q->pilot_estimates) {
free(q->pilot_estimates); free(q->pilot_estimates);
} }
@ -162,10 +190,57 @@ void srslte_chest_dl_free(srslte_chest_dl_t *q)
bzero(q, sizeof(srslte_chest_dl_t)); bzero(q, sizeof(srslte_chest_dl_t));
} }
int srslte_chest_dl_set_mbsfn_area_id(srslte_chest_dl_t *q, uint16_t mbsfn_area_id){
if(!q->mbsfn_refs[mbsfn_area_id]){
q->mbsfn_refs[mbsfn_area_id] = calloc(1, sizeof(srslte_refsignal_t));
}
if(q->mbsfn_refs[mbsfn_area_id]) {
if(srslte_refsignal_mbsfn_init(q->mbsfn_refs[mbsfn_area_id], q->cell, mbsfn_area_id)) {
return SRSLTE_ERROR;
}
}
return SRSLTE_SUCCESS;
}
int srslte_chest_dl_set_cell(srslte_chest_dl_t *q, srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
{
if (q->cell.id != cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
ret = srslte_refsignal_cs_set_cell(&q->csr_refs, cell);
if (ret != SRSLTE_SUCCESS) {
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
return SRSLTE_ERROR;
}
if (srslte_pss_generate(q->pss_signal, cell.id%3)) {
fprintf(stderr, "Error initializing PSS signal for noise estimation\n");
return SRSLTE_ERROR;
}
if (srslte_interp_linear_vector_resize(&q->srslte_interp_linvec, SRSLTE_NRE*q->cell.nof_prb)) {
fprintf(stderr, "Error initializing vector interpolator\n");
return SRSLTE_ERROR;
}
if (srslte_interp_linear_resize(&q->srslte_interp_lin, 2*q->cell.nof_prb, SRSLTE_NRE/2)) {
fprintf(stderr, "Error initializing interpolator\n");
return SRSLTE_ERROR;
}
}
ret = SRSLTE_SUCCESS;
}
return ret;
}
/* Uses the difference between the averaged and non-averaged pilot estimates */ /* Uses the difference between the averaged and non-averaged pilot estimates */
static float estimate_noise_pilots(srslte_chest_dl_t *q, uint32_t port_id) static float estimate_noise_pilots(srslte_chest_dl_t *q, uint32_t port_id)
{ {
int nref=SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id); int nref=SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id);
/* Substract noisy pilot estimates */ /* Substract noisy pilot estimates */
srslte_vec_sub_ccc(q->pilot_estimates_average, q->pilot_estimates, q->tmp_noise, nref); srslte_vec_sub_ccc(q->pilot_estimates_average, q->pilot_estimates, q->tmp_noise, nref);
@ -223,21 +298,43 @@ static float estimate_noise_empty_sc(srslte_chest_dl_t *q, cf_t *input) {
#define cesymb(i) ce[SRSLTE_RE_IDX(q->cell.nof_prb,i,0)] #define cesymb(i) ce[SRSLTE_RE_IDX(q->cell.nof_prb,i,0)]
static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t *ce, uint32_t port_id) static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t *ce, uint32_t port_id, srslte_sf_t ch_mode)
{ {
/* interpolate the symbols with references in the freq domain */ /* interpolate the symbols with references in the freq domain */
uint32_t l; uint32_t l;
uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(port_id); uint32_t nsymbols = (ch_mode == SRSLTE_SF_MBSFN ) ? srslte_refsignal_mbsfn_nof_symbols() + 1 : srslte_refsignal_cs_nof_symbols(port_id);
uint32_t fidx_offset = 0;
/* Interpolate in the frequency domain */ /* Interpolate in the frequency domain */
for (l=0;l<nsymbols;l++) {
uint32_t fidx_offset = srslte_refsignal_cs_fidx(q->cell, l, port_id, 0); // we add one to nsymbols to allow for inclusion of the non-mbms references in the channel estimation
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);
srslte_interp_linear_offset(&q->srslte_interp_lin, &pilot_estimates[2*q->cell.nof_prb*l], srslte_interp_linear_offset(&q->srslte_interp_lin, &pilot_estimates[2*q->cell.nof_prb*l],
&ce[srslte_refsignal_cs_nsymbol(l,q->cell.cp, port_id) * q->cell.nof_prb * SRSLTE_NRE], &ce[srslte_refsignal_cs_nsymbol(l,q->cell.cp, port_id) * q->cell.nof_prb * SRSLTE_NRE],
fidx_offset, SRSLTE_NRE/2-fidx_offset); fidx_offset, SRSLTE_NRE/2-fidx_offset);
} else {
fidx_offset = srslte_refsignal_mbsfn_fidx(l - 1);
srslte_interp_linear_offset(&q->srslte_interp_lin_mbsfn, &pilot_estimates[(2*q->cell.nof_prb) + 6*q->cell.nof_prb*(l - 1)],
&ce[srslte_refsignal_mbsfn_nsymbol(l - 1) * q->cell.nof_prb * SRSLTE_NRE],
fidx_offset, SRSLTE_NRE/6-fidx_offset);
}
} else {
fidx_offset = srslte_refsignal_cs_fidx(q->cell, l, port_id, 0);
srslte_interp_linear_offset(&q->srslte_interp_lin, &pilot_estimates[2*q->cell.nof_prb*l],
&ce[srslte_refsignal_cs_nsymbol(l,q->cell.cp, port_id) * q->cell.nof_prb * SRSLTE_NRE],
fidx_offset, SRSLTE_NRE/2-fidx_offset);
}
} }
/* Now interpolate in the time domain between symbols */ /* Now interpolate in the time domain between symbols */
if (ch_mode == SRSLTE_SF_MBSFN) {
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(2), &cesymb(1), 2, 1);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(2), &cesymb(6), &cesymb(3), 4, 3);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(6), &cesymb(10), &cesymb(7), 4, 3);
srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(6), &cesymb(10), &cesymb(10), &cesymb(11), 4, 1);
} else {
if (SRSLTE_CP_ISNORM(q->cell.cp)) { if (SRSLTE_CP_ISNORM(q->cell.cp)) {
if (nsymbols == 4) { if (nsymbols == 4) {
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(4), &cesymb(1), 4, 3); srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(4), &cesymb(1), 4, 3);
@ -261,8 +358,10 @@ static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(7), &cesymb(8), 6, 4); srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(7), &cesymb(8), 6, 4);
} }
} }
}
} }
void srslte_chest_dl_set_smooth_filter(srslte_chest_dl_t *q, float *filter, uint32_t filter_len) { void srslte_chest_dl_set_smooth_filter(srslte_chest_dl_t *q, float *filter, uint32_t filter_len) {
if (filter_len < SRSLTE_CHEST_MAX_SMOOTH_FIL_LEN) { if (filter_len < SRSLTE_CHEST_MAX_SMOOTH_FIL_LEN) {
if (filter) { if (filter) {
@ -289,9 +388,9 @@ void srslte_chest_dl_set_smooth_filter3_coeff(srslte_chest_dl_t* q, float w)
q->smooth_filter[1] = 1-2*w; q->smooth_filter[1] = 1-2*w;
} }
static void average_pilots(srslte_chest_dl_t *q, cf_t *input, cf_t *output, uint32_t port_id) { static void average_pilots(srslte_chest_dl_t *q, cf_t *input, cf_t *output, uint32_t port_id, srslte_sf_t ch_mode) {
uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(port_id); 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 = 2*q->cell.nof_prb; uint32_t nref = (ch_mode == SRSLTE_SF_MBSFN)?6*q->cell.nof_prb:2*q->cell.nof_prb;
// Average in the frequency domain // Average in the frequency domain
for (int l=0;l<nsymbols;l++) { for (int l=0;l<nsymbols;l++) {
@ -311,22 +410,14 @@ float srslte_chest_dl_rssi(srslte_chest_dl_t *q, cf_t *input, uint32_t port_id)
return rssi/nsymbols; return rssi/nsymbols;
} }
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) 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){
{
/* Get references from the input signal */
srslte_refsignal_cs_get_sf(q->cell, port_id, input, q->pilot_recv_signal);
/* Use the known CSR signal to compute Least-squares estimates */
srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->csr_signal.pilots[port_id/2][sf_idx],
q->pilot_estimates, SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id));
if (ce != NULL) { if (ce != NULL) {
/* Smooth estimates (if applicable) and interpolate */ /* Smooth estimates (if applicable) and interpolate */
if (q->smooth_filter_len == 0 || (q->smooth_filter_len == 3 && q->smooth_filter[0] == 0)) { if (q->smooth_filter_len == 0 || (q->smooth_filter_len == 3 && q->smooth_filter[0] == 0)) {
interpolate_pilots(q, q->pilot_estimates, ce, port_id); interpolate_pilots(q, q->pilot_estimates, ce, port_id, ch_mode);
} else { } else {
average_pilots(q, q->pilot_estimates, q->pilot_estimates_average, port_id); average_pilots(q, q->pilot_estimates, q->pilot_estimates_average, port_id, ch_mode);
interpolate_pilots(q, q->pilot_estimates_average, ce, port_id); interpolate_pilots(q, q->pilot_estimates_average, ce, port_id, ch_mode);
} }
/* Estimate noise power */ /* Estimate noise power */
@ -341,7 +432,6 @@ int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, u
q->noise_estimate[rxant_id][port_id] = estimate_noise_empty_sc(q, input); q->noise_estimate[rxant_id][port_id] = estimate_noise_empty_sc(q, input);
} }
} }
} }
/* Compute RSRP for the channel estimates in this port */ /* Compute RSRP for the channel estimates in this port */
@ -350,10 +440,44 @@ int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, u
/* compute rssi only for port 0 */ /* compute rssi only for port 0 */
q->rssi[rxant_id][port_id] = srslte_chest_dl_rssi(q, input, port_id); q->rssi[rxant_id][port_id] = srslte_chest_dl_rssi(q, input, port_id);
} }
}
int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id, uint32_t rxant_id)
{
/* Get references from the input signal */
srslte_refsignal_cs_get_sf(q->cell, port_id, input, q->pilot_recv_signal);
/* Use the known CSR signal to compute Least-squares estimates */
srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->csr_refs.pilots[port_id/2][sf_idx],
q->pilot_estimates, SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id));
chest_interpolate_noise_est(q, input, ce, sf_idx, port_id, rxant_id, SRSLTE_SF_NORM);
return 0;
}
int srslte_chest_dl_estimate_port_mbsfn(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id, uint32_t rxant_id, uint16_t mbsfn_area_id)
{
/* Use the known CSR signal to compute Least-squares estimates */
srslte_refsignal_mbsfn_get_sf(q->cell, port_id, input, q->pilot_recv_signal);
// estimate for non-mbsfn section of subframe
srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->csr_refs.pilots[port_id/2][sf_idx],
q->pilot_estimates, (2*q->cell.nof_prb));
srslte_vec_prod_conj_ccc(q->pilot_recv_signal+(2*q->cell.nof_prb), q->mbsfn_refs[mbsfn_area_id]->pilots[port_id/2][sf_idx],
q->pilot_estimates+(2*q->cell.nof_prb), SRSLTE_REFSIGNAL_NUM_SF_MBSFN(q->cell.nof_prb, port_id)-(2*q->cell.nof_prb));
chest_interpolate_noise_est(q, input, ce, sf_idx, port_id, rxant_id, SRSLTE_SF_MBSFN);
return 0; 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) 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++) { for (uint32_t rxant_id=0;rxant_id<nof_rx_antennas;rxant_id++) {
@ -380,6 +504,21 @@ int srslte_chest_dl_estimate(srslte_chest_dl_t *q, cf_t *input, cf_t *ce[SRSLTE_
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
int srslte_chest_dl_estimate_multi_mbsfn(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, uint16_t mbsfn_area_id)
{
for (uint32_t rxant_id=0;rxant_id<nof_rx_antennas;rxant_id++) {
for (uint32_t port_id=0;port_id<q->cell.nof_ports;port_id++) {
if (srslte_chest_dl_estimate_port_mbsfn(q, input[rxant_id], ce[port_id][rxant_id], sf_idx, port_id, rxant_id, mbsfn_area_id)) {
return SRSLTE_ERROR;
}
}
}
q->last_nof_antennas = nof_rx_antennas;
return SRSLTE_SUCCESS;
}
float srslte_chest_dl_get_noise_estimate(srslte_chest_dl_t *q) { float srslte_chest_dl_get_noise_estimate(srslte_chest_dl_t *q) {
float n = 0; float n = 0;
for (int i=0;i<q->last_nof_antennas;i++) { for (int i=0;i<q->last_nof_antennas;i++) {
@ -417,12 +556,15 @@ float srslte_chest_dl_get_rsrq(srslte_chest_dl_t *q) {
} }
float srslte_chest_dl_get_rsrp(srslte_chest_dl_t *q) { float srslte_chest_dl_get_rsrp_port(srslte_chest_dl_t *q, uint32_t port) {
// Note: use only port 0 but average across antennas
float n = 0; float n = 0;
for (int i=0;i<q->last_nof_antennas;i++) { for (int i = 0; i < q->last_nof_antennas; i++) {
n += q->rsrp[i][0]; n += q->rsrp[i][port];
} }
return n/q->last_nof_antennas; return n / q->last_nof_antennas;
} }
float srslte_chest_dl_get_rsrp(srslte_chest_dl_t *q) {
// Note: use only port 0 but average across antennas
return srslte_chest_dl_get_rsrp_port(q, 0);
}

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

@ -75,17 +75,44 @@ uint32_t srslte_refsignal_cs_v(uint32_t port_id, uint32_t ref_symbol_idx)
uint32_t srslte_refsignal_cs_nof_symbols(uint32_t port_id) uint32_t srslte_refsignal_cs_nof_symbols(uint32_t port_id)
{ {
uint32_t ret;
if (port_id < 2) { if (port_id < 2) {
return 4; ret = 4;
} else { } else {
return 2; ret = 2;
}
return ret;
}
uint32_t srslte_refsignal_mbsfn_nof_symbols()
{
if(false){
return 3;
}else{
return 3;
} }
} }
inline uint32_t srslte_refsignal_cs_fidx(srslte_cell_t cell, uint32_t l, uint32_t port_id, uint32_t m) { inline uint32_t srslte_refsignal_cs_fidx(srslte_cell_t cell, uint32_t l, uint32_t port_id, uint32_t m) {
return 6*m + ((srslte_refsignal_cs_v(port_id, l) + (cell.id % 6)) % 6); return 6*m + ((srslte_refsignal_cs_v(port_id, l) + (cell.id % 6)) % 6);
} }
inline uint32_t srslte_refsignal_mbsfn_fidx(uint32_t l)
{
uint32_t ret = 0;
if(l == 0){
ret = 0;
}else if (l == 1){
ret = 1;
}else if(l == 2){
ret = 0;
}
return ret;
}
inline uint32_t srslte_refsignal_cs_nsymbol(uint32_t l, srslte_cp_t cp, uint32_t port_id) { inline uint32_t srslte_refsignal_cs_nsymbol(uint32_t l, srslte_cp_t cp, uint32_t port_id) {
if (port_id < 2) { if (port_id < 2) {
if (l % 2) { if (l % 2) {
@ -97,12 +124,134 @@ inline uint32_t srslte_refsignal_cs_nsymbol(uint32_t l, srslte_cp_t cp, uint32_t
return 1+l*SRSLTE_CP_NSYMB(cp); return 1+l*SRSLTE_CP_NSYMB(cp);
} }
} }
inline uint32_t srslte_refsignal_mbsfn_nsymbol(uint32_t l)
{
uint32_t ret = 0;
if(l == 0){
ret = 2;
} else if (l == 1) {
ret = 6;
} else if (l == 2){
ret = 10;
}
return ret;
}
int srslte_refsignal_mbsfn_gen_seq(srslte_refsignal_t * q, srslte_cell_t cell, uint32_t N_mbsfn_id)
{
uint32_t c_init;
uint32_t i, ns, l, p;
uint32_t mp;
int ret = SRSLTE_ERROR;
srslte_sequence_t seq_mbsfn;
bzero(&seq_mbsfn, sizeof(srslte_sequence_t));
if (srslte_sequence_init(&seq_mbsfn, 20* SRSLTE_MAX_PRB)) {
goto free_and_exit;
}
for(ns=0; ns<SRSLTE_NSUBFRAMES_X_FRAME;ns++){
for(p=0;p<2;p++) {
uint32_t nsymbols = 3; // replace with function
for(l=0;l<nsymbols;l++) {
uint32_t lp = (srslte_refsignal_mbsfn_nsymbol(l))%6;
uint32_t slot =(l)?(ns*2+1):(ns*2);
c_init = 512*(7*(slot+1)+lp+1)*(2*N_mbsfn_id + 1) + N_mbsfn_id;
srslte_sequence_set_LTE_pr(&seq_mbsfn,SRSLTE_MAX_PRB*20 ,c_init);
for(i=0;i< 6*q->cell.nof_prb;i++) {
mp = i + 3*(SRSLTE_MAX_PRB - cell.nof_prb);
q->pilots[p][ns][ SRSLTE_REFSIGNAL_PILOT_IDX_MBSFN(i, l ,q->cell)] = (1 - 2 * (float) seq_mbsfn.c[2 * mp]) / sqrt(2) +_Complex_I * (1 - 2 * (float) seq_mbsfn.c[2 * mp + 1]) / sqrt(2);
}
}
}
}
srslte_sequence_free(&seq_mbsfn);
ret = SRSLTE_SUCCESS;
free_and_exit:
if (ret == SRSLTE_ERROR) {
srslte_sequence_free(&seq_mbsfn);
srslte_refsignal_free(q);
}
return ret;
}
int srslte_refsignal_mbsfn_init(srslte_refsignal_t * q, srslte_cell_t cell, uint16_t mbsfn_area_id)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
uint32_t i, p;
if (q != NULL &&
srslte_cell_isvalid(&cell))
{
ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_refsignal_t));
q->cell = cell;
q->type = SRSLTE_SF_MBSFN;
q->mbsfn_area_id = mbsfn_area_id;
for (p=0;p<2;p++) {
for (i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
q->pilots[p][i] = srslte_vec_malloc(sizeof(cf_t) * q->cell.nof_prb * 18);
if (!q->pilots[p][i]) {
perror("malloc");
goto free_and_exit;
}
}
}
if(srslte_refsignal_mbsfn_gen_seq(q, q->cell, q->mbsfn_area_id)) {
goto free_and_exit;
}
ret = SRSLTE_SUCCESS;
}
free_and_exit:
if (ret == SRSLTE_ERROR) {
srslte_refsignal_free(q);
}
return ret;
}
/** Allocates memory for the 20 slots in a subframe
*/
int srslte_refsignal_cs_init(srslte_refsignal_t * q, uint32_t max_prb)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL)
{
ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_refsignal_t));
for (int p=0;p<2;p++) {
for (int i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
q->pilots[p][i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_NUM_SF(max_prb, 2*p));
if (!q->pilots[p][i]) {
perror("malloc");
goto free_and_exit;
}
}
}
ret = SRSLTE_SUCCESS;
}
free_and_exit:
if (ret == SRSLTE_ERROR) {
srslte_refsignal_free(q);
}
return ret;
}
/** Allocates and precomputes the Cell-Specific Reference (CSR) signal for /** Allocates and precomputes the Cell-Specific Reference (CSR) signal for
* the 20 slots in a subframe * the 20 slots in a subframe
*/ */
int srslte_refsignal_cs_init(srslte_refsignal_cs_t * q, srslte_cell_t cell) int srslte_refsignal_cs_set_cell(srslte_refsignal_t * q, srslte_cell_t cell)
{ {
uint32_t c_init; uint32_t c_init;
@ -114,12 +263,12 @@ int srslte_refsignal_cs_init(srslte_refsignal_cs_t * q, srslte_cell_t cell)
if (q != NULL && if (q != NULL &&
srslte_cell_isvalid(&cell)) srslte_cell_isvalid(&cell))
{ {
ret = SRSLTE_ERROR; if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
bzero(q, sizeof(srslte_refsignal_cs_t));
bzero(&seq, sizeof(srslte_sequence_t)); bzero(&seq, sizeof(srslte_sequence_t));
if (srslte_sequence_init(&seq, 2 * 2 * SRSLTE_MAX_PRB)) { if (srslte_sequence_init(&seq, 2*2*SRSLTE_MAX_PRB)) {
goto free_and_exit; return SRSLTE_ERROR;
} }
if (SRSLTE_CP_ISNORM(cell.cp)) { if (SRSLTE_CP_ISNORM(cell.cp)) {
@ -128,18 +277,6 @@ int srslte_refsignal_cs_init(srslte_refsignal_cs_t * q, srslte_cell_t cell)
N_cp = 0; N_cp = 0;
} }
q->cell = cell;
for (p=0;p<2;p++) {
for (i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
q->pilots[p][i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, 2*p));
if (!q->pilots[p][i]) {
perror("malloc");
goto free_and_exit;
}
}
}
for (ns=0;ns<SRSLTE_NSLOTS_X_FRAME;ns++) { for (ns=0;ns<SRSLTE_NSLOTS_X_FRAME;ns++) {
for (p=0;p<2;p++) { for (p=0;p<2;p++) {
uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(2*p)/2; uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(2*p)/2;
@ -150,7 +287,7 @@ int srslte_refsignal_cs_init(srslte_refsignal_cs_t * q, srslte_cell_t cell)
+ 2 * cell.id + N_cp; + 2 * cell.id + N_cp;
/* generate sequence for this symbol and slot */ /* generate sequence for this symbol and slot */
srslte_sequence_set_LTE_pr(&seq, c_init); srslte_sequence_set_LTE_pr(&seq, 2*2*SRSLTE_MAX_PRB, c_init);
/* Compute signal */ /* Compute signal */
for (i = 0; i < 2*q->cell.nof_prb; i++) { for (i = 0; i < 2*q->cell.nof_prb; i++) {
@ -161,36 +298,31 @@ int srslte_refsignal_cs_init(srslte_refsignal_cs_t * q, srslte_cell_t cell)
_Complex_I * (1 - 2 * (float) seq.c[2 * mp + 1]) / sqrt(2); _Complex_I * (1 - 2 * (float) seq.c[2 * mp + 1]) / sqrt(2);
} }
} }
} }
} }
srslte_sequence_free(&seq); srslte_sequence_free(&seq);
ret = SRSLTE_SUCCESS;
} }
free_and_exit: ret = SRSLTE_SUCCESS;
if (ret == SRSLTE_ERROR) {
srslte_sequence_free(&seq);
srslte_refsignal_cs_free(q);
} }
return ret; return ret;
} }
/** Deallocates a srslte_refsignal_cs_t object allocated with srslte_refsignal_cs_init */ /** Deallocates a srslte_refsignal_cs_t object allocated with srslte_refsignal_cs_init */
void srslte_refsignal_cs_free(srslte_refsignal_cs_t * q) void srslte_refsignal_free(srslte_refsignal_t * q)
{ {
int i, p; for (int p=0;p<2;p++) {
for (int i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
for (p=0;p<2;p++) {
for (i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
if (q->pilots[p][i]) { if (q->pilots[p][i]) {
free(q->pilots[p][i]); free(q->pilots[p][i]);
} }
} }
} }
bzero(q, sizeof(srslte_refsignal_cs_t)); bzero(q, sizeof(srslte_refsignal_t));
} }
/* Maps a reference signal initialized with srslte_refsignal_cs_init() into an array of subframe symbols */ /* Maps a reference signal initialized with srslte_refsignal_cs_init() into an array of subframe symbols */
int srslte_refsignal_cs_put_sf(srslte_cell_t cell, uint32_t port_id, cf_t *pilots, cf_t *sf_symbols) int srslte_refsignal_cs_put_sf(srslte_cell_t cell, uint32_t port_id, cf_t *pilots, cf_t *sf_symbols)
{ {
@ -218,6 +350,45 @@ int srslte_refsignal_cs_put_sf(srslte_cell_t cell, uint32_t port_id, cf_t *pilot
} }
} }
SRSLTE_API int srslte_refsignal_mbsfn_put_sf(srslte_cell_t cell,
uint32_t port_id,
cf_t *cs_pilots,
cf_t *mbsfn_pilots,
cf_t *sf_symbols)
{
uint32_t i, l;
uint32_t fidx;
if (srslte_cell_isvalid(&cell) &&
srslte_portid_isvalid(port_id) &&
cs_pilots != NULL &&
mbsfn_pilots != NULL &&
sf_symbols != NULL)
{
// adding CS refs for the non-mbsfn section of the sub-frame
fidx = ((srslte_refsignal_cs_v(port_id, 0) + (cell.id % 6)) % 6);
for (i = 0; i < 2*cell.nof_prb; i++) {
sf_symbols[SRSLTE_RE_IDX(cell.nof_prb, 0, fidx)] = cs_pilots[SRSLTE_REFSIGNAL_PILOT_IDX(i,0,cell)];
fidx += SRSLTE_NRE/2; // 1 reference every 6 RE
}
for (l = 0; l<srslte_refsignal_mbsfn_nof_symbols(); l++) {
uint32_t nsymbol = srslte_refsignal_mbsfn_nsymbol(l);
fidx = srslte_refsignal_mbsfn_fidx(l);
for (i = 0; i < 6*cell.nof_prb; i++) {
sf_symbols[SRSLTE_RE_IDX(cell.nof_prb, nsymbol, fidx)] = mbsfn_pilots[SRSLTE_REFSIGNAL_PILOT_IDX_MBSFN(i,l,cell)];
fidx += SRSLTE_NRE/6;
}
}
return SRSLTE_SUCCESS;
} else {
return SRSLTE_ERROR_INVALID_INPUTS;
}
}
/** Copies the RE containing references from an array of subframe symbols to the pilots array. */ /** Copies the RE containing references from an array of subframe symbols to the pilots array. */
int srslte_refsignal_cs_get_sf(srslte_cell_t cell, uint32_t port_id, cf_t *sf_symbols, cf_t *pilots) int srslte_refsignal_cs_get_sf(srslte_cell_t cell, uint32_t port_id, cf_t *sf_symbols, cf_t *pilots)
{ {
@ -244,4 +415,39 @@ int srslte_refsignal_cs_get_sf(srslte_cell_t cell, uint32_t port_id, cf_t *sf_sy
} }
} }
int srslte_refsignal_mbsfn_get_sf(srslte_cell_t cell, uint32_t port_id, cf_t *sf_symbols, cf_t *pilots)
{
uint32_t i, l;
uint32_t fidx;
uint32_t nsymbol;
if (srslte_cell_isvalid(&cell) &&
srslte_portid_isvalid(port_id) &&
pilots != NULL &&
sf_symbols != NULL)
{
// getting refs from non mbsfn section of subframe
nsymbol = srslte_refsignal_cs_nsymbol(0, cell.cp, port_id);
fidx = ((srslte_refsignal_cs_v(port_id, 0) + (cell.id % 6)) % 6);
for (i = 0; i < 2*cell.nof_prb; i++) {
pilots[SRSLTE_REFSIGNAL_PILOT_IDX(i,0,cell)] = sf_symbols[SRSLTE_RE_IDX(cell.nof_prb, nsymbol, fidx)];
fidx += SRSLTE_NRE/2; // 2 references per PRB
}
for (l = 0; l< srslte_refsignal_mbsfn_nof_symbols() ;l++){
nsymbol = srslte_refsignal_mbsfn_nsymbol(l);
fidx = srslte_refsignal_mbsfn_fidx(l);
for (i = 0; i < 6*cell.nof_prb; i++) {
pilots[SRSLTE_REFSIGNAL_PILOT_IDX_MBSFN(i,l,cell) + (2*cell.nof_prb)] = sf_symbols[SRSLTE_RE_IDX(cell.nof_prb, nsymbol, fidx)];
fidx += SRSLTE_NRE/6;
}
}
return SRSLTE_SUCCESS;
} else {
return SRSLTE_ERROR_INVALID_INPUTS;
}
}

@ -29,6 +29,7 @@
#include <strings.h> #include <strings.h>
#include <stdlib.h> #include <stdlib.h>
#include <complex.h> #include <complex.h>
#include <srslte/phy/common/phy_common.h>
#include "srslte/phy/common/phy_common.h" #include "srslte/phy/common/phy_common.h"
#include "srslte/phy/ch_estimation/refsignal_ul.h" #include "srslte/phy/ch_estimation/refsignal_ul.h"
@ -138,8 +139,8 @@ static int generate_n_prs(srslte_refsignal_ul_t * q) {
} }
q->n_prs_pusch[delta_ss][ns] = n_prs; q->n_prs_pusch[delta_ss][ns] = n_prs;
} }
srslte_sequence_free(&seq);
} }
srslte_sequence_free(&seq);
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
@ -160,9 +161,9 @@ static int generate_srslte_sequence_hopping_v(srslte_refsignal_ul_t *q) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
q->v_pusch[ns][delta_ss] = seq.c[ns]; q->v_pusch[ns][delta_ss] = seq.c[ns];
srslte_sequence_free(&seq);
} }
} }
srslte_sequence_free(&seq);
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
@ -170,62 +171,79 @@ static int generate_srslte_sequence_hopping_v(srslte_refsignal_ul_t *q) {
/** Initializes srslte_refsignal_ul_t object according to 3GPP 36.211 5.5 /** Initializes srslte_refsignal_ul_t object according to 3GPP 36.211 5.5
* *
*/ */
int srslte_refsignal_ul_init(srslte_refsignal_ul_t * q, srslte_cell_t cell) int srslte_refsignal_ul_init(srslte_refsignal_ul_t * q, uint32_t max_prb)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && srslte_cell_isvalid(&cell)) { if (q != NULL) {
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_refsignal_ul_t)); bzero(q, sizeof(srslte_refsignal_ul_t));
q->cell = cell;
// Allocate temporal buffer for computing signal argument // Allocate temporal buffer for computing signal argument
q->tmp_arg = srslte_vec_malloc(SRSLTE_NRE * q->cell.nof_prb * sizeof(cf_t)); q->tmp_arg = srslte_vec_malloc(SRSLTE_NRE * max_prb * sizeof(cf_t));
if (!q->tmp_arg) { if (!q->tmp_arg) {
perror("malloc"); perror("malloc");
goto free_and_exit; goto free_and_exit;
} }
ret = SRSLTE_SUCCESS;
}
free_and_exit:
if (ret == SRSLTE_ERROR) {
srslte_refsignal_ul_free(q);
}
return ret;
}
void srslte_refsignal_ul_free(srslte_refsignal_ul_t * q) {
if (q->tmp_arg) {
free(q->tmp_arg);
}
bzero(q, sizeof(srslte_refsignal_ul_t));
}
/** Initializes srslte_refsignal_ul_t object according to 3GPP 36.211 5.5
*
*/
int srslte_refsignal_ul_set_cell(srslte_refsignal_ul_t * q, srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && srslte_cell_isvalid(&cell)) {
if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
srslte_pucch_cfg_default(&q->pucch_cfg); srslte_pucch_cfg_default(&q->pucch_cfg);
// Precompute n_prs // Precompute n_prs
if (generate_n_prs(q)) { if (generate_n_prs(q)) {
goto free_and_exit; return SRSLTE_ERROR;
} }
// Precompute group hopping values u. // Precompute group hopping values u.
if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) { if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) {
goto free_and_exit; return SRSLTE_ERROR;
} }
// Precompute sequence hopping values v. Uses f_ss_pusch // Precompute sequence hopping values v. Uses f_ss_pusch
if (generate_srslte_sequence_hopping_v(q)) { if (generate_srslte_sequence_hopping_v(q)) {
goto free_and_exit; return SRSLTE_ERROR;
} }
if (srslte_pucch_n_cs_cell(q->cell, q->n_cs_cell)) { if (srslte_pucch_n_cs_cell(q->cell, q->n_cs_cell)) {
goto free_and_exit; return SRSLTE_ERROR;
} }
ret = SRSLTE_SUCCESS;
} }
free_and_exit: ret = SRSLTE_SUCCESS;
if (ret == SRSLTE_ERROR) {
srslte_refsignal_ul_free(q);
} }
return ret; return ret;
} }
void srslte_refsignal_ul_free(srslte_refsignal_ul_t * q) {
if (q->tmp_arg) {
free(q->tmp_arg);
}
bzero(q, sizeof(srslte_refsignal_ul_t));
}
void srslte_refsignal_ul_set_cfg(srslte_refsignal_ul_t *q, void srslte_refsignal_ul_set_cfg(srslte_refsignal_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg, srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
srslte_pucch_cfg_t *pucch_cfg, srslte_pucch_cfg_t *pucch_cfg,
@ -363,15 +381,38 @@ void compute_r(srslte_refsignal_ul_t *q, uint32_t nof_prb, uint32_t ns, uint32_t
} }
int srslte_refsignal_dmrs_pusch_pregen_init(srslte_refsignal_ul_t *q, srslte_refsignal_ul_dmrs_pregen_t *pregen,
uint32_t max_prb)
{
for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) {
for (uint32_t cs=0;cs<SRSLTE_NOF_CSHIFT;cs++) {
pregen->r[cs][sf_idx] = (cf_t**) calloc(sizeof(cf_t*), max_prb + 1);
if (pregen->r[cs][sf_idx]) {
for (uint32_t n=0;n<=max_prb;n++) {
if (srslte_dft_precoding_valid_prb(n)) {
pregen->r[cs][sf_idx][n] = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*n*2*SRSLTE_NRE);
if (pregen->r[cs][sf_idx][n]) {
} else {
return SRSLTE_ERROR;
}
}
}
} else {
return SRSLTE_ERROR;
}
}
}
return SRSLTE_SUCCESS;
}
int srslte_refsignal_dmrs_pusch_pregen(srslte_refsignal_ul_t *q, srslte_refsignal_ul_dmrs_pregen_t *pregen) int srslte_refsignal_dmrs_pusch_pregen(srslte_refsignal_ul_t *q, srslte_refsignal_ul_dmrs_pregen_t *pregen)
{ {
for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) { for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) {
for (uint32_t cs=0;cs<SRSLTE_NOF_CSHIFT;cs++) { for (uint32_t cs=0;cs<SRSLTE_NOF_CSHIFT;cs++) {
pregen->r[cs][sf_idx] = (cf_t**) calloc(sizeof(cf_t*), q->cell.nof_prb + 1);
if (pregen->r[cs][sf_idx]) { if (pregen->r[cs][sf_idx]) {
for (uint32_t n=0;n<=q->cell.nof_prb;n++) { for (uint32_t n=0;n<=q->cell.nof_prb;n++) {
if (srslte_dft_precoding_valid_prb(n)) { if (srslte_dft_precoding_valid_prb(n)) {
pregen->r[cs][sf_idx][n] = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*n*2*SRSLTE_NRE);
if (pregen->r[cs][sf_idx][n]) { if (pregen->r[cs][sf_idx][n]) {
if (srslte_refsignal_dmrs_pusch_gen(q, n, sf_idx, cs, pregen->r[cs][sf_idx][n])) { if (srslte_refsignal_dmrs_pusch_gen(q, n, sf_idx, cs, pregen->r[cs][sf_idx][n])) {
return SRSLTE_ERROR; return SRSLTE_ERROR;

@ -52,4 +52,3 @@ add_test(chest_test_ul_cellid1 chest_test_ul -c 2 -r 50)

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

Loading…
Cancel
Save