mirror of https://github.com/PentHertz/srsLTE.git
Restored LS estimator + averaging. Fixed some issues in higher rates
This commit is contained in:
parent
cd5f750c86
commit
1454286ae3
Binary file not shown.
Before Width: | Height: | Size: 14 KiB |
|
@ -1,25 +1,47 @@
|
||||||
clear
|
clear
|
||||||
enbConfig=struct('NCellID',1,'CyclicPrefix','Normal','CellRefP',1);
|
enbConfig=struct('NCellID',0,'CyclicPrefix','Normal','CellRefP',1);
|
||||||
pdschConfig=struct('Modulation','64QAM','RV',0,'TxScheme','Port0');
|
pdschConfig=struct('Modulation','64QAM','RV',1,'TxScheme','Port0','NTurboDecIts',10);
|
||||||
|
|
||||||
addpath('../../build/srslte/lib/phch/test')
|
addpath('../../build/srslte/lib/phch/test')
|
||||||
|
|
||||||
TBs=36696;
|
%TBs=18336;
|
||||||
e_bits=41400;
|
i=1;
|
||||||
error=zeros(size(TBs));
|
e_bits=3450*6;
|
||||||
for i=1:length(TBs)
|
%error=zeros(size(TBs));
|
||||||
trblkin=randi(2,TBs(i),1)-1;
|
%for i=1:length(TBs)
|
||||||
|
%trblkin=randi(2,TBs(i),1)-1;
|
||||||
|
trblkin=read_uchar('../../build/data_in');
|
||||||
|
|
||||||
|
fprintf('e_bits=%d, trblkin=%d\n',e_bits,length(trblkin));
|
||||||
|
|
||||||
[mat, info]=lteDLSCH(enbConfig,pdschConfig,e_bits,trblkin);
|
[mat, info]=lteDLSCH(enbConfig,pdschConfig,e_bits,trblkin);
|
||||||
lib=srslte_dlsch_encode(enbConfig,pdschConfig,e_bits,trblkin);
|
lib=srslte_dlsch_encode(enbConfig,pdschConfig,e_bits,trblkin);
|
||||||
error(i)=mean(abs(double(mat)-double(lib)));
|
error(i)=mean(abs(double(mat)-double(lib)));
|
||||||
end
|
mat(mat==0)=-1;
|
||||||
|
mat=mat*10;
|
||||||
|
|
||||||
if (length(TBs) == 1)
|
rec = lteRateRecoverTurbo(mat,length(trblkin),pdschConfig.RV);
|
||||||
%disp(info)
|
rec2 = reshape(reshape(rec{1},[],3)',[],1);
|
||||||
disp(error)
|
out = lteTurboDecode(rec{1});
|
||||||
n=1:length(mat);
|
|
||||||
plot(abs(double(mat)-double(lib)))
|
x=read_int16('../../build/rmout_0.dat');
|
||||||
else
|
subplot(2,1,1)
|
||||||
plot(error)
|
plot(abs(double(x)-double(rec2)));
|
||||||
end
|
t=1:100;
|
||||||
|
%plot(t,double(x(t)),t,double(rec2(t)))
|
||||||
|
subplot(2,1,2)
|
||||||
|
llr=read_int16('../../build/llr.dat');
|
||||||
|
plot(abs(double(mat)-double(llr)))
|
||||||
|
|
||||||
|
[data, crc,state] = lteDLSCHDecode(enbConfig, pdschConfig, length(trblkin), mat);
|
||||||
|
disp(crc)
|
||||||
|
%end
|
||||||
|
%
|
||||||
|
% if (length(TBs) == 1)
|
||||||
|
% %disp(info)
|
||||||
|
% disp(error)
|
||||||
|
% n=1:length(mat);
|
||||||
|
% plot(abs(double(mat)-double(lib)))
|
||||||
|
% else
|
||||||
|
% plot(error)
|
||||||
|
% end
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 53 KiB |
|
@ -6,25 +6,25 @@ clear
|
||||||
|
|
||||||
plot_noise_estimation_only=false;
|
plot_noise_estimation_only=false;
|
||||||
|
|
||||||
SNR_values_db=30;%linspace(0,40,7);
|
SNR_values_db=30;%linspace(0,30,8);
|
||||||
Nrealizations=1;
|
Nrealizations=1;
|
||||||
|
|
||||||
Lp=10;
|
Lp=5;
|
||||||
|
|
||||||
N=512;
|
N=512;
|
||||||
K=300;
|
enb.NDLRB = 25; % Number of resource blocks
|
||||||
|
|
||||||
|
enb.CellRefP = 1; % One transmit antenna port
|
||||||
|
enb.NCellID = 0; % Cell ID
|
||||||
|
enb.CyclicPrefix = 'Normal'; % Normal cyclic prefix
|
||||||
|
enb.DuplexMode = 'FDD'; % FDD
|
||||||
|
|
||||||
|
K=enb.NDLRB*12;
|
||||||
rstart=(N-K)/2;
|
rstart=(N-K)/2;
|
||||||
P=K/6;
|
P=K/6;
|
||||||
Rhphp=zeros(P,P);
|
Rhphp=zeros(P,P);
|
||||||
Rhhp=zeros(K,P);
|
Rhhp=zeros(K,P);
|
||||||
Rhh=zeros(K,K);
|
Rhh=zeros(K,K);
|
||||||
|
|
||||||
enb.NDLRB = 25; % Number of resource blocks
|
|
||||||
enb.CellRefP = 1; % One transmit antenna port
|
|
||||||
enb.NCellID = 0; % Cell ID
|
|
||||||
enb.CyclicPrefix = 'Normal'; % Normal cyclic prefix
|
|
||||||
enb.DuplexMode = 'FDD'; % FDD
|
|
||||||
|
|
||||||
%% Channel Model Configuration
|
%% Channel Model Configuration
|
||||||
cfg.Seed = 0; % Random channel seed
|
cfg.Seed = 0; % Random channel seed
|
||||||
cfg.InitTime = 0;
|
cfg.InitTime = 0;
|
||||||
|
@ -33,7 +33,7 @@ cfg.DelayProfile = 'EPA';
|
||||||
|
|
||||||
% doppler 5, 70 300
|
% doppler 5, 70 300
|
||||||
|
|
||||||
cfg.DopplerFreq = 50; % 120Hz Doppler frequency
|
cfg.DopplerFreq = 5; % 120Hz Doppler frequency
|
||||||
cfg.MIMOCorrelation = 'Low'; % Low (no) MIMO correlation
|
cfg.MIMOCorrelation = 'Low'; % Low (no) MIMO correlation
|
||||||
cfg.NTerms = 16; % Oscillators used in fading model
|
cfg.NTerms = 16; % Oscillators used in fading model
|
||||||
cfg.ModelType = 'GMEDS'; % Rayleigh fading model type
|
cfg.ModelType = 'GMEDS'; % Rayleigh fading model type
|
||||||
|
@ -58,7 +58,7 @@ L = gridsize(2); % Number of OFDM symbols in one subframe
|
||||||
Ports = gridsize(3); % Number of transmit antenna ports
|
Ports = gridsize(3); % Number of transmit antenna ports
|
||||||
|
|
||||||
%% Allocate memory
|
%% Allocate memory
|
||||||
Ntests=5;
|
Ntests=4;
|
||||||
hest=cell(1,Ntests);
|
hest=cell(1,Ntests);
|
||||||
for i=1:Ntests
|
for i=1:Ntests
|
||||||
hest{i}=zeros(K,140);
|
hest{i}=zeros(K,140);
|
||||||
|
@ -67,7 +67,7 @@ hls=zeros(4,4*P*10);
|
||||||
MSE=zeros(Ntests,Nrealizations,length(SNR_values_db));
|
MSE=zeros(Ntests,Nrealizations,length(SNR_values_db));
|
||||||
noiseEst=zeros(Ntests,Nrealizations,length(SNR_values_db));
|
noiseEst=zeros(Ntests,Nrealizations,length(SNR_values_db));
|
||||||
|
|
||||||
legends={'matlab','ls.linear','mmse','r.mmse','r.mmse2'};
|
legends={'matlab','ls.linear','mmse','r.smooth'};
|
||||||
colors={'bo-','rx-','m*-','k+-','c+-'};
|
colors={'bo-','rx-','m*-','k+-','c+-'};
|
||||||
colors2={'b-','r-','m-','k-','c-'};
|
colors2={'b-','r-','m-','k-','c-'};
|
||||||
|
|
||||||
|
@ -224,72 +224,39 @@ snr_lin=10^(SNR_values_db(snr_idx)/10);
|
||||||
Wi=((Rhphp+(1/snr_lin)*eye(P)))^-1;
|
Wi=((Rhphp+(1/snr_lin)*eye(P)))^-1;
|
||||||
W = Rhhp*Wi;
|
W = Rhhp*Wi;
|
||||||
|
|
||||||
% for i=1:length(hidx)
|
|
||||||
% hp=hls(3,(1:P)+P*(i-1));
|
|
||||||
% hest{3}(:,hidx(i))=W*transpose(hp);
|
|
||||||
% end
|
|
||||||
|
|
||||||
w=reshape(transpose(W),1,[]);
|
w=reshape(transpose(W),1,[]);
|
||||||
[tmp, ~, ~, noiseEst(3,nreal,snr_idx)] = srslte_chest(enb.NCellID,enb.CellRefP,rxGrid,w);
|
[tmp, ~, ~, noiseEst(3,nreal,snr_idx)] = srslte_chest(enb.NCellID,enb.CellRefP,rxGrid,w);
|
||||||
hest{3}=reshape(tmp, size(hest{1}));
|
hest{3}=reshape(tmp, size(hest{1}));
|
||||||
|
|
||||||
|
|
||||||
%% Robust MMSE estimation using srsLTE (Eurecom paper)
|
%% Low-pass filter smoother
|
||||||
|
|
||||||
|
prows=rstart+(1:6:K);
|
||||||
t=0:Lp-1;
|
t=0:Lp-1;
|
||||||
alfa=log(2*Lp)/Lp;
|
alfa=log(2*Lp)/Lp;
|
||||||
c_l=exp(-t*alfa);
|
c_l=exp(-t*alfa);
|
||||||
c_l=c_l/sum(c_l);
|
c_l2=[c_l zeros(1,N-Lp)];
|
||||||
C_l=diag(1./c_l);
|
|
||||||
prows=rstart+(1:6:K);
|
|
||||||
|
|
||||||
F=dftmtx(N);
|
|
||||||
F_p=F(prows,1:Lp);
|
|
||||||
F_l=F((rstart+1):(K+rstart),1:Lp);
|
|
||||||
Wi=(F_p'*F_p+C_l*0.01)^(-1);
|
|
||||||
W2=F_l*Wi*F_p';
|
|
||||||
|
|
||||||
% for i=1:length(hidx)
|
|
||||||
% hp=hls(3,(1:P)+P*(i-1));
|
|
||||||
% hest{4}(:,hidx(i))=W2*transpose(hp);
|
|
||||||
% end
|
|
||||||
|
|
||||||
w2=reshape(transpose(W2),1,[]);
|
|
||||||
[tmp, ~, ~, noiseEst(4,nreal,snr_idx)] = srslte_chest(enb.NCellID,enb.CellRefP,rxGrid,w2);
|
|
||||||
hest{4}=reshape(tmp, size(hest{1}));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%% Another robust method from Infocom research paper
|
|
||||||
|
|
||||||
c_l=ones(Lp,1)/Lp;
|
|
||||||
c_l2=[c_l; zeros(N-Lp,1)];
|
|
||||||
C_l=diag(c_l2);
|
C_l=diag(c_l2);
|
||||||
F=dftmtx(N);
|
F=dftmtx(N);
|
||||||
R_hh=F*C_l*F';
|
R_hh=F*C_l*F';
|
||||||
R_hphp=R_hh(prows,prows);
|
R_hh=R_hh(prows,prows);
|
||||||
R_hhp=R_hh((rstart+1):(K+rstart),prows);
|
W3=R_hh*(R_hh+0.05*eye(P))^-1;
|
||||||
W3=R_hhp*(R_hphp+(1/snr_lin)*eye(P))^-1;
|
|
||||||
|
|
||||||
% for i=1:length(hidx)
|
|
||||||
% hp=hls(3,(1:P)+P*(i-1));
|
|
||||||
% hest{5}(:,hidx(i))=W3*transpose(hp);
|
|
||||||
% end
|
|
||||||
|
|
||||||
w3=reshape(transpose(W3),1,[]);
|
w3=reshape(transpose(W3),1,[]);
|
||||||
[tmp, ~, ~, noiseEst(5,nreal,snr_idx)] = srslte_chest(enb.NCellID,enb.CellRefP,rxGrid,w3);
|
[tmp, pilot_avg, ~, noiseEst(4,nreal,snr_idx)] = srslte_chest(enb.NCellID,enb.CellRefP,rxGrid,w3);
|
||||||
hest{5}=reshape(tmp, size(hest{1}));
|
hest{4}=reshape(tmp, size(hest{1}));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%% Compute MSE
|
%% Compute MSE
|
||||||
for i=1:Ntests
|
for i=1:Ntests
|
||||||
MSE(i,nreal,snr_idx)=mean(mean(abs(h(:,:)-hest{i}(:,:)).^2));
|
MSE(i,nreal,snr_idx)=mean(mean(abs(h(:,hidx)-hest{i}(:,hidx)).^2));
|
||||||
fprintf('MSE test %d: %f\n',i, 10*log10(MSE(i,nreal,snr_idx)));
|
fprintf('MSE test %d: %f\n',i, 10*log10(MSE(i,nreal,snr_idx)));
|
||||||
end
|
end
|
||||||
|
|
||||||
%% Plot a single realization
|
%% Plot a single realization
|
||||||
if (length(SNR_values_db) == 1)
|
if (length(SNR_values_db) == 1)
|
||||||
subplot(1,2,1)
|
subplot(2,1,1)
|
||||||
sym=1;
|
sym=1;
|
||||||
ref_idx=1:P;
|
ref_idx=1:P;
|
||||||
ref_idx_x=[1:6:K];% (292:6:360)-216];% 577:6:648];
|
ref_idx_x=[1:6:K];% (292:6:360)-216];% 577:6:648];
|
||||||
|
@ -311,32 +278,12 @@ if (length(SNR_values_db) == 1)
|
||||||
ylabel('Channel Gain')
|
ylabel('Channel Gain')
|
||||||
grid on;
|
grid on;
|
||||||
|
|
||||||
u(1+ceil(chinfo.PathSampleDelays))=chinfo.PathGains(1,:);
|
|
||||||
|
|
||||||
subplot(1,2,2)
|
|
||||||
plot(1:P,real(W(150,:)),1:P,real(W2(150,:)),1:P,real(W3(150,:)))
|
|
||||||
legend('mmse','robust1','robust2')
|
|
||||||
grid on
|
|
||||||
|
|
||||||
fprintf('Mean MMSE Robust %.2f dB\n', 10*log10(MSE(4,nreal,snr_idx)))
|
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)))
|
fprintf('Mean MMSE matlab %.2f dB\n', 10*log10(MSE(1,nreal,snr_idx)))
|
||||||
|
|
||||||
% u=zeros(N,1);
|
subplot(2,1,2)
|
||||||
% u(1+ceil(chinfo.PathSampleDelays))=mean(chinfo.PathGains(7680+(1:512+40),:));
|
plot(1:P,abs(W3(P/2,:)))
|
||||||
%
|
|
||||||
% subplot(2,2,1)
|
|
||||||
% plot(1:length(u),abs(u))
|
|
||||||
%
|
|
||||||
% subplot(2,2,2)
|
|
||||||
% plot(abs(fftshift(fft(u,N))))
|
|
||||||
%
|
|
||||||
% subplot(2,2,3)
|
|
||||||
% hf=[zeros((N-K)/2,1); h(1:K/2,1); 0; h(K/2+1:end,1); zeros((N-K)/2-1,1)];
|
|
||||||
% plot(1:Lp,real(ifft(ifftshift(h(:,1)),Lp)))
|
|
||||||
%
|
|
||||||
% subplot(2,2,4)
|
|
||||||
% plot(abs(hf))
|
|
||||||
%
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -350,7 +297,7 @@ mean_snr=10*log10(1./mean(noiseEst,2));
|
||||||
|
|
||||||
%% Plot average over all SNR values
|
%% Plot average over all SNR values
|
||||||
if (length(SNR_values_db) > 1)
|
if (length(SNR_values_db) > 1)
|
||||||
subplot(1,2,1)
|
subplot(1,1,1)
|
||||||
for i=1:Ntests
|
for i=1:Ntests
|
||||||
plot(SNR_values_db, 10*log10(mean_mse(i,:)),colors{i})
|
plot(SNR_values_db, 10*log10(mean_mse(i,:)),colors{i})
|
||||||
hold on;
|
hold on;
|
||||||
|
@ -361,21 +308,21 @@ if (length(SNR_values_db) > 1)
|
||||||
xlabel('SNR (dB)')
|
xlabel('SNR (dB)')
|
||||||
ylabel('MSE (dB)')
|
ylabel('MSE (dB)')
|
||||||
|
|
||||||
subplot(1,2,2)
|
% subplot(1,2,2)
|
||||||
plot(SNR_values_db, SNR_values_db,'k:')
|
% plot(SNR_values_db, SNR_values_db,'k:')
|
||||||
hold on;
|
% hold on;
|
||||||
for i=1:Ntests
|
% for i=1:Ntests
|
||||||
plot(SNR_values_db, mean_snr(i,:), colors{i})
|
% plot(SNR_values_db, mean_snr(i,:), colors{i})
|
||||||
end
|
% end
|
||||||
hold off
|
% hold off
|
||||||
tmp=cell(Ntests+1,1);
|
% tmp=cell(Ntests+1,1);
|
||||||
tmp{1}='Theory';
|
% tmp{1}='Theory';
|
||||||
for i=2:Ntests+1
|
% for i=2:Ntests+1
|
||||||
tmp{i}=legends{i-1};
|
% tmp{i}=legends{i-1};
|
||||||
end
|
% end
|
||||||
legend(tmp)
|
% legend(tmp)
|
||||||
grid on
|
% grid on
|
||||||
xlabel('SNR (dB)')
|
% xlabel('SNR (dB)')
|
||||||
ylabel('Estimated SNR (dB)')
|
% ylabel('Estimated SNR (dB)')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 52 KiB |
Binary file not shown.
Before Width: | Height: | Size: 33 KiB |
|
@ -6,8 +6,8 @@
|
||||||
|
|
||||||
recordedSignal=[];
|
recordedSignal=[];
|
||||||
|
|
||||||
Npackets = 100;
|
Npackets = 20;
|
||||||
SNR_values = linspace(2,10,10);
|
SNR_values = linspace(2,6,10);
|
||||||
|
|
||||||
Lp=12;
|
Lp=12;
|
||||||
N=256;
|
N=256;
|
||||||
|
@ -127,7 +127,7 @@ for snr_idx=1:length(SNR_values)
|
||||||
if (rmccFgOut.PDSCH.TrBlkSizes(sf_idx+1) > 0)
|
if (rmccFgOut.PDSCH.TrBlkSizes(sf_idx+1) > 0)
|
||||||
[dec2, data, pdschRx, pdschSymbols2, cws2] = srslte_pdsch(rmccFgOut, rmccFgOut.PDSCH, ...
|
[dec2, data, pdschRx, pdschSymbols2, cws2] = srslte_pdsch(rmccFgOut, rmccFgOut.PDSCH, ...
|
||||||
rmccFgOut.PDSCH.TrBlkSizes(sf_idx+1), ...
|
rmccFgOut.PDSCH.TrBlkSizes(sf_idx+1), ...
|
||||||
subframe_rx,w2);
|
subframe_rx);
|
||||||
else
|
else
|
||||||
dec2 = 1;
|
dec2 = 1;
|
||||||
end
|
end
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
@ -74,7 +74,6 @@ typedef struct {
|
||||||
bool disable_plots;
|
bool disable_plots;
|
||||||
bool disable_plots_except_constellation;
|
bool disable_plots_except_constellation;
|
||||||
bool disable_cfo;
|
bool disable_cfo;
|
||||||
bool use_robust_lmmse;
|
|
||||||
uint32_t time_offset;
|
uint32_t time_offset;
|
||||||
int force_N_id_2;
|
int force_N_id_2;
|
||||||
uint16_t rnti;
|
uint16_t rnti;
|
||||||
|
@ -95,7 +94,6 @@ typedef struct {
|
||||||
|
|
||||||
void args_default(prog_args_t *args) {
|
void args_default(prog_args_t *args) {
|
||||||
args->disable_plots = false;
|
args->disable_plots = false;
|
||||||
args->use_robust_lmmse = false;
|
|
||||||
args->disable_plots_except_constellation = false;
|
args->disable_plots_except_constellation = false;
|
||||||
args->nof_subframes = -1;
|
args->nof_subframes = -1;
|
||||||
args->rnti = SRSLTE_SIRNTI;
|
args->rnti = SRSLTE_SIRNTI;
|
||||||
|
@ -118,7 +116,7 @@ void args_default(prog_args_t *args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void usage(prog_args_t *args, char *prog) {
|
void usage(prog_args_t *args, char *prog) {
|
||||||
printf("Usage: %s [agpPoOcilLdDnruv] -f rx_frequency (in Hz) | -i input_file\n", prog);
|
printf("Usage: %s [agpPoOcildDnruv] -f rx_frequency (in Hz) | -i input_file\n", prog);
|
||||||
#ifndef DISABLE_RF
|
#ifndef DISABLE_RF
|
||||||
printf("\t-a RF args [Default %s]\n", args->rf_args);
|
printf("\t-a RF args [Default %s]\n", args->rf_args);
|
||||||
printf("\t-g RF fix RX gain [Default AGC]\n");
|
printf("\t-g RF fix RX gain [Default AGC]\n");
|
||||||
|
@ -133,7 +131,6 @@ void usage(prog_args_t *args, char *prog) {
|
||||||
printf("\t-c cell_id for input file [Default %d]\n", args->file_cell_id);
|
printf("\t-c cell_id for input file [Default %d]\n", args->file_cell_id);
|
||||||
printf("\t-r RNTI in Hex [Default 0x%x]\n",args->rnti);
|
printf("\t-r RNTI in Hex [Default 0x%x]\n",args->rnti);
|
||||||
printf("\t-l Force N_id_2 [Default best]\n");
|
printf("\t-l Force N_id_2 [Default best]\n");
|
||||||
printf("\t-L (Experimental) Use Robust LMMSE estimation [Default false]\n");
|
|
||||||
printf("\t-C Disable CFO correction [Default %s]\n", args->disable_cfo?"Disabled":"Enabled");
|
printf("\t-C Disable CFO correction [Default %s]\n", args->disable_cfo?"Disabled":"Enabled");
|
||||||
printf("\t-t Add time offset [Default %d]\n", args->time_offset);
|
printf("\t-t Add time offset [Default %d]\n", args->time_offset);
|
||||||
#ifndef DISABLE_GRAPHICS
|
#ifndef DISABLE_GRAPHICS
|
||||||
|
@ -153,7 +150,7 @@ void usage(prog_args_t *args, char *prog) {
|
||||||
void parse_args(prog_args_t *args, int argc, char **argv) {
|
void parse_args(prog_args_t *args, int argc, char **argv) {
|
||||||
int opt;
|
int opt;
|
||||||
args_default(args);
|
args_default(args);
|
||||||
while ((opt = getopt(argc, argv, "aoglLipPcOCtdDnvrfuUsS")) != -1) {
|
while ((opt = getopt(argc, argv, "aoglipPcOCtdDnvrfuUsS")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'i':
|
case 'i':
|
||||||
args->input_file_name = argv[optind];
|
args->input_file_name = argv[optind];
|
||||||
|
@ -197,9 +194,6 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
|
||||||
case 'l':
|
case 'l':
|
||||||
args->force_N_id_2 = atoi(argv[optind]);
|
args->force_N_id_2 = atoi(argv[optind]);
|
||||||
break;
|
break;
|
||||||
case 'L':
|
|
||||||
args->use_robust_lmmse = true;
|
|
||||||
break;
|
|
||||||
case 'u':
|
case 'u':
|
||||||
args->net_port = atoi(argv[optind]);
|
args->net_port = atoi(argv[optind]);
|
||||||
break;
|
break;
|
||||||
|
@ -413,11 +407,6 @@ int main(int argc, char **argv) {
|
||||||
/* Configure downlink receiver for the SI-RNTI since will be the only one we'll use */
|
/* Configure downlink receiver for the SI-RNTI since will be the only one we'll use */
|
||||||
srslte_ue_dl_set_rnti(&ue_dl, prog_args.rnti);
|
srslte_ue_dl_set_rnti(&ue_dl, prog_args.rnti);
|
||||||
|
|
||||||
/* (Experimental) setup robust LMMSE estimation */
|
|
||||||
if (prog_args.use_robust_lmmse) {
|
|
||||||
srslte_chest_dl_set_robust_mmse_filter(&ue_dl.chest);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize subframe counter */
|
/* Initialize subframe counter */
|
||||||
sf_cnt = 0;
|
sf_cnt = 0;
|
||||||
|
|
||||||
|
|
|
@ -50,16 +50,18 @@
|
||||||
#include "srslte/common/phy_common.h"
|
#include "srslte/common/phy_common.h"
|
||||||
#include "srslte/sync/pss.h"
|
#include "srslte/sync/pss.h"
|
||||||
|
|
||||||
#define SRSLTE_CHEST_MAX_FILTER_FREQ_LEN 21
|
#define SRSLTE_CHEST_DL_MAX_SMOOTH_FIL_LEN 65
|
||||||
#define SRSLTE_CHEST_MAX_FILTER_TIME_LEN 40
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
srslte_cell_t cell;
|
srslte_cell_t cell;
|
||||||
srslte_refsignal_cs_t csr_signal;
|
srslte_refsignal_cs_t csr_signal;
|
||||||
cf_t *pilot_estimates;
|
cf_t *pilot_estimates;
|
||||||
|
cf_t *pilot_estimates_average;
|
||||||
cf_t *pilot_recv_signal;
|
cf_t *pilot_recv_signal;
|
||||||
cf_t *tmp_noise;
|
cf_t *tmp_noise;
|
||||||
cf_t *w_filter;
|
|
||||||
|
uint32_t smooth_filter_len;
|
||||||
|
float smooth_filter[SRSLTE_CHEST_DL_MAX_SMOOTH_FIL_LEN];
|
||||||
|
|
||||||
srslte_interp_linsrslte_vec_t srslte_interp_linvec;
|
srslte_interp_linsrslte_vec_t srslte_interp_linvec;
|
||||||
srslte_interp_lin_t srslte_interp_lin;
|
srslte_interp_lin_t srslte_interp_lin;
|
||||||
|
@ -80,10 +82,9 @@ SRSLTE_API int srslte_chest_dl_init(srslte_chest_dl_t *q,
|
||||||
|
|
||||||
SRSLTE_API void srslte_chest_dl_free(srslte_chest_dl_t *q);
|
SRSLTE_API void srslte_chest_dl_free(srslte_chest_dl_t *q);
|
||||||
|
|
||||||
SRSLTE_API void srslte_chest_dl_set_filter_w(srslte_chest_dl_t *q,
|
SRSLTE_API void srslte_chest_dl_set_smooth_filter(srslte_chest_dl_t *q,
|
||||||
cf_t *w);
|
float *filter,
|
||||||
|
uint32_t filter_len);
|
||||||
SRSLTE_API void srslte_chest_dl_set_robust_mmse_filter(srslte_chest_dl_t *q);
|
|
||||||
|
|
||||||
SRSLTE_API int srslte_chest_dl_estimate(srslte_chest_dl_t *q,
|
SRSLTE_API int srslte_chest_dl_estimate(srslte_chest_dl_t *q,
|
||||||
cf_t *input,
|
cf_t *input,
|
||||||
|
|
|
@ -49,12 +49,8 @@ SRSLTE_API void srslte_scrambling_b_offset(srslte_sequence_t *s,
|
||||||
int len);
|
int len);
|
||||||
|
|
||||||
SRSLTE_API void srslte_scrambling_bytes(srslte_sequence_t *s,
|
SRSLTE_API void srslte_scrambling_bytes(srslte_sequence_t *s,
|
||||||
uint8_t *data);
|
uint8_t *data,
|
||||||
|
int len);
|
||||||
SRSLTE_API void srslte_scrambling_bytes_offset(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);
|
||||||
|
|
|
@ -41,8 +41,28 @@
|
||||||
|
|
||||||
#define ESTIMATE_NOISE_LS_PSS
|
#define ESTIMATE_NOISE_LS_PSS
|
||||||
|
|
||||||
#include "robust_mmse_25prb.h"
|
#define DEFAULT_FILTER_LEN 3
|
||||||
#include "robust_mmse_50prb.h"
|
|
||||||
|
static void set_default_filter(srslte_chest_dl_t *q, int filter_len) {
|
||||||
|
|
||||||
|
float fil[SRSLTE_CHEST_DL_MAX_SMOOTH_FIL_LEN];
|
||||||
|
|
||||||
|
for (int i=0;i<filter_len/2;i++) {
|
||||||
|
fil[i] = i+1;
|
||||||
|
fil[i+filter_len/2+1]=filter_len/2-i;
|
||||||
|
}
|
||||||
|
fil[filter_len/2]=filter_len/2+1;
|
||||||
|
|
||||||
|
float s=0;
|
||||||
|
for (int i=0;i<filter_len;i++) {
|
||||||
|
s+=fil[i];
|
||||||
|
}
|
||||||
|
for (int i=0;i<filter_len;i++) {
|
||||||
|
fil[i]/=s;
|
||||||
|
}
|
||||||
|
|
||||||
|
srslte_chest_dl_set_smooth_filter(q, fil, filter_len);
|
||||||
|
}
|
||||||
|
|
||||||
/** 3GPP LTE Downlink channel estimator and equalizer.
|
/** 3GPP LTE Downlink channel estimator and equalizer.
|
||||||
* Estimates the channel in the resource elements transmitting references and interpolates for the rest
|
* Estimates the channel in the resource elements transmitting references and interpolates for the rest
|
||||||
|
@ -77,6 +97,11 @@ int srslte_chest_dl_init(srslte_chest_dl_t *q, srslte_cell_t cell)
|
||||||
perror("malloc");
|
perror("malloc");
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
|
q->pilot_estimates_average = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb));
|
||||||
|
if (!q->pilot_estimates_average) {
|
||||||
|
perror("malloc");
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb));
|
q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb));
|
||||||
if (!q->pilot_recv_signal) {
|
if (!q->pilot_recv_signal) {
|
||||||
perror("malloc");
|
perror("malloc");
|
||||||
|
@ -98,7 +123,8 @@ int srslte_chest_dl_init(srslte_chest_dl_t *q, srslte_cell_t cell)
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
q->w_filter = NULL;
|
q->smooth_filter_len = 0;
|
||||||
|
set_default_filter(q, DEFAULT_FILTER_LEN);
|
||||||
|
|
||||||
q->cell = cell;
|
q->cell = cell;
|
||||||
}
|
}
|
||||||
|
@ -125,28 +151,15 @@ void srslte_chest_dl_free(srslte_chest_dl_t *q)
|
||||||
if (q->pilot_estimates) {
|
if (q->pilot_estimates) {
|
||||||
free(q->pilot_estimates);
|
free(q->pilot_estimates);
|
||||||
}
|
}
|
||||||
|
if (q->pilot_estimates_average) {
|
||||||
|
free(q->pilot_estimates_average);
|
||||||
|
}
|
||||||
if (q->pilot_recv_signal) {
|
if (q->pilot_recv_signal) {
|
||||||
free(q->pilot_recv_signal);
|
free(q->pilot_recv_signal);
|
||||||
}
|
}
|
||||||
bzero(q, sizeof(srslte_chest_dl_t));
|
bzero(q, sizeof(srslte_chest_dl_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
void srslte_chest_dl_set_filter_w(srslte_chest_dl_t *q, cf_t *w) {
|
|
||||||
q->w_filter = w;
|
|
||||||
}
|
|
||||||
|
|
||||||
void srslte_chest_dl_set_robust_mmse_filter(srslte_chest_dl_t *q) {
|
|
||||||
if (q->cell.nof_prb == 25) {
|
|
||||||
printf("Using robust LMMSE interpolation filter\n");
|
|
||||||
srslte_chest_dl_set_filter_w(q, (cf_t*) w_robust_25prb);
|
|
||||||
} else if (q->cell.nof_prb == 50) {
|
|
||||||
printf("Using robust LMMSE interpolation filter\n");
|
|
||||||
srslte_chest_dl_set_filter_w(q, (cf_t*) w_robust_50prb);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Error setting robust MMSE filter. Not available for %d PRB\n", q->cell.nof_prb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Uses the difference between the averaged and non-averaged pilot estimates */
|
/* Uses the difference between the averaged and non-averaged pilot estimates */
|
||||||
static float estimate_noise_pilots(srslte_chest_dl_t *q, cf_t *ce, uint32_t port_id)
|
static float estimate_noise_pilots(srslte_chest_dl_t *q, cf_t *ce, uint32_t port_id)
|
||||||
{
|
{
|
||||||
|
@ -156,7 +169,7 @@ static float estimate_noise_pilots(srslte_chest_dl_t *q, cf_t *ce, uint32_t port
|
||||||
/* Substract noisy pilot estimates */
|
/* Substract noisy pilot estimates */
|
||||||
srslte_vec_sub_ccc(q->tmp_noise, q->pilot_estimates, q->tmp_noise, nref);
|
srslte_vec_sub_ccc(q->tmp_noise, q->pilot_estimates, q->tmp_noise, nref);
|
||||||
/* Compute average power */
|
/* Compute average power */
|
||||||
float power = sqrt(2.0)*q->cell.nof_ports*srslte_vec_avg_power_cf(q->tmp_noise, nref);
|
float power = sqrt(2)*q->cell.nof_ports*srslte_vec_avg_power_cf(q->tmp_noise, nref);
|
||||||
return power;
|
return power;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +189,7 @@ static float estimate_noise_pss(srslte_chest_dl_t *q, cf_t *input, cf_t *ce)
|
||||||
srslte_vec_sub_ccc(q->tmp_pss_noisy, q->tmp_pss, q->tmp_pss_noisy, SRSLTE_PSS_LEN);
|
srslte_vec_sub_ccc(q->tmp_pss_noisy, q->tmp_pss, q->tmp_pss_noisy, SRSLTE_PSS_LEN);
|
||||||
|
|
||||||
/* Compute average power */
|
/* Compute average power */
|
||||||
float power = q->cell.nof_ports*srslte_vec_avg_power_cf(q->tmp_pss_noisy, SRSLTE_PSS_LEN)/sqrt(2);
|
float power = sqrt(2)*q->cell.nof_ports*srslte_vec_avg_power_cf(q->tmp_pss_noisy, SRSLTE_PSS_LEN);
|
||||||
return power;
|
return power;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,45 +213,6 @@ static float estimate_noise_empty_sc(srslte_chest_dl_t *q, cf_t *input) {
|
||||||
|
|
||||||
#define cesymb(i) ce[SRSLTE_RE_IDX(q->cell.nof_prb,i,0)]
|
#define cesymb(i) ce[SRSLTE_RE_IDX(q->cell.nof_prb,i,0)]
|
||||||
|
|
||||||
static void interpolate_filter_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t *w, cf_t *ce, uint32_t port_id)
|
|
||||||
{
|
|
||||||
int nsymbols = srslte_refsignal_cs_nof_symbols(port_id);
|
|
||||||
int nsc=SRSLTE_NRE*q->cell.nof_prb;
|
|
||||||
int nref=2*q->cell.nof_prb;
|
|
||||||
|
|
||||||
// Interpolation filter in frequency domain
|
|
||||||
for (uint32_t s=0;s<nsymbols;s++) {
|
|
||||||
for (int i=0;i<nsc;i++) {
|
|
||||||
uint32_t sym_idx=srslte_refsignal_cs_nsymbol(s,q->cell.cp, port_id);
|
|
||||||
ce[nsc*sym_idx+i] = srslte_vec_dot_prod_ccc(&pilot_estimates[s*nref], &w[i*nref], nref);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Now interpolate in the time domain between symbols */
|
|
||||||
if (SRSLTE_CP_ISNORM(q->cell.cp)) {
|
|
||||||
if (nsymbols == 4) {
|
|
||||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(4), &cesymb(1), 3);
|
|
||||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(4), &cesymb(7), &cesymb(5), 2);
|
|
||||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(7), &cesymb(11), &cesymb(8), 3);
|
|
||||||
srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(7), &cesymb(11), &cesymb(11), &cesymb(12), 2);
|
|
||||||
} else {
|
|
||||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(8), &cesymb(1), &cesymb(0), 1);
|
|
||||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(8), &cesymb(2), 6);
|
|
||||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(8), &cesymb(9), 5);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (nsymbols == 4) {
|
|
||||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(3), &cesymb(1), 2);
|
|
||||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(3), &cesymb(6), &cesymb(4), 2);
|
|
||||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(6), &cesymb(9), &cesymb(7), 2);
|
|
||||||
srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(6), &cesymb(9), &cesymb(9), &cesymb(10), 2);
|
|
||||||
} else {
|
|
||||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(7), &cesymb(1), &cesymb(0), 1);
|
|
||||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(7), &cesymb(2), 5);
|
|
||||||
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(7), &cesymb(8), 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t *ce, uint32_t port_id)
|
static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t *ce, uint32_t port_id)
|
||||||
{
|
{
|
||||||
/* interpolate the symbols with references in the freq domain */
|
/* interpolate the symbols with references in the freq domain */
|
||||||
|
@ -279,6 +253,25 @@ static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void srslte_chest_dl_set_smooth_filter(srslte_chest_dl_t *q, float *filter, uint32_t filter_len) {
|
||||||
|
if (filter_len < SRSLTE_CHEST_DL_MAX_SMOOTH_FIL_LEN) {
|
||||||
|
memcpy(q->smooth_filter, filter, filter_len*sizeof(float));
|
||||||
|
q->smooth_filter_len = filter_len;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Error setting smoothing filter: filter len exceeds maximum (%d>%d)\n",
|
||||||
|
filter_len, SRSLTE_CHEST_DL_MAX_SMOOTH_FIL_LEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void average_pilots(srslte_chest_dl_t *q, cf_t *input, cf_t *output, uint32_t port_id) {
|
||||||
|
uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(port_id);
|
||||||
|
uint32_t nref = 2*q->cell.nof_prb;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
float srslte_chest_dl_rssi(srslte_chest_dl_t *q, cf_t *input, uint32_t port_id) {
|
float srslte_chest_dl_rssi(srslte_chest_dl_t *q, cf_t *input, uint32_t port_id) {
|
||||||
uint32_t l;
|
uint32_t l;
|
||||||
|
|
||||||
|
@ -300,15 +293,14 @@ int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, u
|
||||||
srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->csr_signal.pilots[port_id/2][sf_idx],
|
srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->csr_signal.pilots[port_id/2][sf_idx],
|
||||||
q->pilot_estimates, SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id));
|
q->pilot_estimates, SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id));
|
||||||
if (ce != NULL) {
|
if (ce != NULL) {
|
||||||
/* TESTING: Use robust MMSE interpolation filter */
|
if (q->smooth_filter_len > 0) {
|
||||||
if (q->w_filter) {
|
average_pilots(q, q->pilot_estimates, q->pilot_estimates_average, port_id);
|
||||||
interpolate_filter_pilots(q, q->pilot_estimates, q->w_filter, ce, port_id);
|
interpolate_pilots(q, q->pilot_estimates_average, ce, port_id);
|
||||||
|
|
||||||
/* Estimate noise from difference from averaged and estimated pilots */
|
/* If averaging, compute noise from difference between received and averaged estimates */
|
||||||
if (sf_idx == 0 || sf_idx == 5) {
|
if (sf_idx == 0 || sf_idx == 5) {
|
||||||
q->noise_estimate[port_id] = estimate_noise_pilots(q, ce, port_id);
|
q->noise_estimate[port_id] = estimate_noise_pilots(q, ce, port_id);
|
||||||
}
|
}
|
||||||
/* If w filter not defined, resort to LS estimate + linear interpolation */
|
|
||||||
} else {
|
} else {
|
||||||
interpolate_pilots(q, q->pilot_estimates, ce, port_id);
|
interpolate_pilots(q, q->pilot_estimates, ce, port_id);
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -116,13 +116,6 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
||||||
|
|
||||||
srslte_precoding_init(&cheq, nof_re);
|
srslte_precoding_init(&cheq, nof_re);
|
||||||
|
|
||||||
|
|
||||||
cf_t *w=NULL;
|
|
||||||
if (nrhs > NOF_INPUTS) {
|
|
||||||
mexutils_read_cf(prhs[NOF_INPUTS], &w);
|
|
||||||
srslte_chest_dl_set_filter_w(&chest, w);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create output values */
|
/* Create output values */
|
||||||
if (nlhs >= 1) {
|
if (nlhs >= 1) {
|
||||||
plhs[0] = mxCreateDoubleMatrix(nof_re * nsubframes, cell.nof_ports, mxCOMPLEX);
|
plhs[0] = mxCreateDoubleMatrix(nof_re * nsubframes, cell.nof_ports, mxCOMPLEX);
|
||||||
|
@ -173,27 +166,23 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nlhs >= 1) {
|
if (nlhs >= 1) {
|
||||||
for (int j=0;j<cell.nof_ports;j++) {
|
for (i=0;i<nof_re;i++) {
|
||||||
for (i=0;i<nof_re;i++) {
|
*outr0 = (double) crealf(ce[0][i]);
|
||||||
*outr0 = (double) crealf(ce[j][i]);
|
if (outi0) {
|
||||||
if (outi0) {
|
*outi0 = (double) cimagf(ce[0][i]);
|
||||||
*outi0 = (double) cimagf(ce[j][i]);
|
|
||||||
}
|
|
||||||
outr0++;
|
|
||||||
outi0++;
|
|
||||||
}
|
}
|
||||||
|
outr0++;
|
||||||
|
outi0++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nlhs >= 2) {
|
if (nlhs >= 2) {
|
||||||
for (int j=0;j<cell.nof_ports;j++) {
|
for (i=0;i<SRSLTE_REFSIGNAL_NUM_SF(cell.nof_prb,0);i++) {
|
||||||
for (i=0;i<SRSLTE_REFSIGNAL_NUM_SF(cell.nof_prb,j);i++) {
|
*outr1 = (double) crealf(chest.pilot_estimates_average[i]);
|
||||||
*outr1 = (double) crealf(chest.pilot_estimates[i]);
|
if (outi1) {
|
||||||
if (outi1) {
|
*outi1 = (double) cimagf(chest.pilot_estimates_average[i]);
|
||||||
*outi1 = (double) cimagf(chest.pilot_estimates[i]);
|
|
||||||
}
|
|
||||||
outr1++;
|
|
||||||
outi1++;
|
|
||||||
}
|
}
|
||||||
|
outr1++;
|
||||||
|
outi1++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nlhs >= 3) {
|
if (nlhs >= 3) {
|
||||||
|
@ -208,10 +197,6 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (w) {
|
|
||||||
free(w);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nlhs >= 4) {
|
if (nlhs >= 4) {
|
||||||
plhs[3] = mxCreateDoubleScalar(noise_power);
|
plhs[3] = mxCreateDoubleScalar(noise_power);
|
||||||
}
|
}
|
||||||
|
|
|
@ -286,6 +286,7 @@ int srslte_rm_turbo_tx_lut(uint8_t *w_buff, uint8_t *systematic, uint8_t *parity
|
||||||
|
|
||||||
int srslte_rm_turbo_rx_lut(int16_t *input, int16_t *output, uint32_t in_len, uint32_t cb_idx, uint32_t rv_idx)
|
int srslte_rm_turbo_rx_lut(int16_t *input, int16_t *output, uint32_t in_len, uint32_t cb_idx, uint32_t rv_idx)
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef LV_HAVE_AVX
|
#ifdef LV_HAVE_AVX
|
||||||
return srslte_rm_turbo_rx_lut_avx(input, output, in_len, cb_idx, rv_idx);
|
return srslte_rm_turbo_rx_lut_avx(input, output, in_len, cb_idx, rv_idx);
|
||||||
#else
|
#else
|
||||||
|
@ -295,9 +296,7 @@ int srslte_rm_turbo_rx_lut(int16_t *input, int16_t *output, uint32_t in_len, uin
|
||||||
if (rv_idx < 4 && cb_idx < SRSLTE_NOF_TC_CB_SIZES) {
|
if (rv_idx < 4 && cb_idx < SRSLTE_NOF_TC_CB_SIZES) {
|
||||||
uint32_t out_len = 3*srslte_cbsegm_cbsize(cb_idx)+12;
|
uint32_t out_len = 3*srslte_cbsegm_cbsize(cb_idx)+12;
|
||||||
uint16_t *deinter = deinterleaver[cb_idx][rv_idx];
|
uint16_t *deinter = deinterleaver[cb_idx][rv_idx];
|
||||||
|
|
||||||
for (int i=0;i<in_len;i++) {
|
for (int i=0;i<in_len;i++) {
|
||||||
//printf("i=%d=%d goes to %d\n", i%out_len, input[i], deinter[i%out_len]);
|
|
||||||
output[deinter[i%out_len]] += input[i];
|
output[deinter[i%out_len]] += input[i];
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -69,8 +69,9 @@ void mod_qpsk_bytes(srslte_modem_table_t* q, uint8_t *bits, cf_t* symbols, uint3
|
||||||
for (int i=0;i<nbits/8;i++) {
|
for (int i=0;i<nbits/8;i++) {
|
||||||
memcpy(&symbols[4*i], &q->symbol_table_qpsk[bits[i]], sizeof(qpsk_packed_t));
|
memcpy(&symbols[4*i], &q->symbol_table_qpsk[bits[i]], sizeof(qpsk_packed_t));
|
||||||
}
|
}
|
||||||
|
// Encode last 1, 2 or 3 bit pairs if not multiple of 8
|
||||||
for (int i=0;i<(nbits%8)/2;i++) {
|
for (int i=0;i<(nbits%8)/2;i++) {
|
||||||
symbols[8*(nbits/8)+i] = q->symbol_table[(bits[8*(nbits/8)]&mask_qpsk[i])>>shift_qpsk[i]];
|
symbols[4*(nbits/8)+i] = q->symbol_table[(bits[nbits/8]&mask_qpsk[i])>>shift_qpsk[i]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +79,10 @@ void mod_16qam_bytes(srslte_modem_table_t* q, uint8_t *bits, cf_t* symbols, uint
|
||||||
for (int i=0;i<nbits/8;i++) {
|
for (int i=0;i<nbits/8;i++) {
|
||||||
memcpy(&symbols[2*i], &q->symbol_table_16qam[bits[i]], sizeof(qam16_packed_t));
|
memcpy(&symbols[2*i], &q->symbol_table_16qam[bits[i]], sizeof(qam16_packed_t));
|
||||||
}
|
}
|
||||||
symbols[8*(nbits/8)] = q->symbol_table[(bits[8*(nbits/8)]&0xf0)>>4];
|
// Encode last 4 bits if not multiple of 8
|
||||||
|
if (nbits%8) {
|
||||||
|
symbols[2*(nbits/8)] = q->symbol_table[(bits[nbits/8]&0xf0)>>4];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mod_64qam_bytes(srslte_modem_table_t* q, uint8_t *bits, cf_t* symbols, uint32_t nbits) {
|
void mod_64qam_bytes(srslte_modem_table_t* q, uint8_t *bits, cf_t* symbols, uint32_t nbits) {
|
||||||
|
@ -101,22 +105,22 @@ void mod_64qam_bytes(srslte_modem_table_t* q, uint8_t *bits, cf_t* symbols, uint
|
||||||
symbols[i*4+3] = q->symbol_table[in3];
|
symbols[i*4+3] = q->symbol_table[in3];
|
||||||
}
|
}
|
||||||
if (nbits%24 >= 6) {
|
if (nbits%24 >= 6) {
|
||||||
in80 = bits[24*(nbits/24)+0];
|
in80 = bits[3*(nbits/24)+0];
|
||||||
in0 = (in80&0xfc)>>2;
|
in0 = (in80&0xfc)>>2;
|
||||||
|
|
||||||
symbols[24*(nbits/24)+0] = q->symbol_table[in0];
|
symbols[4*(nbits/24)+0] = q->symbol_table[in0];
|
||||||
}
|
}
|
||||||
if (nbits%24 >= 12) {
|
if (nbits%24 >= 12) {
|
||||||
in81 = bits[24*(nbits/24)+1];
|
in81 = bits[3*(nbits/24)+1];
|
||||||
in1 = (in80&0x03)<<4 | ((in81&0xf0)>>4);
|
in1 = (in80&0x03)<<4 | ((in81&0xf0)>>4);
|
||||||
|
|
||||||
symbols[24*(nbits/24)+1] = q->symbol_table[in1];
|
symbols[4*(nbits/24)+1] = q->symbol_table[in1];
|
||||||
}
|
}
|
||||||
if (nbits%24 >= 18) {
|
if (nbits%24 >= 18) {
|
||||||
in82 = bits[24*(nbits/24)+2];
|
in82 = bits[3*(nbits/24)+2];
|
||||||
in2 = (in81&0x0f)<<2 | ((in82&0xc0)>>6);
|
in2 = (in81&0x0f)<<2 | ((in82&0xc0)>>6);
|
||||||
|
|
||||||
symbols[24*(nbits/24)+2] = q->symbol_table[in2];
|
symbols[4*(nbits/24)+2] = q->symbol_table[in2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -141,7 +141,7 @@ 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"
|
/* SNR-to-CQI conversion, got from "Downlink SNR to CQI Mapping for Different Multiple Antenna Techniques in LTE"
|
||||||
* Table III.
|
* 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, 24, 26, 28, 30};
|
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)
|
uint8_t srslte_cqi_from_snr(float snr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -522,10 +522,10 @@ int srslte_pdsch_encode_rnti(srslte_pdsch_t *q,
|
||||||
if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) {
|
if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) {
|
||||||
return SRSLTE_ERROR;
|
return SRSLTE_ERROR;
|
||||||
}
|
}
|
||||||
srslte_scrambling_bytes_offset(&seq, (uint8_t*) q->e, 0, cfg->nbits.nof_bits);
|
srslte_scrambling_bytes(&seq, (uint8_t*) q->e, cfg->nbits.nof_bits);
|
||||||
srslte_sequence_free(&seq);
|
srslte_sequence_free(&seq);
|
||||||
} else {
|
} else {
|
||||||
srslte_scrambling_bytes_offset(&q->seq[cfg->sf_idx], (uint8_t*) q->e, 0, cfg->nbits.nof_bits);
|
srslte_scrambling_bytes(&q->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);
|
srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->e, q->d, cfg->nbits.nof_bits);
|
||||||
|
|
|
@ -527,10 +527,10 @@ 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_bytes_offset(&seq, (uint8_t*) q->q, 0, cfg->nbits.nof_bits);
|
srslte_scrambling_bytes(&seq, (uint8_t*) q->q, cfg->nbits.nof_bits);
|
||||||
srslte_sequence_free(&seq);
|
srslte_sequence_free(&seq);
|
||||||
} else {
|
} else {
|
||||||
srslte_scrambling_bytes_offset(&q->seq[cfg->sf_idx], (uint8_t*) q->q, 0, cfg->nbits.nof_bits);
|
srslte_scrambling_bytes(&q->seq[cfg->sf_idx], (uint8_t*) q->q, cfg->nbits.nof_bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Correct UCI placeholder bits
|
// Correct UCI placeholder bits
|
||||||
|
|
|
@ -390,7 +390,6 @@ static int decode_tb(srslte_sch_t *q,
|
||||||
n_e = Qm * ((uint32_t) ceilf((float) Gp/cb_segm->C));
|
n_e = Qm * ((uint32_t) ceilf((float) Gp/cb_segm->C));
|
||||||
}
|
}
|
||||||
|
|
||||||
bzero(softbuffer->buffer_f[i], (3*cb_len+12)*sizeof(int16_t));
|
|
||||||
/* Rate Unmatching */
|
/* Rate Unmatching */
|
||||||
if (srslte_rm_turbo_rx_lut(&e_bits[rp], softbuffer->buffer_f[i], n_e, cblen_idx, rv)) {
|
if (srslte_rm_turbo_rx_lut(&e_bits[rp], softbuffer->buffer_f[i], n_e, cblen_idx, rv)) {
|
||||||
fprintf(stderr, "Error in rate matching\n");
|
fprintf(stderr, "Error in rate matching\n");
|
||||||
|
|
|
@ -95,6 +95,8 @@ TARGET_LINK_LIBRARIES(pdsch_test srslte)
|
||||||
ADD_TEST(pdsch_test_qpsk pdsch_test -m 10 -n 50 -r 1)
|
ADD_TEST(pdsch_test_qpsk pdsch_test -m 10 -n 50 -r 1)
|
||||||
ADD_TEST(pdsch_test_qam16 pdsch_test -m 20 -n 100)
|
ADD_TEST(pdsch_test_qam16 pdsch_test -m 20 -n 100)
|
||||||
ADD_TEST(pdsch_test_qam64 pdsch_test -m 28 -n 100 -r 0)
|
ADD_TEST(pdsch_test_qam64 pdsch_test -m 28 -n 100 -r 0)
|
||||||
|
ADD_TEST(pdsch_test_qam64 pdsch_test -m 28 -n 100 -r 1)
|
||||||
|
ADD_TEST(pdsch_test_qam64 pdsch_test -m 28 -n 25 -r 2)
|
||||||
|
|
||||||
BuildMex(MEXNAME pdsch SOURCES pdsch_test_mex.c LIBRARIES srslte srslte_mex)
|
BuildMex(MEXNAME pdsch SOURCES pdsch_test_mex.c LIBRARIES srslte srslte_mex)
|
||||||
BuildMex(MEXNAME dlsch_encode SOURCES dlsch_encode_test_mex.c LIBRARIES srslte srslte_mex)
|
BuildMex(MEXNAME dlsch_encode SOURCES dlsch_encode_test_mex.c LIBRARIES srslte srslte_mex)
|
||||||
|
|
|
@ -108,6 +108,15 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
||||||
mexErrMsgTxt("Error computing CB segmentation\n");
|
mexErrMsgTxt("Error computing CB segmentation\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
uint32_t tmp_rv=cfg.rv;
|
||||||
|
if (tmp_rv) {
|
||||||
|
cfg.rv = 0;
|
||||||
|
if (srslte_dlsch_encode(&dlsch, &cfg, &softbuffer, trblkin, e_bits)) {
|
||||||
|
mexErrMsgTxt("Error encoding TB\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cfg.rv = tmp_rv;
|
||||||
|
}
|
||||||
if (srslte_dlsch_encode(&dlsch, &cfg, &softbuffer, trblkin, e_bits)) {
|
if (srslte_dlsch_encode(&dlsch, &cfg, &softbuffer, trblkin, e_bits)) {
|
||||||
mexErrMsgTxt("Error encoding TB\n");
|
mexErrMsgTxt("Error encoding TB\n");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -118,14 +118,6 @@ cf_t *slot_symbols[SRSLTE_MAX_PORTS];
|
||||||
srslte_pdsch_t pdsch;
|
srslte_pdsch_t pdsch;
|
||||||
srslte_ofdm_t ofdm_tx, ofdm_rx;
|
srslte_ofdm_t ofdm_tx, ofdm_rx;
|
||||||
|
|
||||||
int dummy_function() {
|
|
||||||
#ifdef DO_OFDM
|
|
||||||
srslte_ofdm_rx_sf(&ofdm_rx, sf_symbols, slot_symbols[1]);
|
|
||||||
#endif
|
|
||||||
srslte_softbuffer_rx_reset_tbs(&softbuffer_rx, grant.mcs.tbs);
|
|
||||||
return srslte_pdsch_decode(&pdsch, &pdsch_cfg, &softbuffer_rx, slot_symbols[0], ce, 0, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
uint32_t i, j;
|
uint32_t i, j;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
@ -228,38 +220,53 @@ int main(int argc, char **argv) {
|
||||||
for (i=0;i<grant.mcs.tbs/8;i++) {
|
for (i=0;i<grant.mcs.tbs/8;i++) {
|
||||||
data[i] = rand()%256;
|
data[i] = rand()%256;
|
||||||
}
|
}
|
||||||
for (rv=0;rv<=rv_idx;rv++) {
|
|
||||||
|
|
||||||
pdsch_cfg.rv = rv;
|
uint8_t databit[100000];
|
||||||
|
srslte_bit_unpack_vector(data, databit, grant.mcs.tbs);
|
||||||
|
srslte_vec_save_file("data_in", databit, grant.mcs.tbs);
|
||||||
|
|
||||||
if (!input_file) {
|
if (!input_file) {
|
||||||
|
|
||||||
|
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, slot_symbols)) {
|
||||||
fprintf(stderr, "Error encoding PDSCH\n");
|
fprintf(stderr, "Error encoding PDSCH\n");
|
||||||
goto quit;
|
goto quit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pdsch_cfg.rv = rv_idx;
|
||||||
|
|
||||||
/* combine outputs */
|
if (srslte_pdsch_encode(&pdsch, &pdsch_cfg, &softbuffer_tx, data, slot_symbols)) {
|
||||||
for (i=0;i<cell.nof_ports;i++) {
|
fprintf(stderr, "Error encoding PDSCH\n");
|
||||||
for (j=0;j<SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);j++) {
|
goto quit;
|
||||||
if (i > 0) {
|
|
||||||
slot_symbols[0][j] += slot_symbols[i][j];
|
|
||||||
}
|
|
||||||
ce[i][j] = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* combine outputs */
|
||||||
|
for (i=0;i<cell.nof_ports;i++) {
|
||||||
|
for (j=0;j<SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);j++) {
|
||||||
|
if (i > 0) {
|
||||||
|
slot_symbols[0][j] += slot_symbols[i][j];
|
||||||
|
}
|
||||||
|
ce[i][j] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DO_OFDM
|
#ifdef DO_OFDM
|
||||||
srslte_ofdm_tx_sf(&ofdm_tx, slot_symbols[0], sf_symbols);
|
srslte_ofdm_tx_sf(&ofdm_tx, slot_symbols[0], sf_symbols);
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
}
|
}
|
||||||
int M=1;
|
int M=1;
|
||||||
int r=0;
|
int r=0;
|
||||||
srslte_sch_set_max_noi(&pdsch.dl_sch, 10);
|
srslte_sch_set_max_noi(&pdsch.dl_sch, 10);
|
||||||
gettimeofday(&t[1], NULL);
|
gettimeofday(&t[1], NULL);
|
||||||
for (i=0;i<M;i++) {
|
for (i=0;i<M;i++) {
|
||||||
r = dummy_function();
|
#ifdef DO_OFDM
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
gettimeofday(&t[2], NULL);
|
gettimeofday(&t[2], NULL);
|
||||||
get_time_interval(t);
|
get_time_interval(t);
|
||||||
|
|
|
@ -184,21 +184,9 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
||||||
ce[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
|
ce[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cf_t *w=NULL;
|
|
||||||
if (nrhs > NOF_INPUTS) {
|
|
||||||
mexutils_read_cf(prhs[NOF_INPUTS], &w);
|
|
||||||
srslte_chest_dl_set_filter_w(&chest, w);
|
|
||||||
srslte_chest_dl_estimate(&chest, input_fft, ce, cfg.sf_idx);
|
|
||||||
free(w);
|
|
||||||
} else {
|
|
||||||
srslte_chest_dl_estimate(&chest, input_fft, ce, cfg.sf_idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (nrhs > NOF_INPUTS) {
|
if (nrhs > NOF_INPUTS) {
|
||||||
cf_t *cearray = NULL;
|
cf_t *cearray = NULL;
|
||||||
nof_re = mexutils_read_cf(prhs[NOF_INPUTS], &cearray);
|
int nof_re = mexutils_read_cf(prhs[NOF_INPUTS], &cearray);
|
||||||
cf_t *cearray_ptr = cearray;
|
cf_t *cearray_ptr = cearray;
|
||||||
for (i=0;i<cell.nof_ports;i++) {
|
for (i=0;i<cell.nof_ports;i++) {
|
||||||
for (int j=0;j<nof_re/cell.nof_ports;j++) {
|
for (int j=0;j<nof_re/cell.nof_ports;j++) {
|
||||||
|
@ -211,13 +199,12 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
||||||
} else {
|
} else {
|
||||||
srslte_chest_dl_estimate(&chest, input_fft, ce, cfg.sf_idx);
|
srslte_chest_dl_estimate(&chest, input_fft, ce, cfg.sf_idx);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
float noise_power;
|
float noise_power;
|
||||||
if (nrhs > NOF_INPUTS + 1) {
|
if (nrhs > NOF_INPUTS + 1) {
|
||||||
noise_power = mxGetScalar(prhs[NOF_INPUTS+1]);
|
noise_power = mxGetScalar(prhs[NOF_INPUTS+1]);
|
||||||
} else {
|
} else {
|
||||||
noise_power = 0;
|
noise_power = srslte_chest_dl_get_noise_estimate(&chest);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *data_bytes = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs.tbs/8);
|
uint8_t *data_bytes = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs.tbs/8);
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include "srslte/utils/bit.h"
|
||||||
#include "srslte/utils/vector.h"
|
#include "srslte/utils/vector.h"
|
||||||
#include "srslte/scrambling/scrambling.h"
|
#include "srslte/scrambling/scrambling.h"
|
||||||
|
|
||||||
|
@ -58,47 +59,47 @@ void srslte_scrambling_c_offset(srslte_sequence_t *s, cf_t *data, int offset, in
|
||||||
srslte_vec_prod_cfc(data, &s->c_float[offset], data, len);
|
srslte_vec_prod_cfc(data, &s->c_float[offset], data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scrambling_b(uint8_t *c, uint8_t *data, int offset, int len) {
|
void scrambling_b(uint8_t *c, uint8_t *data, int len) {
|
||||||
int i;
|
int i;
|
||||||
// Do XOR on a word basis
|
for (i = 0; i < len; i++) {
|
||||||
|
data[i] = (data[i] ^ c[i]);
|
||||||
if (!(len%8)) {
|
|
||||||
uint64_t *x = (uint64_t*) data;
|
|
||||||
uint64_t *y = (uint64_t*) &c[offset];
|
|
||||||
for (int i=0;i<len/8;i++) {
|
|
||||||
x[i] = (x[i] ^ y[i]);
|
|
||||||
}
|
|
||||||
} else if (!(len%4)) {
|
|
||||||
uint32_t *x = (uint32_t*) data;
|
|
||||||
uint32_t *y = (uint32_t*) &c[offset];
|
|
||||||
for (int i=0;i<len/4;i++) {
|
|
||||||
x[i] = (x[i] ^ y[i]);
|
|
||||||
}
|
|
||||||
} else if (!(len%2)) {
|
|
||||||
uint16_t *x = (uint16_t*) data;
|
|
||||||
uint16_t *y = (uint16_t*) &c[offset];
|
|
||||||
for (int i=0;i<len/2;i++) {
|
|
||||||
x[i] = (x[i] ^ y[i]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
data[i] = (data[i] ^ c[i + offset]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void scrambling_b_word(uint8_t *c, uint8_t *data, int len) {
|
||||||
|
// Do XOR every 64 bits
|
||||||
|
// FIXME: Use 32-bit in 32-bit machines
|
||||||
|
uint64_t *x = (uint64_t*) data;
|
||||||
|
uint64_t *y = (uint64_t*) c;
|
||||||
|
for (int i=0;i<len/8;i++) {
|
||||||
|
x[i] = (x[i] ^ y[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do XOR every 8 bits
|
||||||
|
scrambling_b(&c[8*(len/8)], &data[8*(len/8)], len%8);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void srslte_scrambling_b(srslte_sequence_t *s, uint8_t *data) {
|
void srslte_scrambling_b(srslte_sequence_t *s, uint8_t *data) {
|
||||||
scrambling_b(s->c, data, 0, s->len);
|
scrambling_b_word(s->c, data, s->len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void srslte_scrambling_b_offset(srslte_sequence_t *s, uint8_t *data, int offset, int len) {
|
void srslte_scrambling_b_offset(srslte_sequence_t *s, uint8_t *data, int offset, int len) {
|
||||||
scrambling_b(s->c, data, offset, len);
|
if (offset%8) {
|
||||||
|
// Do not load words if offset is not word-aligned
|
||||||
|
scrambling_b(&s->c[offset], data, len);
|
||||||
|
} else {
|
||||||
|
scrambling_b_word(&s->c[offset], data, len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void srslte_scrambling_bytes(srslte_sequence_t *s, uint8_t *data) {
|
void srslte_scrambling_bytes(srslte_sequence_t *s, uint8_t *data, int len) {
|
||||||
scrambling_b(s->c_bytes, data, 0, s->len/8);
|
scrambling_b_word(s->c_bytes, data, len/8);
|
||||||
}
|
// Scramble last bits
|
||||||
|
if (len%8) {
|
||||||
void srslte_scrambling_bytes_offset(srslte_sequence_t *s, uint8_t *data, int offset, int len) {
|
uint8_t tmp_bits[8];
|
||||||
scrambling_b(s->c_bytes, data, offset, len/8);
|
srslte_bit_unpack_vector(&data[len/8], tmp_bits, len%8);
|
||||||
|
scrambling_b(&s->c[8*(len/8)], tmp_bits, len%8);
|
||||||
|
srslte_bit_pack_vector(tmp_bits, &data[len/8], len%8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue