Added CQI support. Restored ue_ul normalization

master
ismagom 9 years ago
parent 510e4c892e
commit dc15e99906

@ -1,10 +1,10 @@
enbConfig=struct('NCellID',1,'CyclicPrefix','Normal','CellRefP',1); enbConfig=struct('NCellID',1,'CyclicPrefix','Normal','CellRefP',1);
pdschConfig=struct('Modulation','QPSK','RV',0,'TxScheme','Port0'); pdschConfig=struct('Modulation','QPSK','RV',0,'TxScheme','Port0');
addpath('../../debug/srslte/lib/phch/test') addpath('/home/ismael/work/srsLTE/debug/srslte/lib/phch/test')
TBs=1:111:15000; TBs=40:8:800;
e_bits=10000; e_bits=1000;
error=zeros(size(TBs)); error=zeros(size(TBs));
for i=1:length(TBs) for i=1:length(TBs)
trblkin=randi(2,TBs(i),1)-1; trblkin=randi(2,TBs(i),1)-1;

@ -51,7 +51,7 @@ cec.InterpType = 'linear'; % 2D interpolation type
cec.InterpWindow = 'Centered'; % Interpolation window type cec.InterpWindow = 'Centered'; % Interpolation window type
cec.InterpWinSize = 1; % Interpolation window size cec.InterpWinSize = 1; % Interpolation window size
addpath('../../debug/srslte/lib/phch/test') addpath('../../build/srslte/lib/phch/test')
decoded = zeros(size(SNR_values)); decoded = zeros(size(SNR_values));
decoded_srslte = zeros(size(SNR_values)); decoded_srslte = zeros(size(SNR_values));

@ -1,6 +1,6 @@
clear clear
ueConfig=struct('NCellID',1,'RNTI',11,'NULRB',6,'NSubframe',1,'CyclicPrefixUL','Normal','NTxAnts',1,'Hopping','Group'); ueConfig=struct('NCellID',1,'RNTI',11,'NULRB',25,'NSubframe',0,'CyclicPrefixUL','Normal','NTxAnts',1,'Hopping','Off');
pucchConfig=struct('NLayers',1,'OrthCover','Off','Shortened',1,'ResourceSize',0); pucchConfig=struct('NLayers',1,'OrthCover','Off','Shortened',0,'ResourceSize',2);
addpath('../../build/srslte/lib/phch/test') addpath('../../build/srslte/lib/phch/test')
@ -11,56 +11,59 @@ for f=0:5
for n=0:7:130 for n=0:7:130
for d=1:3 for d=1:3
for ncs=0:d:7 for ncs=0:d:7
pucchConfig.ResourceIdx= n; for nsf=0:9
pucchConfig.DeltaShift = d; pucchConfig.ResourceIdx= n;
pucchConfig.CyclicShifts = ncs; pucchConfig.DeltaShift = d;
if (f >= 3) pucchConfig.CyclicShifts = ncs;
nb=20; ueConfig.NSubframe=nsf;
nb_ack=f-3; if (f >= 3)
else nb=20;
nb=f; nb_ack=f-3;
nb_ack=0; else
end nb=f;
bits=randi(2,nb,1)-1; nb_ack=0;
bits_ack=randi(2,nb_ack,1)-1; end
fprintf('Testing PUCCH Format: %s, n_pucch=%d, DeltaShift=%d, CyclicShift=%d\n',format_str{f+1},n,d,ncs); bits=mod(0:nb-1,2);
if (f >= 3) bits_ack=randi(2,nb_ack,1)-1;
[sym_mat, info]=ltePUCCH2(ueConfig,pucchConfig,bits); fprintf('Testing PUCCH Format: %s, n_pucch=%d, DeltaShift=%d, CyclicShift=%d, Nsf=%d\n',format_str{f+1},n,d,ncs,nsf);
idx=ltePUCCH2Indices(ueConfig,pucchConfig); if (f >= 3)
[dmrs_mat, info_dmrs]=ltePUCCH2DRS(ueConfig,pucchConfig,bits_ack); [sym_mat, info]=ltePUCCH2(ueConfig,pucchConfig,bits);
idx_dmrs=ltePUCCH2DRSIndices(ueConfig,pucchConfig); idx=ltePUCCH2Indices(ueConfig,pucchConfig);
else [dmrs_mat, info_dmrs]=ltePUCCH2DRS(ueConfig,pucchConfig,bits_ack);
[sym_mat, info]=ltePUCCH1(ueConfig,pucchConfig,bits); idx_dmrs=ltePUCCH2DRSIndices(ueConfig,pucchConfig);
idx=ltePUCCH1Indices(ueConfig,pucchConfig); else
[dmrs_mat, info_dmrs]=ltePUCCH1DRS(ueConfig,pucchConfig); [sym_mat, info]=ltePUCCH1(ueConfig,pucchConfig,bits);
idx_dmrs=ltePUCCH1DRSIndices(ueConfig,pucchConfig); idx=ltePUCCH1Indices(ueConfig,pucchConfig);
end [dmrs_mat, info_dmrs]=ltePUCCH1DRS(ueConfig,pucchConfig);
subframe_mat = lteULResourceGrid(ueConfig); idx_dmrs=ltePUCCH1DRSIndices(ueConfig,pucchConfig);
subframe_mat(idx)=sym_mat; end
subframe_mat(idx_dmrs)=dmrs_mat; subframe_mat = lteULResourceGrid(ueConfig);
subframe_mat(idx)=sym_mat;
subframe_mat(idx_dmrs)=dmrs_mat;
[sym, dmrs, subframe]=srslte_pucch_encode(ueConfig,pucchConfig,[bits; bits_ack]); [sym, dmrs, subframe]=srslte_pucch_encode(ueConfig,pucchConfig,[bits; bits_ack]);
error_sym=max(abs(sym-sym_mat));
error_dmrs=max(abs(dmrs-dmrs_mat));
error_sf=max(abs(subframe_mat(:)-subframe));
k=k+1;
if (error_sym > 1e-5) error_sym=max(abs(sym-sym_mat));
disp(info) error_dmrs=max(abs(dmrs-dmrs_mat));
plot(1:length(sym),sym,1:length(sym_mat),sym_mat) error_sf=max(abs(subframe_mat(:)-subframe));
legend('srsLTE','Matlab') k=k+1;
error('Error in symbols');
end if (error_sym > 1e-5)
if (error_dmrs > 1e-5) disp(info)
disp(info_dmrs) plot(1:length(sym),sym,1:length(sym_mat),sym_mat)
plot(angle(dmrs)-angle(dmrs_mat)) legend('srsLTE','Matlab')
error('Error in DMRS'); error('Error in symbols');
end end
if (error_sf > 1e-5) if (error_dmrs > 1e-5)
disp(info) disp(info_dmrs)
plot(abs(subframe-subframe_mat(:))) plot(angle(dmrs)-angle(dmrs_mat))
error('Error in subframe'); error('Error in DMRS');
end
if (error_sf > 1e-5)
disp(info)
plot(abs(subframe-subframe_mat(:)))
error('Error in subframe');
end
end end
end end
end end

