Merge branch 'next'

master
Andre Puschmann 7 years ago
commit 4bbcfaa1dc

@ -42,6 +42,8 @@ include(SRSLTEPackage) #setup cpack
include(CTest)
set(CTEST_MEMORYCHECK_COMMAND valgrind)
set(CTEST_MEMORYCHECK_COMMAND_OPTIONS "--trace-children=yes --leak-check=full" )
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/CTestCustom.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake"
@ -66,7 +68,7 @@ option(ENABLE_BLADERF "Enable BladeRF" ON)
option(BUILD_STATIC "Attempt to statically link external deps" OFF)
option(RPATH "Enable RPATH" OFF)
option(USE_LTE_RATES "Use standard LTE sampling rates" OFF)
option(USE_LTE_RATES "Use standard LTE sampling rates" OFF)
set(GCC_ARCH native CACHE STRING "GCC compile for specific architecture.")
@ -74,28 +76,62 @@ set(GCC_ARCH native CACHE STRING "GCC compile for specific architecture.")
########################################################################
# Find dependencies
########################################################################
# Threads
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)
if (POLARSSL_FOUND)
set(SEC_INCLUDE_DIRS "${POLARSSL_INCLUDE_DIRS}")
set(SEC_LIBRARIES "${POLARSSL_LIBRARIES}")
if(BUILD_STATIC)
set(SEC_LIBRARIES "${POLARSSL_STATIC_LIBRARIES}")
else(BUILD_STATIC)
set(SEC_LIBRARIES "${POLARSSL_LIBRARIES}")
endif(BUILD_STATIC)
add_definitions(-DHAVE_POLARSSL)
else(POLARSSL_FOUND)
find_package(MbedTLS REQUIRED)
if (MBEDTLS_FOUND)
set(SEC_INCLUDE_DIRS "${MBEDTLS_INCLUDE_DIRS}")
set(SEC_LIBRARIES "${MBEDTLS_LIBRARIES}")
if(BUILD_STATIC)
set(SEC_LIBRARIES "${MBEDTLS_STATIC_LIBRARIES}")
else(BUILD_STATIC)
set(SEC_LIBRARIES "${MBEDTLS_LIBRARIES}")
endif(BUILD_STATIC)
add_definitions(-DHAVE_MBEDTLS)
else(MBEDTLS_FOUND)
message(FATAL_ERROR "Either PolarSSL or mbedTLS are required to build srsLTE")
endif (MBEDTLS_FOUND)
endif(POLARSSL_FOUND)
# UHD
find_package(UHD)
if(UHD_FOUND)
include_directories(${UHD_INCLUDE_DIRS})
link_directories(${UHD_LIBRARY_DIRS})
endif(UHD_FOUND)
# BladeRF
if(ENABLE_BLADERF)
find_package(bladeRF)
if(BLADERF_FOUND)
@ -104,6 +140,7 @@ if(ENABLE_BLADERF)
endif(BLADERF_FOUND)
endif(ENABLE_BLADERF)
# Soapy
find_package(SoapySDR)
if(SOAPYSDR_FOUND)
include_directories(${SOAPYSDR_INCLUDE_DIRS})
@ -117,8 +154,12 @@ else(BLADERF_FOUND OR UHD_FOUND OR SOAPYSDR_FOUND)
add_definitions(-DDISABLE_RF)
endif(BLADERF_FOUND OR UHD_FOUND OR SOAPYSDR_FOUND)
# Boost
if(ENABLE_SRSUE OR ENABLE_SRSENB)
# Find Boost
if(BUILD_STATIC)
set(Boost_USE_STATIC_LIBS ON)
endif(BUILD_STATIC)
set(BOOST_REQUIRED_COMPONENTS
program_options
system
@ -138,7 +179,7 @@ if(ENABLE_SRSUE OR ENABLE_SRSENB)
find_package(Boost "1.35" COMPONENTS ${BOOST_REQUIRED_COMPONENTS})
endif(ENABLE_SRSUE OR ENABLE_SRSENB)
# srsGUI
if(ENABLE_GUI)
find_package(SRSGUI)
if(SRSGUI_FOUND)
@ -148,6 +189,7 @@ if(ENABLE_GUI)
endif(SRSGUI_FOUND)
endif(ENABLE_GUI)
# VOLK
include(CheckFunctionExistsMath)
if(ENABLE_VOLK)
find_package(Volk)
@ -162,7 +204,6 @@ else(ENABLE_VOLK)
message(STATUS "VOLK library disabled")
endif(ENABLE_VOLK)
########################################################################
# Install Dirs
########################################################################

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

@ -15,11 +15,12 @@ srsLTE is released under the AGPLv3 license and uses software from the OpenLTE p
Common Features
---------------
* LTE Release 8 compliant
* LTE Release 8 compliant (with selected features of Release 9)
* FDD configuration
* Tested bandwidths: 1.4, 3, 5, 10, 15 and 20 MHz
* Transmission mode 1 (single antenna) 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
* Evolved multimedia broadcast and multicast service (eMBMS)
* 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
* 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
* Soft USIM supporting Milenage and XOR authentication
* 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.
* 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 X300
* bladeRF
* limeSDR
* limeSDR (currently, only the PHY-layer examples, i.e., pdsch_enodeb/ue are supported)
Build Instructions
------------------
* Mandatory requirements:
* Common:
* cmake https://cmake.org/
* libfftw http://www.fftw.org/
* PolarSSL/mbedTLS https://tls.mbed.org
* srsUE:
@ -83,7 +86,7 @@ Build Instructions
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.

@ -15,6 +15,12 @@ find_path(FFTW3F_INCLUDE_DIR
PATHS /usr/local/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
NAMES fftw3f libfftw3f libfftw3f-3
HINTS ${PC_FFTW3F_LIBDIR} ${PC_FFTW3F_LIBRARY_DIRS} $ENV{FFTW3_DIR}/lib
@ -22,12 +28,17 @@ find_library(FFTW3F_LIBRARY
/usr/lib)
set(FFTW3F_LIBRARIES ${FFTW3F_LIBRARY} )
set(FFTW3F_STATIC_LIBRARIES ${FFTW3F_STATIC_LIBRARY} )
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)
# handle the QUIETLY and REQUIRED arguments and set FFTW3F_FOUND to TRUE
# if all listed variables are TRUE
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
)
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 STATIC LIBRARIES: " ${MBEDTLS_STATIC_LIBRARIES})
message(STATUS "MBEDTLS INCLUDE DIRS: " ${MBEDTLS_INCLUDE_DIRS})
INCLUDE(FindPackageHandleStandardArgs)
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
)
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 STATIC LIBRARIES: " ${POLARSSL_STATIC_LIBRARIES})
message(STATUS "POLARSSL INCLUDE DIRS: " ${POLARSSL_INCLUDE_DIRS})
INCLUDE(FindPackageHandleStandardArgs)
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_AVX "Enable compile-time AVX support." ON)
option(ENABLE_AVX2 "Enable compile-time AVX2 support." ON)
option(ENABLE_FMA "Enable compile-time FMA support." ON)
if (ENABLE_SSE)
#
@ -97,8 +98,43 @@ if (ENABLE_SSE)
if (HAVE_AVX2)
message(STATUS "AVX2 is enabled - target CPU must support it")
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()
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
PATHS /usr/local/lib
/usr/lib
/usr/lib/x86_64-linux-gnu
/usr/local/lib64
/usr/local/lib32
)

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

@ -118,7 +118,7 @@ int parse_args(prog_args_t *args, int argc, char **argv) {
/**********************************************************************/
/* TODO: Do something with the output data */
uint8_t data[1000000];
uint8_t *data[SRSLTE_MAX_CODEWORDS];
bool go_exit = false;
void sig_int_handler(int signo)
@ -160,7 +160,8 @@ int main(int argc, char **argv) {
int sfn_offset;
float rssi_utra=0,rssi=0, rsrp=0, rsrq=0, snr=0;
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)) {
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));
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
data[i] = srslte_vec_malloc(sizeof(uint8_t) * 1500*8);
}
sigset_t sigset;
sigemptyset(&sigset);
@ -237,19 +241,31 @@ int main(int argc, char **argv) {
srslte_rf_stop_rx_stream(&rf);
srslte_rf_flush_buffer(&rf);
if (srslte_ue_sync_init_multi(&ue_sync, cell, srslte_rf_recv_wrapper, 1, (void*) &rf)) {
if (srslte_ue_sync_init_multi(&ue_sync, cell.nof_prb, cell.id==1000, srslte_rf_recv_wrapper, 1, (void*) &rf)) {
fprintf(stderr, "Error initiating ue_sync\n");
return -1;
}
if (srslte_ue_dl_init_multi(&ue_dl, cell, 1)) {
if (srslte_ue_sync_set_cell(&ue_sync, cell)) {
fprintf(stderr, "Error initiating ue_sync\n");
return -1;
}
if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, 1)) {
fprintf(stderr, "Error initiating UE downlink processing module\n");
return -1;
}
if (srslte_ue_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)) {
if (srslte_ue_mib_init(&ue_mib, cell.nof_prb)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
return -1;
}
if (srslte_ue_mib_set_cell(&ue_mib, cell)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
return -1;
}
/* Configure downlink receiver for the SI-RNTI since will be the only one we'll use */
srslte_ue_dl_set_rnti(&ue_dl, SRSLTE_SIRNTI);
@ -260,11 +276,15 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error initiating FFT\n");
return -1;
}
if (srslte_chest_dl_init(&chest, cell)) {
if (srslte_chest_dl_init(&chest, cell.nof_prb)) {
fprintf(stderr, "Error initiating channel estimator\n");
return -1;
}
if (srslte_chest_dl_set_cell(&chest, cell)) {
fprintf(stderr, "Error initiating channel estimator\n");
return -1;
}
int sf_re = SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);
cf_t *sf_symbols = srslte_vec_malloc(sf_re * sizeof(cf_t));
@ -310,19 +330,18 @@ int main(int argc, char **argv) {
case DECODE_SIB:
/* We are looking for SI Blocks, search only in appropiate places */
if ((srslte_ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%2)==0)) {
n = srslte_ue_dl_decode_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) {
fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);
return -1;
} 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_sch_average_noi(&ue_dl.pdsch.dl_sch),
(float) ue_dl.nof_detected/nof_trials);
(float) ue_dl.nof_detected/nof_trials);
nof_trials++;
} else {
printf("Decoded SIB1. Payload: ");
srslte_vec_fprint_byte(stdout, data, n/8);;
srslte_vec_fprint_byte(stdout, data[0], n/8);;
state = MEASURE;
}
}
@ -386,6 +405,12 @@ int main(int argc, char **argv) {
sf_cnt++;
} // Main loop
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (data[i]) {
free(data[i]);
}
}
srslte_ue_sync_free(&ue_sync);
srslte_rf_close(&rf);
printf("\nBye\n");

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

