diff --git a/CHANGELOG b/CHANGELOG index 8832d4268..3aa324c0a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,25 @@ Change Log for Releases ============================== +## 001.004.000 + * Fixed issue in rv for format1C causing incorrect SIB1 decoding in some networks + * Improved PDCCH decoding BER (fixed incorrect trellis initialization) + * Improved PUCCH RX performance + +## 001.003.000 + +* Bugfixes: + * x300 master clock rate + * PHICH: fixed bug causing more NACKs + * PBCH: fixed bug in encoding function + * channel estimation: fixed issue in time interpolation + * DCI: Fixed bug in Format1A packing + * DCI: Fixed bug in Format1C for RA-RNTI + * DCI: Fixed overflow in MIMO formats + +* Improvements: + * Changed and cleaned DCI blind search API + * Added eNodeB PHY processing functions ## 001.002.000 diff --git a/CMakeLists.txt b/CMakeLists.txt index c77a24fc6..ae8e9c532 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,9 @@ endif(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) ######################################################################## CMAKE_MINIMUM_REQUIRED (VERSION 2.6) PROJECT (SRSLTE) +MESSAGE( STATUS "CMAKE_SYSTEM: " ${CMAKE_SYSTEM} ) +MESSAGE( STATUS "CMAKE_SYSTEM_PROCESSOR: " ${CMAKE_SYSTEM_PROCESSOR} ) +MESSAGE( STATUS "CMAKE_CXX_COMPILER: " ${CMAKE_CXX_COMPILER} ) list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/modules") include(SRSLTEVersion) #sets version information @@ -48,7 +51,9 @@ configure_file( ######################################################################## # Options ######################################################################## -option(DisableMEX "DisableMEX" ON) +option(DisableMEX "DisableMEX" ON) +option(StaticMKL "StaticMKL" OFF) +option(DisableBladeRF "DisableBladeRF" OFF) ######################################################################## # Install Dirs @@ -95,16 +100,28 @@ endif(CMAKE_COMPILER_IS_GNUCXX) if(CMAKE_COMPILER_IS_GNUCC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-write-strings -Wno-format-extra-args -Winline -Wno-unused-result -Wno-format -std=c99 -D_GNU_SOURCE -g") - + if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0") - else(${CMAKE_BUILD_TYPE} STREQUAL "Debug") find_package(SSE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0") if(HAVE_AVX) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mfpmath=sse -mavx -DLV_HAVE_AVX -DLV_HAVE_SSE") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mfpmath=sse -mavx -DLV_HAVE_AVX -DLV_HAVE_SSE") elseif(HAVE_SSE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mfpmath=sse -msse4.1 -DLV_HAVE_SSE") endif(HAVE_AVX) + else(${CMAKE_BUILD_TYPE} STREQUAL "Debug") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3") + find_package(SSE) + if (HAVE_AVX2) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mfpmath=sse -mavx2 -Ofast -funroll-loops -DLV_HAVE_AVX -DLV_HAVE_SSE") + else (HAVE_AVX2) + if(HAVE_AVX) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mfpmath=sse -mavx -Ofast -funroll-loops -DLV_HAVE_AVX -DLV_HAVE_SSE") + elseif(HAVE_SSE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mfpmath=sse -msse4.1 -Ofast -funroll-loops -DLV_HAVE_SSE") + endif(HAVE_AVX) + endif (HAVE_AVX2) + endif(${CMAKE_BUILD_TYPE} STREQUAL "Debug") @@ -149,9 +166,7 @@ add_custom_target(uninstall # Macro to add -fPIC property to static libs ######################################################################## macro(SRSLTE_SET_PIC) - if( CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" ) - set_target_properties(${ARGV} PROPERTIES COMPILE_FLAGS -fPIC) - endif( CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" ) + set_target_properties(${ARGV} PROPERTIES COMPILE_FLAGS -fPIC) endmacro(SRSLTE_SET_PIC) ######################################################################## diff --git a/COPYRIGHT b/COPYRIGHT index 7844c6d07..592199877 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,4 +1,4 @@ -Copyright (C) 2013-2015 Software Radio Systems Limited. All rights reserved. +Copyright (C) 2013-2016 Software Radio Systems Limited. All rights reserved. The following copyright notices are for libraries used within srsLTE: diff --git a/README.md b/README.md index e6597fdde..5df567913 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ srsLTE ======== -srsLTE is a free and open-source LTE library for SDR UE and eNodeB developed by SRS (www.softwareradiosystems.com). The library is highly modular with minimum inter-module or external dependencies. It is entirely written in C and, if available in the system, uses the acceleration library VOLK distributed in GNURadio. +[![Coverity Scan Build Status](https://scan.coverity.com/projects/10045/badge.svg)](https://scan.coverity.com/projects/10045) -**srsLTE is used by srsUE, a full stack (PHY to IP) implementation of an LTE UE. srsUE is available at https://github.com/srslte/srsue** +srsLTE is a free and open-source LTE library for SDR UE and eNodeB developed by SRS (www.softwareradiosystems.com). The library is highly modular with minimum inter-module or external dependencies. It is entirely written in C and, if available in the system, uses the acceleration library VOLK distributed in GNURadio. -*News*: We have just released srsUE 1.2 containing important bugfixes and improvements in the synchronization procedure. Checkout the [CHANGELOG](CHANGELOG) +**srsLTE is used by srsUE, a full stack (PHY to IP) implementation of an LTE UE. srsUE is available at https://github.com/srslte/srsue** The srsLTE software license is AGPLv3. @@ -26,7 +26,6 @@ Current Features: Missing Features: * Closed-loop power control * Semi-Persistent Scheduling - * Aperiodic CQI reports Hardware ======== diff --git a/cmake/modules/FindMKL.cmake b/cmake/modules/FindMKL.cmake index 2320cf065..80adeafd7 100644 --- a/cmake/modules/FindMKL.cmake +++ b/cmake/modules/FindMKL.cmake @@ -5,23 +5,49 @@ # MKL_LIBRARIES - The libraries needed to use mkl # MKL_DEFINITIONS - Compiler switches required for using mkl -find_path(MKL_INCLUDE_DIR +find_path(MKL_INCLUDE_DIR NAMES mkl.h HINTS $ENV{MKL_DIR}/include PATHS) -find_library(MKL_LIBRARY +find_path(MKL_FFTW_INCLUDE_DIR + NAMES fftw3.h + HINTS $ENV{MKL_DIR}/include/fftw + PATHS) + +find_library(MKL_LIBRARIES NAMES mkl_rt HINTS $ENV{MKL_DIR}/lib/intel64 PATHS) -set(MKL_LIBRARIES ${MKL_LIBRARY} ) -set(MKL_INCLUDE_DIRS ${MKL_INCLUDE_DIR} ) +find_library(MKL_CORE + NAMES libmkl_core.a + HINTS $ENV{MKL_DIR}/lib/intel64 + PATHS) + +find_library(MKL_ILP + NAMES libmkl_intel_ilp64.a + HINTS $ENV{MKL_DIR}/lib/intel64 + PATHS) + +find_library(MKL_SEQ + NAMES libmkl_sequential.a + HINTS $ENV{MKL_DIR}/lib/intel64 + PATHS) + +set(MKL_STATIC_LIBRARIES -Wl,--start-group ${MKL_CORE} ${MKL_ILP} ${MKL_SEQ} -Wl,--end-group -lpthread -lm -ldl) +set(MKL_INCLUDE_DIRS ${MKL_INCLUDE_DIR} ${MKL_FFTW_INCLUDE_DIR}) include(FindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRED arguments and set MKL_FOUND to TRUE # if all listed variables are TRUE find_package_handle_standard_args(mkl DEFAULT_MSG - MKL_LIBRARY MKL_INCLUDE_DIR) + MKL_LIBRARIES MKL_CORE MKL_ILP MKL_SEQ MKL_INCLUDE_DIRS) + +if(MKL_FOUND) + MESSAGE(STATUS "Found MKL_INCLUDE_DIRS: ${MKL_INCLUDE_DIRS}" ) + MESSAGE(STATUS "Found MKL_LIBRARIES: ${MKL_LIBRARIES}" ) + MESSAGE(STATUS "Found MKL_STATIC_LIBRARIES: ${MKL_STATIC_LIBRARIES}" ) +endif(MKL_FOUND) -mark_as_advanced(MKL_INCLUDE_DIR MKL_LIBRARY ) +mark_as_advanced(MKL_INCLUDE_DIRS MKL_LIBRARIES MKL_CORE MKL_ILP MKL_SEQ) diff --git a/cmake/modules/FindSSE.cmake b/cmake/modules/FindSSE.cmake index 8647e9413..7b258f70f 100644 --- a/cmake/modules/FindSSE.cmake +++ b/cmake/modules/FindSSE.cmake @@ -1,11 +1,9 @@ -if (NOT CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|^i[3,9]86$") - return() -endif() 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) if (ENABLE_SSE) # @@ -39,11 +37,21 @@ if (ENABLE_SSE) set(CMAKE_REQUIRED_FLAGS "-mavx") check_c_source_runs(" #include - int main() { - __m256i a = _mm256_setzero_si256(); - return 0; + __m256 a, b, c; + 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_add_ps( a, b ); + _mm256_storeu_ps( dst, c ); + for( int i = 0; i < 8; i++ ){ + if( ( src[i] + src[i] ) != dst[i] ){ + return -1; + } + } + return 0; }" HAVE_AVX) endif() @@ -52,7 +60,40 @@ if (ENABLE_SSE) message(STATUS "AVX is enabled - target CPU must support it") endif() endif() + + if (ENABLE_AVX2) + + # + # Check compiler for AVX intrinsics + # + if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG ) + set(CMAKE_REQUIRED_FLAGS "-mavx2") + check_c_source_runs(" + #include + int main() + { + __m256i a, b, c; + const int src[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + int dst[8]; + a = _mm256_loadu_si256( (__m256i*)src ); + b = _mm256_loadu_si256( (__m256i*)src ); + c = _mm256_add_epi32( a, b ); + _mm256_storeu_si256( (__m256i*)dst, c ); + for( int i = 0; i < 8; i++ ){ + if( ( src[i] + src[i] ) != dst[i] ){ + return -1; + } + } + return 0; + }" + HAVE_AVX2) + endif() + + if (HAVE_AVX2) + message(STATUS "AVX2 is enabled - target CPU must support it") + endif() + endif() endif() -mark_as_advanced(HAVE_SSE, HAVE_AVX) \ No newline at end of file +mark_as_advanced(HAVE_SSE, HAVE_AVX, HAVE_AVX2) \ No newline at end of file diff --git a/cmake/modules/SRSLTEVersion.cmake b/cmake/modules/SRSLTEVersion.cmake index 13a83bded..07959f188 100644 --- a/cmake/modules/SRSLTEVersion.cmake +++ b/cmake/modules/SRSLTEVersion.cmake @@ -19,6 +19,6 @@ # SET(SRSLTE_VERSION_MAJOR 001) -SET(SRSLTE_VERSION_MINOR 002) +SET(SRSLTE_VERSION_MINOR 004) SET(SRSLTE_VERSION_PATCH 000) SET(SRSLTE_VERSION_STRING "${SRSLTE_VERSION_MAJOR}.${SRSLTE_VERSION_MINOR}.${SRSLTE_VERSION_PATCH}") diff --git a/matlab/tests/equalizer_test.m b/matlab/tests/equalizer_test.m index 1391d5e53..816a29957 100644 --- a/matlab/tests/equalizer_test.m +++ b/matlab/tests/equalizer_test.m @@ -6,11 +6,11 @@ clear plot_noise_estimation_only=false; -SNR_values_db=100;%linspace(20,35,8); -Nrealizations=1; +SNR_values_db=linspace(0,30,8); +Nrealizations=10; w1=0.1; -w2=0.3; +w2=0.2; enb.NDLRB = 6; % Number of resource blocks @@ -55,7 +55,7 @@ L = gridsize(2); % Number of OFDM symbols in one subframe Ports = gridsize(3); % Number of transmit antenna ports %% Allocate memory -Ntests=2; +Ntests=4; hest=cell(1,Ntests); tmpnoise=cell(1,Ntests); for i=1:Ntests @@ -181,8 +181,8 @@ for i=1:10 rxGrid_sf = rxGrid(:,(i-1)*14+1:i*14); %% Channel Estimation with Matlab - [hest{1}(:,(1:14)+(i-1)*14), tmpnoise{1}(i), hls(:,(1:4*P)+(i-1)*4*P)] = ... - lteDLChannelEstimate2(enb,cec,rxGrid_sf); + [hest{1}(:,(1:14)+(i-1)*14), tmpnoise{1}(i)] = ... + lteDLChannelEstimate(enb,cec,rxGrid_sf); tmpnoise{1}(i)=tmpnoise{1}(i)*sqrt(2)*enb.CellRefP; %% LS-Linear estimation with srsLTE @@ -233,11 +233,6 @@ if (length(SNR_values_db) == 1) fprintf('Mean MMSE Robust %.2f dB\n', 10*log10(MSE(4,nreal,snr_idx))) fprintf('Mean MMSE matlab %.2f dB\n', 10*log10(MSE(1,nreal,snr_idx))) -<<<<<<< HEAD - -======= - ->>>>>>> master end end diff --git a/matlab/tests/pdsch_decode_signal.m b/matlab/tests/pdsch_decode_signal.m index d376c5c3f..72b733eb5 100644 --- a/matlab/tests/pdsch_decode_signal.m +++ b/matlab/tests/pdsch_decode_signal.m @@ -1,6 +1,6 @@ -enb=struct('NCellID',137,'NDLRB',50,'NSubframe',8,'CFI',1,'CyclicPrefix','Normal','CellRefP',2,'Ng','One','PHICHDuration','Normal','DuplexMode','FDD'); +enb=struct('NCellID',313,'NDLRB',75,'NSubframe',5,'CFI',1,'CyclicPrefix','Normal','CellRefP',2,'Ng','One','PHICHDuration','Normal','DuplexMode','FDD'); -RNTI=5; +RNTI=65535; addpath('../../build/srslte/lib/phch/test') @@ -44,12 +44,15 @@ if ~isempty(dci) [sib1, crc] = lteDLSCHDecode(enb, pdsch, trblklen, dlschBits); - [dec2, data, pdschRx2, pdschSymbols2, e_bits] = srslte_pdsch(enb, pdsch, ... + [dec2, data, pdschRx2, pdschSymbols2, e_bits, ce] = srslte_pdsch(enb, pdsch, ... trblklen, ... subframe_rx); + subplot(2,1,1) scatter(real(pdschSymbols{1}),imag(pdschSymbols{1})) + subplot(2,1,2) + scatter(real(pdschSymbols2),imag(pdschSymbols2)) if crc == 0 fprintf('PDSCH Matlab OK.\n\n'); diff --git a/matlab/tests/pdsch_equal.m b/matlab/tests/pdsch_equal.m index d418f485a..1bd949532 100644 --- a/matlab/tests/pdsch_equal.m +++ b/matlab/tests/pdsch_equal.m @@ -100,7 +100,7 @@ for snr_idx=1:length(SNR_values) %% Same with srsLTE if (rmccFgOut.PDSCH.TrBlkSizes(sf_idx+1) > 0) - [dec2, data, pdschRx, pdschSymbols2, cws2] = srslte_pdsch(rmccFgOut, rmccFgOut.PDSCH, ... + [dec2, data, pdschRx, pdschSymbols2, cws2, ce] = srslte_pdsch(rmccFgOut, rmccFgOut.PDSCH, ... rmccFgOut.PDSCH.TrBlkSizes(sf_idx+1), ... subframe_rx); else diff --git a/matlab/tests/prach_detect_test.m b/matlab/tests/prach_detect_test.m index 7a2fc1802..51bda6c21 100644 --- a/matlab/tests/prach_detect_test.m +++ b/matlab/tests/prach_detect_test.m @@ -1,13 +1,13 @@ %% PRACH Detection Conformance Test %clear -d=50;%linspace(4,14,6); +d=80;%linspace(4,14,6); pDetection2 = zeros(2,length(d)); for dd=1:length(d) detect_factor=d(dd); numSubframes = 1; % Number of subframes frames to simulate at each SNR -SNRdB = 10;%linspace(-14,10,8); % SNR points to simulate +SNRdB = 50;%linspace(-14,10,8); % SNR points to simulate foffset = 0.0; % Frequency offset in Hertz delay=0; add_fading=false; @@ -26,7 +26,7 @@ ue.NTxAnts = 1; % Number of transmission antennas prach.Format = 0; % PRACH format: TS36.104, Table 8.4.2.1-1 prach.HighSpeed = 0; % Normal mode: TS36.104, Table 8.4.2.1-1 -prach.FreqOffset = 4; % Default frequency location +prach.FreqOffset = 2; % Default frequency location info = ltePRACHInfo(ue, prach); % PRACH information %% Propagation Channel Configuration @@ -67,9 +67,10 @@ for nSNR = 1:length(SNRdB) % Loop for each subframe for nsf = 1:numSubframes - prach.SeqIdx = 0;%randi(838,1,1)-1; % Logical sequence index: TS36.141, Table A.6-1 + prach.SeqIdx = 41;%randi(838,1,1)-1; % Logical sequence index: TS36.141, Table A.6-1 prach.CyclicShiftIdx = 11;%randi(16,1,1)-1; % Cyclic shift index: TS36.141, Table A.6-1 prach.PreambleIdx = 1;%randi(64,1,1)-1; % Preamble index: TS36.141, Table A.6-1 + prach.TimingOffset = 0; info = ltePRACHInfo(ue, prach); % PRACH information % PRACH transmission @@ -99,7 +100,7 @@ for nSNR = 1:length(SNRdB) rxwave = rxwave((fadinginfo.ChannelFilterDelay + 1):end, :); end - rxwave=x; + rxwave=lteFrequencyCorrect(ue, x, -20); % rxwave=[zeros(delay,1); txwave(1:end-delay)]; % Apply frequency offset diff --git a/matlab/tests/pucch_bler.m b/matlab/tests/pucch_bler.m new file mode 100644 index 000000000..7ab269497 --- /dev/null +++ b/matlab/tests/pucch_bler.m @@ -0,0 +1,134 @@ +clear +ueConfig=struct('NCellID',1,'RNTI',46,'NULRB',25,'CyclicPrefixUL','Normal','NTxAnts',1,'Hopping','Off'); +pucchConfig=struct('NLayers',1,'OrthCover','Off','Shortened',0); + +format_str={'1','1a'}; + +threshold=[0.5 0]; +formats=1; +pucchConfig.ResourceIdx= 0; +pucchConfig.DeltaShift = 2; +pucchConfig.CyclicShifts = 0; +pucchConfig.ResourceSize=2; +ueConfig.NSubframe=9; + +enable_fading=false; + +SNR_values=-5;%linspace(-8,0,8); +Nreal=50; + +% Setup Fading channel model +cfg.Seed = 8; % Random channel seed +cfg.NRxAnts = 1; % 1 receive antenna +cfg.DelayProfile = 'EVA'; % EVA delay spread +cfg.DopplerFreq = 5; % 120Hz Doppler frequency +cfg.MIMOCorrelation = 'Low'; % Low (no) MIMO correlation +cfg.InitTime = 0; % Initialize at time zero +cfg.NTerms = 16; % Oscillators used in fading model +cfg.ModelType = 'GMEDS'; % Rayleigh fading model type +cfg.InitPhase = 'Random'; % Random initial phases +cfg.NormalizePathGains = 'On'; % Normalize delay profile power +cfg.NormalizeTxAnts = 'On'; % Normalize for transmit antennas + +% Setup matlab channel equalizer +cec.PilotAverage = 'UserDefined'; % Type of pilot averaging +cec.FreqWindow = 9; % Frequency window size +cec.TimeWindow = 9; % Time window size +cec.InterpType = 'linear'; % 2D interpolation type +cec.InterpWindow = 'Causal'; % Interpolation window type +cec.InterpWinSize = 1; % Interpolation window size + + +addpath('../../debug/srslte/lib/phch/test') + + +ber=zeros(length(formats),length(SNR_values)); +ber2=zeros(length(formats),length(SNR_values)); +for f=1:length(formats) + nb=formats(f); + for s=1:length(SNR_values) + SNRdB=SNR_values(s); + SNR = 10^(SNRdB/10); % Linear SNR + + errors = 0; + errors2 = 0; + for n=1:Nreal + bits=randi(2,nb-1,1)-1; + + [sym_mat, info]=ltePUCCH1(ueConfig,pucchConfig,bits); + idx=ltePUCCH1Indices(ueConfig,pucchConfig); + [dmrs_mat, info_dmrs]=ltePUCCH1DRS(ueConfig,pucchConfig); + idx_dmrs=ltePUCCH1DRSIndices(ueConfig,pucchConfig); + + % Resource mapping + subframe_tx = lteULResourceGrid(ueConfig); + subframe_tx(idx)=sym_mat; + subframe_tx(idx_dmrs)=dmrs_mat; + + [txWaveform, info] = lteSCFDMAModulate(ueConfig,subframe_tx); + cfg.SamplingRate = info.SamplingRate; + + % Fading + if (enable_fading) + rxWaveform = lteFadingChannel(cfg,txWaveform); + else + rxWaveform = txWaveform; + end + + % Noise Addition + N0 = 1/(sqrt(2.0*double(info.Nfft))*SNR); + noise = N0*complex(randn(size(rxWaveform)), randn(size(rxWaveform))); % Generate noise + rxWaveform = rxWaveform + noise; + + % Demodulate + subframe_rx = lteSCFDMADemodulate(ueConfig, rxWaveform); + + % Perform channel estimation + [hest, nest] = lteULChannelEstimatePUCCH1(ueConfig, pucchConfig, cec, subframe_rx); + + % Equalize + pucchSymbols = lteEqualizeMMSE(subframe_rx(idx), hest(idx), nest); + + % Decoding + bits_rx = ltePUCCH1Decode(ueConfig, pucchConfig, length(bits), pucchSymbols); + + % Check errors + a=size(bits_rx); + if (a(2) ~= 1) + errors = errors + 1; + elseif (formats(f) == 2) + if (a(1) ~= 1) + errors = errors + 1; + elseif (bits_rx(1) ~= bits(1)) + errors = errors + 1; + end + end + + % Decoding srsLTE + [bits_rx,z,ce]= srslte_pucch(ueConfig, pucchConfig, length(bits), subframe_rx, threshold); + + % Check errors + a=size(bits_rx); + if (a(2) ~= 1) + errors2 = errors2 + 1; + elseif (formats(f) == 2) + if (a(1) ~= 1) + errors2 = errors2 + 1; + elseif (bits_rx(1) ~= bits(1)) + errors2 = errors2 + 1; + end + end + + end + ber(f,s)=errors/Nreal; + ber2(f,s)=errors2/Nreal; + fprintf('Format %s, SNR=%.1f dB, errors=%d, errors2=%d\n', format_str{formats(f)},SNRdB,errors,errors2); + end +end + +semilogy(SNR_values,ber,SNR_values,ber2) +xlabel('SNR (dB)') +ylabel('BER') +grid on +legend(format_str(formats)) + diff --git a/matlab/tests/pusch_encode_test.m b/matlab/tests/pusch_encode_test.m index 13a94a7b5..5d09e88f5 100644 --- a/matlab/tests/pusch_encode_test.m +++ b/matlab/tests/pusch_encode_test.m @@ -3,11 +3,11 @@ puschConfig=struct('NLayers',1,'OrthCover','Off','Shortened',0,'NBundled',0); addpath('../../build//srslte/lib/phch/test') -cqilen=[0 4 20]; +cqilen=0;%[0 4 20]; mods={'64QAM'}; rvs=0; -betas=[0 5.0, 20.0]; -for p=1:ueConfig.NULRB +betas=0;%[0 5.0, 20.0]; +for p=1 for i=0:26 for m=1:length(mods) for r=1:length(rvs) diff --git a/srslte/CMakeLists.txt b/srslte/CMakeLists.txt index 0ecf9ddf6..d4f336d57 100644 --- a/srslte/CMakeLists.txt +++ b/srslte/CMakeLists.txt @@ -61,11 +61,13 @@ if(UHD_FOUND) link_directories(${UHD_LIBRARY_DIRS}) endif(UHD_FOUND) -find_package(bladeRF) -if(BLADERF_FOUND) - include_directories(${BLADERF_INCLUDE_DIRS}) - link_directories(${BLADERF_LIBRARY_DIRS}) -endif(BLADERF_FOUND) +if(NOT DisableBladeRF) + find_package(bladeRF) + if(BLADERF_FOUND) + include_directories(${BLADERF_INCLUDE_DIRS}) + link_directories(${BLADERF_LIBRARY_DIRS}) + endif(BLADERF_FOUND) +endif(NOT DisableBladeRF) if(BLADERF_FOUND OR UHD_FOUND) set(RF_FOUND TRUE CACHE INTERNAL "RF frontend found") diff --git a/srslte/examples/cell_measurement.c b/srslte/examples/cell_measurement.c index 6de938c78..de9962513 100644 --- a/srslte/examples/cell_measurement.c +++ b/srslte/examples/cell_measurement.c @@ -307,8 +307,7 @@ int main(int argc, char **argv) { case DECODE_SIB: /* We are looking for SI Blocks, search only in appropiate places */ if ((srslte_ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%2)==0)) { - n = srslte_ue_dl_decode_rnti_rv(&ue_dl, sf_buffer, data, srslte_ue_sync_get_sfidx(&ue_sync), SRSLTE_SIRNTI, - ((int) ceilf((float)3*(((sfn)/2)%4)/2))%4); + n = srslte_ue_dl_decode(&ue_dl, sf_buffer, data, sfn*10+srslte_ue_sync_get_sfidx(&ue_sync)); if (n < 0) { fprintf(stderr, "Error decoding UE DL\n");fflush(stdout); return -1; @@ -357,7 +356,7 @@ int main(int argc, char **argv) { printf("CFO: %+8.4f kHz, SFO: %+8.4f kHz, RSSI: %5.1f dBm, RSSI/ref-symbol: %+5.1f dBm, " "RSRP: %+5.1f dBm, RSRQ: %5.1f dB, SNR: %5.1f dB\r", - srslte_ue_sync_get_cfo(&ue_sync)/1000, srslte_ue_sync_get_sfo(&ue_sync)/1000, + srslte_ue_sync_get_cfo(&ue_sync)/1000, srslte_ue_sync_get_sfo(&ue_sync), 10*log10(rssi*1000) - rx_gain_offset, 10*log10(rssi_utra*1000)- rx_gain_offset, 10*log10(rsrp*1000) - rx_gain_offset, diff --git a/srslte/examples/cell_search.c b/srslte/examples/cell_search.c index fb4933ebd..02c3d8ada 100644 --- a/srslte/examples/cell_search.c +++ b/srslte/examples/cell_search.c @@ -218,6 +218,7 @@ 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); diff --git a/srslte/examples/pdsch_enodeb.c b/srslte/examples/pdsch_enodeb.c index fdacde801..28c020708 100644 --- a/srslte/examples/pdsch_enodeb.c +++ b/srslte/examples/pdsch_enodeb.c @@ -57,7 +57,6 @@ char *output_file_name = NULL; srslte_cell_t cell = { 25, // nof_prb 1, // nof_ports - 0, // bw idx 0, // cell_id SRSLTE_CP_NORM, // cyclic prefix SRSLTE_PHICH_R_1, // PHICH resources @@ -624,7 +623,7 @@ int main(int argc, char **argv) { } /* Encode PDSCH */ - if (srslte_pdsch_encode(&pdsch, &pdsch_cfg, &softbuffer, data, sf_symbols)) { + if (srslte_pdsch_encode(&pdsch, &pdsch_cfg, &softbuffer, data, UE_CRNTI, sf_symbols)) { fprintf(stderr, "Error encoding PDSCH\n"); exit(-1); } diff --git a/srslte/examples/pdsch_ue.c b/srslte/examples/pdsch_ue.c index b0a9c5fd6..a9f48b941 100644 --- a/srslte/examples/pdsch_ue.c +++ b/srslte/examples/pdsch_ue.c @@ -426,6 +426,7 @@ int main(int argc, char **argv) { #ifndef DISABLE_GRAPHICS if (!prog_args.disable_plots) { init_plots(cell); + sleep(1); } #endif @@ -494,7 +495,7 @@ 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%8)==0)) { + if ((srslte_ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%2)==0)) { decode_pdsch = true; } else { decode_pdsch = false; @@ -502,28 +503,15 @@ int main(int argc, char **argv) { } if (decode_pdsch) { INFO("Attempting DL decode SFN=%d\n", sfn); - if (prog_args.rnti != SRSLTE_SIRNTI) { - n = srslte_ue_dl_decode(&ue_dl, &sf_buffer[prog_args.time_offset], data, srslte_ue_sync_get_sfidx(&ue_sync)); - } else { - // RV for SIB1 is predefined - uint32_t k = (sfn/2)%4; - uint32_t rv = ((uint32_t) ceilf((float)1.5*k))%4; - n = srslte_ue_dl_decode_rnti_rv(&ue_dl, &sf_buffer[prog_args.time_offset], data, - srslte_ue_sync_get_sfidx(&ue_sync), - SRSLTE_SIRNTI, rv); - - /* - if (!n) { - printf("Saving signal...\n"); - srslte_ue_dl_save_signal(&ue_dl, &ue_dl.softbuffer, sfn*10+srslte_ue_sync_get_sfidx(&ue_sync), rv); - exit(-1); - } - */ - } + n = srslte_ue_dl_decode(&ue_dl, + &sf_buffer[prog_args.time_offset], + data, + sfn*10+srslte_ue_sync_get_sfidx(&ue_sync)); + 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); @@ -536,7 +524,7 @@ int main(int argc, char **argv) { memcmp(&ue_dl.dl_dci.type2_alloc, &old_dl_dci.type2_alloc, sizeof(srslte_ra_type2_t))) { memcpy(&old_dl_dci, &ue_dl.dl_dci, sizeof(srslte_ra_dl_dci_t)); - fflush(stdout);printf("\nCFI:\t%d\n", ue_dl.cfi); + fflush(stdout); printf("Format: %s\n", srslte_dci_format_string(ue_dl.dci_format)); srslte_ra_pdsch_fprint(stdout, &old_dl_dci, cell.nof_prb); srslte_ra_dl_grant_fprint(stdout, &ue_dl.pdsch_cfg.grant); @@ -702,14 +690,16 @@ void *plot_thread_run(void *arg) { tmp_plot[i] = -80; } } + int sz = srslte_symbol_sz(ue_dl.cell.nof_prb); + bzero(tmp_plot2, sizeof(float)*sz); + int g = (sz - 12*ue_dl.cell.nof_prb)/2; for (i = 0; i < 12*ue_dl.cell.nof_prb; i++) { - tmp_plot2[i] = 20 * log10f(cabsf(ue_dl.ce[0][i])); - if (isinf(tmp_plot2[i])) { - tmp_plot2[i] = -80; + tmp_plot2[g+i] = 20 * log10(cabs(ue_dl.ce[0][i])); + if (isinf(tmp_plot2[g+i])) { + tmp_plot2[g+i] = -80; } } - - plot_real_setNewData(&pce, tmp_plot2, i); + plot_real_setNewData(&pce, tmp_plot2, sz); if (!prog_args.input_file_name) { if (plot_track) { diff --git a/srslte/examples/synch_file.c b/srslte/examples/synch_file.c index 798db953e..a9e3e7146 100644 --- a/srslte/examples/synch_file.c +++ b/srslte/examples/synch_file.c @@ -182,7 +182,7 @@ int main(int argc, char **argv) { } gettimeofday(&tdata[2], NULL); get_time_interval(tdata); - printf("done in %d s %d ms\n", (int) tdata[0].tv_sec, (int) tdata[0].tv_usec/1000); + printf("done in %ld s %ld ms\n", (int) tdata[0].tv_sec, (int) tdata[0].tv_usec/1000); printf("\n\tFr.Cnt\tN_id_2\tN_id_1\tSubf\tPSS Peak/Avg\tIdx\tm0\tm1\tCFO\n"); printf("\t===============================================================================\n"); diff --git a/srslte/include/srslte/ch_estimation/chest_ul.h b/srslte/include/srslte/ch_estimation/chest_ul.h index 37800d02a..90a706cc7 100644 --- a/srslte/include/srslte/ch_estimation/chest_ul.h +++ b/srslte/include/srslte/ch_estimation/chest_ul.h @@ -57,6 +57,7 @@ typedef struct { cf_t *pilot_estimates; cf_t *pilot_recv_signal; + cf_t *pilot_known_signal; cf_t *tmp_noise; #ifdef FREQ_SEL_SNR @@ -99,6 +100,13 @@ SRSLTE_API int srslte_chest_ul_estimate(srslte_chest_ul_t *q, uint32_t cyclic_shift_for_dmrs, uint32_t n_prb[2]); +SRSLTE_API int srslte_chest_ul_estimate_pucch(srslte_chest_ul_t *q, + cf_t *input, + cf_t *ce, + srslte_pucch_format_t format, + uint32_t n_pucch, + uint32_t sf_idx); + SRSLTE_API float srslte_chest_ul_get_noise_estimate(srslte_chest_ul_t *q); SRSLTE_API float srslte_chest_ul_get_snr(srslte_chest_ul_t *q); diff --git a/srslte/include/srslte/ch_estimation/refsignal_ul.h b/srslte/include/srslte/ch_estimation/refsignal_ul.h index 0d8b7f5fb..1c6814b63 100644 --- a/srslte/include/srslte/ch_estimation/refsignal_ul.h +++ b/srslte/include/srslte/ch_estimation/refsignal_ul.h @@ -46,6 +46,7 @@ #define SRSLTE_REFSIGNAL_UL_L(ns_idx, cp) ((ns_idx+1)*SRSLTE_CP_NSYMB(cp)-4) +/* PUSCH DMRS common configuration (received in SIB2) */ typedef struct SRSLTE_API { uint32_t cyclic_shift; uint32_t delta_ss; @@ -53,15 +54,19 @@ typedef struct SRSLTE_API { bool sequence_hopping_en; }srslte_refsignal_dmrs_pusch_cfg_t; + typedef struct SRSLTE_API { + // Common Configuration uint32_t subframe_config; - uint32_t I_srs; uint32_t bw_cfg; + + // Dedicated configuration + uint32_t B; + uint32_t b_hop; uint32_t n_srs; + uint32_t I_srs; uint32_t k_tc; uint32_t n_rrc; - uint32_t B; - uint32_t b_hop; bool configured; }srslte_refsignal_srs_cfg_t; @@ -101,6 +106,13 @@ SRSLTE_API void srslte_refsignal_ul_set_cfg(srslte_refsignal_ul_t *q, SRSLTE_API void srslte_refsignal_r_uv_arg_1prb(float *arg, uint32_t u); +SRSLTE_API uint32_t srslte_refsignal_dmrs_N_rs(srslte_pucch_format_t format, + srslte_cp_t cp); + +SRSLTE_API uint32_t srslte_refsignal_dmrs_pucch_symbol(uint32_t m, + srslte_pucch_format_t format, + srslte_cp_t cp); + 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); @@ -150,6 +162,12 @@ SRSLTE_API int srslte_refsignal_dmrs_pucch_put(srslte_refsignal_ul_t* q, cf_t *r_pucch, cf_t *output); +SRSLTE_API int srslte_refsignal_dmrs_pucch_get(srslte_refsignal_ul_t* q, + srslte_pucch_format_t format, + uint32_t n_pucch, + cf_t *input, + cf_t *r_pucch); + SRSLTE_API int srslte_refsignal_srs_pregen(srslte_refsignal_ul_t *q, srslte_refsignal_srs_pregen_t *pregen); diff --git a/srslte/include/srslte/common/phy_common.h b/srslte/include/srslte/common/phy_common.h index 23f9a9930..aac6702ca 100644 --- a/srslte/include/srslte/common/phy_common.h +++ b/srslte/include/srslte/common/phy_common.h @@ -159,7 +159,6 @@ typedef enum { typedef struct SRSLTE_API { uint32_t nof_prb; uint32_t nof_ports; - uint32_t bw_idx; uint32_t id; srslte_cp_t cp; srslte_phich_length_t phich_length; @@ -248,8 +247,12 @@ SRSLTE_API char *srslte_mod_string(srslte_mod_t mod); SRSLTE_API uint32_t srslte_mod_bits_x_symbol(srslte_mod_t mod); +SRSLTE_API int srslte_band_get_band(uint32_t earfcn); + SRSLTE_API float srslte_band_fd(uint32_t earfcn); +SRSLTE_API float srslte_band_fu(uint32_t earfcn); + SRSLTE_API int srslte_band_get_fd_band(uint32_t band, srslte_earfcn_t *earfcn, int earfcn_start, diff --git a/srslte/include/srslte/dft/dft_precoding.h b/srslte/include/srslte/dft/dft_precoding.h index eac79e6c8..e860e5b7b 100644 --- a/srslte/include/srslte/dft/dft_precoding.h +++ b/srslte/include/srslte/dft/dft_precoding.h @@ -44,8 +44,8 @@ typedef struct SRSLTE_API { uint32_t max_prb; - srslte_dft_plan_t dft_plan[SRSLTE_MAX_PRB]; - srslte_dft_plan_t idft_plan[SRSLTE_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; diff --git a/srslte/include/srslte/enb/enb_dl.h b/srslte/include/srslte/enb/enb_dl.h index 7f3b034e0..560441c70 100644 --- a/srslte/include/srslte/enb/enb_dl.h +++ b/srslte/include/srslte/enb/enb_dl.h @@ -87,12 +87,12 @@ typedef struct SRSLTE_API { float sss_signal0[SRSLTE_SSS_LEN]; float sss_signal5[SRSLTE_SSS_LEN]; - uint32_t nof_rnti; + float tx_amp; } srslte_enb_dl_t; typedef struct { - uint32_t rnti_idx; + uint16_t rnti; srslte_ra_dl_dci_t grant; srslte_dci_location_t location; srslte_softbuffer_tx_t *softbuffer; @@ -100,20 +100,24 @@ typedef struct { } srslte_enb_dl_pdsch_t; typedef struct { + uint16_t rnti; uint8_t ack; - uint32_t rnti_idx; + uint32_t n_prb_lowest; + uint32_t n_dmrs; } srslte_enb_dl_phich_t; /* This function shall be called just after the initial synchronization */ SRSLTE_API int srslte_enb_dl_init(srslte_enb_dl_t *q, - srslte_cell_t cell, - uint32_t nof_rntis); + srslte_cell_t cell); 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, uint32_t cfi); +SRSLTE_API void srslte_enb_dl_set_amp(srslte_enb_dl_t *q, + float amp); + SRSLTE_API void srslte_enb_dl_clear_sf(srslte_enb_dl_t *q); SRSLTE_API void srslte_enb_dl_put_sync(srslte_enb_dl_t *q, @@ -140,17 +144,16 @@ SRSLTE_API void srslte_enb_dl_put_base(srslte_enb_dl_t *q, SRSLTE_API void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q, cf_t *signal_buffer); -SRSLTE_API int srslte_enb_dl_cfg_rnti(srslte_enb_dl_t *q, - uint32_t idx, +SRSLTE_API int srslte_enb_dl_add_rnti(srslte_enb_dl_t *q, uint16_t rnti); -SRSLTE_API int srslte_enb_dl_rem_rnti(srslte_enb_dl_t *q, - uint32_t idx); +SRSLTE_API void srslte_enb_dl_rem_rnti(srslte_enb_dl_t *q, + uint16_t rnti); SRSLTE_API int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q, srslte_ra_dl_grant_t *grant, srslte_softbuffer_tx_t *softbuffer, - uint32_t rnti_idx, + uint16_t rnti, uint32_t rv_idx, uint32_t sf_idx, uint8_t *data); @@ -159,13 +162,13 @@ 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, - uint32_t rnti_idx, + uint16_t rnti, uint32_t sf_idx); SRSLTE_API int srslte_enb_dl_put_pdcch_ul(srslte_enb_dl_t *q, srslte_ra_ul_dci_t *grant, srslte_dci_location_t location, - uint32_t rnti_idx, + uint16_t rnti, uint32_t sf_idx); diff --git a/srslte/include/srslte/enb/enb_ul.h b/srslte/include/srslte/enb/enb_ul.h index bd1f0c908..6e426b81c 100644 --- a/srslte/include/srslte/enb/enb_ul.h +++ b/srslte/include/srslte/enb/enb_ul.h @@ -58,9 +58,16 @@ typedef struct { uint32_t n_dmrs; } srslte_enb_ul_phich_info_t; +typedef struct { + bool uci_cfg_en; + bool srs_cfg_en; + srslte_uci_cfg_t uci_cfg; + srslte_refsignal_srs_cfg_t srs_cfg; + srslte_pucch_sched_t pucch_sched; +} srslte_enb_ul_user_t; + typedef struct SRSLTE_API { srslte_cell_t cell; - uint32_t nof_rnti; cf_t *sf_symbols; cf_t *ce; @@ -73,18 +80,23 @@ typedef struct SRSLTE_API { srslte_prach_t prach; srslte_pusch_cfg_t pusch_cfg; - + + srslte_pusch_hopping_cfg_t hopping_cfg; + + // Configuration for each user + srslte_enb_ul_user_t **users; + } srslte_enb_ul_t; typedef struct { - uint32_t rnti_idx; + uint16_t rnti; srslte_ra_ul_dci_t grant; srslte_dci_location_t location; uint32_t rv_idx; uint32_t current_tx_nb; - bool needs_pdcch; uint8_t *data; srslte_softbuffer_rx_t *softbuffer; + bool needs_pdcch; } srslte_enb_ul_pusch_t; /* This function shall be called just after the initial synchronization */ @@ -92,25 +104,36 @@ 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_pucch_cfg_t *pucch_cfg, - uint32_t nof_rntis); + srslte_pusch_hopping_cfg_t *hopping_cfg, + srslte_pucch_cfg_t *pucch_cfg); SRSLTE_API void srslte_enb_ul_free(srslte_enb_ul_t *q); -SRSLTE_API int srslte_enb_ul_cfg_rnti(srslte_enb_ul_t *q, - uint32_t idx, +SRSLTE_API int srslte_enb_ul_add_rnti(srslte_enb_ul_t *q, + uint16_t rnti); + +SRSLTE_API void srslte_enb_ul_rem_rnti(srslte_enb_ul_t *q, uint16_t rnti); -SRSLTE_API int srslte_enb_ul_rem_rnti(srslte_enb_ul_t *q, - uint32_t idx); +SRSLTE_API int srslte_enb_ul_cfg_ue(srslte_enb_ul_t *q, uint16_t rnti, + srslte_uci_cfg_t *uci_cfg, + srslte_pucch_sched_t *pucch_sched, + srslte_refsignal_srs_cfg_t *srs_cfg); + SRSLTE_API void srslte_enb_ul_fft(srslte_enb_ul_t *q, cf_t *signal_buffer); +SRSLTE_API int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, + uint16_t rnti, + uint32_t pdcch_n_cce, + uint32_t sf_rx, + srslte_uci_data_t *uci_data); + SRSLTE_API int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q, srslte_ra_ul_grant_t *grant, srslte_softbuffer_rx_t *softbuffer, - uint32_t rnti_idx, + uint16_t rnti, uint32_t rv_idx, uint32_t current_tx_nb, uint8_t *data, @@ -123,7 +146,7 @@ SRSLTE_API int srslte_enb_ul_detect_prach(srslte_enb_ul_t *q, cf_t *signal, uint32_t *indices, float *offsets, - float *peak2avg); + float *peak2avg); #endif diff --git a/srslte/include/srslte/io/netsink.h b/srslte/include/srslte/io/netsink.h index 154d33feb..3339716c1 100644 --- a/srslte/include/srslte/io/netsink.h +++ b/srslte/include/srslte/io/netsink.h @@ -59,8 +59,8 @@ typedef struct SRSLTE_API { }srslte_netsink_t; SRSLTE_API int srslte_netsink_init(srslte_netsink_t *q, - char *address, - int port, + const char *address, + uint16_t port, srslte_netsink_type_t type); SRSLTE_API void srslte_netsink_free(srslte_netsink_t *q); diff --git a/srslte/include/srslte/io/netsource.h b/srslte/include/srslte/io/netsource.h index b581a1ef1..e10d8d644 100644 --- a/srslte/include/srslte/io/netsource.h +++ b/srslte/include/srslte/io/netsource.h @@ -60,8 +60,8 @@ typedef struct SRSLTE_API { }srslte_netsource_t; SRSLTE_API int srslte_netsource_init(srslte_netsource_t *q, - char *address, - int port, + const char *address, + uint16_t port, srslte_netsource_type_t type); SRSLTE_API void srslte_netsource_free(srslte_netsource_t *q); diff --git a/srslte/include/srslte/phch/cqi.h b/srslte/include/srslte/phch/cqi.h index 68ed8ca2a..9a7b243be 100644 --- a/srslte/include/srslte/phch/cqi.h +++ b/srslte/include/srslte/phch/cqi.h @@ -40,7 +40,7 @@ #include "srslte/config.h" #include "srslte/common/phy_common.h" -#define SRSLTE_CQI_MAX_BITS 20 +#define SRSLTE_CQI_MAX_BITS 64 typedef struct { bool configured; @@ -104,6 +104,8 @@ typedef struct { } srslte_cqi_value_t; +SRSLTE_API int srslte_cqi_size(srslte_cqi_value_t *value); + SRSLTE_API int srslte_cqi_value_pack(srslte_cqi_value_t *value, uint8_t buff[SRSLTE_CQI_MAX_BITS]); @@ -119,11 +121,28 @@ SRSLTE_API int srslte_cqi_format2_wideband_pack(srslte_cqi_format2_wideband_t *m SRSLTE_API int srslte_cqi_format2_subband_pack(srslte_cqi_format2_subband_t *msg, uint8_t buff[SRSLTE_CQI_MAX_BITS]); +SRSLTE_API int srslte_cqi_value_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], + srslte_cqi_value_t *value); + +SRSLTE_API int srslte_cqi_hl_subband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], + srslte_cqi_hl_subband_t *msg); + +SRSLTE_API int srslte_cqi_ue_subband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], + srslte_cqi_ue_subband_t *msg); + +SRSLTE_API int srslte_cqi_format2_wideband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], + srslte_cqi_format2_wideband_t *msg); + +SRSLTE_API int srslte_cqi_format2_subband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], + srslte_cqi_format2_subband_t *msg); + SRSLTE_API bool srslte_cqi_send(uint32_t I_cqi_pmi, uint32_t tti); SRSLTE_API uint8_t srslte_cqi_from_snr(float snr); +SRSLTE_API float srslte_cqi_to_coderate(uint32_t cqi); + SRSLTE_API int srslte_cqi_hl_get_subband_size(int num_prbs); SRSLTE_API int srslte_cqi_hl_get_no_subbands(int num_prbs); diff --git a/srslte/include/srslte/phch/dci.h b/srslte/include/srslte/phch/dci.h index c3fe268e1..dcc8cf215 100644 --- a/srslte/include/srslte/phch/dci.h +++ b/srslte/include/srslte/phch/dci.h @@ -43,10 +43,12 @@ #include "srslte/common/phy_common.h" #include "srslte/phch/ra.h" -#define SRSLTE_DCI_MAX_BITS 57 +#define SRSLTE_DCI_MAX_BITS 128 #define SRSLTE_RAR_GRANT_LEN 20 +SRSLTE_API extern int harq_pid_len; + typedef enum { SRSLTE_DCI_FORMAT0 = 0, SRSLTE_DCI_FORMAT1, diff --git a/srslte/include/srslte/phch/pdcch.h b/srslte/include/srslte/phch/pdcch.h index b0f09a898..5f080cbd8 100644 --- a/srslte/include/srslte/phch/pdcch.h +++ b/srslte/include/srslte/phch/pdcch.h @@ -90,6 +90,12 @@ SRSLTE_API int srslte_pdcch_init(srslte_pdcch_t *q, SRSLTE_API void srslte_pdcch_free(srslte_pdcch_t *q); +SRSLTE_API void srslte_pdcch_set_cfi(srslte_pdcch_t *q, + uint32_t cfi); + +SRSLTE_API float srslte_pdcch_coderate(uint32_t nof_bits, + uint32_t l); + /* Encoding function */ SRSLTE_API int srslte_pdcch_encode(srslte_pdcch_t *q, srslte_dci_msg_t *msg, diff --git a/srslte/include/srslte/phch/pdsch.h b/srslte/include/srslte/phch/pdsch.h index b65260eac..305402de5 100644 --- a/srslte/include/srslte/phch/pdsch.h +++ b/srslte/include/srslte/phch/pdsch.h @@ -47,13 +47,15 @@ #include "srslte/phch/sch.h" #include "srslte/phch/pdsch_cfg.h" +typedef struct { + srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME]; +} srslte_pdsch_user_t; + /* PDSCH object */ typedef struct SRSLTE_API { srslte_cell_t cell; uint32_t max_re; - bool rnti_is_set; - uint16_t rnti; /* buffers */ // void buffers are shared for tx and rx @@ -66,12 +68,8 @@ typedef struct SRSLTE_API { /* tx & rx objects */ srslte_modem_table_t mod[4]; - srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME]; - // This is to generate the scrambling seq for multiple CRNTIs - uint32_t nof_crnti; - srslte_sequence_t *seq_multi[SRSLTE_NSUBFRAMES_X_FRAME]; - uint16_t *rnti_multi; + srslte_pdsch_user_t **users; srslte_sch_t dl_sch; @@ -85,15 +83,11 @@ SRSLTE_API void srslte_pdsch_free(srslte_pdsch_t *q); SRSLTE_API int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti); -SRSLTE_API int srslte_pdsch_init_rnti_multi(srslte_pdsch_t *q, - uint32_t nof_rntis); - -SRSLTE_API int srslte_pdsch_set_rnti_multi(srslte_pdsch_t *q, - uint32_t idx, - uint16_t rnti); +SRSLTE_API void srslte_pdsch_free_rnti(srslte_pdsch_t *q, + uint16_t rnti); -SRSLTE_API uint16_t srslte_pdsch_get_rnti_multi(srslte_pdsch_t *q, - uint32_t idx); +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_cell_t cell, @@ -106,39 +100,18 @@ 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_API int srslte_pdsch_encode_rnti_idx(srslte_pdsch_t *q, - srslte_pdsch_cfg_t *cfg, - srslte_softbuffer_tx_t *softbuffer, - uint8_t *data, - uint32_t rnti_idx, - cf_t *sf_symbols[SRSLTE_MAX_PORTS]); - -SRSLTE_API int srslte_pdsch_encode_rnti(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_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, + uint16_t rnti, uint8_t *data); -SRSLTE_API int srslte_pdsch_decode_rnti(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, - uint16_t rnti, - uint8_t *data); - SRSLTE_API float srslte_pdsch_average_noi(srslte_pdsch_t *q); SRSLTE_API uint32_t srslte_pdsch_last_noi(srslte_pdsch_t *q); diff --git a/srslte/include/srslte/phch/prach.h b/srslte/include/srslte/phch/prach.h index de2085317..346447e8b 100644 --- a/srslte/include/srslte/phch/prach.h +++ b/srslte/include/srslte/phch/prach.h @@ -110,7 +110,8 @@ typedef enum SRSLTE_API { typedef struct { uint32_t config_idx; uint32_t root_seq_idx; - uint32_t zero_corr_zone; + uint32_t zero_corr_zone; + uint32_t freq_offset; bool hs_flag; } srslte_prach_cfg_t; @@ -155,7 +156,7 @@ SRSLTE_API int srslte_prach_detect_offset(srslte_prach_t *p, uint32_t sig_len, uint32_t *indices, float *t_offsets, - float *peak_to_avg, + float *peak_to_avg, uint32_t *ind_len); SRSLTE_API void srslte_prach_set_detect_factor(srslte_prach_t *p, diff --git a/srslte/include/srslte/phch/pucch.h b/srslte/include/srslte/phch/pucch.h index 92b493fa4..2ed0743b4 100644 --- a/srslte/include/srslte/phch/pucch.h +++ b/srslte/include/srslte/phch/pucch.h @@ -40,10 +40,11 @@ #include "srslte/common/sequence.h" #include "srslte/modem/mod.h" #include "srslte/phch/cqi.h" +#include "srslte/phch/uci.h" #define SRSLTE_PUCCH_N_SEQ 12 #define SRSLTE_PUCCH_MAX_BITS SRSLTE_CQI_MAX_BITS -#define SRSLTE_PUCCH_MAX_SYMBOLS 120 +#define SRSLTE_PUCCH_MAX_SYMBOLS 120 typedef enum SRSLTE_API { SRSLTE_PUCCH_FORMAT_1 = 0, @@ -51,7 +52,8 @@ typedef enum SRSLTE_API { SRSLTE_PUCCH_FORMAT_1B, SRSLTE_PUCCH_FORMAT_2, SRSLTE_PUCCH_FORMAT_2A, - SRSLTE_PUCCH_FORMAT_2B + SRSLTE_PUCCH_FORMAT_2B, + SRSLTE_PUCCH_FORMAT_ERROR, } srslte_pucch_format_t; typedef struct SRSLTE_API { @@ -64,15 +66,19 @@ typedef struct SRSLTE_API { }srslte_pucch_sched_t; typedef struct SRSLTE_API { + // Common configuration uint32_t delta_pucch_shift; uint32_t n_rb_2; uint32_t N_cs; + uint32_t n1_pucch_an; + + // SRS configuration bool srs_configured; uint32_t srs_cs_subf_cfg; bool srs_simul_ack; } srslte_pucch_cfg_t; -/* PUSCH object */ +/* PUCCH object */ typedef struct SRSLTE_API { srslte_cell_t cell; srslte_pucch_cfg_t pucch_cfg; @@ -84,10 +90,21 @@ typedef struct SRSLTE_API { uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB]; uint32_t f_gh[SRSLTE_NSLOTS_X_FRAME]; float tmp_arg[SRSLTE_PUCCH_N_SEQ]; - cf_t z[SRSLTE_PUCCH_MAX_SYMBOLS]; + + cf_t *z; + cf_t *z_tmp; + cf_t *ce; + bool rnti_is_set; bool shortened; bool group_hopping_en; + + float threshold_format1; + float threshold_format1a; + float last_corr; + uint32_t last_n_prb; + uint32_t last_n_pucch; + }srslte_pucch_t; @@ -100,6 +117,10 @@ 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 int srslte_pucch_set_crnti(srslte_pucch_t *q, uint16_t c_rnti); @@ -107,6 +128,8 @@ SRSLTE_API uint32_t srslte_pucch_nof_symbols(srslte_pucch_cfg_t *cfg, srslte_pucch_format_t format, bool shortened); +SRSLTE_API float srslte_pucch_get_last_corr(srslte_pucch_t* q); + SRSLTE_API int srslte_pucch_encode(srslte_pucch_t *q, srslte_pucch_format_t format, uint32_t n_pucch, // n_pucch_1 or n_pucch_2 depending on format @@ -114,6 +137,15 @@ SRSLTE_API int srslte_pucch_encode(srslte_pucch_t *q, uint8_t bits[SRSLTE_PUCCH_MAX_BITS], cf_t *sf_symbols); +SRSLTE_API int srslte_pucch_decode(srslte_pucch_t *q, + srslte_pucch_format_t format, + uint32_t n_pucch, // n_pucch_1 or n_pucch_2 depending on format + uint32_t sf_idx, + cf_t *sf_symbols, + cf_t *ce, + float noise_estimate, + uint8_t bits[SRSLTE_PUCCH_MAX_BITS]); + SRSLTE_API float srslte_pucch_alpha_format1(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB], srslte_pucch_cfg_t *cfg, uint32_t n_pucch, @@ -135,6 +167,21 @@ SRSLTE_API uint32_t srslte_pucch_m(srslte_pucch_cfg_t *cfg, uint32_t n_pucch, srslte_cp_t cp); +SRSLTE_API srslte_pucch_format_t srslte_pucch_get_format(srslte_uci_data_t *uci_data, + srslte_cp_t cp); + +SRSLTE_API uint32_t srslte_pucch_get_npucch(uint32_t n_cce, + srslte_pucch_format_t format, + bool has_scheduling_request, + srslte_pucch_sched_t *pucch_sched); + +SRSLTE_API uint32_t srslte_pucch_n_prb(srslte_pucch_cfg_t *cfg, + srslte_pucch_format_t format, + uint32_t n_pucch, + uint32_t nof_prb, + srslte_cp_t cp, + uint32_t ns); + SRSLTE_API int srslte_pucch_n_cs_cell(srslte_cell_t cell, uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB]); diff --git a/srslte/include/srslte/phch/pusch.h b/srslte/include/srslte/phch/pusch.h index d8a5f3f53..25f4f40d8 100644 --- a/srslte/include/srslte/phch/pusch.h +++ b/srslte/include/srslte/phch/pusch.h @@ -51,9 +51,6 @@ #define SRSLTE_PUSCH_MAX_TDEC_ITERS 5 - - - typedef struct { enum { SRSLTE_PUSCH_HOP_MODE_INTER_SF = 1, @@ -63,13 +60,15 @@ typedef struct { uint32_t n_sb; } srslte_pusch_hopping_cfg_t; +typedef struct { + srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME]; +} srslte_pusch_user_t; + /* PUSCH object */ typedef struct SRSLTE_API { srslte_cell_t cell; uint32_t max_re; - bool rnti_is_set; - uint16_t rnti; srslte_dft_precoding_t dft_precoding; @@ -84,13 +83,11 @@ typedef struct SRSLTE_API { /* tx & rx objects */ srslte_modem_table_t mod[4]; - srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME]; srslte_sequence_t seq_type2_fo; // This is to generate the scrambling seq for multiple CRNTIs - uint32_t nof_crnti; - srslte_sequence_t *seq_multi[SRSLTE_NSUBFRAMES_X_FRAME]; - uint16_t *rnti_multi; + srslte_pusch_user_t **users; + srslte_sequence_t tmp_seq; srslte_sch_t ul_sch; bool shortened; @@ -116,44 +113,16 @@ 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 int srslte_pusch_init_rnti_multi(srslte_pusch_t *q, - uint32_t nof_rntis); - -SRSLTE_API int srslte_pusch_set_rnti_multi(srslte_pusch_t *q, - uint32_t idx, - uint16_t rnti); - -SRSLTE_API uint16_t srslte_pusch_get_rnti_multi(srslte_pusch_t *q, - uint32_t idx); - +SRSLTE_API void srslte_pusch_clear_rnti(srslte_pusch_t *q, + uint16_t rnti); SRSLTE_API int srslte_pusch_encode(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, uint8_t *data, - cf_t *sf_symbols); - -SRSLTE_API int srslte_pusch_encode_rnti(srslte_pusch_t *q, - srslte_pusch_cfg_t *cfg, - srslte_softbuffer_tx_t *softbuffer, - uint8_t *data, - uint16_t rnti, - cf_t *sf_symbols); - -SRSLTE_API int srslte_pusch_uci_encode(srslte_pusch_t *q, - srslte_pusch_cfg_t *cfg, - srslte_softbuffer_tx_t *softbuffer, - uint8_t *data, srslte_uci_data_t uci_data, - cf_t *sf_symbols); - -SRSLTE_API int srslte_pusch_uci_encode_rnti(srslte_pusch_t *q, - srslte_pusch_cfg_t *cfg, - srslte_softbuffer_tx_t *softbuffer, - uint8_t *data, - srslte_uci_data_t uci_data, - uint16_t rnti, - cf_t *sf_symbols); + uint16_t rnti, + cf_t *sf_symbols); SRSLTE_API int srslte_pusch_decode(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, @@ -161,26 +130,9 @@ SRSLTE_API int srslte_pusch_decode(srslte_pusch_t *q, cf_t *sf_symbols, cf_t *ce, float noise_estimate, - uint8_t *data); - -SRSLTE_API int srslte_pusch_uci_decode(srslte_pusch_t *q, - srslte_pusch_cfg_t *cfg, - srslte_softbuffer_rx_t *softbuffer, - cf_t *sf_symbols, - cf_t *ce, - float noise_estimate, - uint8_t *data, - srslte_uci_data_t *uci_data); - -SRSLTE_API int srslte_pusch_uci_decode_rnti_idx(srslte_pusch_t *q, - srslte_pusch_cfg_t *cfg, - srslte_softbuffer_rx_t *softbuffer, - cf_t *sf_symbols, - cf_t *ce, - float noise_estimate, - uint32_t rnti_idx, - uint8_t *data, - srslte_uci_data_t *uci_data); + uint16_t rnti, + uint8_t *data, + srslte_uci_data_t *uci_data); SRSLTE_API float srslte_pusch_average_noi(srslte_pusch_t *q); diff --git a/srslte/include/srslte/phch/ra.h b/srslte/include/srslte/phch/ra.h index 0b51331f3..fb17703dd 100644 --- a/srslte/include/srslte/phch/ra.h +++ b/srslte/include/srslte/phch/ra.h @@ -102,8 +102,11 @@ typedef struct SRSLTE_API { typedef struct SRSLTE_API { bool prb_idx[2][SRSLTE_MAX_PRB]; uint32_t nof_prb; - uint32_t Qm; + uint32_t Qm; + uint32_t Qm2; srslte_ra_mcs_t mcs; + srslte_ra_mcs_t mcs2; + uint32_t nof_tb; } srslte_ra_dl_grant_t; /** Unpacked DCI message for DL grant */ @@ -130,6 +133,10 @@ typedef struct SRSLTE_API { bool pconf; bool power_offset; + uint8_t tpc_pucch; + + bool tb_en[2]; + bool dci_is_1a; bool dci_is_1c; } srslte_ra_dl_dci_t; @@ -175,7 +182,7 @@ typedef struct SRSLTE_API { uint32_t n_dmrs; bool ndi; bool cqi_request; - uint32_t tpc_pusch; + uint8_t tpc_pusch; } srslte_ra_ul_dci_t; @@ -202,6 +209,10 @@ SRSLTE_API void srslte_ra_dl_grant_to_nbits(srslte_ra_dl_grant_t *grant, uint32_t sf_idx, srslte_ra_nbits_t *nbits); +SRSLTE_API uint32_t srslte_ra_dl_approx_nof_re(srslte_cell_t cell, + uint32_t nof_prb, + uint32_t nof_ctrl_symbols); + SRSLTE_API uint32_t srslte_ra_dl_grant_nof_re(srslte_ra_dl_grant_t *grant, srslte_cell_t cell, uint32_t sf_idx, @@ -218,13 +229,19 @@ SRSLTE_API void srslte_ra_ul_grant_to_nbits(srslte_ra_ul_grant_t *grant, uint32_t N_srs, srslte_ra_nbits_t *nbits); -SRSLTE_API int srslte_ul_dci_to_grant_prb_allocation(srslte_ra_ul_dci_t *dci, +SRSLTE_API int srslte_ra_ul_dci_to_grant_prb_allocation(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *grant, uint32_t n_rb_ho, uint32_t nof_prb); +SRSLTE_API int srslte_ra_dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, + srslte_ra_dl_grant_t *grant, + uint32_t nof_prb); + SRSLTE_API int srslte_ra_tbs_idx_from_mcs(uint32_t mcs); +SRSLTE_API srslte_mod_t srslte_ra_mod_from_mcs(uint32_t mcs); + SRSLTE_API int srslte_ra_mcs_from_tbs_idx(uint32_t tbs_idx); SRSLTE_API int srslte_ra_tbs_from_idx(uint32_t tbs_idx, diff --git a/srslte/include/srslte/sync/sync.h b/srslte/include/srslte/sync/sync.h index de13244df..364baed19 100644 --- a/srslte/include/srslte/sync/sync.h +++ b/srslte/include/srslte/sync/sync.h @@ -76,6 +76,7 @@ typedef struct SRSLTE_API { uint32_t max_offset; bool enable_cfo_corr; float mean_cfo; + float mean_cfo2; int cfo_i; bool find_cfo_i; bool find_cfo_i_initiated; @@ -83,6 +84,7 @@ typedef struct SRSLTE_API { uint32_t nof_symbols; uint32_t cp_len; srslte_cfo_t cfocorr; + srslte_cfo_t cfocorr2; sss_alg_t sss_alg; bool detect_cp; bool sss_en; @@ -93,6 +95,7 @@ typedef struct SRSLTE_API { float m1_value; float M_norm_avg; float M_ext_avg; + cf_t *temp; }srslte_sync_t; diff --git a/srslte/include/srslte/ue/ue_dl.h b/srslte/include/srslte/ue/ue_dl.h index 07bcd9470..0efe89ada 100644 --- a/srslte/include/srslte/ue/ue_dl.h +++ b/srslte/include/srslte/ue/ue_dl.h @@ -60,6 +60,18 @@ #include "srslte/config.h" + +#define MAX_CANDIDATES_UE 16 // From 36.213 Table 9.1.1-1 +#define MAX_CANDIDATES_COM 6 // From 36.213 Table 9.1.1-1 +#define MAX_CANDIDATES (MAX_CANDIDATES_UE + MAX_CANDIDATES_COM) + + +typedef struct { + srslte_dci_format_t format; + srslte_dci_location_t loc[MAX_CANDIDATES]; + uint32_t nof_locations; +} dci_blind_search_t; + typedef struct SRSLTE_API { srslte_pcfich_t pcfich; srslte_pdcch_t pdcch; @@ -80,14 +92,15 @@ typedef struct SRSLTE_API { cf_t *ce[SRSLTE_MAX_PORTS]; srslte_dci_format_t dci_format; - uint32_t cfi; uint64_t pkt_errors; uint64_t pkts_total; uint64_t nof_detected; uint16_t current_rnti; - uint32_t last_n_cce; + dci_blind_search_t current_ss_ue[3][10]; + dci_blind_search_t current_ss_common[3]; srslte_dci_location_t last_location; + srslte_dci_location_t last_location_ul; srslte_dci_msg_t pending_ul_dci_msg; uint16_t pending_ul_dci_rnti; @@ -117,23 +130,23 @@ SRSLTE_API int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q, uint32_t rvidx); SRSLTE_API int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t *q, - srslte_dci_msg_t *dci_msg, uint32_t cfi, uint32_t sf_idx, - uint16_t rnti); + uint16_t rnti, + srslte_dci_msg_t *dci_msg); SRSLTE_API int srslte_ue_dl_find_dl_dci(srslte_ue_dl_t *q, - srslte_dci_msg_t *dci_msg, uint32_t cfi, uint32_t sf_idx, - uint16_t rnti); + uint16_t rnti, + srslte_dci_msg_t *dci_msg); SRSLTE_API int srslte_ue_dl_find_dl_dci_type(srslte_ue_dl_t *q, - srslte_dci_msg_t *dci_msg, uint32_t cfi, uint32_t sf_idx, uint16_t rnti, - srslte_rnti_type_t rnti_type); + srslte_rnti_type_t rnti_type, + srslte_dci_msg_t *dci_msg); SRSLTE_API uint32_t srslte_ue_dl_get_ncce(srslte_ue_dl_t *q); @@ -143,21 +156,14 @@ SRSLTE_API void srslte_ue_dl_set_sample_offset(srslte_ue_dl_t * q, SRSLTE_API int srslte_ue_dl_decode(srslte_ue_dl_t * q, cf_t *input, uint8_t *data, - uint32_t sf_idx); + uint32_t tti); SRSLTE_API int srslte_ue_dl_decode_rnti(srslte_ue_dl_t * q, cf_t *input, uint8_t *data, - uint32_t sf_idx, + uint32_t tti, uint16_t rnti); -SRSLTE_API int srslte_ue_dl_decode_rnti_rv(srslte_ue_dl_t * q, - cf_t *input, - uint8_t * data, - uint32_t sf_idx, - uint16_t rnti, - uint32_t rvidx); - SRSLTE_API bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t n_prb_lowest, @@ -172,7 +178,8 @@ SRSLTE_API void srslte_ue_dl_save_signal(srslte_ue_dl_t *q, srslte_softbuffer_rx_t *softbuffer, uint32_t tti, uint32_t rv_idx, - uint16_t rnti); + uint16_t rnti, + uint32_t cfi); #endif diff --git a/srslte/include/srslte/ue/ue_ul.h b/srslte/include/srslte/ue/ue_ul.h index b0264a6e5..20642cdcc 100644 --- a/srslte/include/srslte/ue/ue_ul.h +++ b/srslte/include/srslte/ue/ue_ul.h @@ -51,8 +51,6 @@ #include "srslte/config.h" -#define SRSLTE_UE_UL_NOF_HARQ_PROCESSES 8 - /* UE UL power control */ typedef struct { // Common configuration diff --git a/srslte/include/srslte/utils/vector.h b/srslte/include/srslte/utils/vector.h index 027487818..7d6c04cba 100644 --- a/srslte/include/srslte/utils/vector.h +++ b/srslte/include/srslte/utils/vector.h @@ -156,6 +156,7 @@ SRSLTE_API float srslte_vec_avg_power_cf(cf_t *x, uint32_t len); SRSLTE_API uint32_t srslte_vec_max_fi(float *x, uint32_t len); SRSLTE_API uint32_t srslte_vec_max_abs_ci(cf_t *x, uint32_t len); SRSLTE_API int16_t srslte_vec_max_star_si(int16_t *x, uint32_t len); +SRSLTE_API int16_t srslte_vec_max_abs_star_si(int16_t *x, uint32_t len); /* maximum between two vectors */ SRSLTE_API void srslte_vec_max_fff(float *x, float *y, float *z, uint32_t len); diff --git a/srslte/lib/CMakeLists.txt b/srslte/lib/CMakeLists.txt index 88024f87b..88431bcde 100644 --- a/srslte/lib/CMakeLists.txt +++ b/srslte/lib/CMakeLists.txt @@ -36,58 +36,46 @@ add_subdirectory(scrambling) add_subdirectory(ue) add_subdirectory(enb) -add_library(srslte SHARED version.c - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ +set(srslte_srcs version.c + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ ) - -if(NOT DisableMEX) - add_library(srslte_static STATIC version.c - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - ) -endif(NOT DisableMEX) - +add_library(srslte SHARED ${srslte_srcs}) target_link_libraries(srslte pthread m) set_target_properties(srslte PROPERTIES VERSION ${SRSLTE_VERSION_MAJOR}.${SRSLTE_VERSION_MINOR}) +if(NOT DisableMEX) + add_library(srslte_static STATIC ${srslte_srcs}) +endif(NOT DisableMEX) + if(MKL_FOUND) - target_link_libraries(srslte ${MKL_LIBRARIES}) - if(NOT DisableMEX) - target_link_libraries(srslte_static ${MKL_LIBRARIES}) - endif(NOT DisableMEX) + if(StaticMKL) + target_link_libraries(srslte ${MKL_STATIC_LIBRARIES}) + if(NOT DisableMEX) + target_link_libraries(srslte_static ${MKL_STATIC_LIBRARIES}) + endif(NOT DisableMEX) + else(StaticMKL) + target_link_libraries(srslte ${MKL_LIBRARIES}) + if(NOT DisableMEX) + target_link_libraries(srslte_static ${MKL_LIBRARIES}) + endif(NOT DisableMEX) + endif(StaticMKL) else(MKL_FOUND) target_link_libraries(srslte ${FFTW3F_LIBRARIES}) if(NOT DisableMEX) @@ -95,7 +83,11 @@ else(MKL_FOUND) endif(NOT DisableMEX) endif(MKL_FOUND) +## This linkage is required for the examples and tests only if(RF_FOUND) + + target_link_libraries(srslte srslte_rf) + if(UHD_FOUND) target_link_libraries(srslte ${UHD_LIBRARIES}) endif(UHD_FOUND) diff --git a/srslte/lib/ch_estimation/chest_dl.c b/srslte/lib/ch_estimation/chest_dl.c index beb7518d2..541f98646 100644 --- a/srslte/lib/ch_estimation/chest_dl.c +++ b/srslte/lib/ch_estimation/chest_dl.c @@ -293,6 +293,7 @@ static void average_pilots(srslte_chest_dl_t *q, cf_t *input, cf_t *output, uint uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(port_id); uint32_t nref = 2*q->cell.nof_prb; + // Average in the frequency domain for (int l=0;lsmooth_filter, &output[l*nref], nref, q->smooth_filter_len); } diff --git a/srslte/lib/ch_estimation/chest_ul.c b/srslte/lib/ch_estimation/chest_ul.c index 4286854c0..7e558c2d0 100644 --- a/srslte/lib/ch_estimation/chest_ul.c +++ b/srslte/lib/ch_estimation/chest_ul.c @@ -84,6 +84,12 @@ int srslte_chest_ul_init(srslte_chest_ul_t *q, srslte_cell_t cell) goto clean_exit; } + q->pilot_known_signal = srslte_vec_malloc(sizeof(cf_t) * (NOF_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)) { fprintf(stderr, "Error initializing vector interpolator\n"); goto clean_exit; @@ -91,11 +97,11 @@ 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; + } + ret = SRSLTE_SUCCESS; clean_exit: @@ -122,6 +128,9 @@ void srslte_chest_ul_free(srslte_chest_ul_t *q) if (q->pilot_recv_signal) { free(q->pilot_recv_signal); } + if (q->pilot_known_signal) { + free(q->pilot_known_signal); + } bzero(q, sizeof(srslte_chest_ul_t)); } @@ -136,13 +145,13 @@ void srslte_chest_ul_set_cfg(srslte_chest_ul_t *q, } /* Uses the difference between the averaged and non-averaged pilot estimates */ -static float estimate_noise_pilots(srslte_chest_ul_t *q, cf_t *ce, uint32_t nrefs) +static float estimate_noise_pilots(srslte_chest_ul_t *q, cf_t *ce, uint32_t nrefs, uint32_t n_prb[2]) { float power = 0; for (int i=0;i<2;i++) { power += srslte_chest_estimate_noise_pilots(&q->pilot_estimates[i*nrefs], - &ce[SRSLTE_REFSIGNAL_UL_L(i, q->cell.cp)*q->cell.nof_prb*SRSLTE_NRE], + &ce[SRSLTE_REFSIGNAL_UL_L(i, q->cell.cp)*q->cell.nof_prb*SRSLTE_NRE+n_prb[i]*SRSLTE_NRE], q->tmp_noise, nrefs); } @@ -159,9 +168,9 @@ static float estimate_noise_pilots(srslte_chest_ul_t *q, cf_t *ce, uint32_t nref } } -#define cesymb(i) ce[SRSLTE_RE_IDX(q->cell.nof_prb,i,0)] - -static void interpolate_pilots(srslte_chest_ul_t *q, cf_t *ce, uint32_t nrefs) +// The interpolator currently only supports same frequency allocation for each subframe +#define cesymb(i) ce[SRSLTE_RE_IDX(q->cell.nof_prb,i,n_prb[0]*SRSLTE_NRE)] +static void interpolate_pilots(srslte_chest_ul_t *q, cf_t *ce, uint32_t nrefs, uint32_t n_prb[2]) { uint32_t L1 = SRSLTE_REFSIGNAL_UL_L(0, q->cell.cp); uint32_t L2 = SRSLTE_REFSIGNAL_UL_L(1, q->cell.cp); @@ -197,10 +206,10 @@ void srslte_chest_ul_set_smooth_filter3_coeff(srslte_chest_ul_t* q, float w) q->smooth_filter_len = 3; } -static void average_pilots(srslte_chest_ul_t *q, cf_t *input, cf_t *ce, uint32_t nrefs) { +static void average_pilots(srslte_chest_ul_t *q, cf_t *input, cf_t *ce, uint32_t nrefs, uint32_t n_prb[2]) { for (int i=0;i<2;i++) { srslte_chest_average_pilots(&input[i*nrefs], - &ce[SRSLTE_REFSIGNAL_UL_L(i, q->cell.cp)*q->cell.nof_prb*SRSLTE_NRE], + &ce[SRSLTE_REFSIGNAL_UL_L(i, q->cell.cp)*q->cell.nof_prb*SRSLTE_NRE+n_prb[i]*SRSLTE_NRE], q->smooth_filter, nrefs, 1, q->smooth_filter_len); } } @@ -228,21 +237,25 @@ int srslte_chest_ul_estimate(srslte_chest_ul_t *q, cf_t *input, cf_t *ce, srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->dmrs_pregen.r[cyclic_shift_for_dmrs][sf_idx][nof_prb], q->pilot_estimates, nrefs_sf); + if (n_prb[0] != n_prb[1]) { + printf("ERROR: intra-subframe frequency hopping not supported in the estimator!!\n"); + } + if (ce != NULL) { if (q->smooth_filter_len > 0) { - average_pilots(q, q->pilot_estimates, ce, nrefs_sym); - interpolate_pilots(q, ce, nrefs_sym); + average_pilots(q, q->pilot_estimates, ce, nrefs_sym, n_prb); + interpolate_pilots(q, ce, nrefs_sym, n_prb); /* If averaging, compute noise from difference between received and averaged estimates */ - q->noise_estimate = estimate_noise_pilots(q, ce, nrefs_sym); + q->noise_estimate = estimate_noise_pilots(q, ce, nrefs_sym, n_prb); } else { // Copy estimates to CE vector without averaging for (int i=0;i<2;i++) { - memcpy(&ce[SRSLTE_REFSIGNAL_UL_L(i, q->cell.cp)*q->cell.nof_prb*SRSLTE_NRE], + memcpy(&ce[SRSLTE_REFSIGNAL_UL_L(i, q->cell.cp)*q->cell.nof_prb*SRSLTE_NRE+n_prb[i]*SRSLTE_NRE], &q->pilot_estimates[i*nrefs_sym], - nrefs_sym*sizeof(cf_t)); + nrefs_sym*sizeof(cf_t)); } - interpolate_pilots(q, ce, nrefs_sym); + interpolate_pilots(q, ce, nrefs_sym, n_prb); q->noise_estimate = 0; } } @@ -252,6 +265,63 @@ int srslte_chest_ul_estimate(srslte_chest_ul_t *q, cf_t *input, cf_t *ce, return 0; } +int srslte_chest_ul_estimate_pucch(srslte_chest_ul_t *q, cf_t *input, cf_t *ce, + srslte_pucch_format_t format, uint32_t n_pucch, uint32_t sf_idx) +{ + if (!q->dmrs_signal_configured) { + fprintf(stderr, "Error must call srslte_chest_ul_set_cfg() before using the UL estimator\n"); + return SRSLTE_ERROR; + } + + int n_rs = srslte_refsignal_dmrs_N_rs(format, q->cell.cp); + if (!n_rs) { + fprintf(stderr, "Error computing N_rs\n"); + return SRSLTE_ERROR; + } + int nrefs_sf = SRSLTE_NRE*n_rs*2; + + /* Get references from the input signal */ + srslte_refsignal_dmrs_pucch_get(&q->dmrs_signal, format, n_pucch, input, q->pilot_recv_signal); + + /* Generate known pilots */ + uint8_t pucch2_bits[2] = {0, 0}; + srslte_refsignal_dmrs_pucch_gen(&q->dmrs_signal, format, n_pucch, sf_idx, pucch2_bits, q->pilot_known_signal), + + /* Use the known DMRS signal to compute Least-squares estimates */ + srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->pilot_known_signal, q->pilot_estimates, nrefs_sf); + + if (ce != NULL) { + /* FIXME: Currently averaging entire slot, performance good enough? */ + for (int ns=0;ns<2;ns++) { + // Average all slot + for (int i=1;ipilot_estimates[ns*n_rs*SRSLTE_NRE], &q->pilot_estimates[(i+ns*n_rs)*SRSLTE_NRE], + &q->pilot_estimates[ns*n_rs*SRSLTE_NRE], + SRSLTE_NRE); + } + srslte_vec_sc_prod_ccc(&q->pilot_estimates[ns*n_rs*SRSLTE_NRE], (float) 1.0/n_rs, + &q->pilot_estimates[ns*n_rs*SRSLTE_NRE], + SRSLTE_NRE); + + // Average in freq domain + srslte_chest_average_pilots(&q->pilot_estimates[ns*n_rs*SRSLTE_NRE], &q->pilot_recv_signal[ns*n_rs*SRSLTE_NRE], + q->smooth_filter, SRSLTE_NRE, 1, q->smooth_filter_len); + + // Determine n_prb + uint32_t n_prb = srslte_pucch_n_prb(&q->dmrs_signal.pucch_cfg, format, n_pucch, q->cell.nof_prb, q->cell.cp, ns); + + // copy estimates to slot + for (int i=0;icell.cp);i++) { + memcpy(&ce[SRSLTE_RE_IDX(q->cell.nof_prb, i+ns*SRSLTE_CP_NSYMB(q->cell.cp), n_prb*SRSLTE_NRE)], + &q->pilot_recv_signal[ns*n_rs*SRSLTE_NRE], sizeof(cf_t)*SRSLTE_NRE); + } + } + } + + return 0; +} + + float srslte_chest_ul_get_noise_estimate(srslte_chest_ul_t *q) { return q->noise_estimate; } diff --git a/srslte/lib/ch_estimation/refsignal_ul.c b/srslte/lib/ch_estimation/refsignal_ul.c index 3c7dcfb02..143bf53f4 100644 --- a/srslte/lib/ch_estimation/refsignal_ul.c +++ b/srslte/lib/ch_estimation/refsignal_ul.c @@ -177,6 +177,8 @@ int srslte_refsignal_ul_init(srslte_refsignal_ul_t * q, srslte_cell_t cell) if (q != NULL && srslte_cell_isvalid(&cell)) { + ret = SRSLTE_ERROR; + bzero(q, sizeof(srslte_refsignal_ul_t)); q->cell = cell; @@ -235,6 +237,8 @@ void srslte_refsignal_ul_set_cfg(srslte_refsignal_ul_t *q, if (pucch_cfg) { if (srslte_pucch_cfg_isvalid(pucch_cfg, q->cell.nof_prb)) { memcpy(&q->pucch_cfg, pucch_cfg, sizeof(srslte_pucch_cfg_t)); + } else { + fprintf(stderr, "Invalid PUCCH configuration in refsignal_ul\n"); } } if (srs_cfg) { @@ -275,11 +279,13 @@ static uint32_t get_q(uint32_t u, uint32_t v, uint32_t N_sz) { static void arg_r_uv_mprb(float *arg, uint32_t M_sc, uint32_t u, uint32_t v) { uint32_t N_sz = largest_prime_lower_than(M_sc); - float q = get_q(u,v,N_sz); - float n_sz = (float) N_sz; - for (uint32_t i = 0; i < M_sc; i++) { - float m = (float) (i%N_sz); - arg[i] = -M_PI * q * m * (m + 1) / n_sz; + if (N_sz > 0) { + float q = get_q(u,v,N_sz); + float n_sz = (float) N_sz; + for (uint32_t i = 0; i < M_sc; i++) { + float m = (float) (i%N_sz); + arg[i] = -M_PI * q * m * (m + 1) / n_sz; + } } } @@ -448,7 +454,7 @@ int srslte_refsignal_dmrs_pusch_gen(srslte_refsignal_ul_t *q, uint32_t nof_prb, } /* Number of PUCCH demodulation reference symbols per slot N_rs_pucch tABLE 5.5.2.2.1-1 36.211 */ -static uint32_t get_N_rs(srslte_pucch_format_t format, srslte_cp_t cp) { +uint32_t srslte_refsignal_dmrs_N_rs(srslte_pucch_format_t format, srslte_cp_t cp) { switch (format) { case SRSLTE_PUCCH_FORMAT_1: case SRSLTE_PUCCH_FORMAT_1A: @@ -467,40 +473,49 @@ static uint32_t get_N_rs(srslte_pucch_format_t format, srslte_cp_t cp) { case SRSLTE_PUCCH_FORMAT_2A: case SRSLTE_PUCCH_FORMAT_2B: return 2; + default: + fprintf(stderr, "Unsupported format %d\n", format); + return 0; } return 0; } /* Table 5.5.2.2.2-1: Demodulation reference signal location for different PUCCH formats. 36.211 */ -static uint32_t get_pucch_dmrs_symbol(uint32_t m, srslte_pucch_format_t format, srslte_cp_t cp) { +uint32_t srslte_refsignal_dmrs_pucch_symbol(uint32_t m, srslte_pucch_format_t format, srslte_cp_t cp) { switch (format) { case SRSLTE_PUCCH_FORMAT_1: case SRSLTE_PUCCH_FORMAT_1A: case SRSLTE_PUCCH_FORMAT_1B: if (SRSLTE_CP_ISNORM(cp)) { - if (m < 4) { + if (m < 3) { return pucch_dmrs_symbol_format1_cpnorm[m]; } } else { - if (m < 3) { + if (m < 2) { return pucch_dmrs_symbol_format1_cpext[m]; } } + break; case SRSLTE_PUCCH_FORMAT_2: if (SRSLTE_CP_ISNORM(cp)) { - if (m < 3) { + if (m < 2) { return pucch_dmrs_symbol_format2_cpnorm[m]; } } else { - if (m < 2) { + if (m < 1) { return pucch_dmrs_symbol_format2_cpext[m]; } } + break; case SRSLTE_PUCCH_FORMAT_2A: case SRSLTE_PUCCH_FORMAT_2B: - if (m < 3) { + if (m < 2) { return pucch_dmrs_symbol_format2_cpnorm[m]; } + break; + default: + fprintf(stderr, "Unsupported format %d\n", format); + return 0; } return 0; } @@ -513,7 +528,7 @@ int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_forma if (q && r_pucch) { ret = SRSLTE_ERROR; - uint32_t N_rs=get_N_rs(format, q->cell.cp); + uint32_t N_rs=srslte_refsignal_dmrs_N_rs(format, q->cell.cp); cf_t z_m_1 = 1.0; if (format == SRSLTE_PUCCH_FORMAT_2A || format == SRSLTE_PUCCH_FORMAT_2B) { @@ -533,7 +548,7 @@ int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_forma for (uint32_t m=0;mcell.cp); + uint32_t l = srslte_refsignal_dmrs_pucch_symbol(m, format, q->cell.cp); // Add cyclic prefix alpha float alpha = 0.0; if (format < SRSLTE_PUCCH_FORMAT_2) { @@ -565,18 +580,17 @@ int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_forma case SRSLTE_PUCCH_FORMAT_2B: w=w_arg_pucch_format2_cpnorm; break; + default: + fprintf(stderr, "Unsupported format %d\n", format); + return SRSLTE_ERROR; } cf_t z_m = 1.0; if (m == 1) { z_m = z_m_1; } - if (w) { - for (uint32_t n=0;ntmp_arg[n]+alpha*n)); - } - } else { - return SRSLTE_ERROR; - } + for (uint32_t n=0;ntmp_arg[n]+alpha*n)); + } } } ret = SRSLTE_SUCCESS; @@ -584,36 +598,48 @@ int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_forma return ret; } -/* Maps PUCCH DMRS to the physical resources as defined in 5.5.2.2.2 in 36.211 */ -int srslte_refsignal_dmrs_pucch_put(srslte_refsignal_ul_t *q, srslte_pucch_format_t format, uint32_t n_pucch, cf_t *r_pucch, cf_t *output) +int srslte_refsignal_dmrs_pucch_cp(srslte_refsignal_ul_t *q, srslte_pucch_format_t format, uint32_t n_pucch, cf_t *source, cf_t *dest, bool source_is_grid) { int ret = SRSLTE_ERROR_INVALID_INPUTS; - if (q && output && r_pucch) { + if (q && source && dest) { ret = SRSLTE_ERROR; uint32_t nsymbols = SRSLTE_CP_ISNORM(q->cell.cp)?SRSLTE_CP_NORM_NSYMB:SRSLTE_CP_EXT_NSYMB; - - // Determine m - uint32_t m = srslte_pucch_m(&q->pucch_cfg, format, n_pucch, q->cell.cp); - - uint32_t N_rs = get_N_rs(format, q->cell.cp); + + uint32_t N_rs = srslte_refsignal_dmrs_N_rs(format, q->cell.cp); for (uint32_t ns=0;ns<2;ns++) { - // Determine n_prb - uint32_t n_prb = m/2; - if ((m+ns)%2) { - n_prb = q->cell.nof_prb-1-m/2; - } - + + // Determine n_prb + uint32_t n_prb = srslte_pucch_n_prb(&q->pucch_cfg, format, n_pucch, q->cell.nof_prb, q->cell.cp, ns); + for (uint32_t i=0;icell.cp); - memcpy(&output[SRSLTE_RE_IDX(q->cell.nof_prb, l+ns*nsymbols, n_prb*SRSLTE_NRE)], - &r_pucch[ns*N_rs*SRSLTE_NRE+i*SRSLTE_NRE], - SRSLTE_NRE*sizeof(cf_t)); + uint32_t l = srslte_refsignal_dmrs_pucch_symbol(i, format, q->cell.cp); + if (!source_is_grid) { + memcpy(&dest[SRSLTE_RE_IDX(q->cell.nof_prb, l+ns*nsymbols, n_prb*SRSLTE_NRE)], + &source[ns*N_rs*SRSLTE_NRE+i*SRSLTE_NRE], + SRSLTE_NRE*sizeof(cf_t)); + } else { + memcpy(&dest[ns*N_rs*SRSLTE_NRE+i*SRSLTE_NRE], + &source[SRSLTE_RE_IDX(q->cell.nof_prb, l+ns*nsymbols, n_prb*SRSLTE_NRE)], + SRSLTE_NRE*sizeof(cf_t)); + } } } ret = SRSLTE_SUCCESS; } - return ret; + return ret; +} + +/* Maps PUCCH DMRS to the physical resources as defined in 5.5.2.2.2 in 36.211 */ +int srslte_refsignal_dmrs_pucch_put(srslte_refsignal_ul_t *q, srslte_pucch_format_t format, uint32_t n_pucch, cf_t *r_pucch, cf_t *output) +{ + return srslte_refsignal_dmrs_pucch_cp(q, format, n_pucch, r_pucch, output, false); +} + +/* Gets PUCCH DMRS from the physical resources as defined in 5.5.2.2.2 in 36.211 */ +int srslte_refsignal_dmrs_pucch_get(srslte_refsignal_ul_t *q, srslte_pucch_format_t format, uint32_t n_pucch, cf_t *input, cf_t *r_pucch) +{ + return srslte_refsignal_dmrs_pucch_cp(q, format, n_pucch, input, r_pucch, true); } @@ -759,21 +785,23 @@ uint32_t srslte_refsignal_srs_rb_L_cs(uint32_t bw_cfg, uint32_t nof_prb) { } uint32_t srs_Fb(srslte_refsignal_srs_cfg_t *cfg, uint32_t b, uint32_t nof_prb, uint32_t tti) { - uint32_t n_srs = tti/T_srs_table(cfg->I_srs); - uint32_t N_b = Nb[srsbwtable_idx(nof_prb)][b][cfg->bw_cfg]; - - uint32_t prod_1=1; - for (uint32_t bp=cfg->b_hop+1;bpbw_cfg]; - } - uint32_t prod_2 = prod_1*Nb[srsbwtable_idx(nof_prb)][b][cfg->bw_cfg]; - uint32_t Fb; - if ((N_b%2) == 0) { - Fb = (N_b/2)*((n_srs%prod_2)/prod_1)+((n_srs%prod_2)/prod_1/2); - } else { - Fb = (N_b/2)*(n_srs/prod_1); + uint32_t Fb = 0; + uint32_t T = T_srs_table(cfg->I_srs); + if (T) { + uint32_t n_srs = tti/T; + uint32_t N_b = Nb[srsbwtable_idx(nof_prb)][b][cfg->bw_cfg]; + + uint32_t prod_1=1; + for (uint32_t bp=cfg->b_hop+1;bpbw_cfg]; + } + uint32_t prod_2 = prod_1*Nb[srsbwtable_idx(nof_prb)][b][cfg->bw_cfg]; + if ((N_b%2) == 0) { + Fb = (N_b/2)*((n_srs%prod_2)/prod_1)+((n_srs%prod_2)/prod_1/2); + } else { + Fb = (N_b/2)*(n_srs/prod_1); + } } - return Fb; } diff --git a/srslte/lib/ch_estimation/test/chest_test_ul.c b/srslte/lib/ch_estimation/test/chest_test_ul.c index 93953dcbc..b3b2331da 100644 --- a/srslte/lib/ch_estimation/test/chest_test_ul.c +++ b/srslte/lib/ch_estimation/test/chest_test_ul.c @@ -178,7 +178,7 @@ int main(int argc, char **argv) { /* Generate random input */ bzero(input, sizeof(cf_t) * num_re); for (i=0;i 0 && lte_bands[i].earfcn_offset>earfcn) { + i--; + } + return lte_bands[i].band; +} + float srslte_band_fd(uint32_t earfcn) { - uint32_t i; - i=0; - while(i < SRSLTE_NOF_LTE_BANDS && lte_bands[i].earfcn_offset lte_bands[SRSLTE_NOF_LTE_BANDS-1].earfcn_max) { + return -1; } - if (i == SRSLTE_NOF_LTE_BANDS) { - fprintf(stderr, "Error: EARFCN %d not found\n", earfcn); - return -1.0; + uint32_t i = SRSLTE_NOF_LTE_BANDS-1; + while(i > 0 && lte_bands[i].earfcn_offset>earfcn) { + i--; + } + return get_fd(<e_bands[i], earfcn); +} + + +float srslte_band_fu(uint32_t earfcn) { + if (earfcn > lte_bands[SRSLTE_NOF_LTE_BANDS-1].earfcn_max) { + return -1; + } + uint32_t i = SRSLTE_NOF_LTE_BANDS-1; + while(i > 0 && lte_bands[i].earfcn_offset>earfcn) { + i--; } - return get_fd(<e_bands[i], earfcn); + return get_fd(<e_bands[i], earfcn) - lte_bands[i].duplex_mhz; } int srslte_band_get_fd_band_all(uint32_t band, srslte_earfcn_t *earfcn, uint32_t max_elems) { diff --git a/srslte/lib/dft/dft_precoding.c b/srslte/lib/dft/dft_precoding.c index bb3753545..bc285d8f6 100644 --- a/srslte/lib/dft/dft_precoding.c +++ b/srslte/lib/dft/dft_precoding.c @@ -85,14 +85,16 @@ void srslte_dft_precoding_free(srslte_dft_precoding_t *q) bzero(q, sizeof(srslte_dft_precoding_t)); } +static bool valid_prb[101]={true,true,true,true,true,true,true,false,true,true,true,false,true,false,false,true,true,false,true,false,true,false,false,false, + true,true,false,true,false,false,true,false,true,false,false,false,true,false,false,false,true,false,false,false,false,true,false,false,true,false, + true,false,false,false,true,false,false,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false,true,false,false,true, + false,false,false,false,true,true,false,false,false,false,false,false,false,false,true,false,false,false,false,false,true,false,false,false,true}; + bool srslte_dft_precoding_valid_prb(uint32_t nof_prb) { - if (nof_prb > 0 && - (nof_prb == 1 || (nof_prb%2) == 0 || (nof_prb%3) == 0 || (nof_prb%5) == 0)) - { - return true; - } else { - return false; + if (nof_prb <= 100) { + return valid_prb[nof_prb]; } + return false; } int srslte_dft_precoding(srslte_dft_precoding_t *q, cf_t *input, cf_t *output, diff --git a/srslte/lib/enb/enb_dl.c b/srslte/lib/enb/enb_dl.c index 958133ea5..82fc8491e 100644 --- a/srslte/lib/enb/enb_dl.c +++ b/srslte/lib/enb/enb_dl.c @@ -37,9 +37,9 @@ #define CURRENT_SLOTLEN_RE SRSLTE_SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp) #define CURRENT_SFLEN_RE SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp) -#define SRSLTE_ENB_RF_AMP 0.8 +#define SRSLTE_ENB_RF_AMP 0.1 -int srslte_enb_dl_init(srslte_enb_dl_t *q, srslte_cell_t cell, uint32_t nof_rnti) +int srslte_enb_dl_init(srslte_enb_dl_t *q, srslte_cell_t cell) { int ret = SRSLTE_ERROR_INVALID_INPUTS; @@ -52,7 +52,7 @@ int srslte_enb_dl_init(srslte_enb_dl_t *q, srslte_cell_t cell, uint32_t nof_rnti q->cell = cell; q->cfi = 3; - q->nof_rnti = nof_rnti; + q->tx_amp = SRSLTE_ENB_RF_AMP; if (srslte_ofdm_tx_init(&q->ifft, q->cell.cp, q->cell.nof_prb)) { fprintf(stderr, "Error initiating FFT\n"); @@ -88,11 +88,6 @@ int srslte_enb_dl_init(srslte_enb_dl_t *q, srslte_cell_t cell, uint32_t nof_rnti goto clean_exit; } - if (srslte_pdsch_init_rnti_multi(&q->pdsch, nof_rnti)) { - fprintf(stderr, "Error initiating multiple RNTIs in PDSCH\n"); - goto clean_exit; - } - if (srslte_refsignal_cs_init(&q->csr_signal, q->cell)) { fprintf(stderr, "Error initializing CSR signal (%d)\n",ret); goto clean_exit; @@ -146,6 +141,11 @@ void srslte_enb_dl_free(srslte_enb_dl_t *q) } } +void srslte_enb_dl_set_amp(srslte_enb_dl_t *q, float amp) +{ + q->tx_amp = amp; +} + void srslte_enb_dl_set_cfi(srslte_enb_dl_t *q, uint32_t cfi) { q->cfi = cfi; @@ -214,26 +214,24 @@ void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q, cf_t *signal_buffer) // TODO: PAPR control float norm_factor = (float) sqrt(q->cell.nof_prb)/15; - srslte_vec_sc_prod_cfc(signal_buffer, SRSLTE_ENB_RF_AMP*norm_factor, signal_buffer, SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); + srslte_vec_sc_prod_cfc(signal_buffer, q->tx_amp*norm_factor, signal_buffer, SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); } -int srslte_enb_dl_cfg_rnti(srslte_enb_dl_t *q, uint32_t idx, uint16_t rnti) +int srslte_enb_dl_add_rnti(srslte_enb_dl_t *q, uint16_t rnti) { - return srslte_pdsch_set_rnti_multi(&q->pdsch, idx, rnti); + return srslte_pdsch_set_rnti(&q->pdsch, rnti); } -int srslte_enb_dl_rem_rnti(srslte_enb_dl_t *q, uint32_t idx) +void srslte_enb_dl_rem_rnti(srslte_enb_dl_t *q, uint16_t rnti) { - return srslte_pdsch_set_rnti_multi(&q->pdsch, idx, 0); + srslte_pdsch_free_rnti(&q->pdsch, rnti); } 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, - uint32_t rnti_idx, uint32_t sf_idx) + uint16_t rnti, uint32_t sf_idx) { srslte_dci_msg_t dci_msg; - - uint16_t rnti = srslte_pdsch_get_rnti_multi(&q->pdsch, rnti_idx); bool rnti_is_user = true; if (rnti == SRSLTE_SIRNTI || rnti == SRSLTE_PRNTI || (rnti >= SRSLTE_RARNTI_START && rnti <= SRSLTE_RARNTI_END)) { @@ -245,23 +243,16 @@ int srslte_enb_dl_put_pdcch_dl(srslte_enb_dl_t *q, srslte_ra_dl_dci_t *grant, fprintf(stderr, "Error encoding DCI message\n"); return SRSLTE_ERROR; } -/* printf("format: %s, sf_idx=%d, rnti=%d, location=%d,%d, cfi=%d\n", - srslte_dci_format_string(format), sf_idx, rnti, location.L, location.ncce, q->cfi); - srslte_ra_pdsch_fprint(stdout, grant, q->cell.nof_prb); - srslte_vec_fprint_hex(stdout, dci_msg.data, dci_msg.nof_bits); -*/ return SRSLTE_SUCCESS; } int srslte_enb_dl_put_pdcch_ul(srslte_enb_dl_t *q, srslte_ra_ul_dci_t *grant, srslte_dci_location_t location, - uint32_t rnti_idx, uint32_t sf_idx) + uint16_t rnti, uint32_t sf_idx) { srslte_dci_msg_t dci_msg; - uint16_t rnti = srslte_pdsch_get_rnti_multi(&q->pdsch, rnti_idx); - srslte_dci_msg_pack_pusch(grant, &dci_msg, q->cell.nof_prb); if (srslte_pdcch_encode(&q->pdcch, &dci_msg, location, rnti, q->sf_symbols, sf_idx, q->cfi)) { fprintf(stderr, "Error encoding DCI message\n"); @@ -272,11 +263,9 @@ int srslte_enb_dl_put_pdcch_ul(srslte_enb_dl_t *q, srslte_ra_ul_dci_t *grant, } int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q, srslte_ra_dl_grant_t *grant, srslte_softbuffer_tx_t *softbuffer, - uint32_t rnti_idx, uint32_t rv_idx, uint32_t sf_idx, + uint16_t rnti, uint32_t rv_idx, uint32_t sf_idx, uint8_t *data) -{ - //srslte_ra_dl_grant_fprint(stdout, grant); - +{ /* Configure pdsch_cfg parameters */ if (srslte_pdsch_cfg(&q->pdsch_cfg, q->cell, grant, q->cfi, sf_idx, rv_idx)) { fprintf(stderr, "Error configuring PDSCH\n"); @@ -284,7 +273,7 @@ int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q, srslte_ra_dl_grant_t *grant, srs } /* Encode PDSCH */ - if (srslte_pdsch_encode_rnti_idx(&q->pdsch, &q->pdsch_cfg, softbuffer, data, rnti_idx, q->sf_symbols)) { + if (srslte_pdsch_encode(&q->pdsch, &q->pdsch_cfg, softbuffer, data, rnti, q->sf_symbols)) { fprintf(stderr, "Error encoding PDSCH\n"); return SRSLTE_ERROR; } diff --git a/srslte/lib/enb/enb_ul.c b/srslte/lib/enb/enb_ul.c index e3732b8ce..d41bfc245 100644 --- a/srslte/lib/enb/enb_ul.c +++ b/srslte/lib/enb/enb_ul.c @@ -37,13 +37,13 @@ #define CURRENT_SLOTLEN_RE SRSLTE_SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp) #define CURRENT_SFLEN_RE SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp) -#define MAX_CANDIDATES 64 +#define MAX_CANDIDATES 16 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_pucch_cfg_t *pucch_cfg, - uint32_t nof_rnti) + srslte_pusch_hopping_cfg_t *hopping_cfg, + srslte_pucch_cfg_t *pucch_cfg) { int ret = SRSLTE_ERROR_INVALID_INPUTS; @@ -55,13 +55,22 @@ int srslte_enb_ul_init(srslte_enb_ul_t *q, srslte_cell_t cell, bzero(q, sizeof(srslte_enb_ul_t)); q->cell = cell; - q->nof_rnti = nof_rnti; + + if (hopping_cfg) { + memcpy(&q->hopping_cfg, hopping_cfg, sizeof(srslte_pusch_hopping_cfg_t)); + } + + q->users = calloc(sizeof(srslte_enb_ul_user_t*), SRSLTE_SIRNTI); + if (!q->users) { + perror("malloc"); + goto clean_exit; + } if (srslte_ofdm_rx_init(&q->fft, q->cell.cp, q->cell.nof_prb)) { fprintf(stderr, "Error initiating FFT\n"); goto clean_exit; } - srslte_ofdm_set_normalize(&q->fft, true); + srslte_ofdm_set_normalize(&q->fft, false); srslte_ofdm_set_freq_shift(&q->fft, -0.5); if (srslte_pucch_init(&q->pucch, q->cell)) { @@ -74,23 +83,24 @@ int srslte_enb_ul_init(srslte_enb_ul_t *q, srslte_cell_t cell, goto clean_exit; } - if (srslte_pusch_init_rnti_multi(&q->pusch, nof_rnti)) { - fprintf(stderr, "Error initiating multiple RNTIs in PUSCH\n"); - goto clean_exit; - } - - if (srslte_prach_init_cfg(&q->prach, prach_cfg, q->cell.nof_prb)) { - fprintf(stderr, "Error initiating PRACH\n"); - goto clean_exit; + if (prach_cfg) { + if (srslte_prach_init_cfg(&q->prach, prach_cfg, q->cell.nof_prb)) { + fprintf(stderr, "Error initiating PRACH\n"); + goto clean_exit; + } + srslte_prach_set_detect_factor(&q->prach, 60); } - srslte_prach_set_detect_factor(&q->prach, 60); - + srslte_pucch_set_threshold(&q->pucch, 0.5, 0.5); + if (srslte_chest_ul_init(&q->chest, cell)) { fprintf(stderr, "Error initiating channel estimator\n"); goto clean_exit; } + // Configure common PUCCH configuration + srslte_pucch_set_cfg(&q->pucch, pucch_cfg, pusch_cfg->group_hopping_en); + // SRS is a dedicated configuration srslte_chest_ul_set_cfg(&q->chest, pusch_cfg, pucch_cfg, NULL); @@ -123,6 +133,16 @@ clean_exit: void srslte_enb_ul_free(srslte_enb_ul_t *q) { if (q) { + + if (q->users) { + for (int i=0;iusers[i]) { + free(q->users[i]); + } + } + free(q->users); + } + srslte_prach_free(&q->prach); srslte_ofdm_rx_free(&q->fft); srslte_pucch_free(&q->pucch); @@ -138,14 +158,52 @@ void srslte_enb_ul_free(srslte_enb_ul_t *q) } } -int srslte_enb_ul_cfg_rnti(srslte_enb_ul_t *q, uint32_t idx, uint16_t rnti) +int srslte_enb_ul_add_rnti(srslte_enb_ul_t *q, uint16_t rnti) { - return srslte_pusch_set_rnti_multi(&q->pusch, idx, rnti); + if (!q->users[rnti]) { + q->users[rnti] = malloc(sizeof(srslte_enb_ul_user_t)); + return srslte_pusch_set_rnti(&q->pusch, rnti); + } else { + fprintf(stderr, "Error adding rnti=0x%x, already exists\n", rnti); + return -1; + } } -int srslte_enb_ul_rem_rnti(srslte_enb_ul_t *q, uint32_t idx) +void srslte_enb_ul_rem_rnti(srslte_enb_ul_t *q, uint16_t rnti) { - return srslte_pusch_set_rnti_multi(&q->pusch, idx, 0); + if (q->users[rnti]) { + free(q->users[rnti]); + q->users[rnti] = NULL; + srslte_pusch_clear_rnti(&q->pusch, rnti); + } +} + +int srslte_enb_ul_cfg_ue(srslte_enb_ul_t *q, uint16_t rnti, + srslte_uci_cfg_t *uci_cfg, + srslte_pucch_sched_t *pucch_sched, + srslte_refsignal_srs_cfg_t *srs_cfg) +{ + if (q->users[rnti]) { + if (uci_cfg) { + memcpy(&q->users[rnti]->uci_cfg, uci_cfg, sizeof(srslte_uci_cfg_t)); + q->users[rnti]->uci_cfg_en = true; + } else { + q->users[rnti]->uci_cfg_en = false; + } + if (pucch_sched) { + memcpy(&q->users[rnti]->pucch_sched, pucch_sched, sizeof(srslte_pucch_sched_t)); + } + if (srs_cfg) { + memcpy(&q->users[rnti]->srs_cfg, srs_cfg, sizeof(srslte_refsignal_srs_cfg_t)); + q->users[rnti]->srs_cfg_en = true; + } else { + q->users[rnti]->srs_cfg_en = false; + } + return SRSLTE_SUCCESS; + } else { + fprintf(stderr, "Error configuring UE: rnti=0x%x not found\n", rnti); + return SRSLTE_ERROR; + } } void srslte_enb_ul_fft(srslte_enb_ul_t *q, cf_t *signal_buffer) @@ -153,27 +211,102 @@ void srslte_enb_ul_fft(srslte_enb_ul_t *q, cf_t *signal_buffer) srslte_ofdm_rx_sf(&q->fft, signal_buffer, q->sf_symbols); } -int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q, srslte_ra_ul_grant_t *grant, srslte_softbuffer_rx_t *softbuffer, - uint32_t rnti_idx, uint32_t rv_idx, uint32_t current_tx_nb, - uint8_t *data, srslte_uci_data_t *uci_data, uint32_t tti) +int get_pucch(srslte_enb_ul_t *q, uint16_t rnti, + uint32_t pdcch_n_cce, uint32_t sf_rx, + srslte_uci_data_t *uci_data, uint8_t bits[SRSLTE_PUCCH_MAX_BITS]) { - - if (srslte_pusch_cfg(&q->pusch, &q->pusch_cfg, grant, NULL, NULL, NULL, tti, rv_idx, current_tx_nb)) { - fprintf(stderr, "Error configuring PDSCH\n"); + float noise_power = srslte_chest_ul_get_noise_estimate(&q->chest); + + srslte_pucch_format_t format = srslte_pucch_get_format(uci_data, q->cell.cp); + + uint32_t n_pucch = srslte_pucch_get_npucch(pdcch_n_cce, format, uci_data->scheduling_request, &q->users[rnti]->pucch_sched); + + if (srslte_chest_ul_estimate_pucch(&q->chest, q->sf_symbols, q->ce, format, n_pucch, sf_rx)) { + fprintf(stderr,"Error estimating PUCCH DMRS\n"); return SRSLTE_ERROR; } + + + int ret_val = srslte_pucch_decode(&q->pucch, format, n_pucch, sf_rx, q->sf_symbols, q->ce, noise_power, bits); + if (ret_val < 0) { + fprintf(stderr,"Error decoding PUCCH\n"); + return SRSLTE_ERROR; + } + return ret_val; +} + +int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti, + uint32_t pdcch_n_cce, uint32_t sf_rx, + srslte_uci_data_t *uci_data) +{ + uint8_t bits[SRSLTE_PUCCH_MAX_BITS]; + + if (q->users[rnti]) { + + int ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, bits); + + // If we are looking for SR and ACK at the same time and ret=0, means there is no SR. + // try again to decode ACK only + if (uci_data->scheduling_request && uci_data->uci_ack_len && ret_val != 1) { + uci_data->scheduling_request = false; + ret_val = get_pucch(q, rnti, pdcch_n_cce, sf_rx, uci_data, bits); + } + + // update schedulign request + if (uci_data->scheduling_request) { + uci_data->scheduling_request = (ret_val==1); + } + + // Save ACK bits + if (uci_data->uci_ack_len > 0) { + uci_data->uci_ack = bits[0]; + } + return SRSLTE_SUCCESS; + } else { + fprintf(stderr, "Error getting PUCCH: rnti=0x%x not found\n", rnti); + return SRSLTE_ERROR; + } +} +int srslte_enb_ul_get_pusch(srslte_enb_ul_t *q, srslte_ra_ul_grant_t *grant, srslte_softbuffer_rx_t *softbuffer, + uint16_t rnti, uint32_t rv_idx, uint32_t current_tx_nb, + uint8_t *data, srslte_uci_data_t *uci_data, uint32_t tti) +{ + if (q->users[rnti]) { + if (srslte_pusch_cfg(&q->pusch, + &q->pusch_cfg, + grant, + q->users[rnti]->uci_cfg_en?&q->users[rnti]->uci_cfg:NULL, + &q->hopping_cfg, + q->users[rnti]->srs_cfg_en?&q->users[rnti]->srs_cfg:NULL, + tti, rv_idx, current_tx_nb)) { + fprintf(stderr, "Error configuring PDSCH\n"); + return SRSLTE_ERROR; + } + } else { + if (srslte_pusch_cfg(&q->pusch, + &q->pusch_cfg, + grant, + NULL, + &q->hopping_cfg, + NULL, + tti, rv_idx, current_tx_nb)) { + fprintf(stderr, "Error configuring PDSCH\n"); + return SRSLTE_ERROR; + } + } + uint32_t cyclic_shift_for_dmrs = 0; srslte_chest_ul_estimate(&q->chest, q->sf_symbols, q->ce, grant->L_prb, tti%10, cyclic_shift_for_dmrs, grant->n_prb); float noise_power = srslte_chest_ul_get_noise_estimate(&q->chest); - return srslte_pusch_uci_decode_rnti_idx(&q->pusch, &q->pusch_cfg, - softbuffer, q->sf_symbols, - q->ce, noise_power, - rnti_idx, data, - uci_data); + return srslte_pusch_decode(&q->pusch, &q->pusch_cfg, + softbuffer, q->sf_symbols, + q->ce, noise_power, + rnti, data, + uci_data); } diff --git a/srslte/lib/fec/convcoder.c b/srslte/lib/fec/convcoder.c index c936c7ee4..e5f486556 100644 --- a/srslte/lib/fec/convcoder.c +++ b/srslte/lib/fec/convcoder.c @@ -36,13 +36,13 @@ int srslte_convcoder_encode(srslte_convcoder_t *q, uint8_t *input, uint8_t *output, uint32_t frame_length) { uint32_t sr; uint32_t i,j; - uint32_t len = q->tail_biting ? frame_length : (frame_length + q->K - 1); if (q != NULL && input != NULL && output != NULL && frame_length > q->K + 1) { + uint32_t len = q->tail_biting ? frame_length : (frame_length + q->K - 1); if (q->tail_biting) { sr = 0; for (i=frame_length - q->K + 1; i>= 1; + ti >>= 1; } Partab[i] = cnt & 1; } diff --git a/srslte/lib/fec/viterbi37_port.c b/srslte/lib/fec/viterbi37_port.c index cf05b3c53..db2acc7e7 100644 --- a/srslte/lib/fec/viterbi37_port.c +++ b/srslte/lib/fec/viterbi37_port.c @@ -33,15 +33,28 @@ struct v37 { decision_t *dp; /* Pointer to current decision */ metric_t *old_metrics, *new_metrics; /* Pointers to path metrics, swapped on every bit */ decision_t *decisions; /* Beginning of decisions for block */ + uint32_t len; }; +void clear_v37(struct v37 *vp) { + bzero(vp->decisions, sizeof(decision_t)*vp->len); + vp->dp = NULL; + bzero(&vp->metrics1, sizeof(metric_t)); + bzero(&vp->metrics2, sizeof(metric_t)); + vp->old_metrics = NULL; + vp->new_metrics = NULL; +} + /* Initialize Viterbi decoder for start of new frame */ int init_viterbi37_port(void *p, int starting_state) { struct v37 *vp = p; uint32_t i; - + if (p == NULL) return -1; + + clear_v37(vp); + for (i = 0; i < 64; i++) vp->metrics1.w[i] = 63; @@ -81,6 +94,8 @@ void *create_viterbi37_port(int polys[3], uint32_t len) { free(vp); return NULL ; } + + vp->len = len+6; return vp; } diff --git a/srslte/lib/fec/viterbi37_sse.c b/srslte/lib/fec/viterbi37_sse.c index 3ecbfeefc..d6dc6a9e2 100644 --- a/srslte/lib/fec/viterbi37_sse.c +++ b/srslte/lib/fec/viterbi37_sse.c @@ -42,6 +42,7 @@ struct v37 { decision_t *dp; /* Pointer to current decision */ metric_t *old_metrics,*new_metrics; /* Pointers to path metrics, swapped on every bit */ decision_t *decisions; /* Beginning of decisions for block */ + uint32_t len; }; void set_viterbi37_polynomial_sse(int polys[3]) { @@ -54,15 +55,26 @@ void set_viterbi37_polynomial_sse(int polys[3]) { } } +void clear_v37_sse(struct v37 *vp) { + bzero(vp->decisions, sizeof(decision_t)*vp->len); + vp->dp = NULL; + bzero(&vp->metrics1, sizeof(metric_t)); + bzero(&vp->metrics2, sizeof(metric_t)); + vp->old_metrics = NULL; + vp->new_metrics = NULL; +} + /* Initialize Viterbi decoder for start of new frame */ int init_viterbi37_sse(void *p, int starting_state) { struct v37 *vp = p; uint32_t i; - + for(i=0;i<64;i++) vp->metrics1.c[i] = 63; + clear_v37_sse(vp); + vp->old_metrics = &vp->metrics1; vp->new_metrics = &vp->metrics2; vp->dp = vp->decisions; @@ -89,6 +101,7 @@ void *create_viterbi37_sse(int polys[3], uint32_t len) { return NULL; } vp->decisions = (decision_t *)p; + vp->len = len+6; return vp; } diff --git a/srslte/lib/io/netsink.c b/srslte/lib/io/netsink.c index bc1648933..0a4c8110d 100644 --- a/srslte/lib/io/netsink.c +++ b/srslte/lib/io/netsink.c @@ -38,7 +38,7 @@ #include "srslte/io/netsink.h" -int srslte_netsink_init(srslte_netsink_t *q, char *address, int port, srslte_netsink_type_t type) { +int srslte_netsink_init(srslte_netsink_t *q, const char *address, uint16_t port, srslte_netsink_type_t type) { bzero(q, sizeof(srslte_netsink_t)); q->sockfd=socket(AF_INET, type==SRSLTE_NETSINK_TCP?SOCK_STREAM:SOCK_DGRAM,0); @@ -47,6 +47,16 @@ int srslte_netsink_init(srslte_netsink_t *q, char *address, int port, srslte_net return -1; } + int enable = 1; +#if defined (SO_REUSEADDR) + if (setsockopt(q->sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0) + perror("setsockopt(SO_REUSEADDR) failed"); +#endif +#if defined (SO_REUSEPORT) + if (setsockopt(q->sockfd, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(int)) < 0) + perror("setsockopt(SO_REUSEPORT) failed"); +#endif + q->servaddr.sin_family = AF_INET; q->servaddr.sin_addr.s_addr=inet_addr(address); q->servaddr.sin_port=htons(port); diff --git a/srslte/lib/io/netsource.c b/srslte/lib/io/netsource.c index 75e311812..4e81331f4 100644 --- a/srslte/lib/io/netsource.c +++ b/srslte/lib/io/netsource.c @@ -36,7 +36,7 @@ #include "srslte/io/netsource.h" -int srslte_netsource_init(srslte_netsource_t *q, char *address, int port, srslte_netsource_type_t type) { +int srslte_netsource_init(srslte_netsource_t *q, const char *address, uint16_t port, srslte_netsource_type_t type) { bzero(q, sizeof(srslte_netsource_t)); q->sockfd=socket(AF_INET,type==SRSLTE_NETSOURCE_TCP?SOCK_STREAM:SOCK_DGRAM,0); @@ -45,6 +45,17 @@ int srslte_netsource_init(srslte_netsource_t *q, char *address, int port, srslte perror("socket"); return -1; } + + // Make sockets reusable + int enable = 1; +#if defined (SO_REUSEADDR) + if (setsockopt(q->sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0) + perror("setsockopt(SO_REUSEADDR) failed"); +#endif +#if defined (SO_REUSEPORT) + if (setsockopt(q->sockfd, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(int)) < 0) + perror("setsockopt(SO_REUSEPORT) failed"); +#endif q->type = type; q->servaddr.sin_family = AF_INET; diff --git a/srslte/lib/mimo/test/precoder_test.c b/srslte/lib/mimo/test/precoder_test.c index 68ff0d8f5..e935a7067 100644 --- a/srslte/lib/mimo/test/precoder_test.c +++ b/srslte/lib/mimo/test/precoder_test.c @@ -173,7 +173,7 @@ int main(int argc, char **argv) { } gettimeofday(&t[2], NULL); get_time_interval(t); - printf("Execution Time: %d us\n", t[0].tv_usec); + printf("Execution Time: %ld us\n", t[0].tv_usec); /* check errors */ mse = 0; diff --git a/srslte/lib/modem/test/modem_test.c b/srslte/lib/modem/test/modem_test.c index 59c80dbfc..d233f7418 100644 --- a/srslte/lib/modem/test/modem_test.c +++ b/srslte/lib/modem/test/modem_test.c @@ -159,7 +159,7 @@ int main(int argc, char **argv) { gettimeofday(&t[2], NULL); get_time_interval(t); - printf("Bit: %d us\n", t[0].tv_usec); + printf("Bit: %ld us\n", t[0].tv_usec); /* Test packed implementation */ srslte_bit_pack_vector(input, input_bytes, num_bits); @@ -170,8 +170,8 @@ int main(int argc, char **argv) { gettimeofday(&t[2], NULL); get_time_interval(t); - printf("Byte: %d us\n", t[0].tv_usec); + printf("Byte: %ld us\n", t[0].tv_usec); for (int i=0;i=0 ? 1 : 0; } diff --git a/srslte/lib/phch/cqi.c b/srslte/lib/phch/cqi.c index a19060961..5ac536341 100644 --- a/srslte/lib/phch/cqi.c +++ b/srslte/lib/phch/cqi.c @@ -39,7 +39,9 @@ #include "srslte/utils/vector.h" #include "srslte/utils/debug.h" - +/******************************************************* + * PACKING FUNCTIONS * + *******************************************************/ int srslte_cqi_hl_subband_pack(srslte_cqi_hl_subband_t *msg, uint8_t buff[SRSLTE_CQI_MAX_BITS]) { uint8_t *body_ptr = buff; @@ -89,6 +91,74 @@ int srslte_cqi_value_pack(srslte_cqi_value_t *value, uint8_t buff[SRSLTE_CQI_MAX return -1; } + +/******************************************************* + * UNPACKING FUNCTIONS * + *******************************************************/ + +int srslte_cqi_hl_subband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_hl_subband_t *msg) +{ + uint8_t *body_ptr = buff; + msg->wideband_cqi = srslte_bit_pack(&body_ptr, 4); + msg->subband_diff_cqi = srslte_bit_pack(&body_ptr, 2*msg->N); + + return 4+2*msg->N; +} + +int srslte_cqi_ue_subband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_ue_subband_t *msg) +{ + uint8_t *body_ptr = buff; + msg->wideband_cqi = srslte_bit_pack(&body_ptr, 4); + msg->subband_diff_cqi = srslte_bit_pack(&body_ptr, 2); + msg->subband_diff_cqi = srslte_bit_pack(&body_ptr, msg->L); + + return 4+2+msg->L; +} + +int srslte_cqi_format2_wideband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_format2_wideband_t *msg) +{ + uint8_t *body_ptr = buff; + msg->wideband_cqi = srslte_bit_pack(&body_ptr, 4); + return 4; +} + +int srslte_cqi_format2_subband_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_format2_subband_t *msg) +{ + uint8_t *body_ptr = buff; + msg->subband_cqi = srslte_bit_pack(&body_ptr, 4); + msg->subband_label = srslte_bit_pack(&body_ptr, msg->subband_label_2_bits?2:1); + return 4+(msg->subband_label_2_bits)?2:1; +} + +int srslte_cqi_value_unpack(uint8_t buff[SRSLTE_CQI_MAX_BITS], srslte_cqi_value_t *value) +{ + switch(value->type) { + case SRSLTE_CQI_TYPE_WIDEBAND: + return srslte_cqi_format2_wideband_unpack(buff, &value->wideband); + case SRSLTE_CQI_TYPE_SUBBAND: + return srslte_cqi_format2_subband_unpack(buff, &value->subband); + case SRSLTE_CQI_TYPE_SUBBAND_UE: + return srslte_cqi_ue_subband_unpack(buff, &value->subband_ue); + case SRSLTE_CQI_TYPE_SUBBAND_HL: + return srslte_cqi_hl_subband_unpack(buff, &value->subband_hl); + } + return -1; +} + +int srslte_cqi_size(srslte_cqi_value_t *value) { + switch(value->type) { + case SRSLTE_CQI_TYPE_WIDEBAND: + return 4; + case SRSLTE_CQI_TYPE_SUBBAND: + return 4+(value->subband.subband_label_2_bits)?2:1; + case SRSLTE_CQI_TYPE_SUBBAND_UE: + return 4+2+value->subband_ue.L; + case SRSLTE_CQI_TYPE_SUBBAND_HL: + return 4+2*value->subband_hl.N; + } + return -1; +} + bool srslte_cqi_send(uint32_t I_cqi_pmi, uint32_t tti) { uint32_t N_p = 0; @@ -129,15 +199,26 @@ bool srslte_cqi_send(uint32_t I_cqi_pmi, uint32_t tti) { } else if (I_cqi_pmi <= 1023) { return false; } - - if ((tti-N_offset)%N_p == 0) { - return true; - } else { - return false; + if (N_p) { + if ((tti-N_offset)%N_p == 0) { + return true; + } } + return false; } +// CQI-to-Spectral Efficiency: 36.213 Table 7.2.3-1 */ +static float cqi_to_coderate[16] = {0, 0.1523, 0.2344, 0.3770, 0.6016, 0.8770, 1.1758, 1.4766, 1.9141, 2.4063, 2.7305, 3.3223, 3.9023, 4.5234, 5.1152, 5.5547}; + +float srslte_cqi_to_coderate(uint32_t cqi) { + if (cqi < 16) { + return cqi_to_coderate[cqi]; + } else { + return 0; + } +} + /* SNR-to-CQI conversion, got from "Downlink SNR to CQI Mapping for Different Multiple Antenna Techniques in LTE" * Table III. */ @@ -181,5 +262,10 @@ int srslte_cqi_hl_get_subband_size(int nof_prb) */ int srslte_cqi_hl_get_no_subbands(int nof_prb) { - return (int)ceil(nof_prb/(float)srslte_cqi_hl_get_subband_size(nof_prb)); + int hl_size = srslte_cqi_hl_get_subband_size(nof_prb); + if (hl_size > 0) { + return (int)ceil((float)nof_prb/hl_size); + } else { + return 0; + } } diff --git a/srslte/lib/phch/dci.c b/srslte/lib/phch/dci.c index 57dc9862a..194220507 100644 --- a/srslte/lib/phch/dci.c +++ b/srslte/lib/phch/dci.c @@ -41,6 +41,8 @@ #include "dci_sz_table.h" +int harq_pid_len = 3; + /* Unpacks a DCI message and configures the DL grant object */ int srslte_dci_msg_to_dl_grant(srslte_dci_msg_t *msg, uint16_t msg_rnti, @@ -62,10 +64,10 @@ int srslte_dci_msg_to_dl_grant(srslte_dci_msg_t *msg, uint16_t msg_rnti, if (msg_rnti >= SRSLTE_CRNTI_START && msg_rnti <= SRSLTE_CRNTI_END) { crc_is_crnti = true; } - srslte_dci_format_t tmp = msg->format; + //srslte_dci_format_t tmp = msg->format; ret = srslte_dci_msg_unpack_pdsch(msg, dl_dci, nof_prb, nof_ports, crc_is_crnti); if (ret) { - fprintf(stderr, "Can't unpack DCI message %s (%d)\n", srslte_dci_format_string(tmp), ret); + fprintf(stderr, "Can't unpack DCI message %s (%d)\n", srslte_dci_format_string(msg->format), msg->format); return ret; } @@ -170,7 +172,7 @@ int srslte_dci_msg_to_ul_grant(srslte_dci_msg_t *msg, uint32_t nof_prb, ret = SRSLTE_ERROR; bzero(ul_dci, sizeof(srslte_ra_ul_dci_t)); - bzero(grant, sizeof(srslte_ra_ul_dci_t)); + bzero(grant, sizeof(srslte_ra_ul_grant_t)); if (srslte_dci_msg_unpack_pusch(msg, ul_dci, nof_prb)) { return ret; @@ -240,7 +242,7 @@ uint32_t dci_format0_sizeof_(uint32_t nof_prb) { uint32_t dci_format1A_sizeof(uint32_t nof_prb) { uint32_t n; - n = 1 + 1 + riv_nbits(nof_prb) + 5 + 3 + 1 + 2 + 2; + n = 1 + 1 + riv_nbits(nof_prb) + 5 + harq_pid_len + 1 + 2 + 2; while (n < dci_format0_sizeof_(nof_prb)) { n++; } @@ -260,7 +262,7 @@ uint32_t dci_format0_sizeof(uint32_t nof_prb) { uint32_t dci_format1_sizeof(uint32_t nof_prb) { - uint32_t n = (uint32_t) ceilf((float) nof_prb / srslte_ra_type0_P(nof_prb)) + 5 + 3 + 1 + 2 + uint32_t n = (uint32_t) ceilf((float) nof_prb / srslte_ra_type0_P(nof_prb)) + 5 + harq_pid_len + 1 + 2 + 2; if (nof_prb > 10) { n++; @@ -316,7 +318,7 @@ uint32_t precoding_bits_f2(uint32_t nof_ports) { } uint32_t dci_format2_sizeof(uint32_t nof_prb, uint32_t nof_ports) { - uint32_t n = (uint32_t) ceilf((float) nof_prb / srslte_ra_type0_P(nof_prb))+2+3+1+2*(5+1+2)+precoding_bits_f2(nof_ports); + uint32_t n = (uint32_t) ceilf((float) nof_prb / srslte_ra_type0_P(nof_prb))+2+harq_pid_len+1+2*(5+1+2)+precoding_bits_f2(nof_ports); if (nof_prb > 10) { n++; } @@ -336,7 +338,7 @@ uint32_t precoding_bits_f2a(uint32_t nof_ports) { } uint32_t dci_format2A_sizeof(uint32_t nof_prb, uint32_t nof_ports) { - uint32_t n = (uint32_t) ceilf((float) nof_prb / srslte_ra_type0_P(nof_prb))+2+3+1+2*(5+1+2)+precoding_bits_f2a(nof_ports); + uint32_t n = (uint32_t) ceilf((float) nof_prb / srslte_ra_type0_P(nof_prb))+2+harq_pid_len+1+2*(5+1+2)+precoding_bits_f2a(nof_ports); if (nof_prb > 10) { n++; } @@ -348,7 +350,7 @@ uint32_t dci_format2A_sizeof(uint32_t nof_prb, uint32_t nof_ports) { } uint32_t dci_format2B_sizeof(uint32_t nof_prb, uint32_t nof_ports) { - uint32_t n = (uint32_t) ceilf((float) nof_prb / srslte_ra_type0_P(nof_prb))+2+3+1+2*(5+1+2); + uint32_t n = (uint32_t) ceilf((float) nof_prb / srslte_ra_type0_P(nof_prb))+2+harq_pid_len+1+2*(5+1+2); if (nof_prb > 10) { n++; } @@ -386,12 +388,13 @@ uint32_t srslte_dci_format_sizeof(srslte_dci_format_t format, uint32_t nof_prb, return dci_format3A_sizeof(nof_prb); */ default: - return SRSLTE_ERROR; + printf("Error computing DCI bits: Unknown format %d\n", format); + return 0; } } uint32_t srslte_dci_format_sizeof_lut(srslte_dci_format_t format, uint32_t nof_prb) { - if (nof_prb <= 100 && format < 11) { + if (nof_prb < 101 && format < 4) { return dci_sz_table[nof_prb][format]; } else { return 0; @@ -444,20 +447,17 @@ int dci_format0_pack(srslte_ra_ul_dci_t *data, srslte_dci_msg_t *msg, uint32_t n *y++ = data->ndi; - // TCP commands not implemented - *y++ = 0; - *y++ = 0; + // TCP command for PUSCH + srslte_bit_unpack(data->tpc_pusch, &y, 2); // DM RS not implemented - *y++ = 0; - *y++ = 0; - *y++ = 0; + srslte_bit_unpack(data->n_dmrs, &y, 3); // CQI request *y++ = data->cqi_request; // Padding with zeros - uint32_t n = srslte_dci_format_sizeof_lut(SRSLTE_DCI_FORMAT0, nof_prb); + uint32_t n = srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT0, nof_prb, 1); while (y - msg->data < n) { *y++ = 0; } @@ -476,7 +476,7 @@ int dci_format0_unpack(srslte_dci_msg_t *msg, srslte_ra_ul_dci_t *data, uint32_t uint32_t n_ul_hop; /* Make sure it's a SRSLTE_DCI_FORMAT0 message */ - if (msg->nof_bits != srslte_dci_format_sizeof_lut(SRSLTE_DCI_FORMAT0, nof_prb)) { + if (msg->nof_bits != srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT0, nof_prb, 1)) { fprintf(stderr, "Invalid message length for format 0\n"); return SRSLTE_ERROR; } @@ -558,19 +558,18 @@ int dci_format1_pack(srslte_ra_dl_dci_t *data, srslte_dci_msg_t *msg, uint32_t n srslte_bit_unpack(data->mcs_idx, &y, 5); /* harq process number */ - srslte_bit_unpack(data->harq_process, &y, 3); + srslte_bit_unpack(data->harq_process, &y, harq_pid_len); *y++ = data->ndi; // rv version srslte_bit_unpack(data->rv_idx, &y, 2); - // TPC not implemented - *y++ = 0; - *y++ = 0; + // TCP command for PUCCH + srslte_bit_unpack(data->tpc_pucch, &y, 2); // Padding with zeros - uint32_t n = srslte_dci_format_sizeof_lut(SRSLTE_DCI_FORMAT1, nof_prb); + uint32_t n = srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT1, nof_prb, 1); while (y - msg->data < n) { *y++ = 0; } @@ -585,7 +584,7 @@ int dci_format1_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32_t uint8_t *y = msg->data; /* Make sure it's a SRSLTE_DCI_FORMAT1 message */ - if (msg->nof_bits != srslte_dci_format_sizeof_lut(SRSLTE_DCI_FORMAT1, nof_prb)) { + if (msg->nof_bits != srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT1, nof_prb, 1)) { fprintf(stderr, "Invalid message length for format 1\n"); return SRSLTE_ERROR; } @@ -618,7 +617,7 @@ int dci_format1_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32_t data->mcs_idx = srslte_bit_pack(&y, 5); /* harq process number */ - data->harq_process = srslte_bit_pack(&y, 3); + data->harq_process = srslte_bit_pack(&y, harq_pid_len); data->ndi = *y++ ? true : false; // rv version @@ -626,6 +625,8 @@ int dci_format1_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32_t // TPC not implemented + data->tb_en[0] = true; + data->tb_en[1] = false; return SRSLTE_SUCCESS; } @@ -646,6 +647,8 @@ int dci_format1As_pack(srslte_ra_dl_dci_t *data, srslte_dci_msg_t *msg, uint32_t fprintf(stderr, "Format 1A accepts type2 resource allocation only\n"); return SRSLTE_ERROR; } + + data->dci_is_1a = true; *y++ = data->type2_alloc.mode; // localized or distributed VRB assignment @@ -687,7 +690,7 @@ int dci_format1As_pack(srslte_ra_dl_dci_t *data, srslte_dci_msg_t *msg, uint32_t // in format1A, MCS = TBS according to 7.1.7.2 of 36.213 srslte_bit_unpack(data->mcs_idx, &y, 5); - srslte_bit_unpack(data->harq_process, &y, 3); + srslte_bit_unpack(data->harq_process, &y, harq_pid_len); if (crc_is_crnti) { if (nof_prb >= 50 && data->type2_alloc.mode == SRSLTE_RA_TYPE2_DIST) { @@ -712,12 +715,12 @@ int dci_format1As_pack(srslte_ra_dl_dci_t *data, srslte_dci_msg_t *msg, uint32_t } // Padding with zeros - uint32_t n = srslte_dci_format_sizeof_lut(SRSLTE_DCI_FORMAT1A, nof_prb); + uint32_t n = srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT1A, nof_prb, 1); while (y - msg->data < n) { *y++ = 0; } msg->nof_bits = (y - msg->data); - + return SRSLTE_SUCCESS; } @@ -731,7 +734,7 @@ int dci_format1As_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32 uint8_t *y = msg->data; /* Make sure it's a SRSLTE_DCI_FORMAT0 message */ - if (msg->nof_bits != srslte_dci_format_sizeof_lut(SRSLTE_DCI_FORMAT1A, nof_prb)) { + if (msg->nof_bits != srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT1A, nof_prb, 1)) { fprintf(stderr, "Invalid message length for format 1A\n"); return SRSLTE_ERROR; } @@ -750,13 +753,13 @@ int dci_format1As_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32 while(inof_bits-1 && y[i] == 0) { i++; } if (i == msg->nof_bits-1) { - printf("Received a Format1A RA PDCCH order. Not implemented!\n"); + //printf("Received a Format1A RA PDCCH order. Not implemented!\n"); return SRSLTE_ERROR; } } @@ -788,7 +791,7 @@ int dci_format1As_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32 // unpack MCS data->mcs_idx = srslte_bit_pack(&y, 5); - data->harq_process = srslte_bit_pack(&y, 3); + data->harq_process = srslte_bit_pack(&y, harq_pid_len); if (!crc_is_crnti) { if (nof_prb >= 50 && data->type2_alloc.mode == SRSLTE_RA_TYPE2_DIST) { @@ -811,6 +814,9 @@ int dci_format1As_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32 y++; // MSB of TPC is reserved data->type2_alloc.n_prb1a = *y++; // LSB indicates N_prb_1a for TBS } + + data->tb_en[0] = true; + data->tb_en[1] = false; return SRSLTE_SUCCESS; } @@ -846,7 +852,7 @@ int dci_format1B_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32_ // unpack MCS, Harq pid and ndi data->mcs_idx = srslte_bit_pack(&y, 5); - data->harq_process = srslte_bit_pack(&y, 3); + data->harq_process = srslte_bit_pack(&y, harq_pid_len); data->ndi = *y++ ? true : false; data->rv_idx = srslte_bit_pack(&y, 2); @@ -855,7 +861,9 @@ int dci_format1B_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32_ data->pinfo = srslte_bit_pack(&y, tpmi_bits(nof_ports)); data->pconf = *y++ ? true : false; - + + data->tb_en[0] = true; + data->tb_en[1] = false; return SRSLTE_SUCCESS; } @@ -873,6 +881,8 @@ int dci_format1Cs_pack(srslte_ra_dl_dci_t *data, srslte_dci_msg_t *msg, uint32_t "Format 1C accepts distributed type2 resource allocation only\n"); return SRSLTE_ERROR; } + + data->dci_is_1c = true; if (nof_prb >= 50) { *y++ = data->type2_alloc.n_gap; @@ -919,7 +929,7 @@ int dci_format1Cs_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32 /* pack bits */ uint8_t *y = msg->data; - if (msg->nof_bits != srslte_dci_format_sizeof_lut(SRSLTE_DCI_FORMAT1C, nof_prb)) { + if (msg->nof_bits != srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT1C, nof_prb, 1)) { fprintf(stderr, "Invalid message length for format 1C\n"); return SRSLTE_ERROR; } @@ -944,9 +954,12 @@ int dci_format1Cs_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32 data->mcs_idx = srslte_bit_pack(&y, 5); - data->rv_idx = -1; // For SI-RNTI, get RV from TTI + data->rv_idx = -1; // Get RV later msg->nof_bits = (y - msg->data); + + data->tb_en[0] = true; + data->tb_en[1] = false; return SRSLTE_SUCCESS; } @@ -982,7 +995,7 @@ int dci_format1D_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32_ // unpack MCS, Harq pid and ndi data->mcs_idx = srslte_bit_pack(&y, 5); - data->harq_process = srslte_bit_pack(&y, 3); + data->harq_process = srslte_bit_pack(&y, harq_pid_len); data->ndi = *y++ ? true : false; data->rv_idx = srslte_bit_pack(&y, 2); @@ -992,6 +1005,8 @@ int dci_format1D_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32_ data->pinfo = srslte_bit_pack(&y, tpmi_bits(nof_ports)); data->power_offset = *y++ ? true : false; + data->tb_en[0] = true; + data->tb_en[1] = false; return SRSLTE_SUCCESS; } @@ -1030,7 +1045,7 @@ int dci_format2AB_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32 y+=2; /* harq process number */ - data->harq_process = srslte_bit_pack(&y, 3); + data->harq_process = srslte_bit_pack(&y, harq_pid_len); // Transpor block to codeword swap flag if (msg->format == SRSLTE_DCI_FORMAT2B) { @@ -1041,16 +1056,23 @@ int dci_format2AB_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32 /* unpack MCS according to 7.1.7 of 36.213 */ data->mcs_idx = srslte_bit_pack(&y, 5); - data->ndi = *y++ ? true : false; - - // rv version data->rv_idx = srslte_bit_pack(&y, 2); + if (data->mcs_idx == 0 && data->rv_idx == 1) { + data->tb_en[0] = false; + } else { + data->tb_en[0] = true; + } // same for tb1 data->mcs_idx_1 = srslte_bit_pack(&y, 5); data->ndi_1 = *y++ ? true : false; data->rv_idx_1 = srslte_bit_pack(&y, 2); + if (data->mcs_idx_1 == 0 && data->rv_idx_1 == 1) { + data->tb_en[1] = false; + } else { + data->tb_en[1] = true; + } // Precoding information if (msg->format == SRSLTE_DCI_FORMAT2A) { @@ -1059,6 +1081,7 @@ int dci_format2AB_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32 data->pinfo = srslte_bit_pack(&y, precoding_bits_f2a(nof_ports)); } + return SRSLTE_SUCCESS; } @@ -1192,16 +1215,16 @@ int srslte_dci_msg_get_type(srslte_dci_msg_t *msg, srslte_dci_msg_type_t *type, uint16_t msg_rnti) { DEBUG("Get message type: nof_bits=%d, msg_rnti=0x%x\n", msg->nof_bits, msg_rnti); - if (msg->nof_bits == srslte_dci_format_sizeof_lut(SRSLTE_DCI_FORMAT0, nof_prb) + if (msg->nof_bits == srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT0, nof_prb, 1) && !msg->data[0]) { type->type = SRSLTE_DCI_MSG_TYPE_PUSCH_SCHED; type->format = SRSLTE_DCI_FORMAT0; return SRSLTE_SUCCESS; - } else if (msg->nof_bits == srslte_dci_format_sizeof_lut(SRSLTE_DCI_FORMAT1, nof_prb)) { + } else if (msg->nof_bits == srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT1, nof_prb, 1)) { type->type = SRSLTE_DCI_MSG_TYPE_PDSCH_SCHED; // only these 2 types supported type->format = SRSLTE_DCI_FORMAT1; return SRSLTE_SUCCESS; - } else if (msg->nof_bits == srslte_dci_format_sizeof_lut(SRSLTE_DCI_FORMAT1A, nof_prb)) { + } else if (msg->nof_bits == srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT1A, nof_prb, 1)) { /* The RNTI is not the only condition. Also some fields in the packet. * if (msg_rnti >= SRSLTE_CRNTI_START && msg_rnti <= SRSLTE_CRNTI_END) { type->type = SRSLTE_DCI_MSG_TYPE_RA_PROC_PDCCH; @@ -1212,7 +1235,7 @@ int srslte_dci_msg_get_type(srslte_dci_msg_t *msg, srslte_dci_msg_type_t *type, type->format = SRSLTE_DCI_FORMAT1A; //} return SRSLTE_SUCCESS; - } else if (msg->nof_bits == srslte_dci_format_sizeof_lut(SRSLTE_DCI_FORMAT1C, nof_prb)) { + } else if (msg->nof_bits == srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT1C, nof_prb, 1)) { if (msg_rnti == SRSLTE_MRNTI) { type->type = SRSLTE_DCI_MSG_TYPE_MCCH_CHANGE; type->format = SRSLTE_DCI_FORMAT1C; diff --git a/srslte/lib/phch/pbch.c b/srslte/lib/phch/pbch.c index 4c5416ab3..5fdacf7b7 100644 --- a/srslte/lib/phch/pbch.c +++ b/srslte/lib/phch/pbch.c @@ -250,8 +250,8 @@ void srslte_pbch_free(srslte_pbch_t *q) { void srslte_pbch_mib_unpack(uint8_t *msg, srslte_cell_t *cell, uint32_t *sfn) { int phich_res; - cell->bw_idx = srslte_bit_pack(&msg, 3); - switch (cell->bw_idx) { + uint32_t bw_idx = srslte_bit_pack(&msg, 3); + switch (bw_idx) { case 0: cell->nof_prb = 6; break; @@ -259,7 +259,7 @@ void srslte_pbch_mib_unpack(uint8_t *msg, srslte_cell_t *cell, uint32_t *sfn) { cell->nof_prb = 15; break; default: - cell->nof_prb = (cell->bw_idx - 1) * 25; + cell->nof_prb = (bw_idx - 1) * 25; break; } if (*msg) { diff --git a/srslte/lib/phch/pdcch.c b/srslte/lib/phch/pdcch.c index 8a67f8d0f..9cf610c01 100644 --- a/srslte/lib/phch/pdcch.c +++ b/srslte/lib/phch/pdcch.c @@ -52,6 +52,13 @@ static void set_cfi(srslte_pdcch_t *q, uint32_t cfi) { } } +void srslte_pdcch_set_cfi(srslte_pdcch_t *q, uint32_t cfi) { + set_cfi(q, cfi); +} + +float srslte_pdcch_coderate(uint32_t nof_bits, uint32_t l) { + return (float) (nof_bits+16)/(4*PDCCH_FORMAT_NOF_REGS(l)); +} /** Initializes the PDCCH transmitter and receiver */ int srslte_pdcch_init(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell) { @@ -201,22 +208,24 @@ uint32_t srslte_pdcch_ue_locations_ncce(uint32_t nof_cce, srslte_dci_location_t L = (1 << l); // For all possible ncce offset for (i = 0; i < SRSLTE_MIN(nof_cce / L, S[l]/PDCCH_FORMAT_NOF_CCE(l)); i++) { - ncce = L * ((Yk + i) % (nof_cce / L)); - if (k < max_candidates && - ncce + PDCCH_FORMAT_NOF_CCE(l) <= nof_cce) - { - c[k].L = l; - c[k].ncce = ncce; - - DEBUG("UE-specific SS Candidate %d: nCCE: %d, L: %d\n", - k, c[k].ncce, c[k].L); + if (nof_cce > L) { + ncce = L * ((Yk + i) % (nof_cce / L)); + if (k < max_candidates && ncce + L <= nof_cce) + { + c[k].L = l; + c[k].ncce = ncce; + + DEBUG("UE-specific SS Candidate %d: nCCE: %d, L: %d\n", + k, c[k].ncce, c[k].L); - k++; - } + k++; + } + } } - } + } - DEBUG("Initiated %d candidate(s) in the UE-specific search space for C-RNTI: 0x%x\n", k, rnti); + DEBUG("Initiated %d candidate(s) in the UE-specific search space for C-RNTI: 0x%x, nsubframe=%d, nof_cce=%d\n", + k, rnti, nsubframe, nof_cce); return k; } @@ -249,7 +258,7 @@ uint32_t srslte_pdcch_common_locations_ncce(uint32_t nof_cce, srslte_dci_locatio c[k].ncce = (L) * (i % (nof_cce / (L))); DEBUG("Common SS Candidate %d: nCCE: %d, L: %d\n", k, c[k].ncce, c[k].L); - k++; + k++; } } } @@ -275,33 +284,36 @@ int srslte_pdcch_dci_decode(srslte_pdcch_t *q, float *e, uint8_t *data, uint32_t uint16_t p_bits, crc_res; uint8_t *x; - if (q != NULL && - data != NULL && - E <= q->max_bits && - nof_bits <= SRSLTE_DCI_MAX_BITS) - { - bzero(q->rm_f, sizeof(float)*3 * (SRSLTE_DCI_MAX_BITS + 16)); - - uint32_t coded_len = 3 * (nof_bits + 16); - - /* unrate matching */ - srslte_rm_conv_rx(e, E, q->rm_f, coded_len); - - /* viterbi decoder */ - srslte_viterbi_decode_f(&q->decoder, q->rm_f, data, nof_bits + 16); + if (q != NULL) { + if (data != NULL && + E <= q->max_bits && + nof_bits <= SRSLTE_DCI_MAX_BITS) + { + bzero(q->rm_f, sizeof(float)*3 * (SRSLTE_DCI_MAX_BITS + 16)); + + uint32_t coded_len = 3 * (nof_bits + 16); + + /* unrate matching */ + srslte_rm_conv_rx(e, E, q->rm_f, coded_len); + + /* viterbi decoder */ + srslte_viterbi_decode_f(&q->decoder, q->rm_f, data, nof_bits + 16); - x = &data[nof_bits]; - p_bits = (uint16_t) srslte_bit_pack(&x, 16); - crc_res = ((uint16_t) srslte_crc_checksum(&q->crc, data, nof_bits) & 0xffff); - - if (crc) { - *crc = p_bits ^ crc_res; + x = &data[nof_bits]; + p_bits = (uint16_t) srslte_bit_pack(&x, 16); + crc_res = ((uint16_t) srslte_crc_checksum(&q->crc, data, nof_bits) & 0xffff); + + if (crc) { + *crc = p_bits ^ crc_res; + } + + return SRSLTE_SUCCESS; + } else { + fprintf(stderr, "Invalid parameters: E: %d, max_bits: %d, nof_bits: %d\n", E, q->max_bits, nof_bits); + return SRSLTE_ERROR_INVALID_INPUTS; } - - return SRSLTE_SUCCESS; } else { - fprintf(stderr, "Invalid parameters: E: %d, max_bits: %d, nof_bits: %d\n", E, q->max_bits, nof_bits); - return SRSLTE_ERROR_INVALID_INPUTS; + return SRSLTE_ERROR_INVALID_INPUTS; } } @@ -319,15 +331,16 @@ int srslte_pdcch_decode_msg(srslte_pdcch_t *q, int ret = SRSLTE_ERROR_INVALID_INPUTS; if (q != NULL && msg != NULL && - srslte_dci_location_isvalid(location) && - crc_rem != NULL) + srslte_dci_location_isvalid(location)) { if (location->ncce * 72 + PDCCH_FORMAT_NOF_BITS(location->L) > q->nof_cce*72) { fprintf(stderr, "Invalid location: nCCE: %d, L: %d, NofCCE: %d\n", location->ncce, location->L, q->nof_cce); } else { - uint32_t nof_bits = srslte_dci_format_sizeof_lut(format, q->cell.nof_prb); + ret = SRSLTE_SUCCESS; + + uint32_t nof_bits = srslte_dci_format_sizeof(format, q->cell.nof_prb, q->cell.nof_ports); uint32_t e_bits = PDCCH_FORMAT_NOF_BITS(location->L); double mean = 0; @@ -346,17 +359,20 @@ int srslte_pdcch_decode_msg(srslte_pdcch_t *q, } else { msg->format = format; } - } + } else { + fprintf(stderr, "Error calling pdcch_dci_decode\n"); + } if (crc_rem) { DEBUG("Decoded DCI: nCCE=%d, L=%d, format=%s, msg_len=%d, mean=%f, crc_rem=0x%x\n", location->ncce, location->L, srslte_dci_format_string(format), nof_bits, mean, *crc_rem); } } else { DEBUG("Skipping DCI: nCCE=%d, L=%d, msg_len=%d, mean=%f\n", - location->ncce, location->L, nof_bits, mean); - ret = SRSLTE_SUCCESS; + location->ncce, location->L, nof_bits, mean); } } + } else { + fprintf(stderr, "Invalid parameters, location=%d,%d\n", location->ncce, location->L); } return ret; } @@ -525,7 +541,7 @@ int srslte_pdcch_encode(srslte_pdcch_t *q, srslte_dci_msg_t *msg, srslte_dci_loc ret = SRSLTE_ERROR; if (location.ncce + PDCCH_FORMAT_NOF_CCE(location.L) <= q->nof_cce && - msg->nof_bits < SRSLTE_DCI_MAX_BITS) + msg->nof_bits < SRSLTE_DCI_MAX_BITS - 16) { DEBUG("Encoding DCI: Nbits: %d, E: %d, nCCE: %d, L: %d, RNTI: 0x%x\n", msg->nof_bits, e_bits, location.ncce, location.L, rnti); diff --git a/srslte/lib/phch/pdsch.c b/srslte/lib/phch/pdsch.c index 10b50bf43..b4ae7621f 100644 --- a/srslte/lib/phch/pdsch.c +++ b/srslte/lib/phch/pdsch.c @@ -57,6 +57,10 @@ extern int indices[100000]; extern int indices_ptr; #endif +float srslte_pdsch_coderate(uint32_t tbs, uint32_t nof_re) +{ + return (float) (tbs + 24)/(nof_re); +} int srslte_pdsch_cp(srslte_pdsch_t *q, cf_t *input, cf_t *output, srslte_ra_dl_grant_t *grant, uint32_t lstart_grant, uint32_t nsubframe, bool put) { @@ -212,7 +216,6 @@ int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell) { q->cell = cell; q->max_re = q->cell.nof_prb * MAX_PDSCH_RE(q->cell.cp); - q->nof_crnti = 0; INFO("Init PDSCH: %d ports %d PRBs, max_symbols: %d\n", q->cell.nof_ports, q->cell.nof_prb, q->max_re); @@ -226,8 +229,6 @@ int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell) { srslte_sch_init(&q->dl_sch); - q->rnti_is_set = false; - // Allocate int16_t for reception (LLRs) q->e = srslte_vec_malloc(sizeof(int16_t) * q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM)); if (!q->e) { @@ -253,7 +254,13 @@ int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell) { goto clean; } } - + + q->users = calloc(sizeof(srslte_pdsch_user_t*), 1+SRSLTE_SIRNTI); + if (!q->users) { + perror("malloc"); + goto clean; + } + ret = SRSLTE_SUCCESS; } clean: @@ -284,23 +291,14 @@ void srslte_pdsch_free(srslte_pdsch_t *q) { } } - for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { - srslte_sequence_free(&q->seq[i]); - } - - for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { - for (int n=0;nnof_crnti;n++) { - srslte_sequence_free(&q->seq_multi[i][n]); - } - if (q->seq_multi[i]) { - free(q->seq_multi[i]); - } - } - - if (q->rnti_multi) { - free(q->rnti_multi); + if (q->users) { + for (uint16_t u=0;uusers[u]) { + srslte_pdsch_free_rnti(q, u); + } + } + free(q->users); } - for (i = 0; i < 4; i++) { srslte_modem_table_free(&q->mod[i]); } @@ -316,19 +314,22 @@ void srslte_pdsch_free(srslte_pdsch_t *q) { */ 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) { - - if (cfg && grant) { - memcpy(&cfg->grant, grant, sizeof(srslte_ra_dl_grant_t)); - } - if (srslte_cbsegm(&cfg->cb_segm, cfg->grant.mcs.tbs)) { - fprintf(stderr, "Error computing Codeblock segmentation for TBS=%d\n", cfg->grant.mcs.tbs); - return SRSLTE_ERROR; - } - srslte_ra_dl_grant_to_nbits(&cfg->grant, cfi, cell, sf_idx, &cfg->nbits); - cfg->sf_idx = sf_idx; - cfg->rv = rvidx; + if (cfg) { + if (grant) { + memcpy(&cfg->grant, grant, sizeof(srslte_ra_dl_grant_t)); + } + if (srslte_cbsegm(&cfg->cb_segm, cfg->grant.mcs.tbs)) { + fprintf(stderr, "Error computing Codeblock segmentation for TBS=%d\n", cfg->grant.mcs.tbs); + return SRSLTE_ERROR; + } + srslte_ra_dl_grant_to_nbits(&cfg->grant, cfi, cell, sf_idx, &cfg->nbits); + cfg->sf_idx = sf_idx; + cfg->rv = rvidx; - return SRSLTE_SUCCESS; + return SRSLTE_SUCCESS; + } else { + return SRSLTE_ERROR_INVALID_INPUTS; + } } @@ -336,100 +337,38 @@ int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_g * to execute, so shall be called once the final C-RNTI has been allocated for the session. */ int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti) { - uint32_t i; - for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { - if (srslte_sequence_pdsch(&q->seq[i], rnti, 0, 2 * i, q->cell.id, - q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) { - return SRSLTE_ERROR; + uint32_t i; + if (!q->users[rnti]) { + q->users[rnti] = calloc(1, sizeof(srslte_pdsch_user_t)); + if (q->users[rnti]) { + for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { + if (srslte_sequence_pdsch(&q->users[rnti]->seq[i], rnti, 0, 2 * i, q->cell.id, + q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) { + return SRSLTE_ERROR; + } + } } } - q->rnti_is_set = true; - q->rnti = rnti; return SRSLTE_SUCCESS; } -/* Initializes the memory to support pre-calculation of multiple scrambling sequences */ -int srslte_pdsch_init_rnti_multi(srslte_pdsch_t *q, uint32_t nof_rntis) +void srslte_pdsch_free_rnti(srslte_pdsch_t* q, uint16_t rnti) { - for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { - q->seq_multi[i] = malloc(sizeof(srslte_sequence_t)*nof_rntis); - if (!q->seq_multi[i]) { - perror("malloc"); - return SRSLTE_ERROR; + if (q->users[rnti]) { + for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { + srslte_sequence_free(&q->users[rnti]->seq[i]); } - } - - q->rnti_multi = srslte_vec_malloc(sizeof(uint16_t)*nof_rntis); - if (!q->rnti_multi) { - perror("malloc"); - return SRSLTE_ERROR; - } - bzero(q->rnti_multi, sizeof(uint16_t)*nof_rntis); - - q->nof_crnti = nof_rntis; - - return SRSLTE_SUCCESS; -} - -int srslte_pdsch_set_rnti_multi(srslte_pdsch_t *q, uint32_t idx, uint16_t rnti) -{ - if (idx < q->nof_crnti) { - if (q->rnti_multi[idx]) { - for (uint32_t i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { - srslte_sequence_free(&q->seq_multi[i][idx]); - } - q->rnti_multi[idx] = 0; - } - q->rnti_multi[idx] = rnti; - q->rnti_is_set = true; - for (uint32_t i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { - if (srslte_sequence_pdsch(&q->seq_multi[i][idx], rnti, 0, 2 * i, q->cell.id, - q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) { - return SRSLTE_ERROR; - } - } - return SRSLTE_SUCCESS; - } else { - return SRSLTE_ERROR_INVALID_INPUTS; - } -} - -uint16_t srslte_pdsch_get_rnti_multi(srslte_pdsch_t *q, uint32_t idx) -{ - if (idx < q->nof_crnti) { - return q->rnti_multi[idx]; - } else { - return SRSLTE_ERROR_INVALID_INPUTS; + free(q->users[rnti]); + q->users[rnti] = NULL; } } +/** Decodes the PDSCH from the received symbols + */ 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, - uint8_t *data) -{ - if (q != NULL && - sf_symbols != NULL && - data != NULL && - cfg != NULL) - { - if (q->rnti_is_set) { - return srslte_pdsch_decode_rnti(q, cfg, softbuffer, sf_symbols, ce, noise_estimate, q->rnti, data); - } else { - fprintf(stderr, "Must call srslte_pdsch_set_rnti() before calling srslte_pdsch_decode()\n"); - return SRSLTE_ERROR; - } - } else { - return SRSLTE_ERROR_INVALID_INPUTS; - } -} - -/** Decodes the PDSCH from the received symbols - */ -int srslte_pdsch_decode_rnti(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, - uint16_t rnti, uint8_t *data) + uint16_t rnti, uint8_t *data) { /* Set pointers for layermapping & precoding */ @@ -497,16 +436,8 @@ int srslte_pdsch_decode_rnti(srslte_pdsch_t *q, */ srslte_demod_soft_demodulate_s(cfg->grant.mcs.mod, q->d, q->e, cfg->nbits.nof_re); - /* - printf("WARNING REMOVE ME!\n"); - int16_t *e=q->e; - for (int i=0;inbits.nof_bits;i++) { - e[i] = e[i]>0?10:-10; - } - */ - /* descramble */ - if (rnti != q->rnti) { + if (!q->users[rnti]) { srslte_sequence_t seq; if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { return SRSLTE_ERROR; @@ -514,7 +445,7 @@ int srslte_pdsch_decode_rnti(srslte_pdsch_t *q, srslte_scrambling_s_offset(&seq, q->e, 0, cfg->nbits.nof_bits); srslte_sequence_free(&seq); } else { - srslte_scrambling_s_offset(&q->seq[cfg->sf_idx], q->e, 0, cfg->nbits.nof_bits); + srslte_scrambling_s_offset(&q->users[rnti]->seq[cfg->sf_idx], q->e, 0, cfg->nbits.nof_bits); } if (SRSLTE_VERBOSE_ISDEBUG()) { @@ -530,27 +461,8 @@ int srslte_pdsch_decode_rnti(srslte_pdsch_t *q, } int srslte_pdsch_encode(srslte_pdsch_t *q, - srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, - uint8_t *data, cf_t *sf_symbols[SRSLTE_MAX_PORTS]) -{ - if (q != NULL && - data != NULL && - cfg != NULL) - { - if (q->rnti_is_set) { - return srslte_pdsch_encode_rnti(q, cfg, softbuffer, data, q->rnti, sf_symbols); - } else { - fprintf(stderr, "Must call srslte_pdsch_set_rnti() to set the encoder/decoder RNTI\n"); - return SRSLTE_ERROR; - } - } else { - return SRSLTE_ERROR_INVALID_INPUTS; - } -} - -int srslte_pdsch_encode_seq(srslte_pdsch_t *q, - srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, - uint8_t *data, srslte_sequence_t *seq, cf_t *sf_symbols[SRSLTE_MAX_PORTS]) + srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, + uint8_t *data, uint16_t rnti, cf_t *sf_symbols[SRSLTE_MAX_PORTS]) { int i; @@ -559,7 +471,6 @@ int srslte_pdsch_encode_seq(srslte_pdsch_t *q, int ret = SRSLTE_ERROR_INVALID_INPUTS; if (q != NULL && - data != NULL && cfg != NULL) { @@ -595,8 +506,18 @@ int srslte_pdsch_encode_seq(srslte_pdsch_t *q, return SRSLTE_ERROR; } - srslte_scrambling_bytes(seq, (uint8_t*) q->e, cfg->nbits.nof_bits); - + /* scramble */ + if (!q->users[rnti]) { + srslte_sequence_t seq; + if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { + return SRSLTE_ERROR; + } + srslte_scrambling_bytes(&q->users[rnti]->seq[cfg->sf_idx], (uint8_t*) q->e, cfg->nbits.nof_bits); + srslte_sequence_free(&seq); + } else { + srslte_scrambling_bytes(&q->users[rnti]->seq[cfg->sf_idx], (uint8_t*) q->e, cfg->nbits.nof_bits); + } + srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->e, q->d, cfg->nbits.nof_bits); /* TODO: only diversity supported */ @@ -618,42 +539,6 @@ int srslte_pdsch_encode_seq(srslte_pdsch_t *q, return ret; } -int srslte_pdsch_encode_rnti_idx(srslte_pdsch_t *q, - srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, - uint8_t *data, uint32_t rnti_idx, cf_t *sf_symbols[SRSLTE_MAX_PORTS]) -{ - if (rnti_idx < q->nof_crnti) { - if (q->rnti_multi[rnti_idx]) { - return srslte_pdsch_encode_seq(q, cfg, softbuffer, data, &q->seq_multi[cfg->sf_idx][rnti_idx], sf_symbols); - } else { - fprintf(stderr, "Error RNTI idx %d not set\n", rnti_idx); - return SRSLTE_ERROR; - } - } else { - return SRSLTE_ERROR_INVALID_INPUTS; - } -} - -/** Converts the PDSCH data bits to symbols mapped to the slot ready for transmission - */ -int srslte_pdsch_encode_rnti(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]) -{ - if (rnti != q->rnti) { - srslte_sequence_t seq; - if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { - return SRSLTE_ERROR; - } - int r = srslte_pdsch_encode_seq(q, cfg, softbuffer, data, &seq, sf_symbols); - srslte_sequence_free(&seq); - return r; - } else { - return srslte_pdsch_encode_seq(q, cfg, softbuffer, data, &q->seq[cfg->sf_idx], sf_symbols); - } -} - - float srslte_pdsch_average_noi(srslte_pdsch_t *q) { return q->dl_sch.average_nof_iterations; diff --git a/srslte/lib/phch/prach.c b/srslte/lib/phch/prach.c index cf47babc5..59ed3d072 100644 --- a/srslte/lib/phch/prach.c +++ b/srslte/lib/phch/prach.c @@ -264,7 +264,7 @@ int srslte_prach_gen_seqs(srslte_prach_t *p) if(((p_*u) % p->N_zc) == 1) break; } - if(p_ >= 0 && p_ < p->N_zc/2){ + if(p_ < p->N_zc/2){ d_u = p_; }else{ d_u = p->N_zc - p_; @@ -341,9 +341,8 @@ int srslte_prach_init(srslte_prach_t *p, int ret = SRSLTE_ERROR; if(p != NULL && N_ifft_ul < 2049 && - config_idx < 16 && - root_seq_index < MAX_ROOTS && - zero_corr_zone_config < 16) + config_idx < 64 && + root_seq_index < MAX_ROOTS) { uint32_t preamble_format = srslte_prach_get_preamble_format(config_idx); p->config_idx = config_idx; @@ -356,14 +355,29 @@ int srslte_prach_init(srslte_prach_t *p, // Determine N_zc and N_cs if(4 == preamble_format){ - p->N_zc = 139; - p->N_cs = prach_Ncs_format4[p->zczc]; + if (p->zczc < 7) { + p->N_zc = 139; + p->N_cs = prach_Ncs_format4[p->zczc]; + } else { + fprintf(stderr, "Invalid zeroCorrelationZoneConfig=%d for format4\n", p->zczc); + return SRSLTE_ERROR; + } }else{ p->N_zc = 839; if(p->hs){ - p->N_cs = prach_Ncs_restricted[p->zczc]; + if (p->zczc < 15) { + p->N_cs = prach_Ncs_restricted[p->zczc]; + } else { + fprintf(stderr, "Invalid zeroCorrelationZoneConfig=%d for restricted set\n", p->zczc); + return SRSLTE_ERROR; + } }else{ - p->N_cs = prach_Ncs_unrestricted[p->zczc]; + if (p->zczc < 16) { + p->N_cs = prach_Ncs_unrestricted[p->zczc]; + } else { + fprintf(stderr, "Invalid zeroCorrelationZoneConfig=%d\n", p->zczc); + return SRSLTE_ERROR; + } } } @@ -586,10 +600,8 @@ int srslte_prach_detect_offset(srslte_prach_t *p, for (int j=0;jpeak_values[j] > p->detect_factor*corr_ave) { - printf("ncs=%d, nzc=%d, nwins=%d, Nroot=%d, i=%d, j=%d, start=%d, peak_value=%f, peak_offset=%d, tseq=%f\n", - p->N_cs, p->N_zc, n_wins, p->N_roots, i, j, (p->N_zc-(j*p->N_cs))%p->N_zc, p->peak_values[j], - p->peak_offsets[j], p->T_seq*1e6); - memcpy(save_corr, p->corr, p->N_zc*sizeof(float)); + //printf("saving prach correlation\n"); + //memcpy(save_corr, p->corr, p->N_zc*sizeof(float)); if (indices) { indices[*n_indices] = (i*n_wins)+j; } diff --git a/srslte/lib/phch/pucch.c b/srslte/lib/phch/pucch.c index 9c55768e1..9472711bb 100644 --- a/srslte/lib/phch/pucch.c +++ b/srslte/lib/phch/pucch.c @@ -38,6 +38,7 @@ #include "srslte/phch/pucch.h" #include "srslte/common/sequence.h" #include "srslte/common/phy_common.h" +#include "srslte/mimo/precoding.h" #include "srslte/scrambling/scrambling.h" #include "srslte/utils/debug.h" #include "srslte/utils/vector.h" @@ -66,7 +67,7 @@ float w_n_oc[2][3][4] = { bool srslte_pucch_cfg_isvalid(srslte_pucch_cfg_t *cfg, uint32_t nof_prb) { if (cfg->delta_pucch_shift > 0 && cfg->delta_pucch_shift < 4 && cfg->N_cs < 8 && (cfg->N_cs%cfg->delta_pucch_shift) == 0 && - cfg->n_rb_2 < nof_prb) { + cfg->n_rb_2 <= nof_prb) { return true; } else { return false; @@ -98,8 +99,10 @@ uint32_t get_N_sf(srslte_pucch_format_t format, uint32_t slot_idx, bool shortene } case SRSLTE_PUCCH_FORMAT_2: case SRSLTE_PUCCH_FORMAT_2A: - case SRSLTE_PUCCH_FORMAT_2B: + case SRSLTE_PUCCH_FORMAT_2B: return 5; + default: + return 0; } return 0; } @@ -127,6 +130,8 @@ uint32_t srslte_pucch_nbits_format(srslte_pucch_format_t format) { return 21; case SRSLTE_PUCCH_FORMAT_2B: return 22; + default: + return 0; } return 0; } @@ -136,7 +141,7 @@ uint32_t get_pucch_symbol(uint32_t m, srslte_pucch_format_t format, srslte_cp_t case SRSLTE_PUCCH_FORMAT_1: case SRSLTE_PUCCH_FORMAT_1A: case SRSLTE_PUCCH_FORMAT_1B: - if (m < 5) { + if (m < 4) { if (SRSLTE_CP_ISNORM(cp)) { return pucch_symbol_format1_cpnorm[m]; } else { @@ -147,7 +152,7 @@ uint32_t get_pucch_symbol(uint32_t m, srslte_pucch_format_t format, srslte_cp_t case SRSLTE_PUCCH_FORMAT_2: case SRSLTE_PUCCH_FORMAT_2A: case SRSLTE_PUCCH_FORMAT_2B: - if (m < 6) { + if (m < 5) { if (SRSLTE_CP_ISNORM(cp)) { return pucch_symbol_format2_cpnorm[m]; } else { @@ -155,10 +160,82 @@ uint32_t get_pucch_symbol(uint32_t m, srslte_pucch_format_t format, srslte_cp_t } } break; + default: + return 0; } return 0; } +/* Choose PUCCH format based on pending transmission as described in 10.1 of 36.213 */ +srslte_pucch_format_t srslte_pucch_get_format(srslte_uci_data_t *uci_data, srslte_cp_t cp) +{ + srslte_pucch_format_t format = SRSLTE_PUCCH_FORMAT_ERROR; + // No CQI data + if (uci_data->uci_cqi_len == 0) { + // 1-bit ACK + optional SR + if (uci_data->uci_ack_len == 1) { + format = SRSLTE_PUCCH_FORMAT_1A; + } + // 2-bit ACK + optional SR + else if (uci_data->uci_ack_len == 2) { + format = SRSLTE_PUCCH_FORMAT_1B; + } + // SR only + else if (uci_data->scheduling_request) { + format = SRSLTE_PUCCH_FORMAT_1; + } + } + // CQI data + else { + // CQI and no ack + if (uci_data->uci_ack_len == 0) { + format = SRSLTE_PUCCH_FORMAT_2; + } + // CQI + 1-bit ACK + else if (uci_data->uci_ack_len == 1 && SRSLTE_CP_ISNORM(cp)) { + format = SRSLTE_PUCCH_FORMAT_2A; + } + // CQI + 2-bit ACK + else if (uci_data->uci_ack_len == 2) { + format = SRSLTE_PUCCH_FORMAT_2B; + } + // CQI + 2-bit ACK + cyclic prefix + else if (uci_data->uci_ack_len == 1 && SRSLTE_CP_ISEXT(cp)) { + format = SRSLTE_PUCCH_FORMAT_2B; + } + } + return format; +} + +/** Choose PUCCH resource as desribed in 10.1 of 36.213 */ +uint32_t srslte_pucch_get_npucch(uint32_t n_cce, srslte_pucch_format_t format, bool has_scheduling_request, srslte_pucch_sched_t *pucch_sched) +{ + uint32_t n_pucch = 0; + if (has_scheduling_request) { + n_pucch = pucch_sched->n_pucch_sr; + } else if (format < SRSLTE_PUCCH_FORMAT_2) { + if (pucch_sched->sps_enabled) { + n_pucch = pucch_sched->n_pucch_1[pucch_sched->tpc_for_pucch%4]; + } else { + n_pucch = n_cce + pucch_sched->N_pucch_1; + } + } else { + n_pucch = pucch_sched->n_pucch_2; + } + return n_pucch; +} + +uint32_t srslte_pucch_n_prb(srslte_pucch_cfg_t *cfg, srslte_pucch_format_t format, uint32_t n_pucch, + uint32_t nof_prb, srslte_cp_t cp, uint32_t ns) +{ + uint32_t m = srslte_pucch_m(cfg, format, n_pucch, cp); + // Determine n_prb + uint32_t n_prb = m/2; + if ((m+ns)%2) { + n_prb = nof_prb-1-m/2; + } + return n_prb; +} // Compute m according to Section 5.4.3 of 36.211 uint32_t srslte_pucch_m(srslte_pucch_cfg_t *cfg, srslte_pucch_format_t format, uint32_t n_pucch, srslte_cp_t cp) { @@ -178,7 +255,10 @@ uint32_t srslte_pucch_m(srslte_pucch_cfg_t *cfg, srslte_pucch_format_t format, u case SRSLTE_PUCCH_FORMAT_2: case SRSLTE_PUCCH_FORMAT_2A: case SRSLTE_PUCCH_FORMAT_2B: - m = n_pucch/SRSLTE_NRE; + m = n_pucch/SRSLTE_NRE; + break; + default: + m = 0; break; } return m; @@ -250,6 +330,9 @@ float srslte_pucch_alpha_format1(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLT n_cs = (n_cs_cell[ns][l]+(n_prime*cfg->delta_pucch_shift+n_oc/n_oc_div)%N_prime)%SRSLTE_NRE; } + DEBUG("n_cs=%d, N_prime=%d, delta_pucch=%d, n_prime=%d, ns=%d, l=%d, ns_cs_cell=%d\n", + n_cs, N_prime, cfg->delta_pucch_shift, n_prime, ns, l, n_cs_cell[ns][l]); + return 2 * M_PI * (n_cs) / SRSLTE_NRE; } @@ -281,40 +364,55 @@ float srslte_pucch_alpha_format2(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLT } /* Map PUCCH symbols to physical resources according to 5.4.3 in 36.211 */ -static int pucch_put(srslte_pucch_t *q, srslte_pucch_format_t format, uint32_t n_pucch, cf_t *output) { +static int pucch_cp(srslte_pucch_t *q, srslte_pucch_format_t format, uint32_t n_pucch, cf_t *source, cf_t *dest, bool source_is_grid) { int ret = SRSLTE_ERROR_INVALID_INPUTS; - if (q && output) { + if (q && source && dest) { ret = SRSLTE_ERROR; uint32_t nsymbols = SRSLTE_CP_ISNORM(q->cell.cp)?SRSLTE_CP_NORM_NSYMB:SRSLTE_CP_EXT_NSYMB; - // Determine m - uint32_t m = srslte_pucch_m(&q->pucch_cfg, format, n_pucch, q->cell.cp); - + uint32_t n_re = 0; uint32_t N_sf_0 = get_N_sf(format, 0, q->shortened); for (uint32_t ns=0;ns<2;ns++) { uint32_t N_sf = get_N_sf(format, ns%2, q->shortened); - // Determine n_prb - uint32_t n_prb = m/2; - if ((m+ns)%2) { - n_prb = q->cell.nof_prb-1-m/2; - } - + + // Determine n_prb + uint32_t n_prb = srslte_pucch_n_prb(&q->pucch_cfg, format, n_pucch, q->cell.nof_prb, q->cell.cp, ns); + q->last_n_prb = n_prb; if (n_prb < q->cell.nof_prb) { for (uint32_t i=0;icell.cp); - memcpy(&output[SRSLTE_RE_IDX(q->cell.nof_prb, l+ns*nsymbols, n_prb*SRSLTE_NRE)], - &q->z[i*SRSLTE_NRE+ns*N_sf_0*SRSLTE_NRE], - SRSLTE_NRE*sizeof(cf_t)); + if (!source_is_grid) { + memcpy(&dest[SRSLTE_RE_IDX(q->cell.nof_prb, l+ns*nsymbols, n_prb*SRSLTE_NRE)], + &source[i*SRSLTE_NRE+ns*N_sf_0*SRSLTE_NRE], + SRSLTE_NRE*sizeof(cf_t)); + } else { + memcpy(&dest[i*SRSLTE_NRE+ns*N_sf_0*SRSLTE_NRE], + &source[SRSLTE_RE_IDX(q->cell.nof_prb, l+ns*nsymbols, n_prb*SRSLTE_NRE)], + SRSLTE_NRE*sizeof(cf_t)); + } + n_re += SRSLTE_NRE; } } else { return SRSLTE_ERROR; } } - ret = SRSLTE_SUCCESS; + ret = n_re; } return ret; } +static int pucch_put(srslte_pucch_t *q, srslte_pucch_format_t format, uint32_t n_pucch, cf_t *z, cf_t *output) { + return pucch_cp(q, format, n_pucch, z, output, false); +} + +static int pucch_get(srslte_pucch_t *q, srslte_pucch_format_t format, uint32_t n_pucch, cf_t *input, cf_t *z) { + return pucch_cp(q, format, n_pucch, input, z, true); +} + +void srslte_pucch_set_threshold(srslte_pucch_t *q, float format1, float format1a) { + q->threshold_format1 = format1; + q->threshold_format1a = format1a; +} /** Initializes the PDCCH transmitter and receiver */ int srslte_pucch_init(srslte_pucch_t *q, srslte_cell_t cell) { @@ -340,6 +438,10 @@ int srslte_pucch_init(srslte_pucch_t *q, srslte_cell_t cell) { if (srslte_pucch_n_cs_cell(q->cell, q->n_cs_cell)) { return SRSLTE_ERROR; } + + q->z = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS); + q->z_tmp = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS); + q->ce = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS); ret = SRSLTE_SUCCESS; } @@ -352,6 +454,16 @@ void srslte_pucch_free(srslte_pucch_t *q) { srslte_sequence_free(&q->seq_f2[sf_idx]); } } + if (q->z) { + free(q->z); + } + if (q->z_tmp) { + free(q->z_tmp); + } + if (q->ce) { + free(q->ce); + } + srslte_modem_table_free(&q->mod); bzero(q, sizeof(srslte_pucch_t)); } @@ -470,9 +582,59 @@ static int uci_mod_bits(srslte_pucch_t *q, srslte_pucch_format_t format, uint8_t // Declare this here, since we can not include refsignal_ul.h void srslte_refsignal_r_uv_arg_1prb(float *arg, uint32_t u); +static int pucch_encode(srslte_pucch_t* q, srslte_pucch_format_t format, + uint32_t n_pucch, uint32_t sf_idx, + uint8_t bits[SRSLTE_PUCCH_MAX_BITS], cf_t z[SRSLTE_PUCCH_MAX_SYMBOLS]) +{ + if (uci_mod_bits(q, format, bits, sf_idx)) { + fprintf(stderr, "Error encoding PUCCH bits\n"); + return SRSLTE_ERROR; + } + uint32_t N_sf_0 = get_N_sf(format, 0, q->shortened); + for (uint32_t ns=2*sf_idx;ns<2*(sf_idx+1);ns++) { + uint32_t N_sf = get_N_sf(format, ns%2, q->shortened); + DEBUG("ns=%d, N_sf=%d\n", ns, N_sf); + // Get group hopping number u + uint32_t f_gh=0; + if (q->group_hopping_en) { + f_gh = q->f_gh[ns]; + } + uint32_t u = (f_gh + (q->cell.id%30))%30; + + srslte_refsignal_r_uv_arg_1prb(q->tmp_arg, u); + uint32_t N_sf_widx = N_sf==3?1:0; + for (uint32_t m=0;mcell.cp); + float alpha=0; + if (format >= SRSLTE_PUCCH_FORMAT_2) { + alpha = srslte_pucch_alpha_format2(q->n_cs_cell, &q->pucch_cfg, n_pucch, ns, l); + for (uint32_t n=0;nd[(ns%2)*N_sf+m]*cexpf(I*(q->tmp_arg[n]+alpha*n)); + } + } else { + uint32_t n_prime_ns=0; + uint32_t n_oc=0; + alpha = srslte_pucch_alpha_format1(q->n_cs_cell, &q->pucch_cfg, n_pucch, q->cell.cp, true, ns, l, &n_oc, &n_prime_ns); + float S_ns = 0; + if (n_prime_ns%2) { + S_ns = M_PI/2; + } + DEBUG("PUCCH d_0: %.1f+%.1fi, alpha: %.1f, n_oc: %d, n_prime_ns: %d, n_rb_2=%d\n", + __real__ q->d[0], __imag__ q->d[0], alpha, n_oc, n_prime_ns, q->pucch_cfg.n_rb_2); + for (uint32_t n=0;nd[0]*cexpf(I*(w_n_oc[N_sf_widx][n_oc%3][m]+q->tmp_arg[n]+alpha*n+S_ns)); + } + } + } + } + return SRSLTE_SUCCESS; +} + /* Encode, modulate and resource mapping of PUCCH bits according to Section 5.4.1 of 36.211 */ int srslte_pucch_encode(srslte_pucch_t* q, srslte_pucch_format_t format, - uint32_t n_pucch, uint32_t sf_idx, uint8_t bits[SRSLTE_PUCCH_MAX_BITS], cf_t *sf_symbols) + uint32_t n_pucch, uint32_t sf_idx, uint8_t bits[SRSLTE_PUCCH_MAX_BITS], + cf_t *sf_symbols) { int ret = SRSLTE_ERROR_INVALID_INPUTS; if (q != NULL && @@ -492,53 +654,16 @@ int srslte_pucch_encode(srslte_pucch_t* q, srslte_pucch_format_t format, } } + q->last_n_pucch = n_pucch; + if (format >= SRSLTE_PUCCH_FORMAT_2 && !q->rnti_is_set) { fprintf(stderr, "Error encoding PUCCH: C-RNTI must be set before encoding PUCCH Format 2/2a/2b\n"); return SRSLTE_ERROR; } - if (uci_mod_bits(q, format, bits, sf_idx)) { - fprintf(stderr, "Error encoding PUCCH bits\n"); + if (pucch_encode(q, format, n_pucch, sf_idx, bits, q->z)) { return SRSLTE_ERROR; } - uint32_t N_sf_0 = get_N_sf(format, 0, q->shortened); - for (uint32_t ns=2*sf_idx;ns<2*(sf_idx+1);ns++) { - uint32_t N_sf = get_N_sf(format, ns%2, q->shortened); - DEBUG("ns=%d, N_sf=%d\n", ns, N_sf); - // Get group hopping number u - uint32_t f_gh=0; - if (q->group_hopping_en) { - f_gh = q->f_gh[ns]; - } - uint32_t u = (f_gh + (q->cell.id%30))%30; - - srslte_refsignal_r_uv_arg_1prb(q->tmp_arg, u); - uint32_t N_sf_widx = N_sf==3?1:0; - for (uint32_t m=0;mcell.cp); - float alpha=0; - if (format >= SRSLTE_PUCCH_FORMAT_2) { - alpha = srslte_pucch_alpha_format2(q->n_cs_cell, &q->pucch_cfg, n_pucch, ns, l); - for (uint32_t n=0;nz[(ns%2)*N_sf*SRSLTE_PUCCH_N_SEQ+m*SRSLTE_PUCCH_N_SEQ+n] = q->d[(ns%2)*N_sf+m]*cexpf(I*(q->tmp_arg[n]+alpha*n)); - } - } else { - uint32_t n_prime_ns=0; - uint32_t n_oc=0; - alpha = srslte_pucch_alpha_format1(q->n_cs_cell, &q->pucch_cfg, n_pucch, q->cell.cp, true, ns, l, &n_oc, &n_prime_ns); - float S_ns = 0; - if (n_prime_ns%2) { - S_ns = M_PI/2; - } - DEBUG("PUCCH d_0: %.1f+%.1fi, alpha: %.1f, n_oc: %d, n_prime_ns: %d, n_rb_2=%d\n", - __real__ q->d[0], __imag__ q->d[0], alpha, n_oc, n_prime_ns, q->pucch_cfg.n_rb_2); - for (uint32_t n=0;nz[(ns%2)*N_sf_0*SRSLTE_PUCCH_N_SEQ+m*SRSLTE_PUCCH_N_SEQ+n] = - q->d[0]*cexpf(I*(w_n_oc[N_sf_widx][n_oc%3][m]+q->tmp_arg[n]+alpha*n+S_ns)); - } - } - } - } - if (pucch_put(q, format, n_pucch, sf_symbols)) { + if (pucch_put(q, format, n_pucch, q->z, sf_symbols) < 0) { fprintf(stderr, "Error putting PUCCH symbols\n"); return SRSLTE_ERROR; } @@ -548,4 +673,115 @@ int srslte_pucch_encode(srslte_pucch_t* q, srslte_pucch_format_t format, return ret; } +float srslte_pucch_get_last_corr(srslte_pucch_t* q) +{ + return q->last_corr; +} +/* Equalize, demodulate and decode PUCCH bits according to Section 5.4.1 of 36.211 */ +int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format, + uint32_t n_pucch, uint32_t sf_idx, cf_t *sf_symbols, cf_t *ce, float noise_estimate, + uint8_t bits[SRSLTE_PUCCH_MAX_BITS]) +{ + int ret = SRSLTE_ERROR_INVALID_INPUTS; + if (q != NULL && + ce != NULL && + sf_symbols != NULL) + { + ret = SRSLTE_ERROR; + + // Shortened PUCCH happen in every cell-specific SRS subframes for Format 1/1a/1b + if (q->pucch_cfg.srs_configured && format < SRSLTE_PUCCH_FORMAT_2) { + q->shortened = false; + // If CQI is not transmitted, PUCCH will be normal unless ACK/NACK and SRS simultaneous transmission is enabled + if (q->pucch_cfg.srs_simul_ack) { + // If simultaneous ACK and SRS is enabled, PUCCH is shortened in cell-specific SRS subframes + if (srslte_refsignal_srs_send_cs(q->pucch_cfg.srs_cs_subf_cfg, sf_idx) == 1) { + q->shortened = true; + } + } + } + + q->last_n_pucch = n_pucch; + + if (format >= SRSLTE_PUCCH_FORMAT_2 && !q->rnti_is_set) { + fprintf(stderr, "Error decoding PUCCH: C-RNTI must be set before encoding PUCCH Format 2/2a/2b\n"); + return SRSLTE_ERROR; + } + int nof_re = pucch_get(q, format, n_pucch, sf_symbols, q->z_tmp); + if (nof_re < 0) { + fprintf(stderr, "Error getting PUCCH symbols\n"); + return SRSLTE_ERROR; + } + + if (pucch_get(q, format, n_pucch, ce, q->ce) < 0) { + fprintf(stderr, "Error getting PUCCH symbols\n"); + return SRSLTE_ERROR; + } + + // Equalization + srslte_predecoding_single(q->z_tmp, q->ce, q->z, nof_re, noise_estimate); + + // Perform ML-decoding + float corr=0, corr_max=-1e9; + int b_max = 0; // default bit value, eg. HI is NACK + switch(format) { + case SRSLTE_PUCCH_FORMAT_1: + bzero(bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t)); + pucch_encode(q, format, n_pucch, sf_idx, bits, q->z_tmp); + corr = crealf(srslte_vec_dot_prod_conj_ccc(q->z, q->z_tmp, nof_re))/nof_re; + if (corr >= q->threshold_format1) { + ret = 1; + } else { + ret = 0; + } + q->last_corr = corr; + DEBUG("format1 corr=%f, nof_re=%d, th=%f\n", corr, nof_re, q->threshold_format1); + break; + case SRSLTE_PUCCH_FORMAT_1A: + bzero(bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t)); + ret = 0; + for (int b=0;b<2;b++) { + bits[0] = b; + pucch_encode(q, format, n_pucch, sf_idx, bits, q->z_tmp); + corr = crealf(srslte_vec_dot_prod_conj_ccc(q->z, q->z_tmp, nof_re))/nof_re; + if (corr > corr_max) { + corr_max = corr; + b_max = b; + } + if (corr_max > q->threshold_format1) { // check with format1 in case ack+sr because ack only is binary + ret = 1; + } + DEBUG("format1a b=%d, corr=%f, nof_re=%d, th=%f\n", b, corr, nof_re, q->threshold_format1a); + } + q->last_corr = corr_max; + +/* + if (corr_max < 0.01) { + srslte_vec_save_file("sf_symbols", sf_symbols, sizeof(cf_t)*SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)); + srslte_vec_save_file("sf_ce", ce, sizeof(cf_t)*SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)); + srslte_vec_save_file("ce", q->ce, sizeof(cf_t)*nof_re); + srslte_vec_save_file("z_before", zz, sizeof(cf_t)*nof_re); + srslte_vec_save_file("z_eq", q->z, sizeof(cf_t)*nof_re); + srslte_vec_save_file("z_1", q->z_tmp, sizeof(cf_t)*nof_re); + bits[0] = 0; + pucch_encode(q, format, n_pucch, sf_idx, bits, q->z_tmp); + srslte_vec_save_file("z_0", q->z_tmp, sizeof(cf_t)*nof_re); + printf("corr_max=%f, b_max=%d, n_pucch=%d, n_prb=%d, sf_idx=%d, nof_re=%d, noise_estimate=%f\n", corr_max, b_max, n_pucch, q->last_n_prb, sf_idx, nof_re, noise_estimate); + exit(-1); + } +*/ + bits[0] = b_max; + break; + default: + fprintf(stderr, "Error decoding PUCCH: Format %d not supported\n", format); + ret = SRSLTE_ERROR; + break; + } + } + + return ret; +} + + + \ No newline at end of file diff --git a/srslte/lib/phch/pusch.c b/srslte/lib/phch/pusch.c index 9cf66e8e9..f82173f54 100644 --- a/srslte/lib/phch/pusch.c +++ b/srslte/lib/phch/pusch.c @@ -209,6 +209,12 @@ int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) { srslte_modem_table_bytes(&q->mod[i]); } + q->users = calloc(sizeof(srslte_pusch_user_t*), 1+SRSLTE_SIRNTI); + if (!q->users) { + perror("malloc"); + goto clean; + } + /* Precompute sequence for type2 frequency hopping */ if (srslte_sequence_LTE_pr(&q->seq_type2_fo, 210, q->cell.id)) { fprintf(stderr, "Error initiating type2 frequency hopping sequence\n"); @@ -222,8 +228,6 @@ int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) { goto clean; } - q->rnti_is_set = false; - // Allocate int16 for reception (LLRs). Buffer casted to uint8_t for transmission q->q = srslte_vec_malloc(sizeof(int16_t) * q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM)); if (!q->q) { @@ -279,10 +283,12 @@ void srslte_pusch_free(srslte_pusch_t *q) { srslte_dft_precoding_free(&q->dft_precoding); - for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { - srslte_sequence_free(&q->seq[i]); + if (q->users) { + for (int rnti=0;rntiusers); } - srslte_sequence_free(&q->seq_type2_fo); for (i = 0; i < 4; i++) { @@ -382,116 +388,39 @@ int srslte_pusch_cfg(srslte_pusch_t *q, /* Precalculate the PUSCH scramble sequences for a given RNTI. This function takes a while * to execute, so shall be called once the final C-RNTI has been allocated for the session. - * For the connection procedure, use srslte_pusch_encode_rnti() or srslte_pusch_decode_rnti() functions */ + * For the connection procedure, use srslte_pusch_encode() functions */ int srslte_pusch_set_rnti(srslte_pusch_t *q, uint16_t rnti) { uint32_t i; - - for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { - if (srslte_sequence_pusch(&q->seq[i], rnti, 2 * i, q->cell.id, - q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) { - return SRSLTE_ERROR; - } - } - q->rnti_is_set = true; - q->rnti = rnti; - return SRSLTE_SUCCESS; -} - - -/* Initializes the memory to support pre-calculation of multiple scrambling sequences */ -int srslte_pusch_init_rnti_multi(srslte_pusch_t *q, uint32_t nof_rntis) -{ - for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { - q->seq_multi[i] = malloc(sizeof(srslte_sequence_t)*nof_rntis); - if (!q->seq_multi[i]) { - perror("malloc"); - return SRSLTE_ERROR; - } - } - q->rnti_multi = srslte_vec_malloc(sizeof(uint16_t)*nof_rntis); - if (!q->rnti_multi) { - perror("malloc"); - return SRSLTE_ERROR; + if (!q->users[rnti]) { + q->users[rnti] = malloc(sizeof(srslte_pusch_user_t)); + if (q->users[rnti]) { + for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { + if (srslte_sequence_pusch(&q->users[rnti]->seq[i], rnti, 2 * i, q->cell.id, + q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) { + return SRSLTE_ERROR; + } + } + } } - bzero(q->rnti_multi, sizeof(uint16_t)*nof_rntis); - - q->nof_crnti = nof_rntis; - return SRSLTE_SUCCESS; } -int srslte_pusch_set_rnti_multi(srslte_pusch_t *q, uint32_t idx, uint16_t rnti) -{ - if (idx < q->nof_crnti) { - if (q->rnti_multi[idx]) { - for (uint32_t i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { - srslte_sequence_free(&q->seq_multi[i][idx]); - } - q->rnti_multi[idx] = 0; - } - q->rnti_multi[idx] = rnti; - q->rnti_is_set = true; +void srslte_pusch_clear_rnti(srslte_pusch_t *q, uint16_t rnti) { + if (q->users[rnti]) { for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { - if (srslte_sequence_pusch(&q->seq_multi[i][idx], rnti, 2 * i, q->cell.id, - q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) { - return SRSLTE_ERROR; - } - } - return SRSLTE_SUCCESS; - } else { - return SRSLTE_ERROR_INVALID_INPUTS; - } -} - -uint16_t srslte_pusch_get_rnti_multi(srslte_pusch_t *q, uint32_t idx) -{ - if (idx < q->nof_crnti) { - return q->rnti_multi[idx]; - } else { - return SRSLTE_ERROR_INVALID_INPUTS; - } -} - -int srslte_pusch_encode_rnti(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, - uint8_t *data, uint16_t rnti, - cf_t *sf_symbols) -{ - srslte_uci_data_t uci_data; - bzero(&uci_data, sizeof(srslte_uci_data_t)); - return srslte_pusch_uci_encode_rnti(q, cfg, softbuffer, data, uci_data, rnti, sf_symbols); -} - -int srslte_pusch_encode(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, - uint8_t *data, cf_t *sf_symbols) -{ - if (q->rnti_is_set) { - srslte_uci_data_t uci_data; - bzero(&uci_data, sizeof(srslte_uci_data_t)); - return srslte_pusch_uci_encode_rnti(q, cfg, softbuffer, data, uci_data, q->rnti, sf_symbols); - } else { - fprintf(stderr, "Must call srslte_pusch_set_rnti() to set the encoder/decoder RNTI\n"); - return SRSLTE_ERROR; - } -} - -int srslte_pusch_uci_encode(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, - uint8_t *data, srslte_uci_data_t uci_data, - cf_t *sf_symbols) -{ - if (q->rnti_is_set) { - return srslte_pusch_uci_encode_rnti(q, cfg, softbuffer, data, uci_data, q->rnti, sf_symbols); - } else { - fprintf(stderr, "Must call srslte_pusch_set_rnti() to set the encoder/decoder RNTI\n"); - return SRSLTE_ERROR; + srslte_sequence_free(&q->users[rnti]->seq[i]); + } + free(q->users[rnti]); + q->users[rnti] = NULL; } } /** Converts the PUSCH data bits to symbols mapped to the slot ready for transmission */ -int srslte_pusch_uci_encode_rnti(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, - uint8_t *data, srslte_uci_data_t uci_data, uint16_t rnti, - cf_t *sf_symbols) +int srslte_pusch_encode(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, + uint8_t *data, srslte_uci_data_t uci_data, uint16_t rnti, + cf_t *sf_symbols) { int ret = SRSLTE_ERROR_INVALID_INPUTS; @@ -515,7 +444,7 @@ int srslte_pusch_uci_encode_rnti(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srs return SRSLTE_ERROR; } - if (rnti != q->rnti || !q->rnti_is_set) { + if (!q->users[rnti]) { srslte_sequence_t seq; if (srslte_sequence_pusch(&seq, rnti, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { return SRSLTE_ERROR; @@ -523,7 +452,7 @@ int srslte_pusch_uci_encode_rnti(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srs srslte_scrambling_bytes(&seq, (uint8_t*) q->q, cfg->nbits.nof_bits); srslte_sequence_free(&seq); } else { - srslte_scrambling_bytes(&q->seq[cfg->sf_idx], (uint8_t*) q->q, cfg->nbits.nof_bits); + srslte_scrambling_bytes(&q->users[rnti]->seq[cfg->sf_idx], (uint8_t*) q->q, cfg->nbits.nof_bits); } // Correct UCI placeholder/repetition bits @@ -558,23 +487,14 @@ int srslte_pusch_uci_encode_rnti(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srs return ret; } + +/** Decodes the PUSCH from the received symbols + */ int srslte_pusch_decode(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, cf_t *sf_symbols, - cf_t *ce, float noise_estimate, - uint8_t *data) -{ - srslte_uci_data_t uci_data; - bzero(&uci_data, sizeof(srslte_uci_data_t)); - return srslte_pusch_uci_decode(q, cfg, softbuffer, sf_symbols, ce, noise_estimate, data, &uci_data); -} - -int srslte_pusch_uci_decode_seq(srslte_pusch_t *q, - srslte_pusch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, - srslte_sequence_t *seq, - cf_t *sf_symbols, - cf_t *ce, float noise_estimate, - uint8_t *data, srslte_uci_data_t *uci_data) + cf_t *ce, float noise_estimate, uint16_t rnti, + uint8_t *data, srslte_uci_data_t *uci_data) { uint32_t n; @@ -585,82 +505,61 @@ int srslte_pusch_uci_decode_seq(srslte_pusch_t *q, cfg != NULL) { - if (q->rnti_is_set) { - INFO("Decoding PUSCH SF: %d, Mod %s, NofBits: %d, NofRE: %d, NofSymbols=%d, NofBitsE: %d, rv_idx: %d\n", - cfg->sf_idx, srslte_mod_string(cfg->grant.mcs.mod), cfg->grant.mcs.tbs, - cfg->nbits.nof_re, cfg->nbits.nof_symb, cfg->nbits.nof_bits, cfg->rv); - - /* extract symbols */ - n = pusch_get(q, &cfg->grant, sf_symbols, q->d); - if (n != cfg->nbits.nof_re) { - fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->nbits.nof_re, n); - return SRSLTE_ERROR; - } - - /* extract channel estimates */ - n = pusch_get(q, &cfg->grant, ce, q->ce); - if (n != cfg->nbits.nof_re) { - fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->nbits.nof_re, n); - return SRSLTE_ERROR; - } + INFO("Decoding PUSCH SF: %d, Mod %s, NofBits: %d, NofRE: %d, NofSymbols=%d, NofBitsE: %d, rv_idx: %d\n", + cfg->sf_idx, srslte_mod_string(cfg->grant.mcs.mod), cfg->grant.mcs.tbs, + cfg->nbits.nof_re, cfg->nbits.nof_symb, cfg->nbits.nof_bits, cfg->rv); + + /* extract symbols */ + n = pusch_get(q, &cfg->grant, sf_symbols, q->d); + if (n != cfg->nbits.nof_re) { + fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->nbits.nof_re, n); + return SRSLTE_ERROR; + } + + /* extract channel estimates */ + n = pusch_get(q, &cfg->grant, ce, q->ce); + if (n != cfg->nbits.nof_re) { + fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->nbits.nof_re, n); + return SRSLTE_ERROR; + } - // Equalization - srslte_predecoding_single(q->d, q->ce, q->z, cfg->nbits.nof_re, noise_estimate); - - // DFT predecoding - srslte_dft_predecoding(&q->dft_precoding, q->z, q->d, cfg->grant.L_prb, cfg->nbits.nof_symb); - - // Soft demodulation - srslte_demod_soft_demodulate_s(cfg->grant.mcs.mod, q->d, q->q, cfg->nbits.nof_re); + // Equalization + srslte_predecoding_single(q->d, q->ce, q->z, cfg->nbits.nof_re, noise_estimate); + + // DFT predecoding + srslte_dft_predecoding(&q->dft_precoding, q->z, q->d, cfg->grant.L_prb, cfg->nbits.nof_symb); + + // Soft demodulation + srslte_demod_soft_demodulate_s(cfg->grant.mcs.mod, q->d, q->q, cfg->nbits.nof_re); + + srslte_sequence_t *seq = NULL; - // Decode RI/HARQ bits before descrambling - if (srslte_ulsch_uci_decode_ri_ack(&q->ul_sch, cfg, softbuffer, q->q, seq->c, uci_data)) { - fprintf(stderr, "Error decoding RI/HARQ bits\n"); + // Create sequence if does not exist + if (!q->users[rnti]) { + seq = &q->tmp_seq; + if (srslte_sequence_pusch(seq, rnti, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { return SRSLTE_ERROR; } - - // Descrambling - srslte_scrambling_s_offset(seq, q->q, 0, cfg->nbits.nof_bits); - - return srslte_ulsch_uci_decode(&q->ul_sch, cfg, softbuffer, q->q, q->g, data, uci_data); } else { - fprintf(stderr, "Must call srslte_pusch_set_rnti() before calling srslte_pusch_decode()\n"); - return SRSLTE_ERROR; - } - } else { - return SRSLTE_ERROR_INVALID_INPUTS; - } -} - -/** Decodes the PUSCH from the received symbols - */ -int srslte_pusch_uci_decode(srslte_pusch_t *q, - srslte_pusch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, - cf_t *sf_symbols, - cf_t *ce, float noise_estimate, - uint8_t *data, srslte_uci_data_t *uci_data) -{ - return srslte_pusch_uci_decode_seq(q, cfg, softbuffer, &q->seq[cfg->sf_idx], sf_symbols, ce, noise_estimate, data, uci_data); -} - -/** Decodes the PUSCH from the received symbols for a given RNTI index - */ -int srslte_pusch_uci_decode_rnti_idx(srslte_pusch_t *q, - srslte_pusch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, - cf_t *sf_symbols, - cf_t *ce, float noise_estimate, - uint32_t rnti_idx, - uint8_t *data, srslte_uci_data_t *uci_data) -{ - if (rnti_idx < q->nof_crnti) { - if (q->rnti_multi[rnti_idx]) { - return srslte_pusch_uci_decode_seq(q, cfg, softbuffer, &q->seq_multi[cfg->sf_idx][rnti_idx], sf_symbols, ce, noise_estimate, data, uci_data); - } else { - fprintf(stderr, "Error RNTI idx %d not set\n", rnti_idx); + seq = &q->users[rnti]->seq[cfg->sf_idx]; + } + + // Decode RI/HARQ bits before descrambling + if (srslte_ulsch_uci_decode_ri_ack(&q->ul_sch, cfg, softbuffer, q->q, seq->c, uci_data)) { + fprintf(stderr, "Error decoding RI/HARQ bits\n"); return SRSLTE_ERROR; } + + // Descrambling + srslte_scrambling_s_offset(seq, q->q, 0, cfg->nbits.nof_bits); + + if (!q->users[rnti]) { + srslte_sequence_free(seq); + } + + return srslte_ulsch_uci_decode(&q->ul_sch, cfg, softbuffer, q->q, q->g, data, uci_data); } else { - return SRSLTE_ERROR_INVALID_INPUTS; + return SRSLTE_ERROR_INVALID_INPUTS; } } diff --git a/srslte/lib/phch/ra.c b/srslte/lib/phch/ra.c index f005cd9aa..e830710f5 100644 --- a/srslte/lib/phch/ra.c +++ b/srslte/lib/phch/ra.c @@ -106,7 +106,7 @@ uint32_t ra_re_x_prb(uint32_t subframe, uint32_t slot, uint32_t prb_idx, uint32_ return re; } -int srslte_ul_dci_to_grant_prb_allocation(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *grant, uint32_t n_rb_ho, uint32_t nof_prb) +int srslte_ra_ul_dci_to_grant_prb_allocation(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *grant, uint32_t n_rb_ho, uint32_t nof_prb) { bzero(grant, sizeof(srslte_ra_ul_grant_t)); @@ -170,7 +170,9 @@ int srslte_ul_dci_to_grant_prb_allocation(srslte_ra_ul_dci_t *dci, srslte_ra_ul_ } srslte_mod_t last_mod[8]; -uint32_t last_tbs_idx[8]; +uint32_t last_ul_tbs_idx[8]; +uint32_t last_dl_tbs[8]; +uint32_t last_dl_tbs2[8]; static int ul_dci_to_grant_mcs(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *grant, uint32_t harq_pid) { int tbs = -1; @@ -180,15 +182,15 @@ static int ul_dci_to_grant_mcs(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *gr if (dci->mcs_idx < 11) { grant->mcs.mod = SRSLTE_MOD_QPSK; tbs = srslte_ra_tbs_from_idx(dci->mcs_idx, grant->L_prb); - last_tbs_idx[harq_pid%8] = dci->mcs_idx; + last_ul_tbs_idx[harq_pid%8] = dci->mcs_idx; } else if (dci->mcs_idx < 21) { grant->mcs.mod = SRSLTE_MOD_16QAM; tbs = srslte_ra_tbs_from_idx(dci->mcs_idx-1, grant->L_prb); - last_tbs_idx[harq_pid%8] = dci->mcs_idx-1; + last_ul_tbs_idx[harq_pid%8] = dci->mcs_idx-1; } else if (dci->mcs_idx < 29) { grant->mcs.mod = SRSLTE_MOD_64QAM; tbs = srslte_ra_tbs_from_idx(dci->mcs_idx-2, grant->L_prb); - last_tbs_idx[harq_pid%8] = dci->mcs_idx-2; + last_ul_tbs_idx[harq_pid%8] = dci->mcs_idx-2; } else { fprintf(stderr, "Invalid MCS index %d\n", dci->mcs_idx); } @@ -196,10 +198,11 @@ static int ul_dci_to_grant_mcs(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *gr } else if (dci->mcs_idx == 29 && dci->cqi_request && grant->L_prb <= 4) { // 8.6.1 and 8.6.2 36.213 second paragraph grant->mcs.mod = SRSLTE_MOD_QPSK; - tbs = srslte_ra_tbs_from_idx(last_tbs_idx[harq_pid%8], grant->L_prb); + tbs = srslte_ra_tbs_from_idx(last_ul_tbs_idx[harq_pid%8], grant->L_prb); + dci->rv_idx = 1; } else if (dci->mcs_idx >= 29) { // Else use last TBS/Modulation and use mcs to obtain rv_idx - tbs = srslte_ra_tbs_from_idx(last_tbs_idx[harq_pid%8], grant->L_prb); + tbs = srslte_ra_tbs_from_idx(last_ul_tbs_idx[harq_pid%8], grant->L_prb); grant->mcs.mod = last_mod[harq_pid%8]; dci->rv_idx = dci->mcs_idx - 28; DEBUG("TTI=%d, harq_pid=%d, mcs_idx=%d, tbs=%d, mod=%d, rv=%d\n", @@ -227,7 +230,7 @@ int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci, uint32_t nof_prb, uint32_ { // Compute PRB allocation - if (!srslte_ul_dci_to_grant_prb_allocation(dci, grant, n_rb_ho, nof_prb)) { + if (!srslte_ra_ul_dci_to_grant_prb_allocation(dci, grant, n_rb_ho, nof_prb)) { // Compute MCS if (!ul_dci_to_grant_mcs(dci, grant, harq_pid)) { @@ -248,6 +251,24 @@ int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci, uint32_t nof_prb, uint32_ return SRSLTE_SUCCESS; } +uint32_t srslte_ra_dl_approx_nof_re(srslte_cell_t cell, uint32_t nof_prb, uint32_t nof_ctrl_symbols) +{ + uint32_t nof_refs = 0; + uint32_t nof_symb = 2*SRSLTE_CP_NSYMB(cell.cp)-nof_ctrl_symbols; + switch(cell.nof_ports) { + case 1: + nof_refs = 2*3; + break; + case 2: + nof_refs = 4*3; + break; + case 4: + nof_refs = 4*4; + break; + } + return nof_prb * (nof_symb*SRSLTE_NRE-nof_refs); +} + /* Computes the number of RE for each PRB in the prb_dist structure */ uint32_t srslte_ra_dl_grant_nof_re(srslte_ra_dl_grant_t *grant, srslte_cell_t cell, uint32_t sf_idx, uint32_t nof_ctrl_symbols) @@ -268,7 +289,7 @@ uint32_t srslte_ra_dl_grant_nof_re(srslte_ra_dl_grant_t *grant, srslte_cell_t ce } /** Compute PRB allocation for Downlink as defined in 7.1.6 of 36.213 */ -static int dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *grant, uint32_t nof_prb) { +int srslte_ra_dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *grant, uint32_t nof_prb) { int i, j; uint32_t bitmask; uint32_t P = srslte_ra_type0_P(nof_prb); @@ -380,6 +401,40 @@ static int dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_dl_ return SRSLTE_SUCCESS; } +static int dl_fill_ra_mcs(srslte_ra_mcs_t *mcs, uint32_t nprb) { + uint32_t i_tbs = 0; + int tbs = -1; + if (mcs->idx < 10) { + mcs->mod = SRSLTE_MOD_QPSK; + i_tbs = mcs->idx; + } else if (mcs->idx < 17) { + mcs->mod = SRSLTE_MOD_16QAM; + i_tbs = mcs->idx-1; + } else if (mcs->idx < 29) { + mcs->mod = SRSLTE_MOD_64QAM; + i_tbs = mcs->idx-2; + } else if (mcs->idx == 29) { + mcs->mod = SRSLTE_MOD_QPSK; + tbs = 0; + i_tbs = 0; + } else if (mcs->idx == 30) { + mcs->mod = SRSLTE_MOD_16QAM; + tbs = 0; + i_tbs = 0; + } else if (mcs->idx == 31) { + mcs->mod = SRSLTE_MOD_64QAM; + tbs = 0; + i_tbs = 0; + } + if (tbs == -1) { + tbs = srslte_ra_tbs_from_idx(i_tbs, nprb); + if (tbs >= 0) { + mcs->tbs = tbs; + } + } + return tbs; +} + /* Modulation order and transport block size determination 7.1.7 in 36.213 */ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *grant, bool crc_is_crnti) { uint32_t n_prb=0; @@ -391,46 +446,57 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr n_prb = dci->type2_alloc.n_prb1a == SRSLTE_RA_TYPE2_NPRB1A_2 ? 2 : 3; i_tbs = dci->mcs_idx; tbs = srslte_ra_tbs_from_idx(i_tbs, n_prb); - } else { + } else if (dci->dci_is_1c) { if (dci->mcs_idx < 32) { tbs = tbs_format1c_table[dci->mcs_idx]; - } + } else { + fprintf(stderr, "Error decoding DCI: Invalid mcs_idx=%d in Format1C\n", dci->mcs_idx); + } + } else { + fprintf(stderr, "Error decoding DCI: P/SI/RA-RNTI supports Format1A/1C only\n"); + return SRSLTE_ERROR; } grant->mcs.mod = SRSLTE_MOD_QPSK; + grant->mcs.tbs = (uint32_t) tbs; } else { - tbs = -1; n_prb = grant->nof_prb; - if (dci->mcs_idx < 10) { - grant->mcs.mod = SRSLTE_MOD_QPSK; - i_tbs = dci->mcs_idx; - } else if (dci->mcs_idx < 17) { - grant->mcs.mod = SRSLTE_MOD_16QAM; - i_tbs = dci->mcs_idx-1; - } else if (dci->mcs_idx < 29) { - grant->mcs.mod = SRSLTE_MOD_64QAM; - i_tbs = dci->mcs_idx-2; - } else if (dci->mcs_idx == 29) { - grant->mcs.mod = SRSLTE_MOD_QPSK; - tbs = 0; - i_tbs = 0; - } else if (dci->mcs_idx == 30) { - grant->mcs.mod = SRSLTE_MOD_16QAM; - tbs = 0; - i_tbs = 0; - } else if (dci->mcs_idx == 31) { - grant->mcs.mod = SRSLTE_MOD_64QAM; - tbs = 0; - i_tbs = 0; + grant->nof_tb = 0; + if (dci->tb_en[0]) { + grant->mcs.idx = dci->mcs_idx; + tbs = dl_fill_ra_mcs(&grant->mcs, n_prb); + if (tbs) { + last_dl_tbs[dci->harq_process%8] = tbs; + } else { + // For mcs>=29, set last TBS received for this PID + grant->mcs.tbs = last_dl_tbs[dci->harq_process%8]; + } + grant->nof_tb++; + } else { + grant->mcs.tbs = 0; } - if (tbs == -1) { - tbs = srslte_ra_tbs_from_idx(i_tbs, n_prb); + if (dci->tb_en[1]) { + grant->mcs2.idx = dci->mcs_idx_1; + tbs = dl_fill_ra_mcs(&grant->mcs2, n_prb); + if (tbs) { + last_dl_tbs2[dci->harq_process%8] = tbs; + } else { + // For mcs>=29, set last TBS received for this PID + grant->mcs2.tbs = last_dl_tbs2[dci->harq_process%8]; + } + grant->nof_tb++; + } else { + grant->mcs2.tbs = 0; } } - + if (dci->tb_en[0]) { + grant->Qm = srslte_mod_bits_x_symbol(grant->mcs.mod); + } + if (dci->tb_en[1]) { + grant->Qm2 = srslte_mod_bits_x_symbol(grant->mcs2.mod); + } if (tbs < 0) { return SRSLTE_ERROR; - } else { - grant->mcs.tbs = (uint32_t) tbs; + } else { return SRSLTE_SUCCESS; } } @@ -453,13 +519,9 @@ int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t *dci, crc_is_crnti = true; } // Compute PRB allocation - if (!dl_dci_to_grant_prb_allocation(dci, grant, nof_prb)) { + if (!srslte_ra_dl_dci_to_grant_prb_allocation(dci, grant, nof_prb)) { // Compute MCS - if (!dl_dci_to_grant_mcs(dci, grant, crc_is_crnti)) { - // Fill rest of grant structure - grant->mcs.idx = dci->mcs_idx; - grant->Qm = srslte_mod_bits_x_symbol(grant->mcs.mod); - + if (!dl_dci_to_grant_mcs(dci, grant, crc_is_crnti)) { // Apply Section 7.1.7.3. If RA-RNTI and Format1C rv_idx=0 if (msg_rnti >= SRSLTE_RARNTI_START && msg_rnti <= SRSLTE_RARNTI_END && dci->dci_is_1c) @@ -567,6 +629,16 @@ int srslte_ra_tbs_idx_from_mcs(uint32_t mcs) { } } +srslte_mod_t srslte_ra_mod_from_mcs(uint32_t mcs) { + if (mcs <= 10 || mcs == 29) { + return SRSLTE_MOD_QPSK; + } else if (mcs <= 17 || mcs == 30) { + return SRSLTE_MOD_16QAM; + } else { + return SRSLTE_MOD_64QAM; + } +} + int srslte_ra_mcs_from_tbs_idx(uint32_t tbs_idx) { for (int i=0;i<29;i++) { if (tbs_idx == mcs_tbs_idx_table[i]) { @@ -595,7 +667,10 @@ int srslte_ra_tbs_to_table_idx(uint32_t tbs, uint32_t n_prb) { if (tbs <= tbs_table[0][n_prb-1]) { return 0; } - for (idx = 0; idx < 27; idx++) { + if (tbs >= tbs_table[26][n_prb-1]) { + return 27; + } + for (idx = 0; idx < 26; idx++) { if (tbs_table[idx][n_prb-1] <= tbs && tbs_table[idx+1][n_prb-1] >= tbs) { return idx+1; } diff --git a/srslte/lib/phch/regs.c b/srslte/lib/phch/regs.c index 9c2764866..8ada33e7f 100644 --- a/srslte/lib/phch/regs.c +++ b/srslte/lib/phch/regs.c @@ -247,6 +247,10 @@ int regs_phich_init(srslte_regs_t *h) { srslte_regs_reg_t **regs_phich[3]; int ret = SRSLTE_ERROR; + for (int i=0;i<3;i++) { + regs_phich[i] = NULL; + } + switch(h->phich_res) { case SRSLTE_PHICH_R_1_6: ng = (float) 1/6; @@ -768,8 +772,10 @@ int srslte_regs_init(srslte_regs_t *h, srslte_cell_t cell) { ret = SRSLTE_SUCCESS; } clean_and_exit: - if (ret != SRSLTE_SUCCESS) { - srslte_regs_free(h); + if (h) { + if (ret != SRSLTE_SUCCESS) { + srslte_regs_free(h); + } } return ret; } diff --git a/srslte/lib/phch/sch.c b/srslte/lib/phch/sch.c index 0550a492f..3b521f794 100644 --- a/srslte/lib/phch/sch.c +++ b/srslte/lib/phch/sch.c @@ -58,7 +58,7 @@ float beta_cqi_offset[16] = {-1.0, -1.0, 1.125, 1.25, 1.375, 1.625, 1.750, 2.0, float srslte_sch_beta_cqi(uint32_t I_cqi) { - if (I_cqi <= 16) { + if (I_cqi < 16) { return beta_cqi_offset[I_cqi]; } else { return 0; @@ -463,10 +463,10 @@ static int decode_tb(srslte_sch_t *q, par_tx = ((uint32_t) parity[0])<<16 | ((uint32_t) parity[1])<<8 | ((uint32_t) parity[2]); if (!par_rx) { - printf("Warning: Received all-zero transport block\n\n", 0); + INFO("Warning: Received all-zero transport block\n\n", 0); } - if (par_rx == par_tx && par_rx) { + if (par_rx == par_tx) { INFO("TB decoded OK\n",i); return SRSLTE_SUCCESS; } else { @@ -646,16 +646,10 @@ int srslte_ulsch_uci_decode(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srslte_sof // Decode CQI (multiplexed at the front of ULSCH) if (uci_data->uci_cqi_len > 0) { - struct timeval t[3]; - gettimeofday(&t[1], NULL); ret = srslte_uci_decode_cqi_pusch(&q->uci_cqi, cfg, g_bits, beta_cqi_offset[cfg->uci_cfg.I_offset_cqi], Q_prime_ri, uci_data->uci_cqi_len, uci_data->uci_cqi, &uci_data->cqi_ack); - gettimeofday(&t[2], NULL); - get_time_interval(t); - printf("texec=%d us\n", t[0].tv_usec); - if (ret < 0) { return ret; } @@ -663,7 +657,7 @@ int srslte_ulsch_uci_decode(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srslte_sof } e_offset += Q_prime_cqi*Qm; - + // Decode ULSCH if (cfg->cb_segm.tbs > 0) { uint32_t G = nb_q/Qm - Q_prime_ri - Q_prime_cqi; diff --git a/srslte/lib/phch/test/CMakeLists.txt b/srslte/lib/phch/test/CMakeLists.txt index 9789a605d..6675e0faf 100644 --- a/srslte/lib/phch/test/CMakeLists.txt +++ b/srslte/lib/phch/test/CMakeLists.txt @@ -81,9 +81,6 @@ target_link_libraries(pdcch_test srslte) add_test(pdcch_test pdcch_test) -add_executable(dci_unpacking dci_unpacking.c) -target_link_libraries(dci_unpacking srslte) - BuildMex(MEXNAME pdcch SOURCES pdcch_test_mex.c LIBRARIES srslte_static srslte_mex) ######################################################################## @@ -149,7 +146,7 @@ target_link_libraries(pucch_test srslte) add_test(pucch_test pucch_test) BuildMex(MEXNAME pucch_encode SOURCES pucch_encode_test_mex.c LIBRARIES srslte_static srslte_mex) - +BuildMex(MEXNAME pucch SOURCES pucch_test_mex.c LIBRARIES srslte_static srslte_mex) diff --git a/srslte/lib/phch/test/dci_unpacking.c b/srslte/lib/phch/test/dci_unpacking.c deleted file mode 100644 index 7e65b433f..000000000 --- a/srslte/lib/phch/test/dci_unpacking.c +++ /dev/null @@ -1,102 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2015 Software Radio Systems Limited - * - * \section LICENSE - * - * This file is part of the srsLTE library. - * - * srsLTE is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. - * - * srsLTE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * A copy of the GNU Affero General Public License can be found in - * the LICENSE file in the top-level directory of this distribution - * and at http://www.gnu.org/licenses/. - * - */ - -#include -#include -#include -#include -#include - -#include "srslte/srslte.h" - -void usage(char *prog) { - printf("Usage: %s nof_prb length_bits Word0 Word1 ...\n", prog); -} - -int main(int argc, char **argv) { - srslte_dci_msg_t msg; - srslte_ra_dl_dci_t ra_dl; - int len, rlen; - int nof_prb; - int nwords; - int i; - uint8_t *y; - - if (argc < 3) { - usage(argv[0]); - exit(-1); - } - - nof_prb = atoi(argv[1]); - len = atoi(argv[2]); - - nwords = (len - 1) / 32 + 1; - - if (argc < 3 + nwords) { - usage(argv[0]); - exit(-1); - } - - y = msg.data; - rlen = 0; - uint32_t x; - for (i = 0; i < nwords; i++) { - x = strtoul(argv[i + 3], NULL, 16); - if (len - rlen < 32) { - srslte_bit_unpack(x, &y, len - rlen); - } else { - srslte_bit_unpack(x, &y, 32); - } - - } - - printf("DCI message len %d:\n", len); - for (i = 0; i < len; i++) { - printf("%d, ", msg.data[i]); - } - printf("\n"); - - srslte_dci_msg_type_t dci_type; - msg.nof_bits = len; - if (srslte_dci_msg_get_type(&msg, &dci_type, nof_prb, SRSLTE_SIRNTI)) { - fprintf(stderr, "Can't obtain DCI message type\n"); - exit(-1); - } - printf("\n"); - printf("Message type:"); - srslte_dci_msg_type_fprint(stdout, dci_type); - switch (dci_type.type) { - case SRSLTE_DCI_MSG_TYPE_PDSCH_SCHED: - bzero(&ra_dl, sizeof(srslte_ra_dl_dci_t)); - srslte_dci_msg_unpack_pdsch(&msg, &ra_dl, nof_prb, 1, false); - srslte_ra_pdsch_fprint(stdout, &ra_dl, nof_prb); - break; - default: - printf("Error expected PDSCH\n"); - exit(-1); - } - printf("\n"); -} diff --git a/srslte/lib/phch/test/pbch_file_test.c b/srslte/lib/phch/test/pbch_file_test.c index 6e9ba5950..f3e4b9b08 100644 --- a/srslte/lib/phch/test/pbch_file_test.c +++ b/srslte/lib/phch/test/pbch_file_test.c @@ -37,7 +37,6 @@ char *input_file_name = NULL; srslte_cell_t cell = { 6, // nof_prb 2, // nof_ports - 0, // bw_idx 150, // cell_id SRSLTE_CP_NORM, // cyclic prefix SRSLTE_PHICH_R_1, // PHICH resources diff --git a/srslte/lib/phch/test/pcfich_file_test.c b/srslte/lib/phch/test/pcfich_file_test.c index 03029c9fc..27b50baeb 100644 --- a/srslte/lib/phch/test/pcfich_file_test.c +++ b/srslte/lib/phch/test/pcfich_file_test.c @@ -39,7 +39,6 @@ char *matlab_file_name = NULL; srslte_cell_t cell = { 6, // nof_prb 1, // nof_ports - 0, // bw_idx 0, // cell_id SRSLTE_CP_NORM, // cyclic prefix SRSLTE_PHICH_R_1, // PHICH resources diff --git a/srslte/lib/phch/test/pdcch_file_test.c b/srslte/lib/phch/test/pdcch_file_test.c index 9f6af1afd..b505e6b68 100644 --- a/srslte/lib/phch/test/pdcch_file_test.c +++ b/srslte/lib/phch/test/pdcch_file_test.c @@ -34,12 +34,9 @@ char *input_file_name = NULL; -#define MAX_CANDIDATES 64 - srslte_cell_t cell = { 6, // cell.cell.cell.nof_prb 1, // cell.cell.nof_ports - 0, // bw_idx 0, // cell.id SRSLTE_CP_NORM, // cyclic prefix SRSLTE_PHICH_R_1, // PHICH resources diff --git a/srslte/lib/phch/test/pdcch_test_mex.c b/srslte/lib/phch/test/pdcch_test_mex.c index 754050b53..e30ef900f 100644 --- a/srslte/lib/phch/test/pdcch_test_mex.c +++ b/srslte/lib/phch/test/pdcch_test_mex.c @@ -36,7 +36,6 @@ #define INPUT prhs[2] #define NOF_INPUTS 3 -#define MAX_CANDIDATES 64 srslte_dci_format_t ue_formats[] = {SRSLTE_DCI_FORMAT1A,SRSLTE_DCI_FORMAT1}; // SRSLTE_DCI_FORMAT1B should go here also diff --git a/srslte/lib/phch/test/pdsch_pdcch_file_test.c b/srslte/lib/phch/test/pdsch_pdcch_file_test.c index 5a8a8e766..33ad2c58d 100644 --- a/srslte/lib/phch/test/pdsch_pdcch_file_test.c +++ b/srslte/lib/phch/test/pdsch_pdcch_file_test.c @@ -32,14 +32,11 @@ #include "srslte/srslte.h" -#define MAX_CANDIDATES 64 - char *input_file_name = NULL; srslte_cell_t cell = { 6, // nof_prb 1, // nof_ports - 0, // bw_idx 0, // cell_id SRSLTE_CP_NORM, // cyclic prefix SRSLTE_PHICH_R_1, // PHICH resources diff --git a/srslte/lib/phch/test/pdsch_test.c b/srslte/lib/phch/test/pdsch_test.c index 2e869f6f2..099400462 100644 --- a/srslte/lib/phch/test/pdsch_test.c +++ b/srslte/lib/phch/test/pdsch_test.c @@ -39,7 +39,6 @@ srslte_cell_t cell = { 6, // nof_prb 1, // nof_ports - 0, 0, // cell_id SRSLTE_CP_NORM, // cyclic prefix SRSLTE_PHICH_R_1_6, // PHICH resources @@ -229,14 +228,14 @@ int main(int argc, char **argv) { if (rv_idx) { /* Do 1st transmission for rv_idx!=0 */ pdsch_cfg.rv = 0; - if (srslte_pdsch_encode(&pdsch, &pdsch_cfg, &softbuffer_tx, data, slot_symbols)) { + if (srslte_pdsch_encode(&pdsch, &pdsch_cfg, &softbuffer_tx, data, rnti, slot_symbols)) { fprintf(stderr, "Error encoding PDSCH\n"); goto quit; } } pdsch_cfg.rv = rv_idx; - if (srslte_pdsch_encode(&pdsch, &pdsch_cfg, &softbuffer_tx, data, slot_symbols)) { + if (srslte_pdsch_encode(&pdsch, &pdsch_cfg, &softbuffer_tx, data, rnti, slot_symbols)) { fprintf(stderr, "Error encoding PDSCH\n"); goto quit; } @@ -265,7 +264,7 @@ int main(int argc, char **argv) { srslte_ofdm_rx_sf(&ofdm_rx, sf_symbols, slot_symbols[1]); #endif srslte_softbuffer_rx_reset_tbs(&softbuffer_rx, grant.mcs.tbs); - r = srslte_pdsch_decode(&pdsch, &pdsch_cfg, &softbuffer_rx, slot_symbols[0], ce, 0, data); + r = srslte_pdsch_decode(&pdsch, &pdsch_cfg, &softbuffer_rx, slot_symbols[0], ce, 0, rnti, data); } gettimeofday(&t[2], NULL); get_time_interval(t); diff --git a/srslte/lib/phch/test/pdsch_test_mex.c b/srslte/lib/phch/test/pdsch_test_mex.c index 699fbb1f6..45bd1ae09 100644 --- a/srslte/lib/phch/test/pdsch_test_mex.c +++ b/srslte/lib/phch/test/pdsch_test_mex.c @@ -97,7 +97,8 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) mexErrMsgTxt("Error initiating PDSCH\n"); return; } - srslte_pdsch_set_rnti(&pdsch, (uint16_t) (rnti32 & 0xffff)); + uint16_t rnti = (uint16_t) (rnti32 & 0xffff); + srslte_pdsch_set_rnti(&pdsch, rnti); if (srslte_softbuffer_rx_init(&softbuffer, cell.nof_prb)) { mexErrMsgTxt("Error initiating soft buffer\n"); @@ -250,7 +251,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) noise_power = srslte_chest_dl_get_noise_estimate(&chest); } - r = srslte_pdsch_decode(&pdsch, &cfg, &softbuffer, input_fft, ce, noise_power, data_bytes); + r = srslte_pdsch_decode(&pdsch, &cfg, &softbuffer, input_fft, ce, noise_power, rnti, data_bytes); } uint8_t *data = malloc(grant.mcs.tbs); @@ -271,7 +272,9 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) if (nlhs >= 5) { mexutils_write_s(pdsch.e, &plhs[4], cfg.nbits.nof_bits, 1); } - + if (nlhs >= 6) { + mexutils_write_cf(ce[0], &plhs[5], SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp), 1); + } srslte_softbuffer_rx_free(&softbuffer); srslte_chest_dl_free(&chest); srslte_pdsch_free(&pdsch); diff --git a/srslte/lib/phch/test/phich_file_test.c b/srslte/lib/phch/test/phich_file_test.c index 1fdc12797..f037a55da 100644 --- a/srslte/lib/phch/test/phich_file_test.c +++ b/srslte/lib/phch/test/phich_file_test.c @@ -38,7 +38,6 @@ char *matlab_file_name = NULL; srslte_cell_t cell = { 50, // cell.nof_prb 2, // cell.nof_ports - 2, // bw_idx 150, // cell.id SRSLTE_CP_NORM, // cyclic prefix SRSLTE_PHICH_R_1, // PHICH resources diff --git a/srslte/lib/phch/test/prach_test.c b/srslte/lib/phch/test/prach_test.c index 088f815c0..ddd05eba0 100644 --- a/srslte/lib/phch/test/prach_test.c +++ b/srslte/lib/phch/test/prach_test.c @@ -114,7 +114,7 @@ int main(int argc, char **argv) { srslte_prach_detect(p, frequency_offset, &preamble[p->N_cp], prach_len, indices, &n_indices); gettimeofday(&t[2], NULL); get_time_interval(t); - printf("texec=%d us\n", t[0].tv_usec); + printf("texec=%ld us\n", t[0].tv_usec); if(n_indices != 1 || indices[0] != seq_index) return -1; } diff --git a/srslte/lib/phch/test/prach_test_usrp.c b/srslte/lib/phch/test/prach_test_usrp.c index acdaf1947..0cd85e39d 100644 --- a/srslte/lib/phch/test/prach_test_usrp.c +++ b/srslte/lib/phch/test/prach_test_usrp.c @@ -45,10 +45,10 @@ uint32_t root_seq_idx = 0; uint32_t seq_idx = 0; uint32_t frequency_offset = 0; uint32_t zero_corr_zone = 11; -uint32_t timeadv = 0; +float timeadv = 0; uint32_t nof_frames = 20; -float uhd_gain=40, uhd_freq=2.4e9; +float uhd_rx_gain=40, uhd_tx_gain=60, uhd_freq=2.4e9; char *uhd_args=""; char *output_filename = "prach_rx"; @@ -56,20 +56,21 @@ void usage(char *prog) { printf("Usage: %s \n", prog); printf("\t-a UHD args [Default %s]\n", uhd_args); printf("\t-f UHD TX/RX frequency [Default %.2f MHz]\n", uhd_freq/1e6); - printf("\t-g UHD TX/RX gain [Default %.1f dB]\n", uhd_gain); + printf("\t-g UHD RX gain [Default %.1f dB]\n", uhd_rx_gain); + printf("\t-G UHD TX gain [Default %.1f dB]\n", uhd_tx_gain); printf("\t-p Number of UL RB [Default %d]\n", nof_prb); printf("\t-F Preamble format [Default %d]\n", preamble_format); printf("\t-O Frequency offset [Default %d]\n", frequency_offset); printf("\t-s sequence index [Default %d]\n", seq_idx); printf("\t-r Root sequence index [Default %d]\n", root_seq_idx); - printf("\t-t Time advance (us) [Default %d]\n", timeadv); + printf("\t-t Time advance (us) [Default %.1f us]\n", timeadv); printf("\t-z Zero correlation zone config [Default %d]\n", zero_corr_zone); printf("\t-o Save transmitted PRACH in file [Default no]\n"); } void parse_args(int argc, char **argv) { int opt; - while ((opt = getopt(argc, argv, "apfFgrstoPOz")) != -1) { + while ((opt = getopt(argc, argv, "apfFgGrstoPOz")) != -1) { switch (opt) { case 'a': uhd_args = argv[optind]; @@ -81,7 +82,10 @@ void parse_args(int argc, char **argv) { uhd_freq = atof(argv[optind]); break; case 'g': - uhd_gain = atof(argv[optind]); + uhd_rx_gain = atof(argv[optind]); + break; + case 'G': + uhd_tx_gain = atof(argv[optind]); break; case 'P': preamble_format = atoi(argv[optind]); @@ -90,7 +94,7 @@ void parse_args(int argc, char **argv) { frequency_offset = atoi(argv[optind]); break; case 't': - timeadv = atoi(argv[optind]); + timeadv = atof(argv[optind]); break; case 'p': nof_prb = atoi(argv[optind]); @@ -129,11 +133,11 @@ int main(int argc, char **argv) { memset(preamble, 0, sizeof(cf_t)*MAX_LEN); srslte_prach_init(p, - srslte_symbol_sz(nof_prb), - preamble_format, - root_seq_idx, - high_speed_flag, - zero_corr_zone); + srslte_symbol_sz(nof_prb), + preamble_format, + root_seq_idx, + high_speed_flag, + zero_corr_zone); int srate = srslte_sampling_freq_hz(nof_prb); uint32_t flen = srate/1000; @@ -153,71 +157,78 @@ int main(int argc, char **argv) { cf_t *buffer = malloc(sizeof(cf_t)*flen*nof_frames); // Send through UHD - srslte_rf_t uhd; - printf("Opening UHD device...\n"); - if (srslte_rf_open(&uhd, uhd_args)) { + srslte_rf_t rf; + printf("Opening RF device...\n"); + if (srslte_rf_open(&rf, uhd_args)) { fprintf(stderr, "Error opening &uhd\n"); exit(-1); } printf("Subframe len: %d samples\n", flen); - printf("Set RX gain: %.1f dB\n", uhd_gain); - printf("Set TX gain: %.1f dB\n", 20+uhd_gain); + printf("Set RX gain: %.1f dB\n", uhd_rx_gain); + printf("Set TX gain: %.1f dB\n", uhd_tx_gain); printf("Set TX/RX freq: %.2f MHz\n", uhd_freq/ 1000000); - srslte_rf_set_rx_gain(&uhd, uhd_gain); - srslte_rf_set_tx_gain(&uhd, 10+uhd_gain); - srslte_rf_set_rx_freq(&uhd, uhd_freq); - srslte_rf_set_tx_freq(&uhd, uhd_freq); + srslte_rf_set_rx_gain(&rf, uhd_rx_gain); + srslte_rf_set_tx_gain(&rf, uhd_tx_gain); + srslte_rf_set_rx_freq(&rf, uhd_freq); + srslte_rf_set_tx_freq(&rf, uhd_freq); - if (srate < 10e6) { - srslte_rf_set_master_clock_rate(&uhd, 4*srate); + if (srate > 1e6) { + if (30720%((int) srate/1000) == 0) { + srslte_rf_set_master_clock_rate(&rf, 30.72e6); + } else { + srslte_rf_set_master_clock_rate(&rf, 23.04e6); + } } else { - srslte_rf_set_master_clock_rate(&uhd, srate); + printf("Invalid sampling rate %d Hz\n", srate); + exit(-1); } printf("Setting sampling rate %.2f MHz\n", (float) srate/1000000); - float srate_rf = srslte_rf_set_rx_srate(&uhd, (double) srate); + float srate_rf = srslte_rf_set_rx_srate(&rf, (double) srate); if (srate_rf != srate) { fprintf(stderr, "Could not set sampling rate\n"); exit(-1); } - srslte_rf_set_tx_srate(&uhd, (double) srate); + srslte_rf_set_tx_srate(&rf, (double) srate); sleep(1); cf_t *zeros = calloc(sizeof(cf_t),flen); - FILE *f = NULL; - if (output_filename) { - f = fopen(output_filename, "w"); - } - srslte_timestamp_t tstamp; - srslte_rf_start_rx_stream(&uhd); + srslte_rf_start_rx_stream(&rf); uint32_t nframe=0; while(nframeN_cp], flen, indices, offsets, NULL, &nof_detected)) { + printf("Error detecting prach\n"); } - if (f) { - fclose(f); + printf("Nof detected PRACHs: %d\n", nof_detected); + for (int i=0;i +#include "srslte/srslte.h" +#include "srslte/mex/mexutils.h" + +/** MEX function to be called from MATLAB to test the channel estimator + */ + +#define UECFG prhs[0] +#define PUCCHCFG prhs[1] +#define N_BITS prhs[2] +#define INPUT prhs[3] +#define THRESHOLD prhs[4] +#define NOF_INPUTS 4 + +void help() +{ + mexErrMsgTxt + ("[data, symbols, ce]=srslte_pucch(ue, chs, n_bits, input)\n\n"); +} + +/* the gateway function */ +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) +{ + + if (nrhs < NOF_INPUTS) { + help(); + return; + } + srslte_verbose = SRSLTE_VERBOSE_NONE; + + srslte_cell_t cell; + bzero(&cell, sizeof(srslte_cell_t)); + cell.nof_ports = 1; + cell.cp = SRSLTE_CP_NORM; + if (mexutils_read_uint32_struct(UECFG, "NCellID", &cell.id)) { + mexErrMsgTxt("Field NCellID not found in UE config\n"); + return; + } + if (mexutils_read_uint32_struct(UECFG, "NULRB", &cell.nof_prb)) { + mexErrMsgTxt("Field NULRB not found in UE config\n"); + return; + } + srslte_pucch_t pucch; + if (srslte_pucch_init(&pucch, cell)) { + mexErrMsgTxt("Error initiating PUSCH\n"); + return; + } + + uint32_t sf_idx = 0; + if (mexutils_read_uint32_struct(UECFG, "NSubframe", &sf_idx)) { + mexErrMsgTxt("Field NSubframe not found in UE config\n"); + return; + } + uint32_t rnti; + if (mexutils_read_uint32_struct(UECFG, "RNTI", &rnti)) { + mexErrMsgTxt("Field NSubframe not found in UE config\n"); + return; + } + if (srslte_pucch_set_crnti(&pucch, (uint16_t) rnti&0xffff)) { + mexErrMsgTxt("Error setting C-RNTI\n"); + return; + } + uint32_t n_pucch; + if (mexutils_read_uint32_struct(PUCCHCFG, "ResourceIdx", &n_pucch)) { + mexErrMsgTxt("Field ResourceIdx not found in PUCCHCFG\n"); + return; + } + srslte_pucch_cfg_t pucch_cfg; + bzero(&pucch_cfg, sizeof(srslte_pucch_cfg_t)); + + if (mexutils_read_uint32_struct(PUCCHCFG, "DeltaShift", &pucch_cfg.delta_pucch_shift)) { + mexErrMsgTxt("Field DeltaShift not found in PUCCHCFG\n"); + return; + } + if (mexutils_read_uint32_struct(PUCCHCFG, "ResourceSize", &pucch_cfg.n_rb_2)) { + mexErrMsgTxt("Field DeltaShift not found in PUCCHCFG\n"); + return; + } + if (mexutils_read_uint32_struct(PUCCHCFG, "CyclicShifts", &pucch_cfg.N_cs)) { + mexErrMsgTxt("Field CyclicShifts not found in PUCCHCFG\n"); + return; + } + bool group_hopping_en = false; + char *hop = mexutils_get_char_struct(UECFG, "Hopping"); + if (hop) { + if (!strcmp(hop, "Group")) { + group_hopping_en = true; + } + mxFree(hop); + } + + pucch.shortened = false; + uint32_t sh = 0; + mexutils_read_uint32_struct(PUCCHCFG, "Shortened", &sh); + if (sh == 1) { + pucch.shortened = true; + } + + float *thresholds; + int th_len = 0; + + if (nrhs > NOF_INPUTS) { + th_len = mexutils_read_f(THRESHOLD, &thresholds); + if (th_len == 2) { + srslte_pucch_set_threshold(&pucch, thresholds[0], thresholds[1]); + } + } + + uint8_t bits[SRSLTE_PUCCH_MAX_BITS]; + int nof_bits = (int) mxGetScalar(N_BITS); + + srslte_pucch_format_t format; + switch(nof_bits) { + case 0: + format = SRSLTE_PUCCH_FORMAT_1; + break; + case 1: + format = SRSLTE_PUCCH_FORMAT_1A; + break; + case 2: + format = SRSLTE_PUCCH_FORMAT_1B; + break; + case 20: + format = SRSLTE_PUCCH_FORMAT_2; + break; + case 21: + format = SRSLTE_PUCCH_FORMAT_2A; + break; + case 22: + format = SRSLTE_PUCCH_FORMAT_2B; + break; + default: + mexErrMsgTxt("Invalid number of bits in parameter ack\n"); + return; + } + if (nof_bits > 20) { + nof_bits = 20; + } + + cf_t *sf_symbols = NULL; + int nof_re = mexutils_read_cf(INPUT, &sf_symbols); + if (nof_re < 0) { + mexErrMsgTxt("Error reading input\n"); + return; + } + cf_t *ce = srslte_vec_malloc(nof_re*sizeof(cf_t)); + if (!ce) { + perror("malloc"); + return; + } + bzero(ce, nof_re*sizeof(cf_t)); + srslte_chest_ul_t chest_ul; + if (srslte_chest_ul_init(&chest_ul, cell)) { + mexErrMsgTxt("Error initiating PUCCH DMRS\n"); + return; + } + srslte_refsignal_dmrs_pusch_cfg_t pusch_cfg; + pusch_cfg.group_hopping_en = group_hopping_en; + pusch_cfg.sequence_hopping_en = false; + srslte_chest_ul_set_cfg(&chest_ul, &pusch_cfg, &pucch_cfg, NULL); + + srslte_pucch_set_cfg(&pucch, &pucch_cfg, group_hopping_en); + + if (srslte_chest_ul_estimate_pucch(&chest_ul, sf_symbols, ce, format, n_pucch, sf_idx)) { + mexErrMsgTxt("Error estimating PUCCH DMRS\n"); + return; + } + + if (srslte_pucch_decode(&pucch, format, n_pucch, sf_idx, sf_symbols, ce, 0, bits)) { + mexErrMsgTxt("Error decoding PUCCH\n"); + return; + } + + if (nlhs >= 1) { + if (format != SRSLTE_PUCCH_FORMAT_1) { + mexutils_write_uint8(bits, &plhs[0], nof_bits, 1); + } else { + if (bits[0] == 1) { + mexutils_write_uint8(bits, &plhs[0], 0, 1); + } else { + mexutils_write_uint8(bits, &plhs[0], 0, 0); + } + } + } + + if (nlhs >= 2) { + mexutils_write_cf(pucch.z, &plhs[1], 2*srslte_refsignal_dmrs_N_rs(format, cell.cp)*SRSLTE_NRE*2, 1); + } + + if (nlhs >= 3) { + mexutils_write_cf(ce, &plhs[2], nof_re, 1); + } + + srslte_pucch_free(&pucch); + free(sf_symbols); + + return; +} + diff --git a/srslte/lib/phch/test/pusch_encode_test_mex.c b/srslte/lib/phch/test/pusch_encode_test_mex.c index 4d8693bbf..59c0bbe15 100644 --- a/srslte/lib/phch/test/pusch_encode_test_mex.c +++ b/srslte/lib/phch/test/pusch_encode_test_mex.c @@ -76,8 +76,9 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) mexErrMsgTxt("Field RNTI not found in pusch config\n"); return; } - srslte_pusch_set_rnti(&pusch, (uint16_t) (rnti32 & 0xffff)); + uint16_t rnti = (uint16_t) (rnti32 & 0xffff); + srslte_pusch_set_rnti(&pusch, rnti); srslte_pusch_cfg_t cfg; @@ -195,7 +196,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) mexPrintf("I_cqi: %2d, I_ri: %2d, I_ack=%2d\n", cfg.uci_cfg.I_offset_cqi, cfg.uci_cfg.I_offset_ri, cfg.uci_cfg.I_offset_ack); mexPrintf("NofRE: %3d, NofBits: %3d, TBS: %3d, N_srs=%d\n", cfg.nbits.nof_re, cfg.nbits.nof_bits, grant.mcs.tbs, N_srs); - int r = srslte_pusch_uci_encode(&pusch, &cfg, &softbuffer, trblkin, uci_data, sf_symbols); + int r = srslte_pusch_encode(&pusch, &cfg, &softbuffer, trblkin, uci_data, rnti, sf_symbols); if (r < 0) { mexErrMsgTxt("Error encoding PUSCH\n"); return; @@ -205,7 +206,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) return; } if (cfg.rv > 0) { - r = srslte_pusch_uci_encode(&pusch, &cfg, &softbuffer, trblkin, uci_data, sf_symbols); + r = srslte_pusch_encode(&pusch, &cfg, &softbuffer, trblkin, uci_data, rnti, sf_symbols); if (r < 0) { mexErrMsgTxt("Error encoding PUSCH\n"); return; diff --git a/srslte/lib/phch/test/pusch_test.c b/srslte/lib/phch/test/pusch_test.c index 8752cc734..29980a83f 100644 --- a/srslte/lib/phch/test/pusch_test.c +++ b/srslte/lib/phch/test/pusch_test.c @@ -164,7 +164,8 @@ int main(int argc, char **argv) { exit(-1); } - srslte_pusch_set_rnti(&pusch, 1234); + uint16_t rnti = 1234; + srslte_pusch_set_rnti(&pusch, rnti); srslte_uci_data_t uci_data_tx; srslte_uci_data_t uci_data_rx; @@ -184,13 +185,13 @@ int main(int argc, char **argv) { sf_symbols = srslte_vec_malloc(sizeof(cf_t) * nof_re); if (!sf_symbols) { perror("malloc"); - goto quit; + exit(-1); } data = srslte_vec_malloc(sizeof(uint8_t) * cfg.grant.mcs.tbs); if (!data) { perror("malloc"); - goto quit; + exit(-1); } for (uint32_t i=0;i 0) { cfg.rv = rv_idx; - if (srslte_pusch_uci_encode(&pusch, &cfg, &softbuffer_tx, data, uci_data_tx, sf_symbols)) { + if (srslte_pusch_encode(&pusch, &cfg, &softbuffer_tx, data, uci_data_tx, rnti, sf_symbols)) { fprintf(stderr, "Error encoding TB\n"); exit(-1); } @@ -230,7 +231,7 @@ int main(int argc, char **argv) { } gettimeofday(&t[1], NULL); - int r = srslte_pusch_uci_decode(&pusch, &cfg, &softbuffer_rx, sf_symbols, ce, 0, data, &uci_data_rx); + int r = srslte_pusch_decode(&pusch, &cfg, &softbuffer_rx, sf_symbols, ce, 0, rnti, data, &uci_data_rx); gettimeofday(&t[2], NULL); get_time_interval(t); if (r) { diff --git a/srslte/lib/phch/test/pusch_test_mex.c b/srslte/lib/phch/test/pusch_test_mex.c index 6178a1f3a..7b29075eb 100644 --- a/srslte/lib/phch/test/pusch_test_mex.c +++ b/srslte/lib/phch/test/pusch_test_mex.c @@ -99,7 +99,8 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) mexErrMsgTxt("Error initiating PDSCH\n"); return; } - srslte_pusch_set_rnti(&pusch, (uint16_t) (rnti32 & 0xffff)); + uint16_t rnti = (uint16_t) (rnti32 & 0xffff); + srslte_pusch_set_rnti(&pusch, rnti); if (srslte_softbuffer_rx_init(&softbuffer, cell.nof_prb)) { mexErrMsgTxt("Error initiating soft buffer\n"); @@ -272,7 +273,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) noise_power = srslte_chest_ul_get_noise_estimate(&chest); } - r = srslte_pusch_uci_decode(&pusch, &cfg, &softbuffer, input_fft, ce, noise_power, data_bytes, &uci_data); + r = srslte_pusch_decode(&pusch, &cfg, &softbuffer, input_fft, ce, noise_power, rnti, data_bytes, &uci_data); } uint8_t *data = malloc(grant.mcs.tbs); diff --git a/srslte/lib/phch/uci.c b/srslte/lib/phch/uci.c index ece0702c2..62d2bedcf 100644 --- a/srslte/lib/phch/uci.c +++ b/srslte/lib/phch/uci.c @@ -298,10 +298,13 @@ int decode_cqi_long(srslte_uci_cqi_pusch_t *q, int16_t *q_bits, uint32_t Q, srslte_rm_conv_rx_s(q_bits, Q, q->encoded_cqi_s, 3 * (nof_bits + 8)); // Set viterbi normalization based on amplitude - int16_t max = srslte_vec_max_star_si(q->encoded_cqi_s, 3 * (nof_bits + 8)); - srslte_viterbi_set_gain_quant_s(&q->viterbi, max/36); - - DEBUG("cconv_rx=", 0); + int16_t max = srslte_vec_max_abs_star_si(q->encoded_cqi_s, 3 * (nof_bits + 8)); + if (abs(max) > 100) { + srslte_viterbi_set_gain_quant_s(&q->viterbi, (float) abs(max)/36); + } else { + srslte_viterbi_set_gain_quant_s(&q->viterbi, 1); + } + DEBUG("cconv_rx=", 0); if (SRSLTE_VERBOSE_ISDEBUG()) { srslte_vec_fprint_s(stdout, q->encoded_cqi_s, 3 * (nof_bits + 8)); } @@ -314,7 +317,7 @@ int decode_cqi_long(srslte_uci_cqi_pusch_t *q, int16_t *q_bits, uint32_t Q, } ret = srslte_crc_checksum(&q->crc, q->tmp_cqi, nof_bits + 8); - if (ret == 0) { + if (ret == 0) { memcpy(data, q->tmp_cqi, nof_bits*sizeof(uint8_t)); ret = 1; } else { diff --git a/srslte/lib/rf/CMakeLists.txt b/srslte/lib/rf/CMakeLists.txt index 3b97dfecf..ae98aaedf 100644 --- a/srslte/lib/rf/CMakeLists.txt +++ b/srslte/lib/rf/CMakeLists.txt @@ -33,6 +33,18 @@ if(RF_FOUND) list(APPEND SOURCES_RF rf_blade_imp.c) endif (BLADERF_FOUND) - add_library(srslte_rf OBJECT ${SOURCES_RF}) + add_compile_options(-march=native -mfpmath=sse -mno-avx -msse4.1) + add_library(srslte_rf SHARED ${SOURCES_RF}) + + + if (UHD_FOUND) + target_link_libraries(srslte_rf ${UHD_LIBRARIES}) + endif (UHD_FOUND) + + if (BLADERF_FOUND) + target_link_libraries(srslte_rf ${BLADERF_LIBRARIES}) + endif (BLADERF_FOUND) + + INSTALL(TARGETS srslte_rf DESTINATION ${LIBRARY_DIR}) SRSLTE_SET_PIC(srslte_rf) -endif(RF_FOUND) +endif(RF_FOUND) \ No newline at end of file diff --git a/srslte/lib/rf/rf_blade_imp.c b/srslte/lib/rf/rf_blade_imp.c index ee7185c88..fbe9b3fc6 100644 --- a/srslte/lib/rf/rf_blade_imp.c +++ b/srslte/lib/rf/rf_blade_imp.c @@ -70,7 +70,12 @@ const unsigned int buffer_size_tx = 1024; const unsigned int num_transfers = 32; const unsigned int timeout_ms = 4000; - + +char* rf_blade_devname(void* h) +{ + return DEVNAME; +} + int rf_blade_start_tx_stream(void *h) { int status; @@ -336,6 +341,10 @@ double rf_blade_set_rx_freq(void *h, double freq) (uint32_t) freq, bladerf_strerror(status)); return -1; } + f_int=0; + bladerf_get_frequency(handler->dev, BLADERF_MODULE_RX, &f_int); + printf("set RX frequency to %u\n", f_int); + return freq; } @@ -350,6 +359,9 @@ double rf_blade_set_tx_freq(void *h, double freq) return -1; } + f_int=0; + bladerf_get_frequency(handler->dev, BLADERF_MODULE_TX, &f_int); + printf("set TX frequency to %u\n", f_int); return freq; } @@ -478,10 +490,12 @@ int rf_blade_send_timed(void *h, if (is_end_of_burst) { meta.flags |= BLADERF_META_FLAG_TX_BURST_END; } + srslte_rf_error_t error; + bzero(&error, sizeof(srslte_rf_error_t)); + status = bladerf_sync_tx(handler->dev, handler->tx_buffer, nsamples, &meta, 2000); if (status == BLADERF_ERR_TIME_PAST) { if (blade_error_handler) { - srslte_rf_error_t error; error.type = SRSLTE_RF_ERROR_LATE; blade_error_handler(error); } else { @@ -492,7 +506,6 @@ int rf_blade_send_timed(void *h, return status; } else if (meta.status == BLADERF_META_STATUS_UNDERRUN) { if (blade_error_handler) { - srslte_rf_error_t error; error.type = SRSLTE_RF_ERROR_UNDERFLOW; blade_error_handler(error); } else { diff --git a/srslte/lib/rf/rf_blade_imp.h b/srslte/lib/rf/rf_blade_imp.h index e6d05804d..552564620 100644 --- a/srslte/lib/rf/rf_blade_imp.h +++ b/srslte/lib/rf/rf_blade_imp.h @@ -28,9 +28,14 @@ #include "srslte/config.h" #include "srslte/rf/rf.h" +#define DEVNAME "bladerf" + SRSLTE_API int rf_blade_open(char *args, void **handler); + +SRSLTE_API char* rf_blade_devname(void *h); + SRSLTE_API int rf_blade_close(void *h); SRSLTE_API void rf_blade_set_tx_cal(void *h, srslte_rf_cal_t *cal); diff --git a/srslte/lib/rf/rf_dev.h b/srslte/lib/rf/rf_dev.h index 09b0c1bfd..2dd65552c 100644 --- a/srslte/lib/rf/rf_dev.h +++ b/srslte/lib/rf/rf_dev.h @@ -28,7 +28,8 @@ /* RF frontend API */ typedef struct { const char *name; - bool (*srslte_rf_rx_wait_lo_locked) (void*); + char* (*srslte_rf_devname) (void *h); + bool (*srslte_rf_rx_wait_lo_locked) (void *h); int (*srslte_rf_start_rx_stream)(void *h); int (*srslte_rf_stop_rx_stream)(void *h); void (*srslte_rf_flush_buffer)(void *h); @@ -67,6 +68,7 @@ typedef struct { static rf_dev_t dev_uhd = { "UHD", + rf_uhd_devname, rf_uhd_rx_wait_lo_locked, rf_uhd_start_rx_stream, rf_uhd_stop_rx_stream, @@ -102,6 +104,7 @@ static rf_dev_t dev_uhd = { static rf_dev_t dev_blade = { "bladeRF", + rf_blade_devname, rf_blade_rx_wait_lo_locked, rf_blade_start_rx_stream, rf_blade_stop_rx_stream, @@ -160,6 +163,7 @@ static rf_dev_t dev_dummy = { dummy_fnc, dummy_fnc, dummy_fnc, + dummy_fnc, dummy_fnc, dummy_fnc, dummy_fnc, diff --git a/srslte/lib/rf/rf_imp.c b/srslte/lib/rf/rf_imp.c index 03c1cdaed..fe93d0e93 100644 --- a/srslte/lib/rf/rf_imp.c +++ b/srslte/lib/rf/rf_imp.c @@ -137,7 +137,7 @@ void srslte_rf_set_rx_cal(srslte_rf_t *rf, srslte_rf_cal_t *cal) { const char* srslte_rf_name(srslte_rf_t *rf) { - return ((rf_dev_t*) rf->dev)->name; + return ((rf_dev_t*) rf->dev)->srslte_rf_devname(rf->handler); } bool srslte_rf_rx_wait_lo_locked(srslte_rf_t *rf) diff --git a/srslte/lib/rf/rf_uhd_imp.c b/srslte/lib/rf/rf_uhd_imp.c index 73e7af981..d16382f52 100644 --- a/srslte/lib/rf/rf_uhd_imp.c +++ b/srslte/lib/rf/rf_uhd_imp.c @@ -36,6 +36,7 @@ #include "uhd_c_api.h" typedef struct { + char *devname; uhd_usrp_handle usrp; uhd_rx_streamer_handle rx_stream; uhd_tx_streamer_handle tx_stream; @@ -62,6 +63,8 @@ srslte_rf_error_handler_t uhd_error_handler = NULL; void msg_handler(const char *msg) { srslte_rf_error_t error; + bzero(&error, sizeof(srslte_rf_error_t)); + if(0 == strcmp(msg, "O")) { error.type = SRSLTE_RF_ERROR_OVERFLOW; } else if(0 == strcmp(msg, "D")) { @@ -115,6 +118,12 @@ static bool isLocked(rf_uhd_handler_t *handler, char *sensor_name, uhd_sensor_va return val_out; } +char* rf_uhd_devname(void* h) +{ + rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; + return handler->devname; +} + bool rf_uhd_rx_wait_lo_locked(void *h) { rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; @@ -236,7 +245,7 @@ int rf_uhd_open(char *args, void **h) /* Set priority to UHD threads */ uhd_set_thread_priority(uhd_default_thread_priority, true); - /* Set correct options for the USRP device */ + /* Find available devices */ uhd_string_vector_handle devices_str; uhd_string_vector_make(&devices_str); uhd_usrp_find("", &devices_str); @@ -249,15 +258,19 @@ int rf_uhd_open(char *args, void **h) if (args == NULL) { args = ""; } + handler->devname = NULL; + /* If device type or name not given in args, choose a B200 */ if (args[0]=='\0') { if (find_string(devices_str, "type=b200") && !strstr(args, "recv_frame_size")) { // If B200 is available, use it - args = "type=b200,recv_frame_size=9232,send_frame_size=9232"; + args = "type=b200"; + handler->devname = DEVNAME_B200; } else if (find_string(devices_str, "type=x300")) { // Else if X300 is available, set master clock rate now (can't be changed later) args = "type=x300,master_clock_rate=184.32e6"; handler->dynamic_rate = false; + handler->devname = DEVNAME_X300; } } else { // If args is set and x300 type is specified, make sure master_clock_rate is defined @@ -265,9 +278,14 @@ int rf_uhd_open(char *args, void **h) sprintf(args2, "%s,master_clock_rate=184.32e6",args); args = args2; handler->dynamic_rate = false; + handler->devname = DEVNAME_X300; + } else if (strstr(args, "type=b200")) { + handler->devname = DEVNAME_B200; } } + uhd_string_vector_free(&devices_str); + /* Create UHD handler */ printf("Opening USRP with args: %s\n", args); uhd_error error = uhd_usrp_make(&handler->usrp, args); @@ -275,7 +293,19 @@ int rf_uhd_open(char *args, void **h) fprintf(stderr, "Error opening UHD: code %d\n", error); return -1; } - + + if (!handler->devname) { + char dev_str[1024]; + uhd_usrp_get_mboard_name(handler->usrp, 0, dev_str, 1024); + if (strstr(dev_str, "B2") || strstr(dev_str, "B2")) { + handler->devname = DEVNAME_B200; + } else if (strstr(dev_str, "X3") || strstr(dev_str, "X3")) { + handler->devname = DEVNAME_X300; + } + } + if (!handler->devname) { + handler->devname = "uhd_unknown"; + } size_t channel = 0; uhd_stream_args_t stream_args = { .cpu_format = "fc32", @@ -284,6 +314,11 @@ int rf_uhd_open(char *args, void **h) .channel_list = &channel, .n_channels = 1 }; + + // Set external clock reference + if (strstr(args, "clock=external")) { + uhd_usrp_set_clock_source(handler->usrp, "external", 0); + } handler->has_rssi = get_has_rssi(handler); if (handler->has_rssi) { @@ -326,6 +361,19 @@ int rf_uhd_close(void *h) { rf_uhd_stop_rx_stream(h); + rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h; + + uhd_tx_metadata_free(&handler->tx_md); + uhd_rx_metadata_free(&handler->rx_md_first); + uhd_rx_metadata_free(&handler->rx_md); + uhd_meta_range_free(&handler->rx_gain_range); + uhd_tx_streamer_free(&handler->tx_stream); + uhd_rx_streamer_free(&handler->rx_stream); + if (handler->has_rssi) { + uhd_sensor_value_free(&handler->rssi_value); + } + uhd_usrp_free(&handler->usrp); + /** Something else to close the USRP?? */ return 0; } diff --git a/srslte/lib/rf/rf_uhd_imp.h b/srslte/lib/rf/rf_uhd_imp.h index 240cfc8f0..ee13ea36e 100644 --- a/srslte/lib/rf/rf_uhd_imp.h +++ b/srslte/lib/rf/rf_uhd_imp.h @@ -30,9 +30,15 @@ #include "srslte/config.h" #include "srslte/rf/rf.h" +#define DEVNAME_B200 "uhd_b200" +#define DEVNAME_X300 "uhd_x300" + + SRSLTE_API int rf_uhd_open(char *args, void **handler); +SRSLTE_API char* rf_uhd_devname(void *h); + SRSLTE_API int rf_uhd_close(void *h); SRSLTE_API void rf_uhd_set_tx_cal(void *h, srslte_rf_cal_t *cal); diff --git a/srslte/lib/scrambling/test/scrambling_test.c b/srslte/lib/scrambling/test/scrambling_test.c index 49679e9e0..9ff47dc85 100644 --- a/srslte/lib/scrambling/test/scrambling_test.c +++ b/srslte/lib/scrambling/test/scrambling_test.c @@ -131,7 +131,7 @@ int main(int argc, char **argv) { srslte_scrambling_b(&seq, scrambled_b); get_time_interval(t); - printf("Texec=%d us for %d bits\n", t[0].tv_usec, seq.len); + printf("Texec=%ld us for %d bits\n", t[0].tv_usec, seq.len); for (i=0;icur_cexp) { free(h->cur_cexp); } - bzero(h, sizeof(cf_t)); + bzero(h, sizeof(srslte_cfo_t)); } void srslte_cfo_set_tol(srslte_cfo_t *h, float tol) { diff --git a/srslte/lib/sync/pss.c b/srslte/lib/sync/pss.c index 16efa4f1b..647baa838 100644 --- a/srslte/lib/sync/pss.c +++ b/srslte/lib/sync/pss.c @@ -94,6 +94,8 @@ int srslte_pss_synch_init_fft_offset(srslte_pss_synch_t *q, uint32_t frame_size, if (q != NULL) { + ret = SRSLTE_ERROR; + uint32_t N_id_2; uint32_t buffer_size; bzero(q, sizeof(srslte_pss_synch_t)); @@ -200,6 +202,8 @@ void srslte_pss_synch_free(srslte_pss_synch_t *q) { if (q->conv_output_avg) { free(q->conv_output_avg); } + + srslte_dft_plan_free(&q->dftp_input); bzero(q, sizeof(srslte_pss_synch_t)); } @@ -302,7 +306,12 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe return SRSLTE_ERROR; } - /* Correlate input with PSS sequence */ + /* Correlate input with PSS sequence + * + * We do not reverse time-domain PSS signal because it's conjugate is symmetric. + * The conjugate operation on pss_signal_time has been done in srslte_pss_synch_init_N_id_2 + * This is why we can use FFT-based convolution + */ if (q->frame_size >= q->fft_size) { #ifdef CONVOLUTION_FFT memcpy(q->tmp_input, input, q->frame_size * sizeof(cf_t)); diff --git a/srslte/lib/sync/sss.c b/srslte/lib/sync/sss.c index d64c0db1d..27818866a 100644 --- a/srslte/lib/sync/sss.c +++ b/srslte/lib/sync/sss.c @@ -139,14 +139,15 @@ uint32_t srslte_sss_synch_subframe(uint32_t m0, uint32_t m1) { /** Returns the N_id_1 value based on the m0 and m1 values */ int srslte_sss_synch_N_id_1(srslte_sss_synch_t *q, uint32_t m0, uint32_t m1) { - if (m0==m1 || m0 > 30 || m1 > 30) { - return SRSLTE_ERROR; - } - int N_id_1; + int N_id_1 = -1; if (m1 > m0) { - N_id_1 = q->N_id_1_table[m0][m1 - 1]; + if (m0 < 30 && m1 - 1 < 30) { + N_id_1 = q->N_id_1_table[m0][m1 - 1]; + } } else { - N_id_1 = q->N_id_1_table[m1][m0 - 1]; + if (m1 < 30 && m0 - 1 < 30) { + N_id_1 = q->N_id_1_table[m1][m0 - 1]; + } } return N_id_1; } diff --git a/srslte/lib/sync/sync.c b/srslte/lib/sync/sync.c index 41a4c5efc..f7ddddd84 100644 --- a/srslte/lib/sync/sync.c +++ b/srslte/lib/sync/sync.c @@ -61,6 +61,7 @@ int srslte_sync_init(srslte_sync_t *q, uint32_t frame_size, uint32_t max_offset, q->detect_cp = true; q->sss_en = true; q->mean_cfo = 0; + q->mean_cfo2 = 0; q->N_id_2 = 1000; q->N_id_1 = 1000; q->cfo_i = 0; @@ -77,9 +78,17 @@ int srslte_sync_init(srslte_sync_t *q, uint32_t frame_size, uint32_t max_offset, fprintf(stderr, "Error initiating CFO\n"); goto clean_exit; } + + if (srslte_cfo_init(&q->cfocorr2, q->frame_size)) { + fprintf(stderr, "Error initiating CFO\n"); + goto clean_exit; + } - // Set a CFO tolerance of approx 100 Hz - srslte_cfo_set_tol(&q->cfocorr, 100/(15000*q->fft_size)); + // Set a CFO tolerance of approx 50 Hz + srslte_cfo_set_tol(&q->cfocorr, 50.0/(15000.0*q->fft_size)); + + // Set a CFO tolerance of approx 50 Hz + srslte_cfo_set_tol(&q->cfocorr2, 50.0/(15000.0*q->fft_size)); for (int i=0;i<2;i++) { q->cfo_i_corr[i] = srslte_vec_malloc(sizeof(cf_t)*q->frame_size); @@ -89,6 +98,12 @@ int srslte_sync_init(srslte_sync_t *q, uint32_t frame_size, uint32_t max_offset, } } + q->temp = srslte_vec_malloc(sizeof(cf_t)*2*q->frame_size); + if (!q->temp) { + perror("malloc"); + goto clean_exit; + } + srslte_sync_set_cp(q, SRSLTE_CP_NORM); if (srslte_pss_synch_init_fft(&q->pss, max_offset, fft_size)) { @@ -124,6 +139,7 @@ void srslte_sync_free(srslte_sync_t *q) { srslte_pss_synch_free(&q->pss); srslte_sss_synch_free(&q->sss); srslte_cfo_free(&q->cfocorr); + srslte_cfo_free(&q->cfocorr2); srslte_cp_synch_free(&q->cp_synch); for (int i=0;i<2;i++) { if (q->cfo_i_corr[i]) { @@ -131,6 +147,9 @@ void srslte_sync_free(srslte_sync_t *q) { } srslte_pss_synch_free(&q->pss_i[i]); } + if (q->temp) { + free(q->temp); + } } } @@ -185,7 +204,7 @@ uint32_t srslte_sync_get_sf_idx(srslte_sync_t *q) { } float srslte_sync_get_cfo(srslte_sync_t *q) { - return q->mean_cfo + q->cfo_i; + return q->mean_cfo2 + q->cfo_i; } void srslte_sync_set_cfo(srslte_sync_t *q, float cfo) { @@ -398,8 +417,11 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t srslte_sync_find_ret_t ret = SRSLTE_SYNC_ERROR; - if (q != NULL && - input != NULL && + if (!q) { + return SRSLTE_ERROR_INVALID_INPUTS; + } + + if (input != NULL && srslte_N_id_2_isvalid(q->N_id_2) && fft_size_isvalid(q->fft_size)) { @@ -410,6 +432,8 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t if (peak_position) { *peak_position = 0; } + + cf_t *input_cfo = input; if (q->enable_cfo_corr) { float cfo = cfo_estimate(q, input); @@ -418,19 +442,21 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t q->mean_cfo = SRSLTE_VEC_EMA(cfo, q->mean_cfo, q->cfo_ema_alpha); /* Correct CFO with the averaged CFO estimation */ - srslte_cfo_correct(&q->cfocorr, input, input, -q->mean_cfo / q->fft_size); + srslte_cfo_correct(&q->cfocorr2, input, q->temp, -q->mean_cfo / q->fft_size); + + input_cfo = q->temp; } /* If integer CFO is enabled, find max PSS correlation for shifted +1/0/-1 integer versions */ if (q->find_cfo_i && q->enable_cfo_corr) { - q->cfo_i = cfo_i_estimate(q, input, find_offset, &peak_pos); + q->cfo_i = cfo_i_estimate(q, input_cfo, find_offset, &peak_pos); if (q->cfo_i != 0) { - srslte_vec_prod_ccc(input, q->cfo_i_corr[q->cfo_i<0?0:1], input, q->frame_size); + srslte_vec_prod_ccc(input_cfo, q->cfo_i_corr[q->cfo_i<0?0:1], input_cfo, q->frame_size); INFO("Compensating cfo_i=%d\n", q->cfo_i); } } else { srslte_pss_synch_set_N_id_2(&q->pss, q->N_id_2); - peak_pos = srslte_pss_synch_find_pss(&q->pss, &input[find_offset], &q->peak_value); + peak_pos = srslte_pss_synch_find_pss(&q->pss, &input_cfo[find_offset], &q->peak_value); if (peak_pos < 0) { fprintf(stderr, "Error calling finding PSS sequence\n"); return SRSLTE_ERROR; @@ -446,7 +472,7 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t // Set an invalid N_id_1 indicating SSS is yet to be detected q->N_id_1 = 1000; - if (sync_sss(q, input, find_offset + peak_pos, q->cp) < 0) { + if (sync_sss(q, input_cfo, find_offset + peak_pos, q->cp) < 0) { DEBUG("No space for SSS processing. Frame starts at %d\n", peak_pos); } } @@ -456,13 +482,16 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t if (q->detect_cp) { if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) { - srslte_sync_set_cp(q, srslte_sync_detect_cp(q, input, peak_pos + find_offset)); + srslte_sync_set_cp(q, srslte_sync_detect_cp(q, input_cfo, peak_pos + find_offset)); } else { DEBUG("Not enough room to detect CP length. Peak position: %d\n", peak_pos); } } if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) { + float cfo2 = srslte_pss_synch_cfo_compute(&q->pss, &input[find_offset + peak_pos - q->fft_size]); + q->mean_cfo2 = SRSLTE_VEC_EMA(cfo2, q->mean_cfo2, q->cfo_ema_alpha); + ret = SRSLTE_SYNC_FOUND; } else { ret = SRSLTE_SYNC_FOUND_NOSPACE; diff --git a/srslte/lib/sync/test/CMakeLists.txt b/srslte/lib/sync/test/CMakeLists.txt index b6239124f..364421114 100644 --- a/srslte/lib/sync/test/CMakeLists.txt +++ b/srslte/lib/sync/test/CMakeLists.txt @@ -18,6 +18,8 @@ # and at http://www.gnu.org/licenses/. # +find_package(SRSGUI) + ######################################################################## # PROGRAM TO DEBUG PSS FROM USRP ######################################################################## @@ -25,21 +27,22 @@ add_executable(pss_file pss_file.c) target_link_libraries(pss_file srslte) +if(UHD_FOUND) + add_executable(pss_usrp pss_usrp.c) + target_link_libraries(pss_usrp srslte) +endif(UHD_FOUND) + + if(SRSGUI_FOUND) + include_directories(${SRSGUI_INCLUDE_DIRS}) target_link_libraries(pss_file ${SRSGUI_LIBRARIES}) + if(UHD_FOUND) + target_link_libraries(pss_usrp ${SRSGUI_LIBRARIES}) + endif(UHD_FOUND) else(SRSGUI_FOUND) - set_target_properties(pss_file PROPERTIES COMPILE_DEFINITIONS "DISABLE_GRAPHICS") + add_definitions(-DDISABLE_GRAPHICS) endif(SRSGUI_FOUND) -if(UHD_FOUND) - add_executable(pss_usrp pss_usrp.c) - target_link_libraries(pss_usrp srslte) - if(SRSGUI_FOUND) - target_link_libraries(pss_usrp ${SRSGUI_LIBRARIES}) - else(SRSGUI_FOUND) - set_target_properties(pss_usrp PROPERTIES COMPILE_DEFINITIONS "DISABLE_GRAPHICS") - endif(SRSGUI_FOUND) -endif(UHD_FOUND) BuildMex(MEXNAME pss SOURCES pss_mex.c LIBRARIES srslte_static srslte_mex) BuildMex(MEXNAME sss SOURCES sss_mex.c LIBRARIES srslte_static srslte_mex) diff --git a/srslte/lib/ue/ue_dl.c b/srslte/lib/ue/ue_dl.c index d6f9fc33f..d7015c46a 100644 --- a/srslte/lib/ue/ue_dl.c +++ b/srslte/lib/ue/ue_dl.c @@ -37,9 +37,8 @@ #define CURRENT_SLOTLEN_RE SRSLTE_SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp) #define CURRENT_SFLEN_RE SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp) -#define MAX_CANDIDATES 64 -static srslte_dci_format_t ue_formats[] = {SRSLTE_DCI_FORMAT1A, SRSLTE_DCI_FORMAT1}; // SRSLTE_DCI_FORMAT1B should go here also +static srslte_dci_format_t ue_formats[] = {SRSLTE_DCI_FORMAT1A, SRSLTE_DCI_FORMAT1}; // Only TM1 and TM2 are currently supported const uint32_t nof_ue_formats = 2; static srslte_dci_format_t common_formats[] = {SRSLTE_DCI_FORMAT1A,SRSLTE_DCI_FORMAT1C}; @@ -159,6 +158,15 @@ void srslte_ue_dl_free(srslte_ue_dl_t *q) { */ void srslte_ue_dl_set_rnti(srslte_ue_dl_t *q, uint16_t rnti) { srslte_pdsch_set_rnti(&q->pdsch, rnti); + + // Compute UE-specific and Common search space for this RNTI + for (int cfi=0;cfi<3;cfi++) { + for (int sf_idx=0;sf_idx<10;sf_idx++) { + q->current_ss_ue[cfi][sf_idx].nof_locations = srslte_pdcch_ue_locations(&q->pdcch, q->current_ss_ue[cfi][sf_idx].loc, MAX_CANDIDATES_UE, sf_idx, cfi+1, rnti); + } + q->current_ss_common[cfi].nof_locations = srslte_pdcch_common_locations(&q->pdcch, q->current_ss_common[cfi].loc, MAX_CANDIDATES_COM, cfi+1); + } + q->current_rnti = rnti; } @@ -178,12 +186,8 @@ void srslte_ue_dl_set_sample_offset(srslte_ue_dl_t * q, float sample_offset) { * - PDCCH decoding: Find DCI for RNTI given by previous call to srslte_ue_dl_set_rnti() * - PDSCH decoding: Decode TB scrambling with RNTI given by srslte_ue_dl_set_rnti() */ -int srslte_ue_dl_decode(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx) { - return srslte_ue_dl_decode_rnti_rv(q, input, data, sf_idx, q->current_rnti, 0); -} - -int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, uint16_t rnti) { - return srslte_ue_dl_decode_rnti_rv(q, input, data, sf_idx, rnti, 0); +int srslte_ue_dl_decode(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t tti) { + return srslte_ue_dl_decode_rnti(q, input, data, tti, q->current_rnti); } int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q, cf_t *input, uint32_t sf_idx, uint32_t *cfi) { @@ -241,91 +245,166 @@ int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint3 return srslte_pdsch_cfg(&q->pdsch_cfg, q->cell, grant, cfi, sf_idx, rvidx); } -int srslte_ue_dl_decode_rnti_rv_packet(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint8_t *data, - uint32_t cfi, uint32_t sf_idx, uint16_t rnti, uint32_t rvidx) +int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t tti, uint16_t rnti) { + srslte_dci_msg_t dci_msg; + srslte_ra_dl_dci_t dci_unpacked; + srslte_ra_dl_grant_t grant; int ret = SRSLTE_ERROR; - - q->nof_detected++; + uint32_t cfi; - /* Setup PDSCH configuration for this CFI, SFIDX and RVIDX */ - if (srslte_ue_dl_cfg_grant(q, grant, cfi, sf_idx, rvidx)) { - return SRSLTE_ERROR; - } + uint32_t sf_idx = tti%10; - if (q->pdsch_cfg.rv == 0) { - srslte_softbuffer_rx_reset_tbs(&q->softbuffer, grant->mcs.tbs); + if ((ret = srslte_ue_dl_decode_fft_estimate(q, input, sf_idx, &cfi)) < 0) { + return ret; } - // Uncoment next line to do ZF by default in pdsch_ue example - //float noise_estimate = 0; - float noise_estimate = srslte_chest_dl_get_noise_estimate(&q->chest); + if (srslte_pdcch_extract_llr(&q->pdcch, q->sf_symbols, q->ce, srslte_chest_dl_get_noise_estimate(&q->chest), sf_idx, cfi)) { + fprintf(stderr, "Error extracting LLRs\n"); + return SRSLTE_ERROR; + } + + int found_dci = srslte_ue_dl_find_dl_dci(q, cfi, sf_idx, rnti, &dci_msg); + if (found_dci == 1) { + + if (srslte_dci_msg_to_dl_grant(&dci_msg, rnti, q->cell.nof_prb, q->cell.nof_ports, &dci_unpacked, &grant)) { + fprintf(stderr, "Error unpacking DCI\n"); + return SRSLTE_ERROR; + } + + /* ===== These lines of code are supposed to be MAC functionality === */ + + + uint32_t rvidx = 0; + if (dci_unpacked.rv_idx < 0) { + uint32_t sfn = tti/10; + uint32_t k = (sfn/2)%4; + rvidx = ((uint32_t) ceilf((float)1.5*k))%4; + srslte_softbuffer_rx_reset_tbs(&q->softbuffer, grant.mcs.tbs); + } else { + rvidx = dci_unpacked.rv_idx; + srslte_softbuffer_rx_reset_tbs(&q->softbuffer, grant.mcs.tbs); + } + + if (srslte_ue_dl_cfg_grant(q, &grant, cfi, sf_idx, rvidx)) { + return SRSLTE_ERROR; + } + + /* ===== End of MAC functionality ========== */ + + q->nof_detected++; - if (q->pdsch_cfg.grant.mcs.mod > 0 && q->pdsch_cfg.grant.mcs.tbs >= 0) { - ret = srslte_pdsch_decode_rnti(&q->pdsch, &q->pdsch_cfg, &q->softbuffer, - q->sf_symbols, q->ce, - noise_estimate, - rnti, data); + // Uncoment next line to do ZF by default in pdsch_ue example + //float noise_estimate = 0; + float noise_estimate = srslte_chest_dl_get_noise_estimate(&q->chest); - if (ret == SRSLTE_ERROR) { - q->pkt_errors++; - } else if (ret == SRSLTE_ERROR_INVALID_INPUTS) { - fprintf(stderr, "Error calling srslte_pdsch_decode()\n"); - } else if (ret == SRSLTE_SUCCESS) { - if (SRSLTE_VERBOSE_ISDEBUG()) { - INFO("Decoded Message: ", 0); - srslte_vec_fprint_hex(stdout, data, q->pdsch_cfg.grant.mcs.tbs); - } + if (q->pdsch_cfg.grant.mcs.mod > 0 && q->pdsch_cfg.grant.mcs.tbs >= 0) { + ret = srslte_pdsch_decode(&q->pdsch, &q->pdsch_cfg, &q->softbuffer, + q->sf_symbols, q->ce, + noise_estimate, + rnti, data); + + if (ret == SRSLTE_ERROR) { + q->pkt_errors++; + } else if (ret == SRSLTE_ERROR_INVALID_INPUTS) { + fprintf(stderr, "Error calling srslte_pdsch_decode()\n"); + } } - q->pkts_total++; + + /* + printf("Saving signal...\n"); + srslte_vec_save_file("input", input, sizeof(cf_t)*SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); + srslte_ue_dl_save_signal(q, &q->softbuffer, sf_idx, rvidx, rnti, cfi); + //exit(-1); + */ + + } + + q->pkts_total++; + + if (found_dci == 1 && ret == SRSLTE_SUCCESS) { + return q->pdsch_cfg.grant.mcs.tbs; + } else { + return 0; } - return ret; } -int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_msg, uint32_t cfi, uint32_t sf_idx, uint16_t rnti) +uint32_t srslte_ue_dl_get_ncce(srslte_ue_dl_t *q) { + return q->last_location.ncce; +} + +static int dci_blind_search(srslte_ue_dl_t *q, dci_blind_search_t *search_space, uint16_t rnti, srslte_dci_msg_t *dci_msg) { - srslte_dci_location_t locations[MAX_CANDIDATES]; - uint32_t nof_locations = srslte_pdcch_ue_locations(&q->pdcch, locations, MAX_CANDIDATES, sf_idx, cfi, rnti); + int ret = SRSLTE_ERROR; uint16_t crc_rem = 0; - if (rnti) { - /* Do not search if an UL DCI is already pending */ - - if (q->pending_ul_dci_rnti == rnti) { - q->pending_ul_dci_rnti = 0; - memcpy(dci_msg, &q->pending_ul_dci_msg, sizeof(srslte_dci_msg_t)); - return 1; - } - - for (uint32_t i=0;ipdcch, dci_msg, &locations[i], SRSLTE_DCI_FORMAT0, &crc_rem)) { + ret = 0; + int i=0; + while (!ret && i < search_space->nof_locations) { + DEBUG("Searching format %s in %d,%d (%d/%d)\n", + srslte_dci_format_string(search_space->format), search_space->loc[i].ncce, search_space->loc[i].L, + i, search_space->nof_locations); + + if (srslte_pdcch_decode_msg(&q->pdcch, dci_msg, &search_space->loc[i], search_space->format, &crc_rem)) { fprintf(stderr, "Error decoding DCI msg\n"); return SRSLTE_ERROR; } - // Check format differentiation - if (dci_msg->format != SRSLTE_DCI_FORMAT0) { - crc_rem = 0; + if (crc_rem == rnti) { + // If searching for Format1A but found Format0 save it for later + if (dci_msg->format == SRSLTE_DCI_FORMAT0 && search_space->format == SRSLTE_DCI_FORMAT1A) + { + q->pending_ul_dci_rnti = crc_rem; + memcpy(&q->pending_ul_dci_msg, dci_msg, sizeof(srslte_dci_msg_t)); + memcpy(&q->last_location_ul, &search_space->loc[i], sizeof(srslte_dci_location_t)); + // Else if we found it, save location and leave + } else if (dci_msg->format == search_space->format) { + ret = 1; + if (dci_msg->format == SRSLTE_DCI_FORMAT0) { + memcpy(&q->last_location_ul, &search_space->loc[i], sizeof(srslte_dci_location_t)); + } else { + memcpy(&q->last_location, &search_space->loc[i], sizeof(srslte_dci_location_t)); + } + } } - DEBUG("Decoded DCI message RNTI: 0x%x\n", crc_rem); - if (crc_rem == rnti) { - memcpy(&q->last_location, &locations[i], sizeof(srslte_dci_location_t)); - } - } - if (crc_rem == rnti) { + i++; + } + } else { + fprintf(stderr, "RNTI not specified\n"); + } + return ret; +} + +int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t *q, uint32_t cfi, uint32_t sf_idx, uint16_t rnti, srslte_dci_msg_t *dci_msg) +{ + if (rnti && cfi > 1 && cfi < 4) { + /* Do not search if an UL DCI is already pending */ + if (q->pending_ul_dci_rnti == rnti) { + q->pending_ul_dci_rnti = 0; + memcpy(dci_msg, &q->pending_ul_dci_msg, sizeof(srslte_dci_msg_t)); return 1; + } + + // Configure and run DCI blind search + dci_blind_search_t search_space; + dci_blind_search_t *current_ss = &search_space; + if (q->current_rnti == rnti) { + current_ss = &q->current_ss_ue[cfi-1][sf_idx]; } else { - return 0; + // If locations are not pre-generated, generate them now + current_ss->nof_locations = srslte_pdcch_ue_locations(&q->pdcch, current_ss->loc, MAX_CANDIDATES_UE, sf_idx, cfi, rnti); } + + srslte_pdcch_set_cfi(&q->pdcch, cfi); + + current_ss->format = SRSLTE_DCI_FORMAT0; + INFO("Searching UL C-RNTI in %d ue locations\n", search_space.nof_locations); + return dci_blind_search(q, current_ss, rnti, dci_msg); } else { return 0; } } -uint32_t srslte_ue_dl_get_ncce(srslte_ue_dl_t *q) { - return q->last_n_cce; -} - -int srslte_ue_dl_find_dl_dci(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_msg, uint32_t cfi, uint32_t sf_idx, uint16_t rnti) +int srslte_ue_dl_find_dl_dci(srslte_ue_dl_t *q, uint32_t cfi, uint32_t sf_idx, uint16_t rnti, srslte_dci_msg_t *dci_msg) { srslte_rnti_type_t rnti_type; if (rnti == SRSLTE_SIRNTI) { @@ -337,94 +416,82 @@ int srslte_ue_dl_find_dl_dci(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_msg, uint3 } else { rnti_type = SRSLTE_RNTI_USER; } - return srslte_ue_dl_find_dl_dci_type(q, dci_msg, cfi, sf_idx, rnti, rnti_type); + return srslte_ue_dl_find_dl_dci_type(q, cfi, sf_idx, rnti, rnti_type, dci_msg); } -int srslte_ue_dl_find_dl_dci_type(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_msg, uint32_t cfi, uint32_t sf_idx, - uint16_t rnti, srslte_rnti_type_t rnti_type) +// Blind search for SI/P/RA-RNTI +static int find_dl_dci_type_siprarnti(srslte_ue_dl_t *q, uint32_t cfi, uint16_t rnti, srslte_dci_msg_t *dci_msg) { - srslte_dci_location_t locations[MAX_CANDIDATES]; - uint32_t nof_locations; - uint32_t nof_formats; - srslte_dci_format_t *formats = NULL; - - /* Generate PDCCH candidates */ - if (rnti_type == SRSLTE_RNTI_SI || rnti_type == SRSLTE_RNTI_PCH || rnti_type == SRSLTE_RNTI_RAR) { - nof_locations = srslte_pdcch_common_locations(&q->pdcch, locations, MAX_CANDIDATES, q->cfi); - formats = common_formats; - nof_formats = nof_common_formats; - } else { - nof_locations = srslte_pdcch_ue_locations(&q->pdcch, locations, MAX_CANDIDATES, sf_idx, q->cfi, rnti); - formats = ue_formats; - nof_formats = nof_ue_formats; - } - - uint16_t crc_rem = 0; - for (int f=0;fcell.nof_prb), locations[i].L, locations[i].ncce); - q->last_n_cce = locations[i].ncce; - if (srslte_pdcch_decode_msg(&q->pdcch, dci_msg, &locations[i], formats[f], &crc_rem)) { - fprintf(stderr, "Error decoding DCI msg\n"); - return SRSLTE_ERROR; + int ret = 0; + // Configure and run DCI blind search + dci_blind_search_t search_space; + search_space.nof_locations = srslte_pdcch_common_locations(&q->pdcch, search_space.loc, MAX_CANDIDATES_COM, cfi); + INFO("Searching SI/P/RA-RNTI in %d common locations, %d formats\n", search_space.nof_locations, nof_common_formats); + // Search for RNTI only if there is room for the common search space + if (search_space.nof_locations > 0) { + for (int f=0;fcell.nof_prb)); - memcpy(&q->last_location, &locations[i], sizeof(srslte_dci_location_t)); - } - if (crc_rem == rnti && dci_msg->format == SRSLTE_DCI_FORMAT0) { - /* Save Format 0 msg. Recovered next call to srslte_ue_dl_find_ul_dci() */ - q->pending_ul_dci_rnti = crc_rem; - memcpy(&q->pending_ul_dci_msg, dci_msg, sizeof(srslte_dci_msg_t)); - crc_rem = 0; - } - DEBUG("Decoded DCI message RNTI: 0x%x\n", crc_rem); } - } - if (crc_rem == rnti) { - return 1; - } else { - INFO("Couldn't find any DCI for RNTI=0x%x\n", rnti); - return 0; } + return SRSLTE_SUCCESS; } - -int srslte_ue_dl_decode_rnti_rv(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, uint16_t rnti, uint32_t rvidx) +// Blind search for C-RNTI +static int find_dl_dci_type_crnti(srslte_ue_dl_t *q, uint32_t cfi, uint32_t sf_idx, uint16_t rnti, srslte_dci_msg_t *dci_msg) { - srslte_dci_msg_t dci_msg; - srslte_ra_dl_dci_t dci_unpacked; - srslte_ra_dl_grant_t grant; - int ret = SRSLTE_ERROR; + int ret = SRSLTE_SUCCESS; + dci_blind_search_t search_space; + dci_blind_search_t *current_ss = &search_space; - if ((ret = srslte_ue_dl_decode_fft_estimate(q, input, sf_idx, &q->cfi)) < 0) { - return ret; + // Search UE-specific search space + if (q->current_rnti == rnti) { + current_ss = &q->current_ss_ue[cfi-1][sf_idx]; + } else { + // If locations are not pre-generated, generate them now + current_ss->nof_locations = srslte_pdcch_ue_locations(&q->pdcch, current_ss->loc, MAX_CANDIDATES_UE, sf_idx, cfi, rnti); } - if (srslte_pdcch_extract_llr(&q->pdcch, q->sf_symbols, q->ce, srslte_chest_dl_get_noise_estimate(&q->chest), sf_idx, q->cfi)) { - fprintf(stderr, "Error extracting LLRs\n"); - return SRSLTE_ERROR; - } - - int found_dci = srslte_ue_dl_find_dl_dci(q, &dci_msg, q->cfi, sf_idx, rnti); - if (found_dci == 1) { - - if (srslte_dci_msg_to_dl_grant(&dci_msg, rnti, q->cell.nof_prb, q->cell.nof_ports, &dci_unpacked, &grant)) { - fprintf(stderr, "Error unpacking DCI\n"); - return SRSLTE_ERROR; + srslte_pdcch_set_cfi(&q->pdcch, cfi); + + INFO("Searching DL C-RNTI in %d ue locations, %d formats\n", current_ss->nof_locations, nof_ue_formats); + for (int f=0;fformat = ue_formats[f]; + if ((ret = dci_blind_search(q, current_ss, rnti, dci_msg))) { + return ret; } - - ret = srslte_ue_dl_decode_rnti_rv_packet(q, &grant, data, q->cfi, sf_idx, rnti, rvidx); } - - if (found_dci == 1 && ret == SRSLTE_SUCCESS) { - return q->pdsch_cfg.grant.mcs.tbs; + + // Search Format 1A in the Common SS also + if (q->current_rnti == rnti) { + current_ss = &q->current_ss_common[cfi-1]; } else { - return 0; + // If locations are not pre-generated, generate them now + current_ss->nof_locations = srslte_pdcch_common_locations(&q->pdcch, current_ss->loc, MAX_CANDIDATES_COM, cfi); } + + srslte_pdcch_set_cfi(&q->pdcch, cfi); + + // Search for RNTI only if there is room for the common search space + if (current_ss->nof_locations > 0) { + current_ss->format = SRSLTE_DCI_FORMAT1A; + INFO("Searching DL C-RNTI in %d ue locations, format 1A\n", current_ss->nof_locations); + return dci_blind_search(q, current_ss, rnti, dci_msg); + } + return SRSLTE_SUCCESS; } +int srslte_ue_dl_find_dl_dci_type(srslte_ue_dl_t *q, uint32_t cfi, uint32_t sf_idx, + uint16_t rnti, srslte_rnti_type_t rnti_type, srslte_dci_msg_t *dci_msg) +{ + if (rnti_type == SRSLTE_RNTI_SI || rnti_type == SRSLTE_RNTI_PCH || rnti_type == SRSLTE_RNTI_RAR) { + return find_dl_dci_type_siprarnti(q, cfi, rnti, dci_msg); + } else { + return find_dl_dci_type_crnti(q, cfi, sf_idx, rnti, dci_msg); + } +} bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t n_prb_lowest, uint32_t n_dmrs) { @@ -432,8 +499,9 @@ bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t n_pr float distance; uint32_t ngroup, nseq; srslte_phich_calc(&q->phich, n_prb_lowest, n_dmrs, &ngroup, &nseq); - DEBUG("Decoding PHICH sf_idx=%d, n_prb_lowest=%d, n_dmrs=%d, n_group=%d, n_seq=%d\n", - sf_idx, n_prb_lowest, n_dmrs, ngroup, nseq); + INFO("Decoding PHICH sf_idx=%d, n_prb_lowest=%d, n_dmrs=%d, n_group=%d, n_seq=%d, Ngroups=%d, Nsf=%d\n", + sf_idx, n_prb_lowest, n_dmrs, ngroup, nseq, + srslte_phich_ngroups(&q->phich), srslte_phich_nsf(&q->phich)); if (!srslte_phich_decode(&q->phich, q->sf_symbols, q->ce, 0, ngroup, nseq, sf_idx, &ack_bit, &distance)) { INFO("Decoded PHICH %d with distance %f\n", ack_bit, distance); } else { @@ -447,7 +515,7 @@ bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t n_pr } } -void srslte_ue_dl_save_signal(srslte_ue_dl_t *q, srslte_softbuffer_rx_t *softbuffer, uint32_t tti, uint32_t rv_idx, uint16_t rnti) { +void srslte_ue_dl_save_signal(srslte_ue_dl_t *q, srslte_softbuffer_rx_t *softbuffer, uint32_t tti, uint32_t rv_idx, uint16_t rnti, uint32_t cfi) { srslte_vec_save_file("sf_symbols", q->sf_symbols, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t)); printf("%d samples\n", SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)); srslte_vec_save_file("ce0", q->ce[0], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t)); @@ -475,7 +543,7 @@ void srslte_ue_dl_save_signal(srslte_ue_dl_t *q, srslte_softbuffer_rx_t *softbuf snprintf(tmpstr,64,"rmout_%d.dat",i); srslte_vec_save_file(tmpstr, softbuffer->buffer_f[i], (3*cb_len+12)*sizeof(int16_t)); } - printf("Saved files for tti=%d, sf=%d, cfi=%d, mcs=%d, rv=%d, rnti=%d\n", tti, tti%10, q->cfi, + printf("Saved files for tti=%d, sf=%d, cfi=%d, mcs=%d, rv=%d, rnti=0x%x\n", tti, tti%10, cfi, q->pdsch_cfg.grant.mcs.idx, rv_idx, rnti); } diff --git a/srslte/lib/ue/ue_sync.c b/srslte/lib/ue/ue_sync.c index d04c5c303..6ef05daff 100644 --- a/srslte/lib/ue/ue_sync.c +++ b/srslte/lib/ue/ue_sync.c @@ -44,7 +44,7 @@ cf_t dummy[MAX_TIME_OFFSET]; #define TRACK_MAX_LOST 4 #define TRACK_FRAME_SIZE 32 #define FIND_NOF_AVG_FRAMES 4 -#define DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD 5 +#define DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD 0 #define DEFAULT_SFO_EMA_COEFF 0.1 cf_t dummy_offset_buffer[1024*1024]; @@ -358,7 +358,6 @@ static int track_peak_ok(srslte_ue_sync_t *q, uint32_t track_idx) { { INFO("Warning: Expected SF idx %d but got %d! (%d frames)\n", q->sf_idx, srslte_sync_get_sf_idx(&q->strack), q->frame_no_cnt); - q->sf_idx = srslte_sync_get_sf_idx(&q->strack); q->frame_no_cnt++; if (q->frame_no_cnt >= TRACK_MAX_LOST) { INFO("\n%d frames lost. Going back to FIND\n", (int) q->frame_no_cnt); @@ -396,11 +395,12 @@ static int track_peak_ok(srslte_ue_sync_t *q, uint32_t track_idx) { } q->mean_sfo = SRSLTE_VEC_EMA(q->mean_sample_offset, q->mean_sfo, q->sfo_ema); - INFO("Time offset adjustment: %d samples (%.2f), mean SFO: %.2f Hz, %.5f samples/5-sf, ema=%f, length=%d\n", + if (q->next_rf_sample_offset) { + INFO("Time offset adjustment: %d samples (%.2f), mean SFO: %.2f Hz, %.5f samples/5-sf, ema=%f, length=%d\n", q->next_rf_sample_offset, q->mean_sample_offset, srslte_ue_sync_get_sfo(q), q->mean_sfo, q->sfo_ema, q->sample_offset_correct_period); - + } q->mean_sample_offset = 0; } @@ -451,7 +451,7 @@ static int receive_samples(srslte_ue_sync_t *q, cf_t *input_buffer) { if (q->next_rf_sample_offset < 0) { q->next_rf_sample_offset = -q->next_rf_sample_offset; } - + /* Get N subframes from the USRP getting more samples and keeping the previous samples, if any */ if (q->recv_callback(q->stream, &input_buffer[q->next_rf_sample_offset], q->frame_len - q->next_rf_sample_offset, &q->last_timestamp) < 0) { return SRSLTE_ERROR; @@ -529,7 +529,7 @@ int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer) { break; case SRSLTE_SYNC_FOUND_NOSPACE: /* If a peak was found but there is not enough space for SSS/CP detection, discard a few samples */ - printf("No space for SSS/CP detection. Realigning frame...\n"); + INFO("No space for SSS/CP detection. Realigning frame...\n",0); q->recv_callback(q->stream, dummy_offset_buffer, q->frame_len/2, NULL); srslte_sync_reset(&q->sfind); ret = SRSLTE_SUCCESS; @@ -605,14 +605,12 @@ int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer) { } q->frame_total_cnt++; - } else { - if (q->correct_cfo) { - srslte_cfo_correct(&q->sfind.cfocorr, + } + if (q->correct_cfo) { + srslte_cfo_correct(&q->sfind.cfocorr, input_buffer, input_buffer, - -srslte_sync_get_cfo(&q->strack) / q->fft_size); - - } + -srslte_sync_get_cfo(&q->strack) / q->fft_size); } break; } diff --git a/srslte/lib/ue/ue_ul.c b/srslte/lib/ue/ue_ul.c index 1e5d7a51f..2b05e2df1 100644 --- a/srslte/lib/ue/ue_ul.c +++ b/srslte/lib/ue/ue_ul.c @@ -65,6 +65,8 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q, goto clean_exit; } + srslte_cfo_set_tol(&q->cfo, 0); + if (srslte_pusch_init(&q->pusch, q->cell)) { fprintf(stderr, "Error creating PUSCH object\n"); goto clean_exit; @@ -218,64 +220,22 @@ int srslte_ue_ul_cfg_grant(srslte_ue_ul_t *q, srslte_ra_ul_grant_t *grant, return srslte_pusch_cfg(&q->pusch, &q->pusch_cfg, grant, &q->uci_cfg, &q->hopping_cfg, &q->srs_cfg, tti, rvidx, current_tx_nb); } -int pucch_encode_bits(srslte_uci_data_t *uci_data, srslte_pucch_format_t *format, - uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS], uint8_t pucch2_bits[2], - srslte_cp_t cp) +// Encode bits from uci_data +void pucch_encode_bits(srslte_uci_data_t *uci_data, srslte_pucch_format_t format, + uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS], + uint8_t pucch2_bits[SRSLTE_PUCCH_MAX_BITS]) { - int ret = SRSLTE_SUCCESS; - - // No CQI data - if (uci_data->uci_cqi_len == 0) { - // 1-bit ACK + optional SR - if (uci_data->uci_ack_len == 1) { - *format = SRSLTE_PUCCH_FORMAT_1A; - pucch_bits[0] = uci_data->uci_ack; - } - // 2-bit ACK + optional SR - else if (uci_data->uci_ack_len == 2) { - *format = SRSLTE_PUCCH_FORMAT_1B; - pucch_bits[0] = uci_data->uci_ack; - pucch_bits[1] = uci_data->uci_ack_2; - } - // SR only - else if (uci_data->scheduling_request) { - *format = SRSLTE_PUCCH_FORMAT_1; - } else { - ret = SRSLTE_ERROR; - } + if (format == SRSLTE_PUCCH_FORMAT_1A || format == SRSLTE_PUCCH_FORMAT_1B) { + pucch_bits[0] = uci_data->uci_ack; + pucch_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 1a } - // CQI data - else { + if (format >= SRSLTE_PUCCH_FORMAT_2) { srslte_uci_encode_cqi_pucch(uci_data->uci_cqi, uci_data->uci_cqi_len, pucch_bits); - // CQI and no ack - if (uci_data->uci_ack_len == 0) { - *format = SRSLTE_PUCCH_FORMAT_2; - } - // CQI + 1-bit ACK - else if (uci_data->uci_cqi_len > 0 && uci_data->uci_ack_len == 1) { - *format = SRSLTE_PUCCH_FORMAT_2A; + if (format > SRSLTE_PUCCH_FORMAT_2) { pucch2_bits[0] = uci_data->uci_ack; + pucch2_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 2a } - // CQI + 2-bit ACK - else if (uci_data->uci_cqi_len > 0 && uci_data->uci_ack_len == 2) { - *format = SRSLTE_PUCCH_FORMAT_2B; - pucch2_bits[0] = uci_data->uci_ack; - pucch2_bits[1] = uci_data->uci_ack_2; - } - // CQI + 2-bit ACK + cyclic prefix - else if (uci_data->uci_cqi_len > 0 && uci_data->uci_ack_len == 1 && SRSLTE_CP_ISEXT(cp)) { - *format = SRSLTE_PUCCH_FORMAT_2B; - pucch2_bits[0] = uci_data->uci_ack; - pucch2_bits[1] = uci_data->uci_ack_2; - } else { - ret = SRSLTE_ERROR; - } - } - if (ret) { - fprintf(stderr, "Unsupported combination of UCI parameters: ack_len=%d, cqi_len=%d\n", - uci_data->uci_ack, uci_data->uci_cqi_len); } - return ret; } /* Choose PUCCH format as in Sec 10.1 of 36.213 and generate PUCCH signal @@ -301,35 +261,25 @@ int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data, bzero(pucch_bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t)); bzero(pucch2_bits, 2*sizeof(uint8_t)); + srslte_pucch_format_t format = srslte_pucch_get_format(&uci_data, q->cell.cp); + // Encode UCI information - if (pucch_encode_bits(&uci_data, &q->last_pucch_format, pucch_bits, pucch2_bits, q->cell.cp)) { - return SRSLTE_ERROR; - } + pucch_encode_bits(&uci_data, format, pucch_bits, pucch2_bits); // Choose n_pucch - uint32_t n_pucch = 0; - if (uci_data.scheduling_request) { - n_pucch = q->pucch_sched.n_pucch_sr; - } else if (q->last_pucch_format < SRSLTE_PUCCH_FORMAT_2) { - if (q->pucch_sched.sps_enabled) { - n_pucch = q->pucch_sched.n_pucch_1[q->pucch_sched.tpc_for_pucch%4]; - } else { - n_pucch = pdcch_n_cce + q->pucch_sched.N_pucch_1; - } - } else { - n_pucch = q->pucch_sched.n_pucch_2; - } - if (srslte_pucch_encode(&q->pucch, q->last_pucch_format, n_pucch, sf_idx, pucch_bits, q->sf_symbols)) { + uint32_t n_pucch = srslte_pucch_get_npucch(pdcch_n_cce, format, uci_data.scheduling_request, &q->pucch_sched); + + if (srslte_pucch_encode(&q->pucch, format, n_pucch, sf_idx, pucch_bits, q->sf_symbols)) { fprintf(stderr, "Error encoding TB\n"); return ret; } - if (srslte_refsignal_dmrs_pucch_gen(&q->signals, q->last_pucch_format, n_pucch, sf_idx, pucch2_bits, q->refsignal)) + if (srslte_refsignal_dmrs_pucch_gen(&q->signals, format, n_pucch, sf_idx, pucch2_bits, q->refsignal)) { fprintf(stderr, "Error generating PUSCH DRMS signals\n"); return ret; } - srslte_refsignal_dmrs_pucch_put(&q->signals, q->last_pucch_format, n_pucch, q->refsignal, q->sf_symbols); + srslte_refsignal_dmrs_pucch_put(&q->signals, format, n_pucch, q->refsignal, q->sf_symbols); if (srslte_ue_ul_srs_tx_enabled(&q->signals.srs_cfg, tti) && q->pucch.shortened) { if (q->signals_pregenerated) { @@ -339,6 +289,8 @@ int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data, srslte_refsignal_srs_put(&q->signals, tti, q->srs_signal, q->sf_symbols); } } + + q->last_pucch_format = format; srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal); @@ -434,13 +386,15 @@ int srslte_ue_ul_pusch_encode_rnti_softbuffer(srslte_ue_ul_t *q, { int ret = SRSLTE_ERROR_INVALID_INPUTS; - bzero(q->sf_symbols, sizeof(cf_t)*SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)); if (q != NULL && softbuffer != NULL && output_signal != NULL) { - if (srslte_pusch_uci_encode_rnti(&q->pusch, &q->pusch_cfg, softbuffer, data, uci_data, rnti, q->sf_symbols)) { + + bzero(q->sf_symbols, sizeof(cf_t)*SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)); + + if (srslte_pusch_encode(&q->pusch, &q->pusch_cfg, softbuffer, data, uci_data, rnti, q->sf_symbols)) { fprintf(stderr, "Error encoding TB\n"); return ret; } diff --git a/srslte/lib/utils/vector.c b/srslte/lib/utils/vector.c index 77c674ba0..469320177 100644 --- a/srslte/lib/utils/vector.c +++ b/srslte/lib/utils/vector.c @@ -729,6 +729,17 @@ int16_t srslte_vec_max_star_si(int16_t *x, uint32_t len) { #endif } +int16_t srslte_vec_max_abs_star_si(int16_t *x, uint32_t len) { + uint32_t i; + int16_t m=-INT16_MIN; + for (i=0;im) { + m=abs(x[i]); + } + } + return m; +} + void srslte_vec_max_fff(float *x, float *y, float *z, uint32_t len) { #ifdef HAVE_VOLK_MAX_VEC_FUNCTION volk_32f_x2_max_32f(z,x,y,len); diff --git a/srslte/lib/utils/vector_simd.c b/srslte/lib/utils/vector_simd.c index 1612f2c07..8fee71f21 100644 --- a/srslte/lib/utils/vector_simd.c +++ b/srslte/lib/utils/vector_simd.c @@ -223,8 +223,8 @@ void srslte_vec_lut_sss_simd(short *x, unsigned short *lut, short *y, uint32_t l __m128i xVal, lutVal; for(;number < points; number++){ - xVal = _mm_load_si128(xPtr); - lutVal = _mm_load_si128(lutPtr); + xVal = _mm_loadu_si128(xPtr); + lutVal = _mm_loadu_si128(lutPtr); for (int i=0;i<8;i++) { int16_t x = (int16_t) _mm_extract_epi16(xVal, i);