@ -1,14 +1,14 @@
ueConfig=struct('NCellID',1,'NULRB',25,'RNTI',64,'CyclicPrefixUL','Normal','NTxAnts',1,'Shortened',0); ueConfig=struct('NCellID',1,'NULRB',6,'RNTI',64,'CyclicPrefixUL','Normal','NTxAnts',1,'Shortened',0,'Hopping','Off','SeqGroup',0,'CyclicShift',0);
puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',(0:23)','Shortened',0); puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',0,'Shortened',0,'DynCyclicShift',0);
addpath('../../build/srslte/lib/phch/test') addpath('../../debug/srslte/lib/phch/test')
TBs=9144; TBs=336;
cqilen=0; cqilen=20;
rvs=0; rvs=0;
mods={'16QAM'}; mods={'16QAM'};
betas=0; betas=5;
subf=5; subf=0;
for i=1:length(TBs) for i=1:length(TBs)
for m=1:length(mods) for m=1:length(mods)
@ -19,7 +19,7 @@ for i=1:length(TBs)
for c=1:length(cqilen) for c=1:length(cqilen)
for s=1:length(subf) for s=1:length(subf)
fprintf('Subf=%d, RV=%d\n', subf(s), rvs(r)); fprintf('Subf=%d, RV=%d\n', subf(s), rvs(r));
trblkin=[0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; trblkin=mod(0:TBs(i)-1,2);
ueConfig.NSubframe=subf(s); ueConfig.NSubframe=subf(s);
puschConfig.Modulation = mods{m}; puschConfig.Modulation = mods{m};
puschConfig.RV = rvs(r); puschConfig.RV = rvs(r);
@ -28,7 +28,7 @@ for i=1:length(TBs)
puschConfig.BetaACK = betas(back); puschConfig.BetaACK = betas(back);
if (betas(bri)>0) if (betas(bri)>0)
ri_bit=randi(2,1,1)-1; ri_bit=randi(2,1,1)-1;
else else
ri_bit=[]; ri_bit=[];
end end
@ -39,20 +39,25 @@ for i=1:length(TBs)
end end
if (cqilen(c)>0 || TBs(i)>0) if (cqilen(c)>0 || TBs(i)>0)
[cw, info]=lteULSCH(ueConfig,puschConfig,trblkin); [enc, info]=lteULSCH(ueConfig,puschConfig,trblkin,ones(1,cqilen(c)),ri_bit,ack_bit);
cw_mat=ltePUSCH(ueConfig,puschConfig,cw); cw_mat=ltePUSCH(ueConfig,puschConfig,enc);
[drs, infodrs]=ltePUSCHDRS(ueConfig,puschConfig); %[drs, infodrs]=ltePUSCHDRS(ueConfig,puschConfig);
idx=ltePUSCHIndices(ueConfig,puschConfig); idx=ltePUSCHIndices(ueConfig,puschConfig);
drs_idx=ltePUSCHDRSIndices(ueConfig,puschConfig); %drs_idx=ltePUSCHDRSIndices(ueConfig,puschConfig);
subframe_mat = lteULResourceGrid(ueConfig); subframe_mat = lteULResourceGrid(ueConfig);
subframe_mat(idx)=cw_mat; subframe_mat(idx)=cw_mat;
subframe_mat(drs_idx)=drs; %subframe_mat(drs_idx)=drs;
waveform = lteSCFDMAModulate(ueConfig,subframe_mat,0); waveform = lteSCFDMAModulate(ueConfig,subframe_mat,0);
[waveform_lib, subframe_lib, cwlib]=srslte_pusch_encode(ueConfig,puschConfig,trblkin,ones(1,cqilen(c)),ri_bit,ack_bit); cw_scram=lteULScramble(enc,0,1,64);
err=max(abs(waveform/0.2041-waveform_lib)); %
[waveform_lib, subframe_lib, cwlib, bits]=srslte_pusch_encode(ueConfig,puschConfig,trblkin,ones(1,cqilen(c)),ri_bit,ack_bit);
err=max(abs(waveform-waveform_lib));
if (err > 10^-5) if (err > 10^-5)
disp(err) disp(err)
t=1:200;
%plot(t,bits(t),t,cw_scram(t))
plot(abs(double(bits)-double(cw_scram)))
error('Error!'); error('Error!');
end end
end end

@ -4,7 +4,7 @@ blen=5184;
SNR_values_db=linspace(-1.3,-0.7,6); SNR_values_db=linspace(-1.3,-0.7,6);
Nrealizations=600; Nrealizations=600;
addpath('../../debug/lte/phy/lib/fec/test') addpath('../../build/srslte/lib/fec/test')
errors1=zeros(1,length(SNR_values_db)); errors1=zeros(1,length(SNR_values_db));
errors2=zeros(1,length(SNR_values_db)); errors2=zeros(1,length(SNR_values_db));

@ -1,14 +1,14 @@
clear clear
ueConfig=struct('NCellID',1,'CyclicPrefixUL','Normal','NTxAnts',1); ueConfig=struct('NCellID',1,'CyclicPrefixUL','Normal','NTxAnts',1);
puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',22,'Shortened',1); puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',0,'Shortened',0);
addpath('../../build/srslte/lib/phch/test') addpath('../../debug/srslte/lib/phch/test')
TBs=336; TBs=336;
cqilen=0; cqilen=0;
mods={'16QAM'}; mods={'16QAM'};
rvs=0; rvs=0;
betas=0; betas=5;
for i=1:length(TBs) for i=1:length(TBs)
@ -23,7 +23,7 @@ for i=1:length(TBs)
puschConfig.Modulation = mods{m}; puschConfig.Modulation = mods{m};
puschConfig.RV = rvs(r); puschConfig.RV = rvs(r);
puschConfig.BetaCQI = betas(bcqi); puschConfig.BetaCQI = 5;
puschConfig.BetaRI = betas(bri); puschConfig.BetaRI = betas(bri);
puschConfig.BetaACK = betas(back); puschConfig.BetaACK = betas(back);
@ -46,6 +46,7 @@ for i=1:length(TBs)
err=sum(abs(double(mat)-double(lib))); err=sum(abs(double(mat)-double(lib)));
if (err > 0) if (err > 0)
disp(err) disp(err)
plot(abs(double(mat)-double(lib)))
error('Error!'); error('Error!');
end end
end end

@ -109,6 +109,8 @@ SRSLTE_API int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q,
SRSLTE_API float srslte_chest_dl_get_noise_estimate(srslte_chest_dl_t *q); SRSLTE_API float srslte_chest_dl_get_noise_estimate(srslte_chest_dl_t *q);
SRSLTE_API float srslte_chest_dl_get_snr(srslte_chest_dl_t *q);
SRSLTE_API float srslte_chest_dl_get_rssi(srslte_chest_dl_t *q); SRSLTE_API float srslte_chest_dl_get_rssi(srslte_chest_dl_t *q);
SRSLTE_API float srslte_chest_dl_get_rsrq(srslte_chest_dl_t *q); SRSLTE_API float srslte_chest_dl_get_rsrq(srslte_chest_dl_t *q);

@ -41,18 +41,24 @@
#include "srslte/config.h" #include "srslte/config.h"
#include "srslte/common/phy_common.h" #include "srslte/common/phy_common.h"
#define SRSLTE_CQI_MAX_BITS 20
typedef struct { typedef struct {
bool configured; bool configured;
uint32_t pmi_idx; uint32_t pmi_idx;
} srslte_cqi_cfg_t; bool simul_cqi_ack;
bool format_is_subband;
uint32_t subband_size;
} srslte_cqi_periodic_cfg_t;
/* Table 5.2.2.6.2-1: Fields for channel quality information feedback for higher layer configured subband /* Table 5.2.2.6.2-1: Fields for channel quality information feedback for higher layer configured subband
CQI reports CQI reports
(transmission mode 1, transmission mode 2, transmission mode 3, transmission mode 7 and (transmission mode 1, transmission mode 2, transmission mode 3, transmission mode 7 and
transmission mode 8 configured without PMI/RI reporting). */ transmission mode 8 configured without PMI/RI reporting). */
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
uint8_t wideband_cqi; // 4-bit width uint8_t wideband_cqi; // 4-bit width
uint32_t subband_diff_cqi; // 2N-bit width uint32_t subband_diff_cqi; // 2N-bit width
uint32_t N;
} srslte_cqi_hl_subband_t; } srslte_cqi_hl_subband_t;
/* Table 5.2.2.6.3-1: Fields for channel quality information feedback for UE selected subband CQI /* Table 5.2.2.6.3-1: Fields for channel quality information feedback for UE selected subband CQI
@ -60,9 +66,10 @@ reports
(transmission mode 1, transmission mode 2, transmission mode 3, transmission mode 7 and (transmission mode 1, transmission mode 2, transmission mode 3, transmission mode 7 and
transmission mode 8 configured without PMI/RI reporting). */ transmission mode 8 configured without PMI/RI reporting). */
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
uint8_t wideband_cqi; // 4-bit width uint8_t wideband_cqi; // 4-bit width
uint8_t subband_diff_cqi; // 2-bit width uint8_t subband_diff_cqi; // 2-bit width
uint32_t position_subband; // L-bit width uint32_t position_subband; // L-bit width
uint32_t L;
} srslte_cqi_ue_subband_t; } srslte_cqi_ue_subband_t;
/* Table 5.2.3.3.1-1: Fields for channel quality information feedback for wideband CQI reports /* Table 5.2.3.3.1-1: Fields for channel quality information feedback for wideband CQI reports
@ -71,34 +78,51 @@ transmission mode 8 configured without PMI/RI reporting).
This is for PUCCH Format 2 reports This is for PUCCH Format 2 reports
*/ */
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
uint8_t wideband_cqi; // 4-bit width uint8_t wideband_cqi; // 4-bit width
} srslte_cqi_format2_wideband_t; } srslte_cqi_format2_wideband_t;
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
uint8_t subband_cqi; // 4-bit width uint8_t subband_cqi; // 4-bit width
uint8_t subband_label; // 1- or 2-bit width uint8_t subband_label; // 1- or 2-bit width
bool subband_label_2_bits; // false, label=1-bit, true label=2-bits
} srslte_cqi_format2_subband_t; } srslte_cqi_format2_subband_t;
typedef enum {
SRSLTE_CQI_TYPE_WIDEBAND = 0,
SRSLTE_CQI_TYPE_SUBBAND,
SRSLTE_CQI_TYPE_SUBBAND_UE,
SRSLTE_CQI_TYPE_SUBBAND_HL
} srslte_cqi_type_t;
typedef struct {
union {
srslte_cqi_format2_wideband_t wideband;
srslte_cqi_format2_subband_t subband;
srslte_cqi_ue_subband_t subband_ue;
srslte_cqi_hl_subband_t subband_hl;
};
srslte_cqi_type_t type;
} srslte_cqi_value_t;
SRSLTE_API int srslte_cqi_value_pack(srslte_cqi_value_t *value,
uint8_t buff[SRSLTE_CQI_MAX_BITS]);
SRSLTE_API int srslte_cqi_hl_subband_pack(srslte_cqi_hl_subband_t *msg, SRSLTE_API int srslte_cqi_hl_subband_pack(srslte_cqi_hl_subband_t *msg,
uint32_t N, uint8_t buff[SRSLTE_CQI_MAX_BITS]);
uint8_t *buff,
uint32_t buff_len);
SRSLTE_API int srslte_cqi_ue_subband_pack(srslte_cqi_ue_subband_t *msg, SRSLTE_API int srslte_cqi_ue_subband_pack(srslte_cqi_ue_subband_t *msg,
uint32_t L, uint8_t buff[SRSLTE_CQI_MAX_BITS]);
uint8_t *buff,
uint32_t buff_len);
SRSLTE_API int srslte_cqi_format2_wideband_pack(srslte_cqi_format2_wideband_t *msg, SRSLTE_API int srslte_cqi_format2_wideband_pack(srslte_cqi_format2_wideband_t *msg,
uint8_t *buff, uint8_t buff[SRSLTE_CQI_MAX_BITS]);
uint32_t buff_len);
SRSLTE_API int srslte_cqi_format2_subband_pack(srslte_cqi_format2_subband_t *msg, SRSLTE_API int srslte_cqi_format2_subband_pack(srslte_cqi_format2_subband_t *msg,
uint8_t *buff, uint8_t buff[SRSLTE_CQI_MAX_BITS]);
uint32_t buff_len);
SRSLTE_API bool srslte_cqi_send(uint32_t I_cqi_pmi, SRSLTE_API bool srslte_cqi_send(uint32_t I_cqi_pmi,
uint32_t tti); uint32_t tti);
SRSLTE_API uint8_t srslte_cqi_from_snr(float snr);
#endif // CQI_ #endif // CQI_