@ -33,15 +33,18 @@
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <srslte/phy/common/phy_common.h>
#include <srslte/phy/phch/pdsch_cfg.h>
#include "srslte/srslte.h"
#define UE_CRNTI 0x1234
#define M_CRNTI 0xFFFD
#ifndef DISABLE_RF
#include "srslte/phy/rf/rf.h"
#include "srslte/phy/common/phy_common.h"
srslte_rf_t rf;
#else
#warning Compiling pdsch_ue with no RF support
@ -55,36 +58,51 @@ char *output_file_name = NULL;
#define DOWN_KEY 66
srslte_cell_t cell = {
25, // nof_prb
1, // nof_ports
0, // cell_id
SRSLTE_CP_NORM, // cyclic prefix
SRSLTE_PHICH_R_1, // PHICH resources
SRSLTE_PHICH_NORM // PHICH length
25, // nof_prb
1, // nof_ports
0, // cell_id
SRSLTE_CP_NORM, // cyclic prefix
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
uint32_t cfi=3;
uint32_t cfi = 2;
uint32_t mcs_idx = 1, last_mcs_idx = 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 = "";
float rf_amp = 0.8, rf_gain = 70.0, rf_freq = 2400000000;
bool null_file_sink=false;
srslte_filesink_t fsink;
srslte_ofdm_t ifft;
srslte_ofdm_t ifft_mbsfn;
srslte_pbch_t pbch;
srslte_pcfich_t pcfich;
srslte_pdcch_t pdcch;
srslte_pdsch_t pdsch;
srslte_pdsch_cfg_t pdsch_cfg;
srslte_softbuffer_tx_t softbuffer;
srslte_pdsch_cfg_t pdsch_cfg;
srslte_pmch_t pmch;
srslte_pdsch_cfg_t pmch_cfg;
srslte_softbuffer_tx_t *softbuffers[SRSLTE_MAX_CODEWORDS];
srslte_regs_t regs;
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;
pthread_t net_thread;
@ -94,12 +112,20 @@ bool net_packet_ready = false;
srslte_netsource_t net_source;
srslte_netsink_t net_sink;
int prbset_num = 1, last_prbset_num = 1;
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) {
printf("Usage: %s [agmfoncvpu]\n", prog);
printf("Usage: %s [agmfoncvpuxb]\n", prog);
#ifndef DISABLE_RF
printf("\t-a RF args [Default %s]\n", rf_args);
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-c cell id [Default %d]\n", cell.id);
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-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) {
int opt;
while ((opt = getopt(argc, argv, "aglfmoncpvu")) != -1) {
while ((opt = getopt(argc, argv, "aglfmoncpvutxbwM")) != -1) {
switch (opt) {
case 'a':
rf_args = argv[optind];
@ -151,6 +184,18 @@ void parse_args(int argc, char **argv) {
case 'c':
cell.id = atoi(argv[optind]);
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':
srslte_verbose++;
break;
@ -166,20 +211,64 @@ void parse_args(int argc, char **argv) {
}
#endif
}
void base_init() {
/* init memory */
sf_buffer = srslte_vec_malloc(sizeof(cf_t) * sf_n_re);
if (!sf_buffer) {
perror("malloc");
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);
}
output_buffer = srslte_vec_malloc(sizeof(cf_t) * sf_n_samples);
if (!output_buffer) {
perror("malloc");
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 */
for (i = 0; i < SRSLTE_MAX_PORTS; i++) {
sf_buffer[i] = srslte_vec_malloc(sizeof(cf_t) * sf_n_re);
if (!sf_buffer[i]) {
perror("malloc");
exit(-1);
}
}
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");
exit(-1);
}
bzero(output_buffer[i], sizeof(cf_t) * sf_n_samples);
}
/* open file or USRP */
if (output_file_name) {
if (strcmp(output_file_name, "NULL")) {
@ -194,7 +283,7 @@ void base_init() {
} else {
#ifndef DISABLE_RF
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");
exit(-1);
}
@ -226,18 +315,36 @@ void base_init() {
fprintf(stderr, "Error creating iFFT object\n");
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);
if (srslte_pbch_init(&pbch, cell)) {
if (srslte_pbch_init(&pbch)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
if (srslte_pbch_set_cell(&pbch, cell)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
if (srslte_regs_init(&regs, cell)) {
fprintf(stderr, "Error initiating regs\n");
exit(-1);
}
if (srslte_pcfich_init(&pcfich, &regs, cell)) {
if (srslte_pcfich_init(&pcfich, 1)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
if (srslte_pcfich_set_cell(&pcfich, &regs, cell)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
@ -247,39 +354,82 @@ void base_init() {
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");
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");
exit(-1);
}
srslte_pdsch_set_rnti(&pdsch, UE_CRNTI);
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);
}
if (srslte_softbuffer_tx_init(&softbuffer, cell.nof_prb)) {
fprintf(stderr, "Error initiating soft buffer\n");
exit(-1);
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");
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_pdcch_free(&pdcch);
srslte_regs_free(&regs);
srslte_pbch_free(&pbch);
if(mbsfn_area_id > -1){
srslte_pmch_free(&pmch);
}
srslte_ofdm_tx_free(&ifft_mbsfn);
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]);
}
}
if (output_buffer) {
free(output_buffer);
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_file_name) {
if (!null_file_sink) {
@ -332,15 +482,45 @@ uint32_t prbset_to_bitmask() {
}
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));
ra_dl.harq_process = 0;
ra_dl.mcs_idx = mcs_idx;
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.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_dl_grant_t dummy_grant;
@ -348,8 +528,21 @@ int update_radl() {
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_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;
}
@ -390,8 +583,47 @@ int update_control() {
break;
}
} else {
last_mcs_idx = mcs_idx;
mcs_idx = atoi(input);
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;
mcs_idx = atoi(input);
}
}
bzero(input,sizeof(input));
if (update_radl()) {
@ -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 */
void *net_thread_fnc(void *arg) {
@ -423,14 +652,16 @@ void *net_thread_fnc(void *arg) {
do {
n = srslte_netsource_read(&net_source, &data2[rpm], DATA_BUFF_SZ-rpm);
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;
INFO("received %d bytes. rpm=%d/%d\n",n,rpm,nbytes);
wpm = 0;
while (rpm >= nbytes) {
// wait for packet to be transmitted
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);
rpm -= nbytes;
wpm += nbytes;
@ -450,6 +681,7 @@ void *net_thread_fnc(void *arg) {
return NULL;
}
int main(int argc, char **argv) {
int nf=0, sf_idx=0, N_id_2=0;
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_location_t locations[SRSLTE_NSUBFRAMES_X_FRAME][30];
uint32_t sfn;
srslte_chest_dl_t est;
srslte_refsignal_t csr_refs;
srslte_refsignal_t mbsfn_refs;
#ifdef DISABLE_RF
if (argc < 3) {
@ -491,17 +724,31 @@ int main(int argc, char **argv) {
srslte_pss_generate(pss_signal, N_id_2);
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");
exit(-1);
}
for (i = 0; i < SRSLTE_MAX_PORTS; i++) { // now there's only 1 port
sf_symbols[i] = sf_buffer;
slot1_symbols[i] = &sf_buffer[SRSLTE_SLOT_LEN_RE(cell.nof_prb, cell.cp)];
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++) {
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
@ -550,36 +797,51 @@ int main(int argc, char **argv) {
/* Initiate valid DCI locations */
for (i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
srslte_pdcch_ue_locations(&pdcch, locations[i], 30, i, cfi, UE_CRNTI);
}
nf = 0;
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
bool start_of_burst = true;
#endif
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++) {
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) {
srslte_pss_put_slot(pss_signal, sf_buffer, cell.nof_prb, SRSLTE_CP_NORM);
srslte_sss_put_slot(sf_idx ? sss_signal5 : sss_signal0, sf_buffer, cell.nof_prb,
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_symbols[0], cell.nof_prb,
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);
if (sf_idx == 0) {
srslte_pbch_encode(&pbch, bch_payload, slot1_symbols, nf%4);
}
srslte_pcfich_encode(&pcfich, cfi, sf_symbols, sf_idx);
srslte_pcfich_encode(&pcfich, cfi, sf_symbols, sf_idx);
/* Update DL resource allocation from control port */
if (update_control(sf_idx)) {
@ -593,9 +855,13 @@ int main(int argc, char **argv) {
INFO("Transmitting packet\n",0);
}
} else {
INFO("SF: %d, Generating %d random bits\n", sf_idx, pdsch_cfg.grant.mcs.tbs);
for (i=0;i<pdsch_cfg.grant.mcs.tbs/8;i++) {
data[i] = rand()%256;
INFO("SF: %d, Generating %d random bits\n", sf_idx, pdsch_cfg.grant.mcs[0].tbs + pdsch_cfg.grant.mcs[1].tbs);
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
if (pdsch_cfg.grant.tb_en[tb]) {
for (i = 0; i < pdsch_cfg.grant.mcs[tb].tbs / 8; i++) {
data[tb][i] = (uint8_t) rand();
}
}
}
/* Uncomment this to transmit on sf 0 and 5 only */
if (sf_idx != 0 && sf_idx != 5) {
@ -603,59 +869,134 @@ int main(int argc, char **argv) {
} else {
send_data = false;
}
}
}
if (send_data) {
/* 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], UE_CRNTI, sf_symbols, sf_idx, cfi)) {
fprintf(stderr, "Error encoding DCI message\n");
exit(-1);
}
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 */
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, 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)) {
fprintf(stderr, "Error encoding DCI message\n");
exit(-1);
}
/* Configure pdsch_cfg parameters */
srslte_ra_dl_grant_t 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)) {
fprintf(stderr, "Error configuring PDSCH\n");
exit(-1);
}
/* Encode PDSCH */
if (srslte_pdsch_encode(&pdsch, &pdsch_cfg, &softbuffer, data, UE_CRNTI, sf_symbols)) {
fprintf(stderr, "Error encoding PDSCH\n");
exit(-1);
}
if (net_port > 0 && net_packet_ready) {
if (null_file_sink) {
srslte_bit_pack_vector(data, data_tmp, pdsch_cfg.grant.mcs.tbs);
if (srslte_netsink_write(&net_sink, data_tmp, 1+(pdsch_cfg.grant.mcs.tbs-1)/8) < 0) {
fprintf(stderr, "Error sending data through UDP socket\n");
}
/* Configure pdsch_cfg parameters */
srslte_ra_dl_grant_t grant;
srslte_ra_dl_dci_to_grant(&ra_dl, cell.nof_prb, UE_CRNTI, &grant);
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");
exit(-1);
}
/* Encode PDSCH */
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");
exit(-1);
}
if (net_port > 0 && net_packet_ready) {
if (null_file_sink) {
srslte_bit_pack_vector(data[0], data_tmp, pmch_cfg.grant.mcs[0].tbs);
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");
}
}
net_packet_ready = false;
sem_post(&net_sem);
}
net_packet_ready = false;
sem_post(&net_sem);
}
}
/* 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 */
if (output_file_name) {
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);
} else {
#ifndef DISABLE_RF
// FIXME
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));
srslte_rf_send2(&rf, output_buffer, sf_n_samples, true, start_of_burst, false);
start_of_burst=false;
float norm_factor = (float) cell.nof_prb/15/sqrtf(pdsch_cfg.grant.nof_prb);
for (i = 0; i < cell.nof_ports; i++) {
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;
#endif
}
}

@ -36,7 +36,8 @@
#include <signal.h>
#include <pthread.h>
#include <semaphore.h>
#include <srslte/phy/common/phy_common.h>
#include "srslte/phy/io/filesink.h"
#include "srslte/srslte.h"
#define ENABLE_AGC_DEFAULT
@ -66,7 +67,7 @@ sem_t plot_sem;
uint32_t plot_sf_idx=0;
bool plot_track = true;
#endif
char *output_file_name;
#define PRINT_CHANGE_SCHEDULIGN
//#define CORRECT_SAMPLE_OFFSET
@ -98,6 +99,9 @@ typedef struct {
int net_port_signal;
char *net_address_signal;
int decimate;
int32_t mbsfn_area_id;
uint8_t non_mbsfn_region;
int verbose;
}prog_args_t;
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->decimate = 0;
args->cpu_affinity = -1;
args->mbsfn_area_id = -1;
args->non_mbsfn_region = 2;
}
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
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);
@ -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-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-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");
}
void parse_args(prog_args_t *args, int argc, char **argv) {
int opt;
args_default(args);
while ((opt = getopt(argc, argv, "aAoglipPcOCtdDnvrfuUsSZy")) != -1) {
while ((opt = getopt(argc, argv, "aAoglipPcOCtdDnvrfuUsSZyWMN")) != -1) {
switch (opt) {
case 'i':
args->input_file_name = argv[optind];
@ -238,6 +246,7 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
break;
case 'v':
srslte_verbose++;
args->verbose = srslte_verbose;
break;
case 'Z':
args->decimate = atoi(argv[optind]);
@ -245,6 +254,15 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
case 'y':
args->cpu_affinity = atoi(argv[optind]);
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:
usage(args, argv[0]);
exit(-1);
@ -258,7 +276,7 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
/**********************************************************************/
/* TODO: Do something with the output data */
uint8_t data[20000];
uint8_t *data[SRSLTE_MAX_CODEWORDS];
bool go_exit = false;
void sig_int_handler(int signo)
@ -266,10 +284,13 @@ void sig_int_handler(int signo)
printf("SIGINT received. Exiting...\n");
if (signo == SIGINT) {
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
int srslte_rf_recv_wrapper(void *h, cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *t) {
@ -296,7 +317,13 @@ srslte_ue_sync_t ue_sync;
prog_args_t prog_args;
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 ret;
@ -304,17 +331,26 @@ int main(int argc, char **argv) {
srslte_cell_t cell;
int64_t sf_cnt;
srslte_ue_mib_t ue_mib;
#ifndef DISABLE_RF
srslte_rf_t rf;
#endif
uint32_t nof_trials = 0;
int n;
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
int sfn_offset;
float cfo = 0;
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) {
cpu_set_t cpuset;
@ -379,10 +415,11 @@ int main(int argc, char **argv) {
srslte_rf_set_master_clock_rate(&rf, 30.72e6);
/* set receiver frequency */
printf("Tunning receiver to %.3f MHz\n", prog_args.rf_freq/1000000);
srslte_rf_set_rx_freq(&rf, prog_args.rf_freq);
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 + prog_args.file_offset_freq);
srslte_rf_rx_wait_lo_locked(&rf);
uint32_t ntrial=0;
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);
@ -435,8 +472,8 @@ int main(int argc, char **argv) {
cell.nof_ports = prog_args.file_nof_ports;
cell.nof_prb = prog_args.file_nof_prb;
if (srslte_ue_sync_init_file(&ue_sync, prog_args.file_nof_prb,
prog_args.input_file_name, prog_args.file_offset_time, prog_args.file_offset_freq)) {
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.rf_nof_rx_ant)) {
fprintf(stderr, "Error initiating ue_sync\n");
exit(-1);
}
@ -455,23 +492,42 @@ int main(int argc, char **argv) {
//ue_sync.decimate = prog_args.decimate;
}
}
if (srslte_ue_sync_init_multi_decim(&ue_sync, cell, srslte_rf_recv_wrapper, prog_args.rf_nof_rx_ant, (void*) &rf,decimate)) {
if (srslte_ue_sync_init_multi_decim(&ue_sync,
cell.nof_prb,
cell.id==1000,
srslte_rf_recv_wrapper,
prog_args.rf_nof_rx_ant,
(void*) &rf,decimate))
{
fprintf(stderr, "Error initiating ue_sync\n");
exit(-1);
}
if (srslte_ue_sync_set_cell(&ue_sync, cell))
{
fprintf(stderr, "Error initiating ue_sync\n");
exit(-1);
}
#endif
}
if (srslte_ue_mib_init(&ue_mib, cell)) {
if (srslte_ue_mib_init(&ue_mib, cell.nof_prb)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
exit(-1);
}
}
if (srslte_ue_mib_set_cell(&ue_mib, cell)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
exit(-1);
}
if (srslte_ue_dl_init_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");
exit(-1);
}
for (int i=0;i<prog_args.rf_nof_rx_ant;i++) {
sf_buffer[i] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
}
@ -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 */
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 */
sf_cnt = 0;
@ -498,9 +559,15 @@ int main(int argc, char **argv) {
// Variables for measurements
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;
for (int i = 0; i < SRSLTE_MAX_LAYERS; i++) {
bzero(sinr[i], sizeof(float)*SRSLTE_MAX_CODEBOOKS);
}
#ifndef DISABLE_RF
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);
@ -521,7 +588,32 @@ int main(int argc, char **argv) {
INFO("\nEntering main loop...\n\n", 0);
/* Main loop */
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);
if (ret < 0) {
fprintf(stderr, "Error calling srslte_ue_sync_work()\n");
@ -534,9 +626,12 @@ int main(int argc, char **argv) {
/* srslte_ue_sync_get_buffer returns 1 if successfully read 1 aligned subframe */
if (ret == 1) {
uint32_t sfidx = srslte_ue_sync_get_sfidx(&ue_sync);
switch (state) {
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);
if (n < 0) {
fprintf(stderr, "Error decoding UE MIB\n");
@ -555,28 +650,64 @@ int main(int argc, char **argv) {
decode_pdsch = true;
} else {
/* 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;
} else {
decode_pdsch = false;
}
}
if (decode_pdsch) {
INFO("Attempting DL decode SFN=%d\n", sfn);
n = srslte_ue_dl_decode_multi(&ue_dl,
sf_buffer,
data,
if (decode_pdsch) {
if(sfidx != 1 || prog_args.mbsfn_area_id < 0){ // Not an MBSFN subframe
if (cell.nof_ports == 1) {
/* Transmission mode 1 */
n = srslte_ue_dl_decode(&ue_dl, sf_buffer, data, 0, sfn*10+srslte_ue_sync_get_sfidx(&ue_sync), acks);
} 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,
data[0],
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) {
// fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);
} else if (n > 0) {
/* Send data if socket active */
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
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)) ||
@ -595,9 +726,15 @@ int main(int argc, char **argv) {
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);
noise = SRSLTE_VEC_EMA(srslte_chest_dl_get_noise_estimate(&ue_dl.chest), noise, 0.05);
rsrq = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrq(&ue_dl.chest), rsrq, 0.1f);
rsrp0 = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp_port(&ue_dl.chest, 0), rsrp0, 0.05f);
rsrp1 = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp_port(&ue_dl.chest, 1), rsrp1, 0.05f);
noise = SRSLTE_VEC_EMA(srslte_chest_dl_get_noise_estimate(&ue_dl.chest), noise, 0.05f);
enodebrate = SRSLTE_VEC_EMA((ue_dl.pdsch_cfg.grant.mcs[0].tbs + ue_dl.pdsch_cfg.grant.mcs[1].tbs)/1000.0f, enodebrate, 0.05f);
uerate = SRSLTE_VEC_EMA(((acks[0]?ue_dl.pdsch_cfg.grant.mcs[0].tbs:0) + (acks[1]?ue_dl.pdsch_cfg.grant.mcs[1].tbs:0))/1000.0f, uerate, 0.01f);
nframes++;
if (isnan(rsrq)) {
rsrq = 0;
@ -605,43 +742,104 @@ int main(int argc, char **argv) {
if (isnan(noise)) {
noise = 0;
}
if (isnan(rsrp)) {
rsrp = 0;
}
if (isnan(rsrp0)) {
rsrp0 = 0;
}
if (isnan(rsrp1)) {
rsrp1 = 0;
}
}
// Plot and Printf
if (srslte_ue_sync_get_sfidx(&ue_sync) == 5) {
if (sfidx == 5) {
float gain = prog_args.rf_gain;
if (gain < 0) {
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,
10*log10(rsrp/noise),
100*(1-(float) ue_dl.nof_detected/nof_trials),
(float) 100*ue_dl.pkt_errors/ue_dl.pkts_total);
/* Print transmission scheme */
if (ue_dl.pdsch_cfg.mimo_type == SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX) {
PRINT_LINE(" Tx scheme: %s (codebook_idx=%d)", srslte_mimotype2str(ue_dl.pdsch_cfg.mimo_type),
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;
}
if (srslte_ue_sync_get_sfidx(&ue_sync) == 9) {
if (sfidx == 9) {
sfn++;
if (sfn == 1024) {
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.pkts_total = 0;
ue_dl.pkts_total = 0;
ue_dl.nof_detected = 0;
nof_trials = 0;
nof_trials = 0;
*/
}
}
#ifndef DISABLE_GRAPHICS
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_track = true;
sem_post(&plot_sem);
@ -674,13 +872,24 @@ int main(int argc, char **argv) {
#endif
srslte_ue_dl_free(&ue_dl);
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
if (!prog_args.input_file_name) {
srslte_ue_mib_free(&ue_mib);
srslte_rf_close(&rf);
}
#endif
printf("\nBye\n");
exit(0);
}
@ -742,7 +951,7 @@ void *plot_thread_run(void *arg) {
while(1) {
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) {
for (i = 0; i < nof_re; 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, ue_dl.pdsch.d, nof_symbols);
plot_scatter_setNewData(&pscatequal, ue_dl.pdsch.d[0], nof_symbols);
if (plot_sf_idx == 1) {
if (prog_args.net_port_signal > 0) {

@ -44,6 +44,7 @@ char *output_file_name;
char *rf_args="";
float rf_gain=40.0, rf_freq=-1.0, rf_rate=0.96e6;
int nof_samples = -1;
int nof_rx_antennas = 1;
void int_handler(int dummy) {
keep_running = false;
@ -55,12 +56,13 @@ void usage(char *prog) {
printf("\t-g RF Gain [Default %.2f dB]\n", rf_gain);
printf("\t-r RF Rate [Default %.6f Hz]\n", rf_rate);
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");
}
void parse_args(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "agrnvfo")) != -1) {
while ((opt = getopt(argc, argv, "agrnvfoA")) != -1) {
switch (opt) {
case 'o':
output_file_name = argv[optind];
@ -80,6 +82,9 @@ void parse_args(int argc, char **argv) {
case 'n':
nof_samples = atoi(argv[optind]);
break;
case 'A':
nof_rx_antennas = atoi(argv[optind]);
break;
case 'v':
srslte_verbose++;
break;
@ -95,11 +100,11 @@ void parse_args(int argc, char **argv) {
}
int main(int argc, char **argv) {
cf_t *buffer;
cf_t *buffer[SRSLTE_MAX_PORTS];
int sample_count, n;
srslte_rf_t rf;
srslte_filesink_t sink;
int32_t buflen;
uint32_t buflen;
signal(SIGINT, int_handler);
@ -107,17 +112,19 @@ int main(int argc, char **argv) {
buflen = 4800;
sample_count = 0;
buffer = malloc(sizeof(cf_t) * buflen);
if (!buffer) {
perror("malloc");
exit(-1);
for (int i = 0; i < nof_rx_antennas; i++) {
buffer[i] = malloc(sizeof(cf_t) * buflen);
if (!buffer[i]) {
perror("malloc");
exit(-1);
}
}
srslte_filesink_init(&sink, output_file_name, SRSLTE_COMPLEX_FLOAT_BIN);
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");
exit(-1);
}
@ -151,18 +158,23 @@ int main(int argc, char **argv) {
while((sample_count < nof_samples || nof_samples == -1)
&& 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) {
fprintf(stderr, "Error receiving samples\n");
exit(-1);
}
srslte_filesink_write(&sink, buffer, buflen);
srslte_filesink_write_multi(&sink, (void**) buffer, buflen, nof_rx_antennas);
sample_count += buflen;
}
for (int i = 0; i < nof_rx_antennas; i++) {
if (buffer[i]) {
free(buffer[i]);
}
}
srslte_filesink_free(&sink);
free(buffer);
srslte_rf_close(&rf);
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_subframes = -1;
int N_id_2 = -1;
uint32_t nof_rx_antennas = 1;
void int_handler(int dummy) {
keep_running = false;
@ -56,12 +57,13 @@ void usage(char *prog) {
printf("\t-g RF Gain [Default %.2f dB]\n", rf_gain);
printf("\t-p nof_prb [Default %d]\n", nof_prb);
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");
}
void parse_args(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "agpnvfol")) != -1) {
while ((opt = getopt(argc, argv, "agpnvfolA")) != -1) {
switch (opt) {
case 'o':
output_file_name = argv[optind];
@ -84,6 +86,9 @@ void parse_args(int argc, char **argv) {
case 'l':
N_id_2 = atoi(argv[optind]);
break;
case 'A':
nof_rx_antennas = (uint32_t) atoi(argv[optind]);
break;
case 'v':
srslte_verbose++;
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) {
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) {
@ -118,13 +123,15 @@ int main(int argc, char **argv) {
srslte_filesink_init(&sink, output_file_name, SRSLTE_COMPLEX_FLOAT_BIN);
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");
exit(-1);
}
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;
sigemptyset(&sigset);
@ -158,11 +165,15 @@ int main(int argc, char **argv) {
cell.nof_prb = nof_prb;
cell.nof_ports = 1;
if (srslte_ue_sync_init_multi(&ue_sync, cell, srslte_rf_recv_wrapper, 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");
exit(-1);
}
uint32_t subframe_count = 0;
bool start_capture = false;
bool stop_capture = false;
@ -181,7 +192,7 @@ int main(int argc, char **argv) {
}
} else {
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++;
}
}
@ -196,6 +207,12 @@ int main(int argc, char **argv) {
srslte_rf_close(&rf);
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);
exit(0);
}

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

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

@ -50,7 +50,7 @@
#define SRSLTE_MAX_BUFFER_SIZE_BYTES 12756
#define SRSLTE_BUFFER_HEADER_OFFSET 1024
#define SRSLTE_BUFFER_POOL_LOG_ENABLED
//#define SRSLTE_BUFFER_POOL_LOG_ENABLED
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
#define pool_allocate (pool->allocate(__FUNCTION__))
@ -83,32 +83,6 @@ static const char error_text[ERROR_N_ITEMS][20] = { "None",
"Can't start",
"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
*

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

@ -38,15 +38,19 @@
#include <stdarg.h>
#include <string>
#include "srslte/common/log.h"
#include "logger.h"
#include "srslte/common/logger.h"
#include "srslte/common/logger_stdout.h"
namespace srslte {
typedef std::string* str_ptr;
class log_filter : public srslte::log
{
public:
log_filter();
log_filter(std::string layer);
log_filter(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;
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, uint8_t *hex, int size);
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
* 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.
* Description: Interface for logging output
*****************************************************************************/
#ifndef LOGGER_H
#define LOGGER_H
#include <stdio.h>
#include <deque>
#include <string>
#include "srslte/common/threads.h"
namespace srslte {
typedef std::string* str_ptr;
class logger : public thread
class logger
{
public:
logger();
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;
virtual void log(std::string *msg) = 0;
};
} // namespace srsue
} // namespace srslte
#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
{
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>
@ -34,9 +34,11 @@ public:
bool init(metrics_interface<metrics_t> *m_, float report_period_secs=1.0) {
m = m_;
start_periodic(report_period_secs*1e6);
return true;
}
void stop() {
thread_cancel();
wait_thread_finish();
}
void add_listener(metrics_listener<metrics_t> *listener) {
@ -45,9 +47,10 @@ public:
private:
void run_period() {
metrics_t metric;
metrics_t metric;
bzero(&metric, sizeof(metrics_t));
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);
}
}

@ -74,7 +74,7 @@ public:
}
void step() {
if (running) {
counter++;
counter++;
if (is_expired()) {
running = false;
if (callback) {
@ -97,11 +97,13 @@ public:
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_;
next_timer = 0;
nof_used_timers = 0;
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;
}
}
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() {
if (next_timer == nof_timers){
printf("No more unique timer ids (Only %d timers available)\n", nof_timers);
next_timer = 0;
if (nof_used_timers >= nof_timers) {
fprintf(stderr, "Error getting unique timer id: no more timers available\n");
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:
uint32_t nof_timers;
uint32_t next_timer;
std::vector<timer> timer_list;
uint32_t nof_used_timers;
uint32_t nof_timers;
std::vector<timer> timer_list;
std::vector<bool> used_timers;
};
} // namespace srslte

@ -28,7 +28,9 @@
#include "srslte/common/common.h"
#include "srslte/common/security.h"
#include "srslte/common/interfaces_common.h"
#include "srslte/interfaces/sched_interface.h"
#include "srslte/upper/rlc_interface.h"
#include "srslte/asn1/liblte_rrc.h"
#include "srslte/asn1/liblte_s1ap.h"
@ -156,7 +158,7 @@ public:
virtual void add_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, 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
@ -174,7 +176,7 @@ public:
virtual void add_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 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,
uint32_t lcid,
uint8_t *k_rrc_enc_,
@ -242,7 +244,7 @@ public:
class gtpu_interface_rrc
{
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_user(uint16_t rnti) = 0;
};

@ -32,7 +32,7 @@
#include "upper/common_enb.h"
#include "upper/s1ap_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 "mac/mac_metrics.h"
#include "phy/phy_metrics.h"

@ -94,7 +94,8 @@ public:
typedef struct {
int priority;
int bsd;
int pbr;
int pbr;
int group;
enum {IDLE = 0, UL, DL, BOTH} direction;
} ue_bearer_cfg_t;
@ -231,7 +232,7 @@ public:
/* UL information */
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_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_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;

@ -39,6 +39,7 @@
#include "srslte/common/interfaces_common.h"
#include "srslte/common/common.h"
#include "srslte/common/security.h"
#include "srslte/upper/rlc_interface.h"
namespace srsue {
@ -97,18 +98,40 @@ class nas_interface_rrc
{
public:
virtual bool is_attached() = 0;
virtual bool is_attaching() = 0;
virtual void notify_connection_setup() = 0;
virtual void write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu) = 0;
virtual uint32_t get_ul_count() = 0;
virtual bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) = 0;
virtual void plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) = 0;
};
// NAS interface for UE
class nas_interface_ue
{
public:
virtual void attach_request() = 0;
virtual void deattach_request() = 0;
};
// NAS interface for UE
class nas_interface_gw
{
public:
virtual void attach_request() = 0;
};
// RRC interface for MAC
class rrc_interface_mac
class rrc_interface_mac_common
{
public:
virtual void ra_problem() = 0;
};
class rrc_interface_mac : public rrc_interface_mac_common
{
public:
virtual void release_pucch_srs() = 0;
virtual void ra_problem() = 0;
};
// RRC interface for PHY
@ -117,6 +140,7 @@ class rrc_interface_phy
public:
virtual void in_sync() = 0;
virtual void out_of_sync() = 0;
virtual void cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) = 0;
};
// RRC interface for NAS
@ -127,15 +151,9 @@ public:
virtual uint16_t get_mcc() = 0;
virtual uint16_t get_mnc() = 0;
virtual void enable_capabilities() = 0;
};
// RRC interface for GW
class rrc_interface_gw
{
public:
virtual bool rrc_connected() = 0;
virtual void rrc_connect() = 0;
virtual bool have_drb() = 0;
virtual void plmn_search() = 0;
virtual void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) = 0;
virtual std::string get_rb_name(uint32_t lcid) = 0;
};
// RRC interface for PDCP
@ -146,6 +164,7 @@ public:
virtual void write_pdu_bcch_bch(srslte::byte_buffer_t *pdu) = 0;
virtual void write_pdu_bcch_dlsch(srslte::byte_buffer_t *pdu) = 0;
virtual void write_pdu_pcch(srslte::byte_buffer_t *pdu) = 0;
virtual std::string get_rb_name(uint32_t lcid) = 0;
};
// RRC interface for RLC
@ -153,6 +172,7 @@ class rrc_interface_rlc
{
public:
virtual void max_retx_attempted() = 0;
virtual std::string get_rb_name(uint32_t lcid) = 0;
};
// PDCP interface for GW
@ -160,6 +180,7 @@ class pdcp_interface_gw
{
public:
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
@ -168,7 +189,7 @@ class pdcp_interface_rrc
public:
virtual void reset() = 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,
uint8_t *k_rrc_enc_,
uint8_t *k_rrc_int_,
@ -193,7 +214,7 @@ class rlc_interface_rrc
public:
virtual void reset() = 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
@ -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
*
@ -243,10 +289,12 @@ public:
uint32_t pid;
uint32_t tti;
uint32_t last_tti;
bool ndi;
bool last_ndi;
uint32_t n_bytes;
int rv;
bool ndi[SRSLTE_MAX_CODEWORDS];
bool last_ndi[SRSLTE_MAX_CODEWORDS];
uint32_t n_bytes[SRSLTE_MAX_CODEWORDS];
int rv[SRSLTE_MAX_CODEWORDS];
bool tb_en[SRSLTE_MAX_CODEWORDS];
bool tb_cw_swap;
uint16_t rnti;
bool is_from_rar;
bool is_sps_release;
@ -256,28 +304,29 @@ public:
} mac_grant_t;
typedef struct {
bool decode_enabled;
int rv;
bool decode_enabled[SRSLTE_MAX_TB];
int rv[SRSLTE_MAX_TB];
uint16_t rnti;
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
bool (*generate_ack_callback)(void*);
void *generate_ack_callback_arg;
uint8_t *payload_ptr;
srslte_softbuffer_rx_t *softbuffer;
uint8_t *payload_ptr[SRSLTE_MAX_TB];
srslte_softbuffer_rx_t *softbuffers[SRSLTE_MAX_TB];
srslte_phy_grant_t phy_grant;
} tb_action_dl_t;
typedef struct {
bool tx_enabled;
bool expect_ack;
uint32_t rv;
uint32_t rv[SRSLTE_MAX_TB];
uint16_t rnti;
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;
uint8_t *payload_ptr;
uint8_t *payload_ptr[SRSLTE_MAX_TB];
} tb_action_ul_t;
/* 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;
/* 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 */
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 */
class mac_interface_rrc
class mac_interface_rrc : public mac_interface_rrc_common
{
public:
@ -319,19 +386,10 @@ public:
LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT main;
LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT rach;
LIBLTE_RRC_SCHEDULING_REQUEST_CONFIG_STRUCT sr;
ul_harq_params_t ul_harq_params;
uint32_t prach_config_index;
} mac_cfg_t;
// 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 */
virtual void bcch_start_rx() = 0;
virtual void bcch_stop_rx() = 0;
@ -377,8 +435,8 @@ typedef struct {
int worker_cpu_mask;
int sync_cpu_affinity;
uint32_t nof_rx_ant;
std::string equalizer_mode;
uint32_t nof_rx_ant;
std::string equalizer_mode;
int cqi_max;
int cqi_fixed;
float snr_ema_coeff;
@ -391,46 +449,50 @@ typedef struct {
float estimator_fil_w;
bool rssi_sensor_enabled;
} phy_args_t;
/* RAT agnostic Interface MAC -> PHY */
class phy_interface_mac_common
{
public:
/* Start synchronization with strongest cell in the current carrier frequency */
virtual bool sync_status() = 0;
/* Sets a C-RNTI allowing the PHY to pregenerate signals if necessary */
virtual void set_crnti(uint16_t rnti) = 0;
/* Time advance commands */
virtual void set_timeadv_rar(uint32_t ta_cmd) = 0;
virtual void set_timeadv(uint32_t ta_cmd) = 0;
/* Sets RAR grant payload */
virtual void set_rar_grant(uint32_t tti, uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN]) = 0;
virtual uint32_t get_current_tti() = 0;
virtual float get_phr() = 0;
virtual float get_pathloss_db() = 0;
};
/* Interface MAC -> PHY */
class phy_interface_mac
class phy_interface_mac : public phy_interface_mac_common
{
public:
/* Configure PRACH using parameters written by RRC */
virtual void configure_prach_params() = 0;
/* Start synchronization with strongest cell in the current carrier frequency */
virtual void sync_start() = 0;
virtual void sync_stop() = 0;
/* Sets a C-RNTI allowing the PHY to pregenerate signals if necessary */
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 */
virtual void set_timeadv_rar(uint32_t ta_cmd) = 0;
virtual void set_timeadv(uint32_t ta_cmd) = 0;
/* Sets RAR grant payload */
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 float get_phr() = 0;
virtual float get_pathloss_db() = 0;
};
class phy_interface_rrc
@ -462,16 +524,21 @@ public:
virtual void set_config_common(phy_cfg_common_t *common) = 0;
virtual void set_config_tdd(LIBLTE_RRC_TDD_CONFIG_STRUCT *tdd) = 0;
virtual void set_config_64qam_en(bool enable) = 0;
/* Cell search and selection procedures */
virtual void cell_search_start() = 0;
virtual void cell_search_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? */
virtual bool status_is_sync() = 0;
virtual bool sync_status() = 0;
virtual void sync_reset() = 0;
/* Configure UL using parameters written with set_param() */
virtual void configure_ul_params(bool pregen_disabled = false) = 0;
virtual void reset() = 0;
virtual void resync_sfn() = 0;
};

@ -60,7 +60,10 @@ typedef enum {
typedef struct {
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_average;
cf_t *pilot_recv_signal;
@ -75,7 +78,7 @@ typedef struct {
srslte_interp_linsrslte_vec_t srslte_interp_linvec;
srslte_interp_lin_t srslte_interp_lin;
srslte_interp_lin_t srslte_interp_lin_mbsfn;
float rssi[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
float rsrp[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
float noise_estimate[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
@ -92,9 +95,16 @@ typedef struct {
SRSLTE_API int srslte_chest_dl_init(srslte_chest_dl_t *q,
srslte_cell_t cell);
uint32_t max_prb);
SRSLTE_API void srslte_chest_dl_free(srslte_chest_dl_t *q);
SRSLTE_API 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_free(srslte_chest_dl_t *q);
SRSLTE_API void srslte_chest_dl_set_smooth_filter(srslte_chest_dl_t *q,
float *filter,
@ -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_chest_dl_noise_alg_t noise_estimation_alg);
SRSLTE_API 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],
@ -117,6 +129,14 @@ SRSLTE_API int srslte_chest_dl_estimate(srslte_chest_dl_t *q,
cf_t *ce[SRSLTE_MAX_PORTS],
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,
cf_t *input,
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_rsrp_port(srslte_chest_dl_t *q,
uint32_t port);
SRSLTE_API float srslte_chest_dl_get_rsrp(srslte_chest_dl_t *q);
#endif

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

@ -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
#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_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_MBSFN(i,l,cell) ((6*cell.nof_prb*(l)+(i)))
/** Cell-Specific Reference Signal */
typedef struct SRSLTE_API {
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
} srslte_refsignal_cs_t;
cf_t *pilots[2][SRSLTE_NSUBFRAMES_X_FRAME]; // Saves the reference signal per subframe for ports 0,1 and ports 2,3
srslte_sf_t type;
uint16_t mbsfn_area_id;
} srslte_refsignal_t;
SRSLTE_API int srslte_refsignal_cs_init(srslte_refsignal_cs_t *q,
srslte_cell_t cell);
SRSLTE_API int srslte_refsignal_cs_init(srslte_refsignal_t *q,
uint32_t max_prb);
SRSLTE_API void srslte_refsignal_cs_free(srslte_refsignal_cs_t *q);
SRSLTE_API int srslte_refsignal_cs_set_cell(srslte_refsignal_t * q,
srslte_cell_t cell);
SRSLTE_API void srslte_refsignal_free(srslte_refsignal_t *q);
SRSLTE_API int srslte_refsignal_cs_put_sf(srslte_cell_t cell,
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 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

@ -94,7 +94,10 @@ typedef struct {
} srslte_refsignal_srs_pregen_t;
SRSLTE_API int srslte_refsignal_ul_init(srslte_refsignal_ul_t *q,
srslte_cell_t cell);
uint32_t max_prb);
SRSLTE_API int srslte_refsignal_ul_set_cell(srslte_refsignal_ul_t *q,
srslte_cell_t cell);
SRSLTE_API void srslte_refsignal_ul_free(srslte_refsignal_ul_t *q);
@ -115,9 +118,13 @@ SRSLTE_API uint32_t srslte_refsignal_dmrs_pucch_symbol(uint32_t m,
SRSLTE_API bool srslte_refsignal_dmrs_pusch_cfg_isvalid(srslte_refsignal_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *cfg,
uint32_t nof_prb);
uint32_t nof_prb);
SRSLTE_API int srslte_refsignal_dmrs_pusch_pregen_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_API void srslte_refsignal_dmrs_pusch_pregen_free(srslte_refsignal_ul_t *q,

@ -52,13 +52,22 @@
#define SRSLTE_MAX_PORTS 4
#define SRSLTE_MAX_LAYERS 4
#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_CRC24B 0X1800063
#define SRSLTE_LTE_CRC16 0x11021
#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_SF_NORM, SRSLTE_SF_MBSFN} srslte_sf_t;
#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)
#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_DEFAULT_MAX_FRAMES_PBCH 500
@ -146,12 +162,13 @@ typedef enum SRSLTE_API {
} srslte_phich_resources_t;
typedef enum {
SRSLTE_RNTI_USER = 0,
SRSLTE_RNTI_SI,
SRSLTE_RNTI_RAR,
SRSLTE_RNTI_TEMP,
SRSLTE_RNTI_SPS,
SRSLTE_RNTI_PCH,
SRSLTE_RNTI_USER = 0, /* Cell RNTI */
SRSLTE_RNTI_SI, /* System Information RNTI */
SRSLTE_RNTI_RAR, /* Random Access RNTI */
SRSLTE_RNTI_TEMP, /* Temporary C-RNTI */
SRSLTE_RNTI_SPS, /* Semi-Persistent Scheduling C-RNTI */
SRSLTE_RNTI_PCH, /* Paging RNTI */
SRSLTE_RNTI_MBSFN,
SRSLTE_RNTI_NOF_TYPES
} srslte_rnti_type_t;
@ -171,6 +188,11 @@ typedef enum SRSLTE_API {
SRSLTE_MIMO_TYPE_CDD
} srslte_mimo_type_t;
typedef enum SRSLTE_API {
SRSLTE_MIMO_DECODER_ZF,
SRSLTE_MIMO_DECODER_MMSE
} srslte_mimo_decoder_t;
typedef enum SRSLTE_API {
SRSLTE_MOD_BPSK = 0,
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,
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 srslte_mod_t srslte_str2mod (char * mod_str);
SRSLTE_API char *srslte_mod_string(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_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,
uint32_t tti2);

@ -44,7 +44,8 @@ typedef struct SRSLTE_API {
uint8_t *c_bytes;
float *c_float;
short *c_short;
uint32_t len;
uint32_t cur_len;
uint32_t max_len;
} srslte_sequence_t;
SRSLTE_API int srslte_sequence_init(srslte_sequence_t *q, uint32_t len);
@ -55,8 +56,9 @@ SRSLTE_API int srslte_sequence_LTE_pr(srslte_sequence_t *q,
uint32_t len,
uint32_t seed);
SRSLTE_API void srslte_sequence_set_LTE_pr(srslte_sequence_t *q,
uint32_t seed);
SRSLTE_API int srslte_sequence_set_LTE_pr(srslte_sequence_t *q,
uint32_t len,
uint32_t seed);
SRSLTE_API int srslte_sequence_pbch(srslte_sequence_t *seq,
srslte_cp_t cp,
@ -92,4 +94,10 @@ SRSLTE_API int srslte_sequence_pucch(srslte_sequence_t *seq,
uint16_t rnti,
uint32_t nslot,
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

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

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

@ -47,6 +47,7 @@
/* This is common for both directions */
typedef struct SRSLTE_API{
srslte_dft_plan_t fft_plan;
uint32_t max_prb;
uint32_t nof_symbols;
uint32_t symbol_sz;
uint32_t nof_guards;
@ -55,7 +56,14 @@ typedef struct SRSLTE_API{
srslte_cp_t cp;
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;
float freq_shift_f;
cf_t *shift_buffer;
}srslte_ofdm_t;
@ -63,11 +71,32 @@ SRSLTE_API int srslte_ofdm_init_(srslte_ofdm_t *q,
srslte_cp_t cp,
int symbol_sz,
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_cp_t cp_type,
uint32_t nof_prb);
uint32_t max_prb);
SRSLTE_API int srslte_ofdm_tx_set_prb(srslte_ofdm_t *q,
srslte_cp_t cp,
uint32_t nof_prb);
SRSLTE_API int srslte_ofdm_rx_set_prb(srslte_ofdm_t *q,
srslte_cp_t cp,
uint32_t nof_prb);
SRSLTE_API void srslte_ofdm_rx_free(srslte_ofdm_t *q);
@ -85,12 +114,22 @@ SRSLTE_API int srslte_ofdm_tx_init(srslte_ofdm_t *q,
srslte_cp_t cp_type,
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_slot(srslte_ofdm_t *q,
cf_t *input,
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,
cf_t *input,
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,
bool normalize_enable);
#endif
SRSLTE_API void srslte_ofdm_set_non_mbsfn_region(srslte_ofdm_t *q,
uint8_t non_mbsfn_region);
#endif

@ -76,7 +76,7 @@ typedef struct SRSLTE_API {
srslte_pdsch_t pdsch;
srslte_phich_t phich;
srslte_refsignal_cs_t csr_signal;
srslte_refsignal_t csr_signal;
srslte_pdsch_cfg_t pdsch_cfg;
srslte_ra_dl_dci_t dl_dci;
@ -88,6 +88,8 @@ typedef struct SRSLTE_API {
float sss_signal5[SRSLTE_SSS_LEN];
float tx_amp;
uint8_t tmp[1024*128];
} srslte_enb_dl_t;
@ -108,11 +110,14 @@ typedef struct {
/* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_enb_dl_init(srslte_enb_dl_t *q,
srslte_cell_t cell);
uint32_t max_prb);
SRSLTE_API void srslte_enb_dl_free(srslte_enb_dl_t *q);
SRSLTE_API void srslte_enb_dl_set_cfi(srslte_enb_dl_t *q,
SRSLTE_API int srslte_enb_dl_set_cell(srslte_enb_dl_t *q,
srslte_cell_t cell);
SRSLTE_API void srslte_enb_dl_set_cfi(srslte_enb_dl_t *q,
uint32_t cfi);
SRSLTE_API void srslte_enb_dl_set_amp(srslte_enb_dl_t *q,
@ -152,18 +157,20 @@ 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_ra_dl_grant_t *grant,
srslte_softbuffer_tx_t *softbuffer,
srslte_softbuffer_tx_t *softbuffer[SRSLTE_MAX_CODEWORDS],
uint16_t rnti,
uint32_t rv_idx,
int rv_idx[SRSLTE_MAX_CODEWORDS],
uint32_t sf_idx,
uint8_t *data);
uint8_t *data[SRSLTE_MAX_CODEWORDS],
srslte_mimo_type_t mimo_type,
uint32_t pmi);
SRSLTE_API int srslte_enb_dl_put_pdcch_dl(srslte_enb_dl_t *q,
srslte_ra_dl_dci_t *grant,
srslte_dci_format_t format,
srslte_dci_location_t location,
uint16_t rnti,
uint32_t sf_idx);
uint32_t sf_idx);
SRSLTE_API int srslte_enb_dl_put_pdcch_ul(srslte_enb_dl_t *q,
srslte_ra_ul_dci_t *grant,
@ -171,5 +178,12 @@ SRSLTE_API int srslte_enb_dl_put_pdcch_ul(srslte_enb_dl_t *q,
uint16_t rnti,
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

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

@ -50,18 +50,14 @@
#define SRSLTE_TCOD_MAX_LEN_CODED (SRSLTE_TCOD_RATE*SRSLTE_TCOD_MAX_LEN_CB+SRSLTE_TCOD_TOTALTAIL)
#include "srslte/phy/fec/turbodecoder_gen.h"
#ifdef LV_HAVE_SSE
#include "srslte/phy/fec/turbodecoder_sse.h"
#endif
#include "srslte/phy/fec/turbodecoder_simd.h"
typedef struct SRSLTE_API {
#ifdef LV_HAVE_SSE
srslte_tdec_sse_t tdec_sse;
#else
float *input_conv;
srslte_tdec_gen_t tdec_gen;
#endif
float *input_conv;
union {
srslte_tdec_simd_t tdec_simd;
srslte_tdec_gen_t tdec_gen;
};
} srslte_tdec_t;
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 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,
int16_t* input,
@ -89,4 +94,27 @@ SRSLTE_API int srslte_tdec_run_all(srslte_tdec_t * h,
uint32_t nof_iterations,
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

@ -66,6 +66,8 @@ typedef struct SRSLTE_API {
float *parity;
int current_cbidx;
uint32_t current_cb_len;
uint32_t n_iter;
srslte_tc_interl_t interleaver[SRSLTE_NOF_TC_CB_SIZES];
} 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,
int nsamples);
SRSLTE_API int srslte_filesink_write_multi(srslte_filesink_t *q,
void **buffer,
int nsamples,
int nchannels);
#endif // FILESINK_

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

@ -65,8 +65,9 @@ SRSLTE_API int srslte_precoding_cdd(cf_t *x[SRSLTE_MAX_LAYERS],
SRSLTE_API int srslte_precoding_type(cf_t *x[SRSLTE_MAX_LAYERS],
cf_t *y[SRSLTE_MAX_PORTS],
int nof_layers,
int nof_ports,
int nof_symbols,
int nof_ports,
int codebook_idx,
int nof_symbols,
srslte_mimo_type_t type);
/* Estimates the vector "x" based on the received signal "y" and the channel estimates "h"
@ -106,14 +107,31 @@ SRSLTE_API int srslte_predecoding_type(cf_t *y,
srslte_mimo_type_t type,
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],
cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
cf_t *x[SRSLTE_MAX_LAYERS],
int nof_rxant,
int nof_ports,
int nof_layers,
int codebook_idx,
int nof_symbols,
srslte_mimo_type_t type,
float noise_estimate);
SRSLTE_API int srslte_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_ */

@ -41,11 +41,15 @@
#include "srslte/phy/common/phy_common.h"
#define SRSLTE_CQI_MAX_BITS 64
#define SRSLTE_DIF_CQI_MAX_BITS 3
#define SRSLTE_PMI_MAX_BITS 4
typedef struct {
bool configured;
uint32_t pmi_idx;
bool simul_cqi_ack;
uint32_t ri_idx;
bool ri_idx_present;
bool simul_cqi_ack;
bool format_is_subband;
uint32_t subband_size;
} srslte_cqi_periodic_cfg_t;
@ -137,7 +141,11 @@ SRSLTE_API int srslte_cqi_format2_subband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BIT
srslte_cqi_format2_subband_t *msg);
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);

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

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

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

@ -48,7 +48,8 @@
#include "srslte/phy/phch/pdsch_cfg.h"
typedef struct {
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
srslte_sequence_t seq[SRSLTE_MAX_CODEWORDS][SRSLTE_NSUBFRAMES_X_FRAME];
uint32_t cell_id;
bool sequence_generated;
} srslte_pdsch_user_t;
@ -57,79 +58,104 @@ typedef struct SRSLTE_API {
srslte_cell_t cell;
uint32_t nof_rx_antennas;
uint32_t last_nof_iterations[SRSLTE_MAX_CODEWORDS];
uint32_t max_re;
uint16_t ue_rnti;
bool is_ue;
/* buffers */
// void buffers are shared for tx and rx
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
cf_t *symbols[SRSLTE_MAX_PORTS];
cf_t *x[SRSLTE_MAX_PORTS];
cf_t *d;
void *e;
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; /* Channel estimation (Rx only) */
cf_t *symbols[SRSLTE_MAX_PORTS]; /* PDSCH Encoded/Decoded Symbols */
cf_t *x[SRSLTE_MAX_LAYERS]; /* Layer mapped */
cf_t *d[SRSLTE_MAX_CODEWORDS]; /* Modulated/Demodulated codewords */
void *e[SRSLTE_MAX_CODEWORDS];
/* tx & rx objects */
srslte_modem_table_t mod[4];
// This is to generate the scrambling seq for multiple CRNTIs
srslte_pdsch_user_t **users;
srslte_sequence_t tmp_seq;
srslte_sch_t dl_sch;
} srslte_pdsch_t;
SRSLTE_API int srslte_pdsch_init(srslte_pdsch_t *q,
srslte_cell_t cell);
SRSLTE_API int srslte_pdsch_init_multi(srslte_pdsch_t *q,
srslte_cell_t cell,
uint32_t nof_rx_antennas);
SRSLTE_API int srslte_pdsch_init_ue(srslte_pdsch_t *q,
uint32_t max_prb,
uint32_t nof_rx_antennas);
SRSLTE_API int srslte_pdsch_init_enb(srslte_pdsch_t *q,
uint32_t max_prb);
SRSLTE_API void srslte_pdsch_free(srslte_pdsch_t *q);
SRSLTE_API int srslte_pdsch_set_rnti(srslte_pdsch_t *q,
SRSLTE_API int srslte_pdsch_set_cell(srslte_pdsch_t *q,
srslte_cell_t cell);
SRSLTE_API int srslte_pdsch_set_rnti(srslte_pdsch_t *q,
uint16_t rnti);
SRSLTE_API void srslte_pdsch_free_rnti(srslte_pdsch_t *q,
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_ra_dl_grant_t *grant,
uint32_t cfi,
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_pdsch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffer,
uint8_t *data,
uint16_t rnti,
cf_t *sf_symbols[SRSLTE_MAX_PORTS]);
srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffers[SRSLTE_MAX_CODEWORDS],
uint8_t *data[SRSLTE_MAX_CODEWORDS],
uint16_t rnti,
cf_t *sf_symbols[SRSLTE_MAX_PORTS]);
SRSLTE_API int srslte_pdsch_decode(srslte_pdsch_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,
srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_rx_t *softbuffers[SRSLTE_MAX_CODEWORDS],
cf_t *sf_symbols[SRSLTE_MAX_PORTS],
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
float noise_estimate,
uint16_t rnti,
uint8_t *data);
SRSLTE_API int srslte_pdsch_decode_multi(srslte_pdsch_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 rnti,
uint8_t *data);
uint8_t *data[SRSLTE_MAX_CODEWORDS],
bool acks[SRSLTE_MAX_CODEWORDS]);
SRSLTE_API int srslte_pdsch_pmi_select(srslte_pdsch_t *q,
srslte_pdsch_cfg_t *cfg,
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
float noise_estimate,
uint32_t nof_ce,
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

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

@ -85,26 +85,24 @@ typedef struct SRSLTE_API {
} srslte_phich_t;
SRSLTE_API int srslte_phich_init(srslte_phich_t *q,
srslte_regs_t *regs,
srslte_cell_t cell);
SRSLTE_API int srslte_phich_init_multi(srslte_phich_t *q,
srslte_regs_t *regs,
srslte_cell_t cell,
uint32_t nof_rx_antennas);
SRSLTE_API int srslte_phich_init(srslte_phich_t *q,
uint32_t nof_rx_antennas);
SRSLTE_API void srslte_phich_free(srslte_phich_t *q);
SRSLTE_API void srslte_phich_calc(srslte_phich_t *q,
SRSLTE_API int srslte_phich_set_cell(srslte_phich_t *q,
srslte_regs_t *regs,
srslte_cell_t cell);
SRSLTE_API void srslte_phich_calc(srslte_phich_t *q,
uint32_t n_prb_lowest,
uint32_t n_dmrs,
uint32_t *ngroup,
uint32_t *nseq);
SRSLTE_API int srslte_phich_decode(srslte_phich_t *q,
cf_t *slot_symbols,
cf_t *ce[SRSLTE_MAX_PORTS],
cf_t *slot_symbols[SRSLTE_MAX_PORTS],
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS],
float noise_estimate,
uint32_t ngroup,
uint32_t nseq,
@ -112,16 +110,6 @@ SRSLTE_API int srslte_phich_decode(srslte_phich_t *q,
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 *ce[SRSLTE_MAX_PORTS][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_encode(srslte_phich_t *q,
uint8_t ack,
uint32_t ngroup,

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

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

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

@ -102,13 +102,18 @@ typedef struct SRSLTE_API {
typedef struct SRSLTE_API {
bool prb_idx[2][SRSLTE_MAX_PRB];
uint32_t nof_prb;
uint32_t Qm;
uint32_t Qm2;
srslte_ra_mcs_t mcs;
srslte_ra_mcs_t mcs2;
uint32_t Qm[SRSLTE_MAX_CODEWORDS];
uint32_t Qm2[SRSLTE_MAX_CODEWORDS];
srslte_ra_mcs_t mcs[SRSLTE_MAX_CODEWORDS];
srslte_ra_mcs_t mcs2[SRSLTE_MAX_CODEWORDS];
uint32_t nof_tb;
srslte_sf_t sf_type;
bool tb_en[SRSLTE_MAX_CODEWORDS];
uint32_t pinfo;
} srslte_ra_dl_grant_t;
#define SRSLTE_RA_DL_GRANT_NOF_TB(G) ((((G)->tb_en[0])?1:0)+(((G)->tb_en[1])?1:0))
/** Unpacked DCI message for DL grant */
typedef struct SRSLTE_API {
@ -206,10 +211,10 @@ SRSLTE_API int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t *dci,
SRSLTE_API void srslte_ra_dl_grant_to_nbits(srslte_ra_dl_grant_t *grant,
uint32_t cfi,
srslte_cell_t cell,
uint32_t sf_idx,
srslte_ra_nbits_t *nbits);
uint32_t sf_idx,
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_ctrl_symbols);
@ -289,4 +294,9 @@ SRSLTE_API void srslte_ra_pusch_fprint(FILE *f,
SRSLTE_API void srslte_ra_ul_grant_fprint(FILE *f,
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_ */

@ -56,10 +56,9 @@
/* DL-SCH AND UL-SCH common functions */
typedef struct SRSLTE_API {
uint32_t max_iterations;
uint32_t nof_iterations;
float average_nof_iterations;
uint32_t max_iterations;
uint32_t nof_iterations;
/* buffers */
uint8_t *cb_in;
uint8_t *parity_bits;
@ -77,6 +76,7 @@ typedef struct SRSLTE_API {
srslte_uci_cqi_pusch_t uci_cqi;
} srslte_sch_t;
#include "srslte/phy/phch/pmch.h"
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,
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 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 *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_pdsch_cfg_t *cfg,
srslte_softbuffer_rx_t *softbuffer,
int16_t *e_bits,
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_pusch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffer,

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

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

@ -73,9 +73,9 @@ SRSLTE_API int srslte_rf_open(srslte_rf_t *h,
SRSLTE_API int srslte_rf_open_multi(srslte_rf_t *h,
char *args,
uint32_t nof_rx_antennas);
uint32_t nof_rx_antennas);
SRSLTE_API int srslte_rf_open_devname(srslte_rf_t *h,
SRSLTE_API int srslte_rf_open_devname(srslte_rf_t *h,
char *devname,
char *args);
@ -200,5 +200,21 @@ SRSLTE_API int srslte_rf_send_timed2(srslte_rf_t *h,
bool is_start_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

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

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

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

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

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

@ -48,6 +48,7 @@
#include "srslte/phy/phch/pcfich.h"
#include "srslte/phy/phch/pdcch.h"
#include "srslte/phy/phch/pdsch.h"
#include "srslte/phy/phch/pmch.h"
#include "srslte/phy/phch/pdsch_cfg.h"
#include "srslte/phy/phch/phich.h"
#include "srslte/phy/phch/ra.h"
@ -76,15 +77,18 @@ typedef struct SRSLTE_API {
srslte_pcfich_t pcfich;
srslte_pdcch_t pdcch;
srslte_pdsch_t pdsch;
srslte_pmch_t pmch;
srslte_phich_t phich;
srslte_regs_t regs;
srslte_ofdm_t fft;
srslte_ofdm_t fft_mbsfn;
srslte_chest_dl_t chest;
srslte_cfo_t sfo_correct;
srslte_pdsch_cfg_t pdsch_cfg;
srslte_softbuffer_rx_t softbuffer;
srslte_pdsch_cfg_t pdsch_cfg;
srslte_pdsch_cfg_t pmch_cfg;
srslte_softbuffer_rx_t *softbuffers[SRSLTE_MAX_CODEWORDS];
srslte_ra_dl_dci_t dl_dci;
srslte_cell_t cell;
@ -94,13 +98,23 @@ typedef struct SRSLTE_API {
cf_t *sf_symbols_m[SRSLTE_MAX_PORTS];
cf_t *ce[SRSLTE_MAX_PORTS]; // compatibility
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;
uint64_t pkt_errors;
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;
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_common[3];
srslte_dci_location_t last_location;
@ -113,34 +127,42 @@ typedef struct SRSLTE_API {
}srslte_ue_dl_t;
/* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_ue_dl_init(srslte_ue_dl_t *q,
srslte_cell_t cell);
SRSLTE_API int srslte_ue_dl_init_multi(srslte_ue_dl_t *q,
srslte_cell_t cell,
uint32_t nof_rx_antennas);
SRSLTE_API int srslte_ue_dl_init(srslte_ue_dl_t *q,
uint32_t max_prb,
uint32_t nof_rx_antennas);
SRSLTE_API void srslte_ue_dl_free(srslte_ue_dl_t *q);
SRSLTE_API int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q,
cf_t *input,
uint32_t sf_idx,
uint32_t *cfi);
SRSLTE_API int srslte_ue_dl_set_cell(srslte_ue_dl_t *q,
srslte_cell_t cell);
SRSLTE_API int srslte_ue_dl_decode_fft_estimate_multi(srslte_ue_dl_t *q,
cf_t *input[SRSLTE_MAX_PORTS],
int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q,
cf_t *input[SRSLTE_MAX_PORTS],
uint32_t sf_idx,
uint32_t *cfi);
SRSLTE_API int srslte_ue_dl_decode_fft_estimate_mbsfn(srslte_ue_dl_t *q,
cf_t *input[SRSLTE_MAX_PORTS],
uint32_t sf_idx,
uint32_t *cfi);
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 *cfi);
SRSLTE_API int srslte_ue_dl_decode_estimate_mbsfn(srslte_ue_dl_t *q,
uint32_t sf_idx,
uint32_t *cfi);
uint32_t *cfi,
srslte_sf_t sf_type);
SRSLTE_API int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q,
srslte_ra_dl_grant_t *grant,
uint32_t cfi,
uint32_t sf_idx,
uint32_t rvidx);
SRSLTE_API int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q,
srslte_ra_dl_grant_t *grant,
uint32_t cfi,
uint32_t sf_idx,
int rvidx[SRSLTE_MAX_CODEWORDS],
srslte_mimo_type_t mimo_type);
SRSLTE_API int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t *q,
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_API int srslte_ue_dl_find_dl_dci(srslte_ue_dl_t *q,
uint32_t tm,
uint32_t cfi,
uint32_t sf_idx,
uint16_t rnti,
srslte_dci_msg_t *dci_msg);
SRSLTE_API int srslte_ue_dl_find_dl_dci_type(srslte_ue_dl_t *q,
uint32_t tm,
uint32_t cfi,
uint32_t sf_idx,
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,
float sample_offset);
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],
SRSLTE_API int srslte_ue_dl_decode(srslte_ue_dl_t *q,
cf_t *input[SRSLTE_MAX_PORTS],
uint8_t *data[SRSLTE_MAX_CODEWORDS],
uint32_t tm,
uint32_t tti,
bool acks[SRSLTE_MAX_CODEWORDS]);
SRSLTE_API int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q,
cf_t *input[SRSLTE_MAX_PORTS],
uint8_t *data[SRSLTE_MAX_CODEWORDS],
uint32_t tm,
uint32_t tti,
uint16_t rnti,
bool acks[SRSLTE_MAX_CODEWORDS]);
/* 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],
uint8_t *data,
uint32_t tti);
SRSLTE_API int srslte_ue_dl_decode_rnti(srslte_ue_dl_t * q,
cf_t *input,
uint8_t *data,
uint32_t tti,
uint16_t rnti);
SRSLTE_API int srslte_ue_dl_decode_rnti_multi(srslte_ue_dl_t * q,
cf_t *input[SRSLTE_MAX_PORTS],
uint8_t *data,
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,
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,
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_softbuffer_rx_t *softbuffer,
uint32_t tti,

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

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

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

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

@ -58,10 +58,16 @@ SRSLTE_API extern int srslte_verbose;
#define PRINT_NONE srslte_verbose=SRSLTE_VERBOSE_NONE
#define DEBUG(_fmt, ...) if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG) \
fprintf(stdout, "[DEBUG]: " _fmt, __VA_ARGS__)
fprintf(stdout, "[DEBUG]: " _fmt, ##__VA_ARGS__)
#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

@ -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 */
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 */
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);
@ -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 */
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
}
#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 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_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_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);
@ -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_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_mult_scalar_cf_f_avx( cf_t *z,const cf_t *x,const float h,const 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);
#ifdef __cplusplus
}
#endif

@ -57,8 +57,7 @@ namespace srslte {
bzero(&end_of_burst_time, sizeof(srslte_timestamp_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;
burst_preamble_samples = 0;
burst_preamble_time_rounded = 0;
@ -72,13 +71,12 @@ namespace srslte {
rx_freq = 0;
trace_enabled = false;
tti = 0;
agc_enabled = false;
offset = 0;
agc_enabled = false;
};
bool init(char *args = NULL, char *devname = NULL);
void stop();
void stop();
void reset();
bool start_agc(bool tx_gain_same_rx);
void set_burst_preamble(double preamble_us);
@ -98,15 +96,16 @@ namespace srslte {
void set_tx_rx_gain_offset(float offset);
double set_rx_gain_th(float gain);
void set_tx_freq(float freq);
void set_rx_freq(float freq);
void set_freq_offset(double freq);
void set_tx_freq(double freq);
void set_rx_freq(double freq);
float get_tx_freq();
float get_rx_freq();
double get_tx_freq();
double get_rx_freq();
void set_master_clock_rate(float rate);
void set_tx_srate(float srate);
void set_rx_srate(float srate);
void set_master_clock_rate(double rate);
void set_tx_srate(double srate);
void set_rx_srate(double srate);
float get_tx_gain();
float get_rx_gain();
@ -122,9 +121,8 @@ namespace srslte {
void stop_rx();
void set_tti(uint32_t tti);
void tx_offset(int offset);
void set_tti_len(uint32_t sf_len);
uint32_t get_tti_len();
bool is_first_of_burst();
void register_error_handler(srslte_rf_error_handler_t h);
@ -156,9 +154,9 @@ namespace srslte {
const static double blade_default_burst_preamble_sec = 0.0;
const static double blade_default_tx_adv_samples = 27;
const static double blade_default_tx_adv_offset_sec = 1e-6;
float tx_freq, rx_freq;
const static double blade_default_tx_adv_offset_sec = 1e-6;
double tx_freq, rx_freq, freq_offset;
trace<uint32_t> tr_local_time;
trace<uint32_t> tr_usrp_time;
@ -167,8 +165,10 @@ namespace srslte {
bool trace_enabled;
uint32_t tti;
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::gw_interface_pdcp *gw_,
log *pdcp_log_,
uint32_t lcid_,
uint8_t direction_);
void stop();
// GW interface
bool is_drb_enabled(uint32_t lcid);
// RRC interface
void reset();
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,
uint8_t *k_rrc_enc,
uint8_t *k_rrc_int,
@ -66,14 +70,14 @@ public:
void write_pdu_pcch(byte_buffer_t *sdu);
private:
log *pdcp_log;
pdcp_entity pdcp_array[SRSLTE_N_RADIO_BEARERS];
srsue::rlc_interface_pdcp *rlc;
srsue::rrc_interface_pdcp *rrc;
srsue::gw_interface_pdcp *gw;
uint8_t direction;
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;
bool valid_lcid(uint32_t lcid);
};

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

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

@ -27,6 +27,8 @@
#ifndef RLC_COMMON_H
#define RLC_COMMON_H
#include "srslte/upper/rlc_interface.h"
namespace srslte {
/****************************************************************************
@ -66,14 +68,6 @@ typedef enum{
static const char rlc_dc_field_text[RLC_DC_FIELD_N_ITEMS][20] = {"Control 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
typedef struct{
uint8_t fi; // Framing info
@ -162,8 +156,9 @@ public:
srsue::pdcp_interface_rlc *pdcp_,
srsue::rrc_interface_rlc *rrc_,
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 stop() = 0;
virtual void empty_queue() = 0;
virtual rlc_mode_t get_mode() = 0;

@ -54,8 +54,10 @@ public:
srsue::rrc_interface_rlc *rrc_,
mac_interface_timers *mac_timers_);
void configure(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg);
void configure(srslte_rlc_config_t cnfg);
void reset();
void stop();
void empty_queue();
bool active();
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::rrc_interface_rlc *rrc_,
mac_interface_timers *mac_timers);
void configure(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg);
void configure(srslte_rlc_config_t cnfg);
void reset();
void stop();
void empty_queue();
rlc_mode_t get_mode();

@ -56,8 +56,9 @@ public:
srsue::pdcp_interface_rlc *pdcp_,
srsue::rrc_interface_rlc *rrc_,
mac_interface_timers *mac_timers_);
void configure(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg);
void configure(srslte_rlc_config_t cnfg);
void reset();
void stop();
void empty_queue();
rlc_mode_t get_mode();
@ -92,9 +93,6 @@ private:
// 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
byte_buffer_t *rx_sdu;
@ -108,9 +106,7 @@ private:
* 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
srslte_rlc_um_config_t cfg;
/****************************************************************************
* State variables and counters
@ -129,7 +125,8 @@ private:
* Timers
* 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;

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

@ -33,7 +33,7 @@
// Table 6.1.3.1-1 Buffer size levels for BSR
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,
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[3] = (payload[2]&0x3F);
} else {
uint32_t nonzero_lcg = (payload[0]&0xc0) >> 6;
nonzero_lcg = (payload[0]&0xc0) >> 6;
buff_size[nonzero_lcg%4] = payload[0]&0x3f;
}
for (int i=0;i<4;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;
@ -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)
{
if (((sch_pdu*)parent)->has_space_ce(2)) {
w_payload_ce[0] = (uint8_t) (crnti&0xff00)>>8;
w_payload_ce[1] = (uint8_t) (crnti&0x00ff);
w_payload_ce[0] = (uint8_t) ((crnti&0xff00)>>8);
w_payload_ce[1] = (uint8_t) ((crnti&0x00ff));
lcid = CRNTI;
((sch_pdu*)parent)->update_space_ce(2);
nof_bytes = 2;

@ -66,7 +66,7 @@ uint8_t* pdu_queue::request(uint32_t len)
void pdu_queue::deallocate(uint8_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);
}
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++;
have_data = true;

@ -55,32 +55,7 @@ set(srslte_srcs $<TARGET_OBJECTS:srslte_agc>
)
add_library(srslte_phy STATIC ${srslte_srcs})
set_target_properties(srslte_phy PROPERTIES
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)
target_link_libraries(srslte_phy ${FFT_LIBRARIES})
if(VOLK_FOUND)
target_link_libraries(srslte_phy ${VOLK_LIBRARIES})

@ -32,6 +32,8 @@
#include <string.h>
#include <complex.h>
#include <math.h>
#include <srslte/phy/common/phy_common.h>
#include <srslte/srslte.h>
#include "srslte/config.h"
@ -72,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.
*/
int srslte_chest_dl_init(srslte_chest_dl_t *q, srslte_cell_t cell)
int srslte_chest_dl_init(srslte_chest_dl_t *q, uint32_t max_prb)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
if (q != NULL)
{
bzero(q, sizeof(srslte_chest_dl_t));
ret = srslte_refsignal_cs_init(&q->csr_signal, cell);
ret = srslte_refsignal_cs_init(&q->csr_refs, max_prb);
if (ret != SRSLTE_SUCCESS) {
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
goto clean_exit;
}
q->tmp_noise = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb));
q->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) {
perror("malloc");
goto clean_exit;
}
q->pilot_estimates = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb));
q->pilot_estimates = srslte_vec_malloc(sizeof(cf_t) * pilot_vec_size);
if (!q->pilot_estimates) {
perror("malloc");
goto clean_exit;
}
q->pilot_estimates_average = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb));
q->pilot_estimates_average = srslte_vec_malloc(sizeof(cf_t) * pilot_vec_size);
if (!q->pilot_estimates_average) {
perror("malloc");
goto clean_exit;
}
q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb));
q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * pilot_vec_size);
if (!q->pilot_recv_signal) {
perror("malloc");
goto clean_exit;
}
if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, SRSLTE_NRE*cell.nof_prb)) {
if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, SRSLTE_NRE*max_prb)) {
fprintf(stderr, "Error initializing vector interpolator\n");
goto clean_exit;
}
if (srslte_interp_linear_init(&q->srslte_interp_lin, 2*cell.nof_prb, SRSLTE_NRE/2)) {
if (srslte_interp_linear_init(&q->srslte_interp_lin, 2*max_prb, SRSLTE_NRE/2)) {
fprintf(stderr, "Error initializing interpolator\n");
goto clean_exit;
}
if (srslte_pss_generate(q->pss_signal, cell.id%3)) {
fprintf(stderr, "Error initializing PSS signal for noise estimation\n");
if (srslte_interp_linear_init(&q->srslte_interp_lin_mbsfn, 6*max_prb, SRSLTE_NRE/6)) {
fprintf(stderr, "Error initializing interpolator\n");
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;
srslte_chest_dl_set_smooth_filter3_coeff(q, 0.1);
q->cell = cell;
}
ret = SRSLTE_SUCCESS;
@ -142,14 +159,25 @@ clean_exit:
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) {
free(q->tmp_noise);
}
srslte_interp_linear_vector_free(&q->srslte_interp_linvec);
srslte_interp_linear_free(&q->srslte_interp_lin);
srslte_interp_linear_free(&q->srslte_interp_lin_mbsfn);
if (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));
}
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 */
static float estimate_noise_pilots(srslte_chest_dl_t *q, uint32_t port_id)
{
int nref=SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id);
/* Substract noisy pilot estimates */
srslte_vec_sub_ccc(q->pilot_estimates_average, q->pilot_estimates, q->tmp_noise, nref);
@ -223,46 +298,70 @@ 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)]
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 */
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 */
for (l=0;l<nsymbols;l++) {
uint32_t 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);
// 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],
&ce[srslte_refsignal_cs_nsymbol(l,q->cell.cp, port_id) * q->cell.nof_prb * SRSLTE_NRE],
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 */
if (SRSLTE_CP_ISNORM(q->cell.cp)) {
if (nsymbols == 4) {
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(4), &cesymb(1), 4, 3);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(4), &cesymb(7), &cesymb(5), 3, 2);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(7), &cesymb(11), &cesymb(8), 4, 3);
srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(7), &cesymb(11), &cesymb(11), &cesymb(12), 4, 2);
if (ch_mode == SRSLTE_SF_MBSFN) {
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(2), &cesymb(1), 2, 1);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(2), &cesymb(6), &cesymb(3), 4, 3);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(6), &cesymb(10), &cesymb(7), 4, 3);
srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(6), &cesymb(10), &cesymb(10), &cesymb(11), 4, 1);
} else {
if (SRSLTE_CP_ISNORM(q->cell.cp)) {
if (nsymbols == 4) {
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(4), &cesymb(1), 4, 3);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(4), &cesymb(7), &cesymb(5), 3, 2);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(7), &cesymb(11), &cesymb(8), 4, 3);
srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(7), &cesymb(11), &cesymb(11), &cesymb(12), 4, 2);
} else {
srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(8), &cesymb(1), &cesymb(1), &cesymb(0), 7, 1);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(8), &cesymb(2), 7, 6);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(8), &cesymb(9), 7, 5);
}
} else {
srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(8), &cesymb(1), &cesymb(1), &cesymb(0), 7, 1);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(8), &cesymb(2), 7, 6);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(8), &cesymb(9), 7, 5);
}
} else {
if (nsymbols == 4) {
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(3), &cesymb(1), 3, 2);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(3), &cesymb(6), &cesymb(4), 3, 2);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(6), &cesymb(9), &cesymb(7), 3, 2);
srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(6), &cesymb(9), &cesymb(9), &cesymb(10), 3, 2);
} else {
srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(7), &cesymb(1), &cesymb(1), &cesymb(0), 6, 1);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(7), &cesymb(2), 6, 5);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(7), &cesymb(8), 6, 4);
}
if (nsymbols == 4) {
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(3), &cesymb(1), 3, 2);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(3), &cesymb(6), &cesymb(4), 3, 2);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(6), &cesymb(9), &cesymb(7), 3, 2);
srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(6), &cesymb(9), &cesymb(9), &cesymb(10), 3, 2);
} else {
srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(7), &cesymb(1), &cesymb(1), &cesymb(0), 6, 1);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(7), &cesymb(2), 6, 5);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(7), &cesymb(8), 6, 4);
}
}
}
}
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) {
@ -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;
}
static void average_pilots(srslte_chest_dl_t *q, cf_t *input, cf_t *output, uint32_t port_id) {
uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(port_id);
uint32_t nref = 2*q->cell.nof_prb;
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 = (ch_mode == SRSLTE_SF_MBSFN)?srslte_refsignal_mbsfn_nof_symbols(port_id):srslte_refsignal_cs_nof_symbols(port_id);
uint32_t nref = (ch_mode == SRSLTE_SF_MBSFN)?6*q->cell.nof_prb:2*q->cell.nof_prb;
// Average in the frequency domain
for (int l=0;l<nsymbols;l++) {
@ -311,24 +410,16 @@ float srslte_chest_dl_rssi(srslte_chest_dl_t *q, cf_t *input, uint32_t port_id)
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)
{
/* 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) {
void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id, uint32_t rxant_id, srslte_sf_t ch_mode){
if (ce != NULL) {
/* Smooth estimates (if applicable) and interpolate */
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 {
average_pilots(q, q->pilot_estimates, q->pilot_estimates_average, port_id);
interpolate_pilots(q, q->pilot_estimates_average, ce, 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, ch_mode);
}
/* Estimate noise power */
if (q->noise_alg == SRSLTE_NOISE_ALG_REFS && q->smooth_filter_len > 0) {
q->noise_estimate[rxant_id][port_id] = estimate_noise_pilots(q, port_id);
@ -340,8 +431,7 @@ int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, u
if (sf_idx == 0 || sf_idx == 5) {
q->noise_estimate[rxant_id][port_id] = estimate_noise_empty_sc(q, input);
}
}
}
}
/* 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 */
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;
}
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++) {
@ -370,7 +494,7 @@ int srslte_chest_dl_estimate_multi(srslte_chest_dl_t *q, cf_t *input[SRSLTE_MAX_
int srslte_chest_dl_estimate(srslte_chest_dl_t *q, cf_t *input, cf_t *ce[SRSLTE_MAX_PORTS], uint32_t sf_idx)
{
uint32_t port_id;
for (port_id=0;port_id<q->cell.nof_ports;port_id++) {
if (srslte_chest_dl_estimate_port(q, input, ce[port_id], sf_idx, port_id, 0)) {
return SRSLTE_ERROR;
@ -380,6 +504,21 @@ int srslte_chest_dl_estimate(srslte_chest_dl_t *q, cf_t *input, cf_t *ce[SRSLTE_
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 n = 0;
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) {
// Note: use only port 0 but average across antennas
float n = 0;
for (int i=0;i<q->last_nof_antennas;i++) {
n += q->rsrp[i][0];
float srslte_chest_dl_get_rsrp_port(srslte_chest_dl_t *q, uint32_t port) {
float n = 0;
for (int i = 0; i < q->last_nof_antennas; i++) {
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 <complex.h>
#include <math.h>
#include <srslte/srslte.h>
#include <srslte/phy/common/phy_common.h>
#include "srslte/config.h"
@ -43,6 +45,9 @@
#define NOF_REFS_SYM (q->cell.nof_prb*SRSLTE_NRE)
#define NOF_REFS_SF (NOF_REFS_SYM*2) // 2 reference symbols per subframe
#define MAX_REFS_SYM (max_prb*SRSLTE_NRE)
#define MAX_REFS_SF (max_prb*SRSLTE_NRE*2) // 2 reference symbols per subframe
/** 3GPP LTE Downlink channel estimator and equalizer.
* Estimates the channel in the resource elements transmitting references and interpolates for the rest
* of the resource grid.
@ -52,52 +57,49 @@
* This object depends on the srslte_refsignal_t object for creating the LTE CSR signal.
*/
int srslte_chest_ul_init(srslte_chest_ul_t *q, srslte_cell_t cell)
int srslte_chest_ul_init(srslte_chest_ul_t *q, uint32_t max_prb)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
if (q != NULL)
{
bzero(q, sizeof(srslte_chest_ul_t));
q->cell = cell;
ret = srslte_refsignal_ul_init(&q->dmrs_signal, cell);
ret = srslte_refsignal_ul_init(&q->dmrs_signal, max_prb);
if (ret != SRSLTE_SUCCESS) {
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
goto clean_exit;
}
q->tmp_noise = srslte_vec_malloc(sizeof(cf_t) * NOF_REFS_SF);
q->tmp_noise = srslte_vec_malloc(sizeof(cf_t) * MAX_REFS_SF);
if (!q->tmp_noise) {
perror("malloc");
goto clean_exit;
}
q->pilot_estimates = srslte_vec_malloc(sizeof(cf_t) * NOF_REFS_SF);
q->pilot_estimates = srslte_vec_malloc(sizeof(cf_t) * MAX_REFS_SF);
if (!q->pilot_estimates) {
perror("malloc");
goto clean_exit;
}
for (int i=0;i<4;i++) {
q->pilot_estimates_tmp[i] = srslte_vec_malloc(sizeof(cf_t) * NOF_REFS_SF);
q->pilot_estimates_tmp[i] = srslte_vec_malloc(sizeof(cf_t) * MAX_REFS_SF);
if (!q->pilot_estimates_tmp[i]) {
perror("malloc");
goto clean_exit;
}
}
q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * (NOF_REFS_SF+1));
q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * (MAX_REFS_SF+1));
if (!q->pilot_recv_signal) {
perror("malloc");
goto clean_exit;
}
q->pilot_known_signal = srslte_vec_malloc(sizeof(cf_t) * (NOF_REFS_SF+1));
q->pilot_known_signal = srslte_vec_malloc(sizeof(cf_t) * (MAX_REFS_SF+1));
if (!q->pilot_known_signal) {
perror("malloc");
goto clean_exit;
}
if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, NOF_REFS_SYM)) {
if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, MAX_REFS_SYM)) {
fprintf(stderr, "Error initializing vector interpolator\n");
goto clean_exit;
}
@ -105,12 +107,17 @@ int srslte_chest_ul_init(srslte_chest_ul_t *q, srslte_cell_t cell)
q->smooth_filter_len = 3;
srslte_chest_ul_set_smooth_filter3_coeff(q, 0.3333);
q->dmrs_signal_configured = false;
q->dmrs_signal_configured = false;
if (srslte_refsignal_dmrs_pusch_pregen_init(&q->dmrs_signal, &q->dmrs_pregen, max_prb)) {
fprintf(stderr, "Error allocating memory for pregenerated signals\n");
goto clean_exit;
}
}
ret = SRSLTE_SUCCESS;
clean_exit:
if (ret != SRSLTE_SUCCESS) {
srslte_chest_ul_free(q);
@ -120,9 +127,8 @@ clean_exit:
void srslte_chest_ul_free(srslte_chest_ul_t *q)
{
if (q->dmrs_signal_configured) {
srslte_refsignal_dmrs_pusch_pregen_free(&q->dmrs_signal, &q->dmrs_pregen);
}
srslte_refsignal_dmrs_pusch_pregen_free(&q->dmrs_signal, &q->dmrs_pregen);
srslte_refsignal_ul_free(&q->dmrs_signal);
if (q->tmp_noise) {
free(q->tmp_noise);
@ -146,6 +152,30 @@ void srslte_chest_ul_free(srslte_chest_ul_t *q)
bzero(q, sizeof(srslte_chest_ul_t));
}
int srslte_chest_ul_set_cell(srslte_chest_ul_t *q, srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
{
if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
ret = srslte_refsignal_ul_set_cell(&q->dmrs_signal, cell);
if (ret != SRSLTE_SUCCESS) {
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
return SRSLTE_ERROR;
}
if (srslte_interp_linear_vector_resize(&q->srslte_interp_linvec, NOF_REFS_SYM)) {
fprintf(stderr, "Error initializing vector interpolator\n");
return SRSLTE_ERROR;
}
}
ret = SRSLTE_SUCCESS;
}
return ret;
}
void srslte_chest_ul_set_cfg(srslte_chest_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
srslte_pucch_cfg_t *pucch_cfg,

@ -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 ret;
if (port_id < 2) {
return 4;
ret = 4;
} 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) {
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) {
if (port_id < 2) {
if (l % 2) {
@ -97,100 +124,205 @@ inline uint32_t srslte_refsignal_cs_nsymbol(uint32_t l, srslte_cp_t cp, uint32_t
return 1+l*SRSLTE_CP_NSYMB(cp);
}
}
/** Allocates and precomputes the Cell-Specific Reference (CSR) signal for
* the 20 slots in a subframe
*/
int srslte_refsignal_cs_init(srslte_refsignal_cs_t * q, srslte_cell_t cell)
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 N_cp, mp;
srslte_sequence_t seq;
int ret = SRSLTE_ERROR_INVALID_INPUTS;
uint32_t mp;
int ret = SRSLTE_ERROR;
if (q != NULL &&
srslte_cell_isvalid(&cell))
{
ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_refsignal_cs_t));
bzero(&seq, sizeof(srslte_sequence_t));
if (srslte_sequence_init(&seq, 2 * 2 * SRSLTE_MAX_PRB)) {
goto free_and_exit;
}
if (SRSLTE_CP_ISNORM(cell.cp)) {
N_cp = 1;
} else {
N_cp = 0;
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;
q->cell = cell;
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) * SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, 2*p));
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;
}
}
}
}
for (ns=0;ns<SRSLTE_NSLOTS_X_FRAME;ns++) {
for (p=0;p<2;p++) {
uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(2*p)/2;
for (l = 0; l < nsymbols; l++) {
/* Compute sequence init value */
uint32_t lp = srslte_refsignal_cs_nsymbol(l, cell.cp, 2*p);
c_init = 1024 * (7 * (ns + 1) + lp + 1) * (2 * cell.id + 1)
+ 2 * cell.id + N_cp;
/* generate sequence for this symbol and slot */
srslte_sequence_set_LTE_pr(&seq, c_init);
/* Compute signal */
for (i = 0; i < 2*q->cell.nof_prb; i++) {
mp = i + SRSLTE_MAX_PRB - cell.nof_prb;
/* save signal */
q->pilots[p][ns/2][SRSLTE_REFSIGNAL_PILOT_IDX(i,(ns%2)*nsymbols+l,q->cell)] =
(1 - 2 * (float) seq.c[2 * mp]) / sqrt(2) +
_Complex_I * (1 - 2 * (float) seq.c[2 * mp + 1]) / sqrt(2);
}
if(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;
}
}
}
}
srslte_sequence_free(&seq);
ret = SRSLTE_SUCCESS;
}
free_and_exit:
if (ret == SRSLTE_ERROR) {
srslte_sequence_free(&seq);
srslte_refsignal_cs_free(q);
srslte_refsignal_free(q);
}
return ret;
}
/** Allocates and precomputes the Cell-Specific Reference (CSR) signal for
* the 20 slots in a subframe
*/
int srslte_refsignal_cs_set_cell(srslte_refsignal_t * q, srslte_cell_t cell)
{
uint32_t c_init;
uint32_t i, ns, l, p;
uint32_t N_cp, mp;
srslte_sequence_t seq;
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));
bzero(&seq, sizeof(srslte_sequence_t));
if (srslte_sequence_init(&seq, 2*2*SRSLTE_MAX_PRB)) {
return SRSLTE_ERROR;
}
if (SRSLTE_CP_ISNORM(cell.cp)) {
N_cp = 1;
} else {
N_cp = 0;
}
for (ns=0;ns<SRSLTE_NSLOTS_X_FRAME;ns++) {
for (p=0;p<2;p++) {
uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(2*p)/2;
for (l = 0; l < nsymbols; l++) {
/* Compute sequence init value */
uint32_t lp = srslte_refsignal_cs_nsymbol(l, cell.cp, 2*p);
c_init = 1024 * (7 * (ns + 1) + lp + 1) * (2 * cell.id + 1)
+ 2 * cell.id + N_cp;
/* generate sequence for this symbol and slot */
srslte_sequence_set_LTE_pr(&seq, 2*2*SRSLTE_MAX_PRB, c_init);
/* Compute signal */
for (i = 0; i < 2*q->cell.nof_prb; i++) {
mp = i + SRSLTE_MAX_PRB - cell.nof_prb;
/* save signal */
q->pilots[p][ns/2][SRSLTE_REFSIGNAL_PILOT_IDX(i,(ns%2)*nsymbols+l,q->cell)] =
(1 - 2 * (float) seq.c[2 * mp]) / sqrt(2) +
_Complex_I * (1 - 2 * (float) seq.c[2 * mp + 1]) / sqrt(2);
}
}
}
}
srslte_sequence_free(&seq);
}
ret = SRSLTE_SUCCESS;
}
return ret;
}
/** Deallocates a srslte_refsignal_cs_t object allocated with srslte_refsignal_cs_init */
void srslte_refsignal_cs_free(srslte_refsignal_cs_t * q)
void srslte_refsignal_free(srslte_refsignal_t * q)
{
int i, p;
for (p=0;p<2;p++) {
for (i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
for (int p=0;p<2;p++) {
for (int i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
if (q->pilots[p][i]) {
free(q->pilots[p][i]);
}
}
}
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 */
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. */
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 <stdlib.h>
#include <complex.h>
#include <srslte/phy/common/phy_common.h>
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/ch_estimation/refsignal_ul.h"
@ -138,8 +139,8 @@ static int generate_n_prs(srslte_refsignal_ul_t * q) {
}
q->n_prs_pusch[delta_ss][ns] = n_prs;
}
srslte_sequence_free(&seq);
}
srslte_sequence_free(&seq);
return SRSLTE_SUCCESS;
}
@ -160,9 +161,9 @@ static int generate_srslte_sequence_hopping_v(srslte_refsignal_ul_t *q) {
return SRSLTE_ERROR;
}
q->v_pusch[ns][delta_ss] = seq.c[ns];
srslte_sequence_free(&seq);
}
}
srslte_sequence_free(&seq);
return SRSLTE_SUCCESS;
}
@ -170,46 +171,24 @@ static int generate_srslte_sequence_hopping_v(srslte_refsignal_ul_t *q) {
/** Initializes srslte_refsignal_ul_t object according to 3GPP 36.211 5.5
*
*/
int srslte_refsignal_ul_init(srslte_refsignal_ul_t * q, srslte_cell_t cell)
int srslte_refsignal_ul_init(srslte_refsignal_ul_t * q, uint32_t max_prb)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && srslte_cell_isvalid(&cell)) {
if (q != NULL) {
ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_refsignal_ul_t));
q->cell = cell;
// Allocate temporal buffer for computing signal argument
q->tmp_arg = srslte_vec_malloc(SRSLTE_NRE * q->cell.nof_prb * sizeof(cf_t));
q->tmp_arg = srslte_vec_malloc(SRSLTE_NRE * max_prb * sizeof(cf_t));
if (!q->tmp_arg) {
perror("malloc");
goto free_and_exit;
}
srslte_pucch_cfg_default(&q->pucch_cfg);
// Precompute n_prs
if (generate_n_prs(q)) {
goto free_and_exit;
}
// Precompute group hopping values u.
if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) {
goto free_and_exit;
}
// Precompute sequence hopping values v. Uses f_ss_pusch
if (generate_srslte_sequence_hopping_v(q)) {
goto free_and_exit;
}
if (srslte_pucch_n_cs_cell(q->cell, q->n_cs_cell)) {
goto free_and_exit;
}
ret = SRSLTE_SUCCESS;
}
free_and_exit:
@ -226,6 +205,45 @@ void srslte_refsignal_ul_free(srslte_refsignal_ul_t * q) {
bzero(q, sizeof(srslte_refsignal_ul_t));
}
/** Initializes srslte_refsignal_ul_t object according to 3GPP 36.211 5.5
*
*/
int srslte_refsignal_ul_set_cell(srslte_refsignal_ul_t * q, srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && srslte_cell_isvalid(&cell)) {
if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
srslte_pucch_cfg_default(&q->pucch_cfg);
// Precompute n_prs
if (generate_n_prs(q)) {
return SRSLTE_ERROR;
}
// Precompute group hopping values u.
if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) {
return SRSLTE_ERROR;
}
// Precompute sequence hopping values v. Uses f_ss_pusch
if (generate_srslte_sequence_hopping_v(q)) {
return SRSLTE_ERROR;
}
if (srslte_pucch_n_cs_cell(q->cell, q->n_cs_cell)) {
return SRSLTE_ERROR;
}
}
ret = SRSLTE_SUCCESS;
}
return ret;
}
void srslte_refsignal_ul_set_cfg(srslte_refsignal_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
srslte_pucch_cfg_t *pucch_cfg,
@ -363,15 +381,38 @@ void compute_r(srslte_refsignal_ul_t *q, uint32_t nof_prb, uint32_t ns, uint32_t
}
int srslte_refsignal_dmrs_pusch_pregen_init(srslte_refsignal_ul_t *q, srslte_refsignal_ul_dmrs_pregen_t *pregen,
uint32_t max_prb)
{
for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) {
for (uint32_t cs=0;cs<SRSLTE_NOF_CSHIFT;cs++) {
pregen->r[cs][sf_idx] = (cf_t**) calloc(sizeof(cf_t*), max_prb + 1);
if (pregen->r[cs][sf_idx]) {
for (uint32_t n=0;n<=max_prb;n++) {
if (srslte_dft_precoding_valid_prb(n)) {
pregen->r[cs][sf_idx][n] = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*n*2*SRSLTE_NRE);
if (pregen->r[cs][sf_idx][n]) {
} else {
return SRSLTE_ERROR;
}
}
}
} else {
return SRSLTE_ERROR;
}
}
}
return SRSLTE_SUCCESS;
}
int srslte_refsignal_dmrs_pusch_pregen(srslte_refsignal_ul_t *q, srslte_refsignal_ul_dmrs_pregen_t *pregen)
{
for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) {
for (uint32_t cs=0;cs<SRSLTE_NOF_CSHIFT;cs++) {
pregen->r[cs][sf_idx] = (cf_t**) calloc(sizeof(cf_t*), q->cell.nof_prb + 1);
if (pregen->r[cs][sf_idx]) {
for (uint32_t n=0;n<=q->cell.nof_prb;n++) {
if (srslte_dft_precoding_valid_prb(n)) {
pregen->r[cs][sf_idx][n] = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*n*2*SRSLTE_NRE);
if (pregen->r[cs][sf_idx][n]) {
if (srslte_refsignal_dmrs_pusch_gen(q, n, sf_idx, cs, pregen->r[cs][sf_idx][n])) {
return SRSLTE_ERROR;

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