Merge branch 'next' into 2rx

master
Ismael Gomez 8 years ago
commit 92fd049cd0

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

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

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

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

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

@ -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 <immintrin.h>
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 <immintrin.h>
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)
mark_as_advanced(HAVE_SSE, HAVE_AVX, HAVE_AVX2)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -51,8 +51,6 @@
#include "srslte/config.h"
#define SRSLTE_UE_UL_NOF_HARQ_PROCESSES 8
/* UE UL power control */
typedef struct {
// Common configuration

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

@ -36,58 +36,46 @@ add_subdirectory(scrambling)
add_subdirectory(ue)
add_subdirectory(enb)
add_library(srslte SHARED version.c
$<TARGET_OBJECTS:srslte_agc>
$<TARGET_OBJECTS:srslte_ch_estimation>
$<TARGET_OBJECTS:srslte_common>
$<TARGET_OBJECTS:srslte_fec>
$<TARGET_OBJECTS:srslte_mimo>
$<TARGET_OBJECTS:srslte_phch>
$<TARGET_OBJECTS:srslte_sync>
$<TARGET_OBJECTS:srslte_utils>
$<TARGET_OBJECTS:srslte_channel>
$<TARGET_OBJECTS:srslte_dft>
$<TARGET_OBJECTS:srslte_io>
$<TARGET_OBJECTS:srslte_modem>
$<TARGET_OBJECTS:srslte_resampling>
$<TARGET_OBJECTS:srslte_scrambling>
$<TARGET_OBJECTS:srslte_ue>
$<TARGET_OBJECTS:srslte_enb>
$<TARGET_OBJECTS:srslte_rf>
set(srslte_srcs version.c
$<TARGET_OBJECTS:srslte_agc>
$<TARGET_OBJECTS:srslte_ch_estimation>
$<TARGET_OBJECTS:srslte_common>
$<TARGET_OBJECTS:srslte_fec>
$<TARGET_OBJECTS:srslte_mimo>
$<TARGET_OBJECTS:srslte_phch>
$<TARGET_OBJECTS:srslte_sync>
$<TARGET_OBJECTS:srslte_utils>
$<TARGET_OBJECTS:srslte_channel>
$<TARGET_OBJECTS:srslte_dft>
$<TARGET_OBJECTS:srslte_io>
$<TARGET_OBJECTS:srslte_modem>
$<TARGET_OBJECTS:srslte_resampling>
$<TARGET_OBJECTS:srslte_scrambling>
$<TARGET_OBJECTS:srslte_ue>
$<TARGET_OBJECTS:srslte_enb>
)
if(NOT DisableMEX)
add_library(srslte_static STATIC version.c
$<TARGET_OBJECTS:srslte_agc>
$<TARGET_OBJECTS:srslte_ch_estimation>
$<TARGET_OBJECTS:srslte_common>
$<TARGET_OBJECTS:srslte_fec>
$<TARGET_OBJECTS:srslte_mimo>
$<TARGET_OBJECTS:srslte_phch>
$<TARGET_OBJECTS:srslte_sync>
$<TARGET_OBJECTS:srslte_utils>
$<TARGET_OBJECTS:srslte_channel>
$<TARGET_OBJECTS:srslte_dft>
$<TARGET_OBJECTS:srslte_io>
$<TARGET_OBJECTS:srslte_modem>
$<TARGET_OBJECTS:srslte_resampling>
$<TARGET_OBJECTS:srslte_scrambling>
$<TARGET_OBJECTS:srslte_ue>
$<TARGET_OBJECTS:srslte_enb>
$<TARGET_OBJECTS:srslte_rf>
)
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)

@ -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;l<nsymbols;l++) {
srslte_conv_same_cf(&input[l*nref], q->smooth_filter, &output[l*nref], nref, q->smooth_filter_len);
}