@ -40,9 +40,10 @@
#include "srslte/common/phy_common.h" #include "srslte/common/phy_common.h"
#include "srslte/common/sequence.h" #include "srslte/common/sequence.h"
#include "srslte/modem/mod.h" #include "srslte/modem/mod.h"
#include "srslte/phch/cqi.h"
#define SRSLTE_PUCCH_N_SEQ 12 #define SRSLTE_PUCCH_N_SEQ 12
#define SRSLTE_PUCCH_MAX_BITS 20 #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 { typedef enum SRSLTE_API {

@ -75,6 +75,7 @@ typedef struct SRSLTE_API {
srslte_crc_t crc_cb; srslte_crc_t crc_cb;
srslte_uci_cqi_pusch_t uci_cqi; srslte_uci_cqi_pusch_t uci_cqi;
srslte_uci_pos_t uci_pos;
} srslte_sch_t; } srslte_sch_t;

@ -40,11 +40,15 @@
#include "srslte/common/phy_common.h" #include "srslte/common/phy_common.h"
#include "srslte/phch/pusch_cfg.h" #include "srslte/phch/pusch_cfg.h"
#include "srslte/fec/crc.h" #include "srslte/fec/crc.h"
#include "srslte/phch/cqi.h"
#define SRSLTE_UCI_MAX_CQI_LEN_PUSCH 512 #define SRSLTE_UCI_MAX_CQI_LEN_PUSCH 512
#define SRSLTE_UCI_MAX_CQI_LEN_PUCCH 13 #define SRSLTE_UCI_MAX_CQI_LEN_PUCCH 13
#define SRSLTE_UCI_CQI_CODED_PUCCH_B 20 #define SRSLTE_UCI_CQI_CODED_PUCCH_B 20
#define SRSLTE_UCI_ACK_RI_PLACEHOLDER_REPETITION 0xC0
#define SRSLTE_UCI_ACK_RI_PLACEHOLDER 0x30
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
srslte_crc_t crc; srslte_crc_t crc;
uint8_t tmp_cqi[SRSLTE_UCI_MAX_CQI_LEN_PUSCH]; uint8_t tmp_cqi[SRSLTE_UCI_MAX_CQI_LEN_PUSCH];
@ -52,7 +56,7 @@ typedef struct SRSLTE_API {
} srslte_uci_cqi_pusch_t; } srslte_uci_cqi_pusch_t;
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
uint8_t *uci_cqi; uint8_t uci_cqi[SRSLTE_CQI_MAX_BITS];
uint32_t uci_cqi_len; uint32_t uci_cqi_len;
uint8_t uci_ri; // Only 1-bit supported for RI uint8_t uci_ri; // Only 1-bit supported for RI
uint32_t uci_ri_len; uint32_t uci_ri_len;
@ -63,6 +67,11 @@ typedef struct SRSLTE_API {
bool channel_selection; bool channel_selection;
} srslte_uci_data_t; } srslte_uci_data_t;
typedef struct {
uint32_t idx;
uint32_t pos[SRSLTE_UCI_MAX_CQI_LEN_PUSCH];
} srslte_uci_pos_t;
SRSLTE_API int srslte_uci_cqi_init(srslte_uci_cqi_pusch_t *q); SRSLTE_API int srslte_uci_cqi_init(srslte_uci_cqi_pusch_t *q);
SRSLTE_API void srslte_uci_cqi_free(srslte_uci_cqi_pusch_t *q); SRSLTE_API void srslte_uci_cqi_free(srslte_uci_cqi_pusch_t *q);
@ -80,6 +89,7 @@ SRSLTE_API int srslte_uci_encode_cqi_pucch(uint8_t *cqi_data,
uint8_t b_bits[SRSLTE_UCI_CQI_CODED_PUCCH_B]); uint8_t b_bits[SRSLTE_UCI_CQI_CODED_PUCCH_B]);
SRSLTE_API int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, SRSLTE_API int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg,
srslte_uci_pos_t *pos,
uint8_t data, uint8_t data,
uint32_t O_cqi, uint32_t O_cqi,
float beta, float beta,

@ -49,11 +49,6 @@ SRSLTE_API void srslte_scrambling_b_offset(srslte_sequence_t *s,
int offset, int offset,
int len); int len);
SRSLTE_API void srslte_scrambling_b_offset_pusch(srslte_sequence_t *s,
uint8_t *data,
int offset,
int len);
SRSLTE_API void srslte_scrambling_f(srslte_sequence_t *s, SRSLTE_API void srslte_scrambling_f(srslte_sequence_t *s,
float *data); float *data);
@ -70,5 +65,4 @@ SRSLTE_API void srslte_scrambling_c_offset(srslte_sequence_t *s,
int offset, int offset,
int len); int len);
#endif // SCRAMBLING_ #endif // SCRAMBLING_

@ -380,6 +380,10 @@ float srslte_chest_dl_get_noise_estimate(srslte_chest_dl_t *q) {
return srslte_vec_acc_ff(q->noise_estimate, q->cell.nof_ports)/q->cell.nof_ports; return srslte_vec_acc_ff(q->noise_estimate, q->cell.nof_ports)/q->cell.nof_ports;
} }
float srslte_chest_dl_get_snr(srslte_chest_dl_t *q) {
return srslte_chest_dl_get_rsrp(q)/srslte_chest_dl_get_noise_estimate(q);
}
float srslte_chest_dl_get_rssi(srslte_chest_dl_t *q) { float srslte_chest_dl_get_rssi(srslte_chest_dl_t *q) {
return 4*q->rssi[0]/q->cell.nof_prb/SRSLTE_NRE; return 4*q->rssi[0]/q->cell.nof_prb/SRSLTE_NRE;
} }