@ -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;i<n_rs;i++) {
srslte_vec_sum_ccc(&q->pilot_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;i<SRSLTE_CP_NSYMB(q->cell.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;
}

@ -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;m<N_rs;m++) {
uint32_t n_oc=0;
uint32_t l = get_pucch_dmrs_symbol(m, format, q->cell.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;n<SRSLTE_NRE;n++) {
r_pucch[(ns%2)*SRSLTE_NRE*N_rs+m*SRSLTE_NRE+n] = z_m*cexpf(I*(w[m]+q->tmp_arg[n]+alpha*n));
}
} else {
return SRSLTE_ERROR;
}
for (uint32_t n=0;n<SRSLTE_NRE;n++) {
r_pucch[(ns%2)*SRSLTE_NRE*N_rs+m*SRSLTE_NRE+n] = z_m*cexpf(I*(w[m]+q->tmp_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;i<N_rs;i++) {
uint32_t l = get_pucch_dmrs_symbol(i, format, q->cell.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;bp<b;bp++) {
prod_1 *= Nb[srsbwtable_idx(nof_prb)][bp][cfg->bw_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;bp<b;bp++) {
prod_1 *= Nb[srsbwtable_idx(nof_prb)][bp][cfg->bw_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;
}

@ -178,7 +178,7 @@ int main(int argc, char **argv) {
/* Generate random input */
bzero(input, sizeof(cf_t) * num_re);
for (i=0;i<num_re;i++) {
input[i] = 0.5-rand()/RAND_MAX+I*(0.5-rand()/RAND_MAX);
input[i] = 0.5-rand()/RAND_MAX+I*(0.5-(float) rand()/RAND_MAX);
}
/* Generate channel and pass input through channel */

@ -131,13 +131,13 @@ int main(int argc, char **argv) {
srslte_refsignal_dmrs_pusch_gen(&refs, nof_prb, sf_idx, cshift_dmrs, signal);
gettimeofday(&t[2], NULL);
get_time_interval(t);
printf("DMRS ExecTime: %d us\n", t[0].tv_usec);
printf("DMRS ExecTime: %ld us\n", t[0].tv_usec);
gettimeofday(&t[1], NULL);
srslte_refsignal_srs_gen(&refs, sf_idx, signal);
gettimeofday(&t[2], NULL);
get_time_interval(t);
printf("SRS ExecTime: %d us\n", t[0].tv_usec);
printf("SRS ExecTime: %ld us\n", t[0].tv_usec);
}
}
}

@ -372,39 +372,40 @@ struct lte_band {
float fd_low_mhz;
uint32_t earfcn_offset;
uint32_t earfcn_max;
float duplex_mhz;
enum band_geographical_area area;
};
struct lte_band lte_bands[SRSLTE_NOF_LTE_BANDS] = {
{1, 2110, 0, 599, SRSLTE_BAND_GEO_AREA_ALL},
{2, 1930, 600, 1199, SRSLTE_BAND_GEO_AREA_NAR},
{3, 1805, 1200, 1949, SRSLTE_BAND_GEO_AREA_ALL},
{4, 2110, 1950, 2399, SRSLTE_BAND_GEO_AREA_NAR},
{5, 869, 2400, 2649, SRSLTE_BAND_GEO_AREA_NAR},
{6, 875, 2650, 2749, SRSLTE_BAND_GEO_AREA_APAC},
{7, 2620, 2750, 3449, SRSLTE_BAND_GEO_AREA_EMEA},
{8, 925, 3450, 3799, SRSLTE_BAND_GEO_AREA_ALL},
{9, 1844.9, 3800, 4149, SRSLTE_BAND_GEO_AREA_APAC},
{10, 2110, 4150, 4749, SRSLTE_BAND_GEO_AREA_NAR},
{11, 1475.9, 4750, 4949, SRSLTE_BAND_GEO_AREA_JAPAN},
{12, 729, 5010, 5179, SRSLTE_BAND_GEO_AREA_NAR},
{13, 746, 5180, 5279, SRSLTE_BAND_GEO_AREA_NAR},
{14, 758, 5280, 5379, SRSLTE_BAND_GEO_AREA_NAR},
{17, 734, 5730, 5849, SRSLTE_BAND_GEO_AREA_NAR},
{18, 860, 5850, 5999, SRSLTE_BAND_GEO_AREA_JAPAN},
{19, 875, 6000, 6149, SRSLTE_BAND_GEO_AREA_JAPAN},
{20, 791, 6150, 6449, SRSLTE_BAND_GEO_AREA_EMEA},
{21, 1495.9, 6450, 6599, SRSLTE_BAND_GEO_AREA_JAPAN},
{22, 3500, 6600, 7399, SRSLTE_BAND_GEO_AREA_NA},
{23, 2180, 7500, 7699, SRSLTE_BAND_GEO_AREA_NAR},
{24, 1525, 7700, 8039, SRSLTE_BAND_GEO_AREA_NAR},
{25, 1930, 8040, 8689, SRSLTE_BAND_GEO_AREA_NAR},
{26, 859, 8690, 9039, SRSLTE_BAND_GEO_AREA_NAR},
{27, 852, 9040, 9209, SRSLTE_BAND_GEO_AREA_NAR},
{28, 758, 9210, 9659, SRSLTE_BAND_GEO_AREA_APAC},
{29, 717, 9660, 9769, SRSLTE_BAND_GEO_AREA_NAR},
{30, 2350, 9770, 9869, SRSLTE_BAND_GEO_AREA_NAR},
{31, 462.5, 9870, 9919, SRSLTE_BAND_GEO_AREA_CALA}
{1, 2110, 0, 599, 190, SRSLTE_BAND_GEO_AREA_ALL},
{2, 1930, 600, 1199, 80, SRSLTE_BAND_GEO_AREA_NAR},
{3, 1805, 1200, 1949, 95, SRSLTE_BAND_GEO_AREA_ALL},
{4, 2110, 1950, 2399, 400, SRSLTE_BAND_GEO_AREA_NAR},
{5, 869, 2400, 2649, 45, SRSLTE_BAND_GEO_AREA_NAR},
{6, 875, 2650, 2749, 45, SRSLTE_BAND_GEO_AREA_APAC},
{7, 2620, 2750, 3449, 120, SRSLTE_BAND_GEO_AREA_EMEA},
{8, 925, 3450, 3799, 45, SRSLTE_BAND_GEO_AREA_ALL},
{9, 1844.9, 3800, 4149, 95, SRSLTE_BAND_GEO_AREA_APAC},
{10, 2110, 4150, 4749, 400, SRSLTE_BAND_GEO_AREA_NAR},
{11, 1475.9, 4750, 4949, 48, SRSLTE_BAND_GEO_AREA_JAPAN},
{12, 729, 5010, 5179, 30, SRSLTE_BAND_GEO_AREA_NAR},
{13, 746, 5180, 5279, -31, SRSLTE_BAND_GEO_AREA_NAR},
{14, 758, 5280, 5379, -30, SRSLTE_BAND_GEO_AREA_NAR},
{17, 734, 5730, 5849, 30, SRSLTE_BAND_GEO_AREA_NAR},
{18, 860, 5850, 5999, 45, SRSLTE_BAND_GEO_AREA_JAPAN},
{19, 875, 6000, 6149, 45, SRSLTE_BAND_GEO_AREA_JAPAN},
{20, 791, 6150, 6449, -41, SRSLTE_BAND_GEO_AREA_EMEA},
{21, 1495.9, 6450, 6599, 48, SRSLTE_BAND_GEO_AREA_JAPAN},
{22, 3500, 6600, 7399, 100, SRSLTE_BAND_GEO_AREA_NA},
{23, 2180, 7500, 7699, 180, SRSLTE_BAND_GEO_AREA_NAR},
{24, 1525, 7700, 8039, -101.5, SRSLTE_BAND_GEO_AREA_NAR},
{25, 1930, 8040, 8689, 80, SRSLTE_BAND_GEO_AREA_NAR},
{26, 859, 8690, 9039, 45, SRSLTE_BAND_GEO_AREA_NAR},
{27, 852, 9040, 9209, 45, SRSLTE_BAND_GEO_AREA_NAR},
{28, 758, 9210, 9659, 55, SRSLTE_BAND_GEO_AREA_APAC},
{29, 717, 9660, 9769, 0, SRSLTE_BAND_GEO_AREA_NAR},
{30, 2350, 9770, 9869, 45, SRSLTE_BAND_GEO_AREA_NAR},
{31, 462.5, 9870, 9919, 10, SRSLTE_BAND_GEO_AREA_CALA}
};
#define EOF_BAND 9919
@ -429,17 +430,35 @@ float get_fd(struct lte_band *band, uint32_t earfcn) {
}
}
int srslte_band_get_band(uint32_t earfcn) {
uint32_t i = SRSLTE_NOF_LTE_BANDS-1;
while(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<earfcn) {
i++;
if (earfcn > 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(&lte_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(&lte_bands[i], earfcn);
return get_fd(&lte_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) {

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

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

@ -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;i<SRSLTE_SIRNTI;i++) {
if (q->users[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);
}

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

@ -22,7 +22,7 @@ void partab_init(void) {
while (ti) {
if (ti & 1)
cnt++;
ti >>= 1;
ti >>= 1;
}
Partab[i] = cnt & 1;
}

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

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

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

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

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

@ -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<num_bits/mod.nbits_x_symbol;i++) {
if (symbols[i] != symbols_bytes[i]) {
printf("error in symbol %d\n", i);
@ -183,8 +183,8 @@ int main(int argc, char **argv) {
gettimeofday(&x, NULL);
srslte_demod_soft_demodulate(modulation, symbols, llr, num_bits / mod.nbits_x_symbol);
gettimeofday(&y, NULL);
printf("\nElapsed time [ns]: %d\n", (int) y.tv_usec - (int) x.tv_usec);
printf("\nElapsed time [ns]: %ld\n", (int) y.tv_usec - (int) x.tv_usec);
for (i=0;i<num_bits;i++) {
output[i] = llr[i]>=0 ? 1 : 0;
}

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

@ -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(i<nof_bits && y[1+i] == 1)
i++;
if (i == nof_bits) {
printf("Warning check me: could this be a RA PDCCH order??\n");
//printf("Warning check me: could this be a RA PDCCH order??\n");
i=1+10+nof_bits;
while(i<msg->nof_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;

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

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

@ -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;n<q->nof_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;u<SRSLTE_SIRNTI;u++) {
if (q->users[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;i<cfg->nbits.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;

@ -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;j<n_wins;j++) {
if(p->peak_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;
}

@ -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;i<N_sf;i++) {
uint32_t l = get_pucch_symbol(i, format, q->cell.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;m<N_sf;m++) {
uint32_t l = get_pucch_symbol(m, format, q->cell.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;n<SRSLTE_PUCCH_N_SEQ;n++) {
z[(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;n<SRSLTE_PUCCH_N_SEQ;n++) {
z[(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));
}
}
}
}
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;m<N_sf;m++) {
uint32_t l = get_pucch_symbol(m, format, q->cell.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;n<SRSLTE_PUCCH_N_SEQ;n++) {
q->z[(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;n<SRSLTE_PUCCH_N_SEQ;n++) {
q->z[(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;
}

@ -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;rnti<SRSLTE_SIRNTI;rnti++) {
srslte_pusch_clear_rnti(q, rnti);
}
free(q->users);
}
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;
}
}

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

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

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

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

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#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");
}

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

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

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

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

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

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

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

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

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

@ -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(nframe<nof_frames) {
printf("Rx subframe %d\n", nframe);
srslte_rf_recv_with_time(&uhd, &buffer[flen*nframe], flen, true, &tstamp.full_secs, &tstamp.frac_secs);
srslte_rf_recv_with_time(&rf, &buffer[flen*nframe], flen, true, &tstamp.full_secs, &tstamp.frac_secs);
nframe++;
if (nframe==9 || nframe==8) {
srslte_timestamp_add(&tstamp, 0, 2e-3-timeadv*1e-6);
if (nframe==8) {
srslte_rf_send_timed2(&uhd, zeros, flen, tstamp.full_secs, tstamp.frac_secs, true, false);
srslte_rf_send_timed2(&rf, zeros, flen, tstamp.full_secs, tstamp.frac_secs, true, false);
printf("Transmitting zeros\n");
} else {
srslte_rf_send_timed2(&uhd, preamble, flen, tstamp.full_secs, tstamp.frac_secs, true, true);
srslte_rf_send_timed2(&rf, preamble, flen, tstamp.full_secs, tstamp.frac_secs, false, true);
printf("Transmitting PRACH\n");
}
}
}
if (f) {
fwrite(buffer, 11*flen*sizeof(cf_t), 1, f);
uint32_t indices[1024];
float offsets[1024];
uint32_t nof_detected;
if (srslte_prach_detect_offset(p, frequency_offset, &buffer[flen*10+p->N_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<nof_detected;i++) {
printf("%d/%d index=%d, offset=%.2f us (%d samples)\n",
i, nof_detected, indices[i], offsets[i]*1e6, (int) (offsets[i]*srate));
}
srslte_vec_save_file(output_filename,buffer,11*flen*sizeof(cf_t));
srslte_prach_free(p);
free(p);

@ -36,7 +36,6 @@
srslte_cell_t cell = {
25, // nof_prb
1, // nof_ports
2, // bw_idx = 5 MHz
1, // cell_id
SRSLTE_CP_NORM, // cyclic prefix
SRSLTE_PHICH_R_1_6, // PHICH resources
@ -90,11 +89,11 @@ int main(int argc, char **argv) {
if (srslte_pucch_init(&pucch, cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
goto quit;
exit(-1);
}
if (srslte_refsignal_ul_init(&dmrs, cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
goto quit;
exit(-1);
}
bzero(&pucch_cfg, sizeof(srslte_pucch_cfg_t));
@ -156,7 +155,7 @@ int main(int argc, char **argv) {
}
gettimeofday(&t[2], NULL);
get_time_interval(t);
INFO("format %d, n_pucch: %d, ncs: %d, d: %d, t_exec=%d us\n", format, n_pucch, ncs, d, t[0].tv_usec);
INFO("format %d, n_pucch: %d, ncs: %d, d: %d, t_exec=%ld us\n", format, n_pucch, ncs, d, t[0].tv_usec);
}
}
}

@ -0,0 +1,225 @@
/**
*
* \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 <string.h>
#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;
}

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

@ -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<cfg.grant.mcs.tbs/8;i++) {
@ -208,13 +209,13 @@ int main(int argc, char **argv) {
uint32_t ntrials = 100;
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);
}
if (rv_idx > 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) {

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

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

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

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

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

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

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

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

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

@ -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;i<seq.len;i++) {
if (scrambled_b[i] != input_b[i]) {
@ -164,7 +164,7 @@ int main(int argc, char **argv) {
srslte_scrambling_f(&seq, scrambled_f);
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;i<seq.len;i++) {
if (scrambled_f[i] != input_f[i]) {

@ -62,7 +62,7 @@ void srslte_cfo_free(srslte_cfo_t *h) {
if (h->cur_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) {

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

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

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

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

@ -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;i<nof_locations && crc_rem != rnti;i++) {
if (srslte_pdcch_decode_msg(&q->pdcch, 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;f<nof_formats && crc_rem != rnti;f++) {
for (int i=0;i<nof_locations && crc_rem != rnti;i++) {
DEBUG("Trying format %s (nbits=%d), location L=%d, ncce=%d\n", srslte_dci_format_string(formats[f]),
srslte_dci_format_sizeof_lut(formats[f], q->cell.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;f<nof_common_formats;f++) {
search_space.format = common_formats[f];
if ((ret = dci_blind_search(q, &search_space, rnti, dci_msg))) {
return ret;
}
if (crc_rem == rnti) {
INFO("Found DCI nCCE: %d, L: %d, n_bits=%d\n", locations[i].ncce, locations[i].L, srslte_dci_format_sizeof_lut(formats[f], q->cell.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;f<nof_ue_formats;f++) {
current_ss->format = 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);
}

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

Loading…
Cancel
Save