@ -41,38 +41,53 @@
#include "srslte/utils/debug.h" #include "srslte/utils/debug.h"
int srslte_cqi_hl_subband_pack(srslte_cqi_hl_subband_t *msg, uint32_t N, uint8_t *buff, uint32_t buff_len) int srslte_cqi_hl_subband_pack(srslte_cqi_hl_subband_t *msg, uint8_t buff[SRSLTE_CQI_MAX_BITS])
{ {
uint8_t *body_ptr = buff; uint8_t *body_ptr = buff;
srslte_bit_pack(msg->wideband_cqi, &body_ptr, 4); srslte_bit_pack(msg->wideband_cqi, &body_ptr, 4);
srslte_bit_pack(msg->subband_diff_cqi, &body_ptr, 2*N); srslte_bit_pack(msg->subband_diff_cqi, &body_ptr, 2*msg->N);
return 4+2*N; return 4+2*msg->N;
} }
int srslte_cqi_ue_subband_pack(srslte_cqi_ue_subband_t *msg, uint32_t L, uint8_t *buff, uint32_t buff_len) int srslte_cqi_ue_subband_pack(srslte_cqi_ue_subband_t *msg, uint8_t buff[SRSLTE_CQI_MAX_BITS])
{ {
uint8_t *body_ptr = buff; uint8_t *body_ptr = buff;
srslte_bit_pack(msg->wideband_cqi, &body_ptr, 4); srslte_bit_pack(msg->wideband_cqi, &body_ptr, 4);
srslte_bit_pack(msg->subband_diff_cqi, &body_ptr, 2); srslte_bit_pack(msg->subband_diff_cqi, &body_ptr, 2);
srslte_bit_pack(msg->subband_diff_cqi, &body_ptr, L); srslte_bit_pack(msg->subband_diff_cqi, &body_ptr, msg->L);
return 4+2+L; return 4+2+msg->L;
} }
int srslte_cqi_format2_wideband_pack(srslte_cqi_format2_wideband_t *msg, uint8_t *buff, uint32_t buff_len) int srslte_cqi_format2_wideband_pack(srslte_cqi_format2_wideband_t *msg, uint8_t buff[SRSLTE_CQI_MAX_BITS])
{ {
uint8_t *body_ptr = buff; uint8_t *body_ptr = buff;
srslte_bit_pack(msg->wideband_cqi, &body_ptr, 4); srslte_bit_pack(msg->wideband_cqi, &body_ptr, 4);
return 4; return 4;
} }
int srslte_cqi_format2_subband_pack(srslte_cqi_format2_subband_t *msg, uint8_t *buff, uint32_t buff_len) int srslte_cqi_format2_subband_pack(srslte_cqi_format2_subband_t *msg, uint8_t buff[SRSLTE_CQI_MAX_BITS])
{ {
uint8_t *body_ptr = buff; uint8_t *body_ptr = buff;
srslte_bit_pack(msg->subband_cqi, &body_ptr, 4); srslte_bit_pack(msg->subband_cqi, &body_ptr, 4);
srslte_bit_pack(msg->subband_label, &body_ptr, 1); srslte_bit_pack(msg->subband_label, &body_ptr, msg->subband_label_2_bits?2:1);
return 4+1; return 4+msg->subband_label_2_bits?2:1;
}
int srslte_cqi_value_pack(srslte_cqi_value_t *value, uint8_t buff[SRSLTE_CQI_MAX_BITS])
{
switch(value->type) {
case SRSLTE_CQI_TYPE_WIDEBAND:
return srslte_cqi_format2_wideband_pack(&value->wideband, buff);
case SRSLTE_CQI_TYPE_SUBBAND:
return srslte_cqi_format2_subband_pack(&value->subband, buff);
case SRSLTE_CQI_TYPE_SUBBAND_UE:
return srslte_cqi_ue_subband_pack(&value->subband_ue, buff);
case SRSLTE_CQI_TYPE_SUBBAND_HL:
return srslte_cqi_hl_subband_pack(&value->subband_hl, buff);
}
return -1;
} }
bool srslte_cqi_send(uint32_t I_cqi_pmi, uint32_t tti) { bool srslte_cqi_send(uint32_t I_cqi_pmi, uint32_t tti) {
@ -123,3 +138,20 @@ bool srslte_cqi_send(uint32_t I_cqi_pmi, uint32_t tti) {
} }
} }
/* SNR-to-CQI conversion, got from "Downlink SNR to CQI Mapping for Different Multiple Antenna Techniques in LTE"
* Table III.
*/
static float cqi_to_snr_table[15] = { 1.95, 4, 6, 8, 10, 11.95, 14.05, 16, 17.9, 19.9, 21.5, 23.45, 25.0, 27.30, 29};
uint8_t srslte_cqi_from_snr(float snr)
{
for (uint8_t cqi=14;cqi>=0;cqi--) {
if (snr >= cqi_to_snr_table[cqi]) {
return cqi+1;
}
}
return 0;
}

@ -276,8 +276,9 @@ float srslte_pucch_alpha_format2(uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLT
} }
} }
uint32_t n_cs = (n_cs_cell[ns][l]+n_prime)%SRSLTE_NRE; uint32_t n_cs = (n_cs_cell[ns][l]+n_prime)%SRSLTE_NRE;
DEBUG("n_pucch: %d, ns: %d, l: %d, n_prime: %d, n_cs: %d\n", n_pucch, ns, l, n_prime, n_cs); float alpha = 2 * M_PI * (n_cs) / SRSLTE_NRE;
return 2 * M_PI * (n_cs) / SRSLTE_NRE; DEBUG("n_pucch: %d, ns: %d, l: %d, n_prime: %d, n_cs: %d, alpha=%f\n", n_pucch, ns, l, n_prime, n_cs, alpha);
return alpha;
} }
/* Map PUCCH symbols to physical resources according to 5.4.3 in 36.211 */ /* Map PUCCH symbols to physical resources according to 5.4.3 in 36.211 */
@ -358,7 +359,7 @@ void srslte_pucch_free(srslte_pucch_t *q) {
int srslte_pucch_set_crnti(srslte_pucch_t *q, uint16_t c_rnti) { int srslte_pucch_set_crnti(srslte_pucch_t *q, uint16_t c_rnti) {
for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) { for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) {
// Precompute scrambling sequence for pucch format 2 // Precompute scrambling sequence for pucch format 2
if (srslte_sequence_pucch(&q->seq_f2[sf_idx], c_rnti, 2*sf_idx, q->cell.id)) { if (srslte_sequence_pucch(&q->seq_f2[sf_idx], c_rnti, 2*sf_idx, q->cell.id)) {
fprintf(stderr, "Error computing PUCCH Format 2 scrambling sequence\n"); fprintf(stderr, "Error computing PUCCH Format 2 scrambling sequence\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -503,19 +504,18 @@ int srslte_pucch_encode(srslte_pucch_t* q, srslte_pucch_format_t format,
uint32_t N_sf_0 = get_N_sf(format, 0, q->shortened); 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++) { 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); 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 // Get group hopping number u
uint32_t f_gh=0; uint32_t f_gh=0;
if (q->group_hopping_en) { if (q->group_hopping_en) {
f_gh = q->f_gh[ns]; f_gh = q->f_gh[ns];
} }
uint32_t u = (f_gh + (q->cell.id%30))%30; uint32_t u = (f_gh + (q->cell.id%30))%30;
srslte_refsignal_r_uv_arg_1prb(q->tmp_arg, u); srslte_refsignal_r_uv_arg_1prb(q->tmp_arg, u);
uint32_t N_sf_widx = N_sf==3?1:0; uint32_t N_sf_widx = N_sf==3?1:0;
for (uint32_t m=0;m<N_sf;m++) { for (uint32_t m=0;m<N_sf;m++) {
uint32_t l = get_pucch_symbol(m, format, q->cell.cp); uint32_t l = get_pucch_symbol(m, format, q->cell.cp);
uint32_t n_prime_ns;
uint32_t n_oc;
float alpha=0; float alpha=0;
if (format >= SRSLTE_PUCCH_FORMAT_2) { if (format >= SRSLTE_PUCCH_FORMAT_2) {
alpha = srslte_pucch_alpha_format2(q->n_cs_cell, &q->pucch_cfg, n_pucch, ns, l); alpha = srslte_pucch_alpha_format2(q->n_cs_cell, &q->pucch_cfg, n_pucch, ns, l);
@ -523,6 +523,8 @@ int srslte_pucch_encode(srslte_pucch_t* q, srslte_pucch_format_t format,
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)); 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 { } 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); 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; float S_ns = 0;
if (n_prime_ns%2) { if (n_prime_ns%2) {
@ -531,12 +533,12 @@ int srslte_pucch_encode(srslte_pucch_t* q, srslte_pucch_format_t format,
DEBUG("PUCCH d_0: %.1f+%.1fi, alpha: %.1f, n_oc: %d, n_prime_ns: %d, n_rb_2=%d\n", 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); __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++) { 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)); 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, sf_symbols)) {
fprintf(stderr, "Error putting PUCCH symbols\n"); fprintf(stderr, "Error putting PUCCH symbols\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;

@ -242,7 +242,7 @@ int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) {
} }
q->d = srslte_vec_malloc(sizeof(cf_t) * q->max_re); q->d = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->d) { if (!q->d) {
goto clean; goto clean;
} }
q->ce = srslte_vec_malloc(sizeof(cf_t) * q->max_re); q->ce = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
@ -538,11 +538,24 @@ int srslte_pusch_uci_encode_rnti(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srs
if (srslte_sequence_pusch(&seq, rnti, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { if (srslte_sequence_pusch(&seq, rnti, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
srslte_scrambling_b_offset_pusch(&seq, (uint8_t*) q->q, 0, cfg->nbits.nof_bits); srslte_scrambling_b_offset(&seq, (uint8_t*) q->q, 0, cfg->nbits.nof_bits);
srslte_sequence_free(&seq); srslte_sequence_free(&seq);
} else { } else {
srslte_scrambling_b_offset_pusch(&q->seq[cfg->sf_idx], (uint8_t*) q->q, 0, cfg->nbits.nof_bits); srslte_scrambling_b_offset(&q->seq[cfg->sf_idx], (uint8_t*) q->q, 0, cfg->nbits.nof_bits);
}
// Correct UCI placeholder bits
uint8_t *d = q->q;
for (int i = 0; i < q->dl_sch.uci_pos.idx; i++) {
if (d[q->dl_sch.uci_pos.pos[i]] & SRSLTE_UCI_ACK_RI_PLACEHOLDER) {
d[q->dl_sch.uci_pos.pos[i]] = 1;
} else if (d[q->dl_sch.uci_pos.pos[i]] & SRSLTE_UCI_ACK_RI_PLACEHOLDER_REPETITION) {
if (q->dl_sch.uci_pos.pos[i] > 1) {
d[q->dl_sch.uci_pos.pos[i]] = d[q->dl_sch.uci_pos.pos[i]-1];
}
}
} }
srslte_mod_modulate(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->q, q->d, cfg->nbits.nof_bits); srslte_mod_modulate(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->q, q->d, cfg->nbits.nof_bits);
srslte_dft_precoding(&q->dft_precoding, q->d, q->z, cfg->grant.L_prb, cfg->nbits.nof_symb); srslte_dft_precoding(&q->dft_precoding, q->d, q->z, cfg->grant.L_prb, cfg->nbits.nof_symb);

@ -274,9 +274,10 @@ static int encode_tb(srslte_sch_t *q,
/* Turbo Encoding */ /* Turbo Encoding */
srslte_tcod_encode(&q->encoder, q->cb_temp, (uint8_t*) q->cb_out, cb_len); srslte_tcod_encode(&q->encoder, q->cb_temp, (uint8_t*) q->cb_out, cb_len);
if (SRSLTE_VERBOSE_ISDEBUG()) { if (SRSLTE_VERBOSE_ISDEBUG()) {
DEBUG("CB#%d encoded: ", i); DEBUG("CB#%d encoded: ", i);
srslte_vec_fprint_b(stdout, q->cb_out, cb_len); srslte_vec_fprint_b(stdout, q->cb_out, 3*cb_len+12);
} }
} }
@ -496,7 +497,8 @@ int srslte_ulsch_decode(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuf
/* UL-SCH channel interleaver according to 5.5.2.8 of 36.212 */ /* UL-SCH channel interleaver according to 5.5.2.8 of 36.212 */
void ulsch_interleave(uint8_t *g_bits, uint32_t Qm, uint32_t H_prime_total, uint32_t N_pusch_symbs, uint8_t *q_bits) void ulsch_interleave(srslte_uci_pos_t *q, uint8_t *g_bits, uint32_t Qm, uint32_t H_prime_total,
uint32_t N_pusch_symbs, uint8_t *q_bits)
{ {
uint32_t rows = H_prime_total/N_pusch_symbs; uint32_t rows = H_prime_total/N_pusch_symbs;
@ -508,6 +510,11 @@ void ulsch_interleave(uint8_t *g_bits, uint32_t Qm, uint32_t H_prime_total, uint
for(uint32_t k=0; k<Qm; k++) { for(uint32_t k=0; k<Qm; k++) {
if (q_bits[j*Qm + i*rows*Qm + k] >= 10) { if (q_bits[j*Qm + i*rows*Qm + k] >= 10) {
q_bits[j*Qm + i*rows*Qm + k] -= 10; q_bits[j*Qm + i*rows*Qm + k] -= 10;
q->pos[q->idx%SRSLTE_UCI_MAX_CQI_LEN_PUSCH] = j*Qm + i*rows*Qm + k;
q->idx++;
if (q->idx >= SRSLTE_UCI_MAX_CQI_LEN_PUSCH) {
fprintf(stderr, "Error number of UCI bits exceeds SRSLTE_UCI_MAX_CQI_LEN_PUSCH\n");
}
} else { } else {
q_bits[j*Qm + i*rows*Qm + k] = g_bits[idx]; q_bits[j*Qm + i*rows*Qm + k] = g_bits[idx];
idx++; idx++;
@ -569,7 +576,7 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q,
} }
e_offset += Q_prime_cqi*Qm; e_offset += Q_prime_cqi*Qm;
// Encode UL-SCH // Encode UL-SCH
if (cfg->cb_segm.tbs > 0) { if (cfg->cb_segm.tbs > 0) {
uint32_t G = nb_q/Qm - Q_prime_ri - Q_prime_cqi; uint32_t G = nb_q/Qm - Q_prime_ri - Q_prime_cqi;
@ -580,17 +587,18 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q,
return ret; return ret;
} }
} }
// Interleave UL-SCH (and RI and CQI) // Interleave UL-SCH (and RI and CQI)
ulsch_interleave(g_bits, Qm, nb_q/Qm, cfg->nbits.nof_symb, q_bits); q->uci_pos.idx=0;
ulsch_interleave(&q->uci_pos, g_bits, Qm, nb_q/Qm, cfg->nbits.nof_symb, q_bits);
// Encode (and interleave) ACK // Encode (and interleave) ACK
if (uci_data.uci_ack_len > 0) { if (uci_data.uci_ack_len > 0) {
float beta = beta_harq_offset[cfg->uci_cfg.I_offset_ack]; float beta = beta_harq_offset[cfg->uci_cfg.I_offset_ack];
if (cfg->cb_segm.tbs == 0) { if (cfg->cb_segm.tbs == 0) {
beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi]; beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi];
} }
ret = srslte_uci_encode_ack(cfg, uci_data.uci_ack, uci_data.uci_cqi_len, beta, nb_q/Qm, q_bits); ret = srslte_uci_encode_ack(cfg, &q->uci_pos, uci_data.uci_ack, uci_data.uci_cqi_len, beta, nb_q/Qm, q_bits);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }

@ -204,7 +204,7 @@ int srslte_uci_encode_cqi_pucch(uint8_t *cqi_data, uint32_t cqi_len, uint8_t b_b
for (uint32_t i=0;i<SRSLTE_UCI_CQI_CODED_PUCCH_B;i++) { for (uint32_t i=0;i<SRSLTE_UCI_CQI_CODED_PUCCH_B;i++) {
uint64_t x=0; uint64_t x=0;
for (uint32_t n=0;n<cqi_len;n++) { for (uint32_t n=0;n<cqi_len;n++) {
x += cqi_data[n]*M_basis_seq_pucch[n][i]; x += cqi_data[n]*M_basis_seq_pucch[i][n];
} }
b_bits[i] = (uint8_t) (x%2); b_bits[i] = (uint8_t) (x%2);
} }
@ -242,7 +242,7 @@ int srslte_uci_encode_cqi_pusch(srslte_uci_cqi_pusch_t *q, srslte_pusch_cfg_t *c
} }
/* Inserts UCI-ACK bits into the correct positions in the g buffer before interleaving */ /* Inserts UCI-ACK bits into the correct positions in the g buffer before interleaving */
static int uci_ulsch_interleave_ack(uint8_t ack_coded_bits[6], uint32_t ack_q_bit_idx, static int uci_ulsch_interleave_ack(srslte_uci_pos_t *q, uint8_t ack_coded_bits[6], uint32_t ack_q_bit_idx,
uint32_t Qm, uint32_t H_prime_total, uint32_t N_pusch_symbs, srslte_cp_t cp, uint32_t Qm, uint32_t H_prime_total, uint32_t N_pusch_symbs, srslte_cp_t cp,
uint8_t *q_bits) { uint8_t *q_bits) {
@ -255,8 +255,14 @@ static int uci_ulsch_interleave_ack(uint8_t ack_coded_bits[6], uint32_t ack_q_bi
uint32_t colidx = (3*ack_q_bit_idx)%4; uint32_t colidx = (3*ack_q_bit_idx)%4;
uint32_t col = SRSLTE_CP_ISNORM(cp)?ack_column_set_norm[colidx]:ack_column_set_ext[colidx]; uint32_t col = SRSLTE_CP_ISNORM(cp)?ack_column_set_norm[colidx]:ack_column_set_ext[colidx];
for(uint32_t k=0; k<Qm; k++) { for(uint32_t k=0; k<Qm; k++) {
q_bits[row *Qm + q_bits[row *Qm + (H_prime_total/N_pusch_symbs)*col*Qm + k] = ack_coded_bits[k];
(H_prime_total/N_pusch_symbs)*col*Qm + k] = ack_coded_bits[k];
// Save position for placeholder bits
q->pos[q->idx%SRSLTE_UCI_MAX_CQI_LEN_PUSCH] = row *Qm + (H_prime_total/N_pusch_symbs)*col*Qm + k;
q->idx++;
if (q->idx >= SRSLTE_UCI_MAX_CQI_LEN_PUSCH) {
fprintf(stderr, "Error number of UCI bits exceeds SRSLTE_UCI_MAX_CQI_LEN_PUSCH\n");
}
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} else { } else {
@ -278,7 +284,7 @@ static int uci_ulsch_interleave_ri(uint8_t ri_coded_bits[6], uint32_t ri_q_bit_i
uint32_t row = H_prime_total/N_pusch_symbs-1-ri_q_bit_idx/4; uint32_t row = H_prime_total/N_pusch_symbs-1-ri_q_bit_idx/4;
uint32_t colidx = (3*ri_q_bit_idx)%4; uint32_t colidx = (3*ri_q_bit_idx)%4;
uint32_t col = SRSLTE_CP_ISNORM(cp)?ri_column_set_norm[colidx]:ri_column_set_ext[colidx]; uint32_t col = SRSLTE_CP_ISNORM(cp)?ri_column_set_norm[colidx]:ri_column_set_ext[colidx];
printf("r=%d-%d\n",H_prime_total/N_pusch_symbs,1+ri_q_bit_idx/4);
for(uint32_t k=0; k<Qm; k++) { for(uint32_t k=0; k<Qm; k++) {
q_bits[row *Qm + (H_prime_total/N_pusch_symbs)*col*Qm + k] = 10+ri_coded_bits[k]; q_bits[row *Qm + (H_prime_total/N_pusch_symbs)*col*Qm + k] = 10+ri_coded_bits[k];
} }
@ -319,16 +325,16 @@ static uint32_t Q_prime_ri_ack(srslte_pusch_cfg_t *cfg,
static void encode_ri_ack(uint8_t data, uint8_t q_encoded_bits[6], uint8_t Qm) { static void encode_ri_ack(uint8_t data, uint8_t q_encoded_bits[6], uint8_t Qm) {
q_encoded_bits[0] = data; q_encoded_bits[0] = data;
q_encoded_bits[1] = 2; q_encoded_bits[1] = SRSLTE_UCI_ACK_RI_PLACEHOLDER_REPETITION;
for (uint32_t i=2;i<Qm;i++) { for (uint32_t i=2;i<Qm;i++) {
q_encoded_bits[i] = 3; q_encoded_bits[i] = SRSLTE_UCI_ACK_RI_PLACEHOLDER;
} }
} }
/* Encode UCI HARQ/ACK bits as described in 5.2.2.6 of 36.212 /* Encode UCI HARQ/ACK bits as described in 5.2.2.6 of 36.212
* Currently only supporting 1-bit HARQ * Currently only supporting 1-bit HARQ
*/ */
int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, srslte_uci_pos_t *pos,
uint8_t data, uint8_t data,
uint32_t O_cqi, float beta, uint32_t H_prime_total, uint32_t O_cqi, float beta, uint32_t H_prime_total,
uint8_t *q_bits) uint8_t *q_bits)
@ -344,7 +350,7 @@ int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg,
encode_ri_ack(data, q_encoded_bits, cfg->grant.Qm); encode_ri_ack(data, q_encoded_bits, cfg->grant.Qm);
for (uint32_t i=0;i<Qprime;i++) { for (uint32_t i=0;i<Qprime;i++) {
uci_ulsch_interleave_ack(q_encoded_bits, i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, q_bits); uci_ulsch_interleave_ack(pos, q_encoded_bits, i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, q_bits);
} }
return (int) Qprime; return (int) Qprime;

@ -45,7 +45,6 @@ void help()
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{ {
srslte_sch_t dlsch; srslte_sch_t dlsch;
uint8_t *trblkin;
srslte_pdsch_cfg_t cfg; srslte_pdsch_cfg_t cfg;
srslte_softbuffer_tx_t softbuffer; srslte_softbuffer_tx_t softbuffer;
@ -61,13 +60,18 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
srslte_cell_t cell; srslte_cell_t cell;
cell.nof_prb = 100; cell.nof_prb = 100;
cell.id=1; cell.id=1;
srslte_verbose = SRSLTE_VERBOSE_NONE;
cfg.grant.mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin); uint8_t *trblkin_bits = NULL;
cfg.grant.mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin_bits);
if (cfg.grant.mcs.tbs == 0) { if (cfg.grant.mcs.tbs == 0) {
mexErrMsgTxt("Error trblklen is zero\n"); mexErrMsgTxt("Error trblklen is zero\n");
return; return;
} }
uint8_t *trblkin = srslte_vec_malloc(cfg.grant.mcs.tbs/8);
srslte_bit_unpack_vector(trblkin_bits, trblkin, cfg.grant.mcs.tbs);
free(trblkin_bits);
if (mexutils_read_uint32_struct(PUSCHCFG, "RV", &cfg.rv)) { if (mexutils_read_uint32_struct(PUSCHCFG, "RV", &cfg.rv)) {
mexErrMsgTxt("Field RV not found in dlsch config\n"); mexErrMsgTxt("Field RV not found in dlsch config\n");
return; return;

@ -136,6 +136,8 @@ int main(int argc, char **argv) {
bzero(&pdsch_cfg, sizeof(srslte_pdsch_cfg_t)); bzero(&pdsch_cfg, sizeof(srslte_pdsch_cfg_t));
bzero(ce, sizeof(cf_t*)*SRSLTE_MAX_PORTS); bzero(ce, sizeof(cf_t*)*SRSLTE_MAX_PORTS);
bzero(slot_symbols, sizeof(cf_t*)*SRSLTE_MAX_PORTS); bzero(slot_symbols, sizeof(cf_t*)*SRSLTE_MAX_PORTS);
bzero(&softbuffer_rx, sizeof(srslte_softbuffer_rx_t));
bzero(&softbuffer_tx, sizeof(srslte_softbuffer_tx_t));
srslte_ra_dl_grant_t grant; srslte_ra_dl_grant_t grant;
grant.mcs.tbs = tbs; grant.mcs.tbs = tbs;

@ -207,13 +207,17 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
noise_power = srslte_chest_dl_get_noise_estimate(&chest); noise_power = srslte_chest_dl_get_noise_estimate(&chest);
} }
uint8_t *data = malloc(sizeof(uint8_t) * grant.mcs.tbs); uint8_t *data_bytes = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs.tbs/8);
if (!data) { if (!data_bytes) {
return; return;
} }
int r = srslte_pdsch_decode(&pdsch, &cfg, &softbuffer, input_fft, ce, noise_power, data); int r = srslte_pdsch_decode(&pdsch, &cfg, &softbuffer, input_fft, ce, noise_power, data_bytes);
free(data_bytes);
uint8_t *data = malloc(grant.mcs.tbs);
srslte_bit_pack_vector(data_bytes, data, grant.mcs.tbs);
if (nlhs >= 1) { if (nlhs >= 1) {
plhs[0] = mxCreateLogicalScalar(r == 0); plhs[0] = mxCreateLogicalScalar(r == 0);

@ -51,6 +51,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
help(); help();
return; return;
} }
srslte_verbose = SRSLTE_VERBOSE_DEBUG;
srslte_cell_t cell; srslte_cell_t cell;
bzero(&cell, sizeof(srslte_cell_t)); bzero(&cell, sizeof(srslte_cell_t));
@ -96,6 +97,10 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexErrMsgTxt("Field DeltaShift not found in PUCCHCFG\n"); mexErrMsgTxt("Field DeltaShift not found in PUCCHCFG\n");
return; 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)) { if (mexutils_read_uint32_struct(PUCCHCFG, "CyclicShifts", &pucch_cfg.N_cs)) {
mexErrMsgTxt("Field CyclicShifts not found in PUCCHCFG\n"); mexErrMsgTxt("Field CyclicShifts not found in PUCCHCFG\n");
return; return;

@ -35,15 +35,16 @@
#include "srslte/srslte.h" #include "srslte/srslte.h"
srslte_cell_t cell = { srslte_cell_t cell = {
6, // nof_prb 25, // nof_prb
1, // nof_ports 1, // nof_ports
0, // cell_id 2, // bw_idx = 5 MHz
1, // cell_id
SRSLTE_CP_NORM, // cyclic prefix SRSLTE_CP_NORM, // cyclic prefix
SRSLTE_PHICH_SRSLTE_PHICH_R_1_6, // PHICH resources SRSLTE_PHICH_SRSLTE_PHICH_R_1_6, // PHICH resources
SRSLTE_PHICH_NORM // PHICH length SRSLTE_PHICH_NORM // PHICH length
}; };
uint32_t subframe = 1; uint32_t subframe = 0;
void usage(char *prog) { void usage(char *prog) {
printf("Usage: %s [csNnv]\n", prog); printf("Usage: %s [csNnv]\n", prog);
@ -100,14 +101,14 @@ int main(int argc, char **argv) {
bzero(&pucch_cfg, sizeof(srslte_pucch_cfg_t)); bzero(&pucch_cfg, sizeof(srslte_pucch_cfg_t));
for (int i=0;i<SRSLTE_PUCCH_MAX_BITS;i++) { for (int i=0;i<SRSLTE_PUCCH_MAX_BITS;i++) {
bits[i] = rand()%2; bits[i] = i%2;
} }
for (int i=0;i<2;i++) { for (int i=0;i<2;i++) {
pucch2_bits[i] = rand()%2; pucch2_bits[i] = i%2;
} }
if (srslte_pucch_set_crnti(&pucch, 1234)) { if (srslte_pucch_set_crnti(&pucch, 11)) {
fprintf(stderr, "Error setting C-RNTI\n"); fprintf(stderr, "Error setting C-RNTI\n");
goto quit; goto quit;
} }
@ -122,6 +123,12 @@ int main(int argc, char **argv) {
for (uint32_t d=1;d<=3;d++) { for (uint32_t d=1;d<=3;d++) {
for (uint32_t ncs=0;ncs<8;ncs+=d) { for (uint32_t ncs=0;ncs<8;ncs+=d) {
for (uint32_t n_pucch=1;n_pucch<130;n_pucch++) { for (uint32_t n_pucch=1;n_pucch<130;n_pucch++) {
format=SRSLTE_PUCCH_FORMAT_2;
uint32_t d=2;
uint32_t ncs=0;
uint32_t n_pucch=0;
struct timeval t[3]; struct timeval t[3];

@ -54,7 +54,8 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
help(); help();
return; return;
} }
srslte_verbose = SRSLTE_VERBOSE_DEBUG;
srslte_cell_t cell; srslte_cell_t cell;
bzero(&cell, sizeof(srslte_cell_t)); bzero(&cell, sizeof(srslte_cell_t));
cell.nof_ports = 1; cell.nof_ports = 1;
@ -123,8 +124,12 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
grant.n_prb[1] = prbset[0]; grant.n_prb[1] = prbset[0];
free(prbset); free(prbset);
uint8_t *trblkin = NULL; uint8_t *trblkin_bits = NULL;
grant.mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin); grant.mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin_bits);
uint8_t *trblkin = srslte_vec_malloc(grant.mcs.tbs/8);
srslte_bit_unpack_vector(trblkin_bits, trblkin, grant.mcs.tbs);
free(trblkin_bits);
grant.M_sc = grant.L_prb*SRSLTE_NRE; grant.M_sc = grant.L_prb*SRSLTE_NRE;
grant.M_sc_init = grant.M_sc; // FIXME: What should M_sc_init be? grant.M_sc_init = grant.M_sc; // FIXME: What should M_sc_init be?
@ -156,8 +161,10 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
srslte_uci_data_t uci_data; srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t)); bzero(&uci_data, sizeof(srslte_uci_data_t));
uci_data.uci_cqi_len = mexutils_read_uint8(CQI, &uci_data.uci_cqi);
uint8_t *tmp; uint8_t *tmp;
uci_data.uci_cqi_len = mexutils_read_uint8(CQI, &tmp);
memcpy(&uci_data.uci_cqi, tmp, uci_data.uci_cqi_len);
free(tmp);
uci_data.uci_ri_len = mexutils_read_uint8(RI, &tmp); uci_data.uci_ri_len = mexutils_read_uint8(RI, &tmp);
if (uci_data.uci_ri_len > 0) { if (uci_data.uci_ri_len > 0) {
uci_data.uci_ri = *tmp; uci_data.uci_ri = *tmp;
@ -229,9 +236,11 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
if (nlhs >= 3) { if (nlhs >= 3) {
mexutils_write_cf(pusch.z, &plhs[2], cfg.nbits.nof_re, 1); mexutils_write_cf(pusch.z, &plhs[2], cfg.nbits.nof_re, 1);
} }
if (nlhs >= 4) {
mexutils_write_uint8(pusch.q, &plhs[3], cfg.nbits.nof_bits, 1);
}
srslte_pusch_free(&pusch); srslte_pusch_free(&pusch);
free(trblkin); free(trblkin);
free(uci_data.uci_cqi);
free(sf_symbols); free(sf_symbols);
free(scfdma); free(scfdma);

@ -167,16 +167,13 @@ int main(int argc, char **argv) {
srslte_uci_data_t uci_data; srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t)); bzero(&uci_data, sizeof(srslte_uci_data_t));
uci_data.uci_cqi_len = 8; uci_data.uci_cqi_len = 20;
uci_data.uci_ri_len = 0; uci_data.uci_ri_len = 0;
uci_data.uci_ack_len = 1; uci_data.uci_ack_len = 1;
uint8_t tmp[20];
for (uint32_t i=0;i<20;i++) { for (uint32_t i=0;i<20;i++) {
tmp[i] = 1; uci_data.uci_cqi [i] = 1;
} }
uci_data.uci_cqi = tmp;
uci_data.uci_ri = 0; uci_data.uci_ri = 0;
uci_data.uci_ack = 0; uci_data.uci_ack = 0;

@ -47,7 +47,7 @@ void help()
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{ {
srslte_sch_t ulsch; srslte_sch_t ulsch;
uint8_t *trblkin;
srslte_pusch_cfg_t cfg; srslte_pusch_cfg_t cfg;
srslte_softbuffer_tx_t softbuffer; srslte_softbuffer_tx_t softbuffer;
srslte_uci_data_t uci_data; srslte_uci_data_t uci_data;
@ -74,10 +74,18 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return; return;
} }
cfg.grant.mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin); uint8_t *trblkin_bits = NULL;
cfg.grant.mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin_bits);
uint8_t *trblkin = srslte_vec_malloc(cfg.grant.mcs.tbs/8);
srslte_bit_unpack_vector(trblkin_bits, trblkin, cfg.grant.mcs.tbs);
free(trblkin_bits);
uci_data.uci_cqi_len = mexutils_read_uint8(CQI, &uci_data.uci_cqi);
uint8_t *tmp; uint8_t *tmp;
uci_data.uci_cqi_len = mexutils_read_uint8(CQI, &tmp);
memcpy(uci_data.uci_cqi, tmp, uci_data.uci_cqi_len);
free(tmp);
uci_data.uci_ri_len = mexutils_read_uint8(RI, &tmp); uci_data.uci_ri_len = mexutils_read_uint8(RI, &tmp);
if (uci_data.uci_ri_len > 0) { if (uci_data.uci_ri_len > 0) {
uci_data.uci_ri = *tmp; uci_data.uci_ri = *tmp;
@ -158,6 +166,8 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexPrintf("Q_m: %d, NPRB: %d, RV: %d, Nsrs=%d\n", srslte_mod_bits_x_symbol(cfg.grant.mcs.mod), cfg.grant.L_prb, cfg.rv, N_srs); mexPrintf("Q_m: %d, NPRB: %d, RV: %d, Nsrs=%d\n", srslte_mod_bits_x_symbol(cfg.grant.mcs.mod), cfg.grant.L_prb, cfg.rv, N_srs);
mexPrintf("I_cqi: %d, I_ri: %d, I_ack=%d\n", cfg.uci_cfg.I_offset_cqi, cfg.uci_cfg.I_offset_ri, cfg.uci_cfg.I_offset_ack);
if (srslte_cbsegm(&cfg.cb_segm, cfg.grant.mcs.tbs)) { if (srslte_cbsegm(&cfg.cb_segm, cfg.grant.mcs.tbs)) {
mexErrMsgTxt("Error configuring HARQ process\n"); mexErrMsgTxt("Error configuring HARQ process\n");
return; return;
@ -195,7 +205,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
free(trblkin); free(trblkin);
free(g_bits); free(g_bits);
free(q_bits); free(q_bits);
free(uci_data.uci_cqi);
return; return;
} }

@ -66,6 +66,7 @@ void srslte_scrambling_b_offset(srslte_sequence_t *s, uint8_t *data, int offset,
int i; int i;
assert (len + offset <= s->len); assert (len + offset <= s->len);
// Do XOR on a word basis // Do XOR on a word basis
if (!(len%8)) { if (!(len%8)) {
uint64_t *x = (uint64_t*) data; uint64_t *x = (uint64_t*) data;
uint64_t *y = (uint64_t*) &s->c[offset]; uint64_t *y = (uint64_t*) &s->c[offset];
@ -75,36 +76,19 @@ void srslte_scrambling_b_offset(srslte_sequence_t *s, uint8_t *data, int offset,
} else if (!(len%4)) { } else if (!(len%4)) {
uint32_t *x = (uint32_t*) data; uint32_t *x = (uint32_t*) data;
uint32_t *y = (uint32_t*) &s->c[offset]; uint32_t *y = (uint32_t*) &s->c[offset];
for (int i=0;i<len/8;i++) { for (int i=0;i<len/4;i++) {
x[i] = (x[i] ^ y[i]); x[i] = (x[i] ^ y[i]);
} }
} else if (!(len%2)) { } else if (!(len%2)) {
uint16_t *x = (uint16_t*) data; uint16_t *x = (uint16_t*) data;
uint16_t *y = (uint16_t*) &s->c[offset]; uint16_t *y = (uint16_t*) &s->c[offset];
for (int i=0;i<len/8;i++) { for (int i=0;i<len/2;i++) {
x[i] = (x[i] ^ y[i]); x[i] = (x[i] ^ y[i]);
} }
} else { } else {
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
data[i] = (data[i] + s->c[i + offset]) % 2; data[i] = (data[i] + s->c[i + offset]) % 2;
} }
} }
} }
/* As defined in 36.211 5.3.1 */
void srslte_scrambling_b_offset_pusch(srslte_sequence_t *s, uint8_t *data, int offset, int len) {
int i;
assert (len + offset <= s->len);
for (i = 0; i < len; i++) {
if (data[i] == 3) {
data[i] = 1;
} else if (data[i] == 2) {
if (i > 1) {
data[i] = data[i-1];
}
} else {
data[i] = (data[i] + s->c[i + offset]) % 2;
}
}
}

@ -57,7 +57,7 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q,
goto clean_exit; goto clean_exit;
} }
srslte_ofdm_set_freq_shift(&q->fft, 0.5); srslte_ofdm_set_freq_shift(&q->fft, 0.5);
srslte_ofdm_set_normalize(&q->fft, false); srslte_ofdm_set_normalize(&q->fft, true);
q->normalize_en = false; q->normalize_en = false;
@ -215,6 +215,66 @@ int srslte_ue_ul_cfg_grant(srslte_ue_ul_t *q, srslte_ra_ul_grant_t *grant,
return srslte_pusch_cfg(&q->pusch, &q->pusch_cfg, grant, &q->uci_cfg, &q->hopping_cfg, &q->srs_cfg, tti, rvidx, current_tx_nb); return srslte_pusch_cfg(&q->pusch, &q->pusch_cfg, grant, &q->uci_cfg, &q->hopping_cfg, &q->srs_cfg, tti, rvidx, current_tx_nb);
} }
int pucch_encode_bits(srslte_uci_data_t *uci_data, srslte_pucch_format_t *format,
uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS], uint8_t pucch2_bits[2],
srslte_cp_t cp)
{
int ret = SRSLTE_SUCCESS;
// No CQI data
if (uci_data->uci_cqi_len == 0) {
// 1-bit ACK + optional SR
if (uci_data->uci_ack_len == 1) {
*format = SRSLTE_PUCCH_FORMAT_1A;
pucch_bits[0] = uci_data->uci_ack;
}
// 2-bit ACK + optional SR
else if (uci_data->uci_ack_len == 2) {
*format = SRSLTE_PUCCH_FORMAT_1B;
pucch_bits[0] = uci_data->uci_ack;
pucch_bits[1] = uci_data->uci_ack_2;
}
// SR only
else if (uci_data->scheduling_request) {
*format = SRSLTE_PUCCH_FORMAT_1;
} else {
ret = SRSLTE_ERROR;
}
}
// CQI data
else {
srslte_uci_encode_cqi_pucch(uci_data->uci_cqi, uci_data->uci_cqi_len, pucch_bits);
// CQI and no ack
if (uci_data->uci_ack_len == 0) {
*format = SRSLTE_PUCCH_FORMAT_2;
}
// CQI + 1-bit ACK
else if (uci_data->uci_cqi_len == SRSLTE_PUCCH_MAX_BITS && uci_data->uci_ack_len == 1) {
*format = SRSLTE_PUCCH_FORMAT_2A;
pucch2_bits[0] = uci_data->uci_ack;
}
// CQI + 2-bit ACK
else if (uci_data->uci_cqi_len == SRSLTE_PUCCH_MAX_BITS && uci_data->uci_ack_len == 2) {
*format = SRSLTE_PUCCH_FORMAT_2B;
pucch2_bits[0] = uci_data->uci_ack;
pucch2_bits[1] = uci_data->uci_ack_2;
}
// CQI + 2-bit ACK + cyclic prefix
else if (uci_data->uci_cqi_len == SRSLTE_PUCCH_MAX_BITS && uci_data->uci_ack_len == 1 && SRSLTE_CP_ISEXT(cp)) {
*format = SRSLTE_PUCCH_FORMAT_2B;
pucch2_bits[0] = uci_data->uci_ack;
pucch2_bits[1] = uci_data->uci_ack_2;
} else {
ret = SRSLTE_ERROR;
}
}
if (ret) {
fprintf(stderr, "Unsupported combination of UCI parameters: ack_len=%d, cqi_len=%d\n",
uci_data->uci_ack, uci_data->uci_cqi_len);
}
return ret;
}
/* Choose PUCCH format as in Sec 10.1 of 36.213 and generate PUCCH signal /* Choose PUCCH format as in Sec 10.1 of 36.213 and generate PUCCH signal
*/ */
int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data, int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data,
@ -238,48 +298,8 @@ int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data,
bzero(pucch_bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t)); bzero(pucch_bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
bzero(pucch2_bits, 2*sizeof(uint8_t)); bzero(pucch2_bits, 2*sizeof(uint8_t));
// 1-bit ACK + optional SR // Encode UCI information
if (uci_data.uci_ack_len == 1) { if (pucch_encode_bits(&uci_data, &format, pucch_bits, pucch2_bits, q->cell.cp)) {
format = SRSLTE_PUCCH_FORMAT_1A;
pucch_bits[0] = uci_data.uci_ack;
}
// 2-bit ACK + optional SR
else if (uci_data.uci_ack_len == 2) {
format = SRSLTE_PUCCH_FORMAT_1B;
pucch_bits[0] = uci_data.uci_ack;
pucch_bits[1] = uci_data.uci_ack_2;
}
// SR only
else if (uci_data.scheduling_request) {
format = SRSLTE_PUCCH_FORMAT_1;
}
// CQI and no ack
else if (uci_data.uci_cqi_len == SRSLTE_PUCCH_MAX_BITS && uci_data.uci_ack_len == 0) {
format = SRSLTE_PUCCH_FORMAT_2;
memcpy(pucch_bits, uci_data.uci_cqi, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
}
// CQI + 1-bit ACK
else if (uci_data.uci_cqi_len == SRSLTE_PUCCH_MAX_BITS && uci_data.uci_ack_len == 1) {
format = SRSLTE_PUCCH_FORMAT_2A;
memcpy(pucch_bits, uci_data.uci_cqi, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
pucch2_bits[0] = uci_data.uci_ack;
}
// CQI + 2-bit ACK
else if (uci_data.uci_cqi_len == 20 && uci_data.uci_ack_len == 2) {
format = SRSLTE_PUCCH_FORMAT_2B;
memcpy(pucch_bits, uci_data.uci_cqi, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
pucch2_bits[0] = uci_data.uci_ack;
pucch2_bits[1] = uci_data.uci_ack_2;
}
// CQI + 2-bit ACK + cyclic prefix
else if (uci_data.uci_cqi_len == 20 && uci_data.uci_ack_len == 1 && SRSLTE_CP_ISEXT(q->cell.cp)) {
format = SRSLTE_PUCCH_FORMAT_2B;
memcpy(pucch_bits, uci_data.uci_cqi, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
pucch2_bits[0] = uci_data.uci_ack;
pucch2_bits[1] = uci_data.uci_ack_2;
} else {
fprintf(stderr, "Unsupported combination of UCI parameters: ack_len=%d, cqi_len=%d\n",
uci_data.uci_ack, uci_data.uci_cqi_len);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -320,7 +340,7 @@ int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data,
} }
if (q->normalize_en) { if (q->normalize_en) {
float norm_factor = (float) 0.9*q->cell.nof_prb/5; float norm_factor = (float) 0.6*q->cell.nof_prb/5;
srslte_vec_sc_prod_cfc(output_signal, norm_factor, output_signal, SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); srslte_vec_sc_prod_cfc(output_signal, norm_factor, output_signal, SRSLTE_SF_LEN_PRB(q->cell.nof_prb));
} }
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
@ -457,7 +477,7 @@ int srslte_ue_ul_pusch_encode_rnti_softbuffer(srslte_ue_ul_t *q,
} }
if (q->normalize_en) { if (q->normalize_en) {
float norm_factor = (float) q->cell.nof_prb/10/sqrtf(q->pusch_cfg.grant.L_prb); float norm_factor = (float) q->cell.nof_prb/15/sqrtf(q->pusch_cfg.grant.L_prb);
srslte_vec_sc_prod_cfc(output_signal, norm_factor, output_signal, SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); srslte_vec_sc_prod_cfc(output_signal, norm_factor, output_signal, SRSLTE_SF_LEN_PRB(q->cell.nof_prb));
} }

Loading…
Cancel
Save