mirror of https://github.com/PentHertz/srsLTE.git
Improved SFBC decoder and added SSE version. Fixed bug in MIB decoding. Improved calibration of synchronization constants
This commit is contained in:
parent
799af37bed
commit
c3268a93e2
|
@ -0,0 +1,46 @@
|
|||
clear
|
||||
|
||||
addpath('../../build/srslte/lib/mimo/test')
|
||||
|
||||
enb = lteRMCDL('R.10');
|
||||
|
||||
cec = struct('FreqWindow',9,'TimeWindow',9,'InterpType','cubic');
|
||||
cec.PilotAverage = 'UserDefined';
|
||||
cec.InterpWinSize = 1;
|
||||
cec.InterpWindow = 'Causal';
|
||||
|
||||
cfg.Seed = 1; % Random channel seed
|
||||
cfg.NRxAnts = 1; % 1 receive antenna
|
||||
cfg.DelayProfile = 'ETU'; % EVA delay spread
|
||||
cfg.DopplerFreq = 100; % 120Hz Doppler frequency
|
||||
cfg.MIMOCorrelation = 'Low'; % Low (no) MIMO correlation
|
||||
cfg.InitTime = 0; % Initialize at time zero
|
||||
cfg.NTerms = 16; % Oscillators used in fading model
|
||||
cfg.ModelType = 'GMEDS'; % Rayleigh fading model type
|
||||
cfg.InitPhase = 'Random'; % Random initial phases
|
||||
cfg.NormalizePathGains = 'On'; % Normalize delay profile power
|
||||
cfg.NormalizeTxAnts = 'On'; % Normalize for transmit antennas
|
||||
|
||||
[txWaveform, ~, info] = lteRMCDLTool(enb,[1;0;0;1]);
|
||||
n = length(txWaveform);
|
||||
cfg.SamplingRate = info.SamplingRate;
|
||||
|
||||
txWaveform = txWaveform+complex(randn(n,2),randn(n,2))*1e-3;
|
||||
|
||||
rxWaveform = lteFadingChannel(cfg,txWaveform);
|
||||
|
||||
rxGrid = lteOFDMDemodulate(enb,sum(rxWaveform,2));
|
||||
|
||||
[h,n0] = lteDLChannelEstimate(enb,cec,rxGrid);
|
||||
|
||||
signal=rxGrid(:,1);
|
||||
hest(:,1,1)=reshape(h(:,1,1,1),[],1);
|
||||
hest(:,1,2)=reshape(h(:,1,1,1),[],1);
|
||||
|
||||
output_mat = lteTransmitDiversityDecode(signal(, hest(1:598,1,:));
|
||||
output_srs = srslte_diversitydecode(signal(1:598), hest(1:598,1,:));
|
||||
|
||||
plot(abs(output_mat-output_srs))
|
||||
mean(abs(output_mat-output_srs).^2)
|
||||
|
||||
|
|
@ -1,18 +1,10 @@
|
|||
%clear
|
||||
% R.1 10 MHz 1 port
|
||||
% R.10 10 MHz 2 ports
|
||||
% R.4 1.4 MHz 1 port
|
||||
% R.11-2 5 MHz 2 ports
|
||||
rmc = lteRMCDL('R.10');
|
||||
clear
|
||||
|
||||
NofPortsTx=1;
|
||||
|
||||
SNR_values_db=1;%linspace(-8,-2,4);
|
||||
Nrealizations=5;
|
||||
enb = struct('NCellID',1,'NDLRB',25,'CellRefP',NofPortsTx,'CyclicPrefix','Normal','DuplexMode','FDD','NSubframe',0);
|
||||
|
||||
griddims = lteResourceGridSize(enb); % Resource grid dimensions
|
||||
L = griddims(2);
|
||||
Nblock=[3];
|
||||
SNR_values_db=100;%linspace(-4,0,6);
|
||||
Nrealizations=1;
|
||||
enb = struct('NCellID',62,'NDLRB',50,'CellRefP',2,'CyclicPrefix','Normal','DuplexMode','FDD',...
|
||||
'NSubframe',0,'PHICHDuration','Normal','Ng','One','NFrame',101,'TotSubframes',40);
|
||||
|
||||
cfg.Seed = 8; % Random channel seed
|
||||
cfg.NRxAnts = 1; % 1 receive antenna
|
||||
|
@ -33,59 +25,91 @@ cec.InterpType = 'linear'; % 2D interpolation type
|
|||
cec.InterpWindow = 'Centered'; % Interpolation window type
|
||||
cec.InterpWinSize = 1; % Interpolation window size
|
||||
|
||||
rmc.PDSCH.Modulation = '16QAM';
|
||||
[waveform,rgrid,info] = lteRMCDLTool(rmc,[1;0;0;1]);
|
||||
griddims = lteResourceGridSize(enb); % Resource grid dimensions
|
||||
L = griddims(2);
|
||||
|
||||
cfg.SamplingRate = info.SamplingRate;
|
||||
% Generate signal
|
||||
mib = lteMIB(enb);
|
||||
bchCoded = lteBCH(enb,mib);
|
||||
mibCRC = lteCRCEncode(mib,'16');
|
||||
mibCoded = lteConvolutionalEncode(mibCRC);
|
||||
pbchSymbolsTx = ltePBCH(enb,bchCoded);
|
||||
pbchIndtx = ltePBCHIndices(enb);
|
||||
subframe_tx = lteDLResourceGrid(enb);
|
||||
rs = lteCellRS(enb);
|
||||
rsind = lteCellRSIndices(enb);
|
||||
subframe_tx(rsind)=rs;
|
||||
|
||||
addpath('../../debug/lte/phy/lib/phch/test')
|
||||
NofPortsTx=enb.CellRefP;
|
||||
|
||||
addpath('../../build/srslte/lib/phch/test')
|
||||
|
||||
txWaveform=cell(length(Nblock));
|
||||
rxWaveform=cell(length(Nblock));
|
||||
for n=1:length(Nblock)
|
||||
subframe_tx2=subframe_tx;
|
||||
subframe_tx2(pbchIndtx)=pbchSymbolsTx(Nblock(n)*240+1:(Nblock(n)+1)*240,:);
|
||||
[txWaveform{n},info] = lteOFDMModulate(enb, subframe_tx2, 0);
|
||||
cfg.SamplingRate = info.SamplingRate;
|
||||
end
|
||||
|
||||
error=zeros(length(SNR_values_db),2);
|
||||
for snr_idx=1:length(SNR_values_db)
|
||||
SNRdB = SNR_values_db(snr_idx); % Desired SNR in dB
|
||||
SNR = 10^(SNRdB/20); % Linear SNR
|
||||
SNR = 10^(SNRdB/10); % Linear SNR
|
||||
|
||||
errorReal = zeros(Nrealizations,2);
|
||||
for i=1:Nrealizations
|
||||
|
||||
rxWaveform = lteFadingChannel(cfg,sum(waveform,2));
|
||||
for n=1:length(Nblock)
|
||||
|
||||
%% Additive Noise
|
||||
N0 = 1/(sqrt(2.0*double(enb.CellRefP)*double(info.Nfft))*SNR);
|
||||
%rxWaveform = lteFadingChannel(cfg,sum(txWaveform,2));
|
||||
rxWaveform{n} = sum(txWaveform{n},2);
|
||||
|
||||
% Create additive white Gaussian noise
|
||||
noise = N0*complex(randn(size(rxWaveform)),randn(size(rxWaveform)));
|
||||
%% Additive Noise
|
||||
N0 = 1/(sqrt(2.0*double(enb.CellRefP)*double(info.Nfft))*SNR);
|
||||
|
||||
rxWaveform = noise + rxWaveform;
|
||||
|
||||
rxWaveform = x((i-1)*76800+1:i*76800);
|
||||
|
||||
% Number of OFDM symbols in a subframe
|
||||
% OFDM demodulate signal
|
||||
rxgrid = lteOFDMDemodulate(enb, rxWaveform);
|
||||
% Create additive white Gaussian noise
|
||||
noise = N0*complex(randn(size(rxWaveform{n})),randn(size(rxWaveform{n})));
|
||||
|
||||
% Perform channel estimation
|
||||
[hest, nest] = lteDLChannelEstimate(enb, cec, rxgrid(:,1:L,:));
|
||||
|
||||
pbchIndices = ltePBCHIndices(enb);
|
||||
[pbchRx, pbchHest] = lteExtractResources( ...
|
||||
pbchIndices, rxgrid(:,1:L,:), hest(:,1:L,:,:));
|
||||
rxWaveform{n} = noise + rxWaveform{n};
|
||||
|
||||
% Decode PBCH
|
||||
[bchBits, pbchSymbols, nfmod4, mib, nof_ports] = ltePBCHDecode(enb, pbchRx, pbchHest, nest);
|
||||
% Number of OFDM symbols in a subframe
|
||||
% OFDM demodulate signal
|
||||
rxgrid = lteOFDMDemodulate(enb, rxWaveform{n}, 0);
|
||||
|
||||
if (nof_ports ~= NofPortsTx)
|
||||
errorReal(i,1)=1;
|
||||
% Perform channel estimation
|
||||
%enb.CellRefP=2;
|
||||
[hest, nest] = lteDLChannelEstimate(enb, cec, rxgrid(:,1:L,:));
|
||||
|
||||
pbchIndices = ltePBCHIndices(enb);
|
||||
[pbchRx, pbchHest] = lteExtractResources(pbchIndices, rxgrid(:,1:L,:), ...
|
||||
hest(:,1:L,:,:));
|
||||
|
||||
% Decode PBCH
|
||||
[bchBits, pbchSymbols, nfmod4, mib, nof_ports] = ltePBCHDecode(enb, pbchRx, pbchHest, nest);
|
||||
|
||||
if (nof_ports ~= NofPortsTx)
|
||||
errorReal(i,1)=1;
|
||||
end
|
||||
end
|
||||
|
||||
[nof_ports2, pbchSymbols2, pbchBits, ce, ce2, pbchRx2, pbchHest2]= srslte_pbch(enb, rxWaveform, hest, nest);
|
||||
%enb.CellRefP=NofPortsTx;
|
||||
[nof_ports2, pbchSymbols2, pbchBits, ce, ce2, pbchRx2, pbchHest2, mod2, codedbits]= ...
|
||||
srslte_pbch(enb, rxWaveform);
|
||||
|
||||
subplot(2,1,1)
|
||||
plot(abs((bchCoded(1:960)>0)-(pbchBits(1:960)>0)))
|
||||
subplot(2,1,2)
|
||||
codedbits2 = reshape(reshape(codedbits,3,[])',1,[]);
|
||||
plot(abs((codedbits2'>0)-(mibCoded>0)))
|
||||
|
||||
%decodedData = lteConvolutionalDecode(noisysymbols);
|
||||
%[decodedData2, quant] = srslte_viterbi(interleavedSymbols);
|
||||
|
||||
if (nof_ports2 ~= NofPortsTx)
|
||||
errorReal(i,2)=1;
|
||||
end
|
||||
% if (errorReal(i,1) ~= errorReal(i,2))
|
||||
% i=1;
|
||||
% end
|
||||
end
|
||||
error(snr_idx,:) = sum(errorReal);
|
||||
fprintf('SNR: %.2f dB\n', SNR_values_db(snr_idx));
|
||||
|
@ -100,5 +124,7 @@ if (length(SNR_values_db) > 1)
|
|||
axis([min(SNR_values_db) max(SNR_values_db) 1/Nrealizations/10 1])
|
||||
else
|
||||
disp(error)
|
||||
disp(nfmod4)
|
||||
disp(mod2)
|
||||
end
|
||||
|
||||
|
|
|
@ -5,25 +5,25 @@
|
|||
% A structure |enbConfig| is used to configure the eNodeB.
|
||||
clear
|
||||
|
||||
Npackets = 1;
|
||||
SNR_values = 100;%linspace(-5,0,8);
|
||||
Npackets = 60;
|
||||
SNR_values = linspace(2,6,6);
|
||||
|
||||
txCFI = 1;
|
||||
enbConfig.NDLRB = 50; % No of Downlink RBs in total BW
|
||||
txCFI = 3;
|
||||
enbConfig.NDLRB = 15; % No of Downlink RBs in total BW
|
||||
enbConfig.CyclicPrefix = 'Normal'; % CP length
|
||||
enbConfig.CFI = txCFI; ; % 4 PDCCH symbols as NDLRB <= 10
|
||||
enbConfig.Ng = 'One'; % HICH groups
|
||||
enbConfig.CellRefP = 2; % 1-antenna ports
|
||||
enbConfig.NCellID = 424; % Physical layer cell identity
|
||||
enbConfig.CellRefP = 1; % 1-antenna ports
|
||||
enbConfig.NCellID = 0; % Physical layer cell identity
|
||||
enbConfig.NSubframe = 5; % Subframe number 0
|
||||
enbConfig.DuplexMode = 'FDD'; % Frame structure
|
||||
enbConfig.PHICHDuration = 'Normal';
|
||||
C_RNTI = 65535; % 16-bit UE-specific mask
|
||||
C_RNTI = 1; % 16-bit UE-specific mask
|
||||
|
||||
%% Setup Fading channel model
|
||||
cfg.Seed = 8; % Random channel seed
|
||||
cfg.NRxAnts = 1; % 1 receive antenna
|
||||
cfg.DelayProfile = 'EPA'; % EVA delay spread
|
||||
cfg.DelayProfile = 'EVA'; % EVA delay spread
|
||||
cfg.DopplerFreq = 5; % 120Hz Doppler frequency
|
||||
cfg.MIMOCorrelation = 'Low'; % Low (no) MIMO correlation
|
||||
cfg.InitTime = 0; % Initialize at time zero
|
||||
|
@ -56,7 +56,7 @@ dciConfig.Allocation.RIV = 26; % Resource indication value
|
|||
if C_RNTI<65535
|
||||
pdcchConfig.RNTI = C_RNTI; % Radio network temporary identifier
|
||||
end
|
||||
pdcchConfig.PDCCHFormat = 2; % PDCCH format
|
||||
pdcchConfig.PDCCHFormat = 0; % PDCCH format
|
||||
ueConfig.RNTI = C_RNTI;
|
||||
|
||||
candidates = ltePDCCHSpace(enbConfig, pdcchConfig, {'bits', '1based'});
|
||||
|
@ -153,7 +153,7 @@ for snr_idx=1:length(SNR_values)
|
|||
%% Same with srsLTE
|
||||
[rxCFI_srslte, pcfichRx2, pcfichSymbols2] = srslte_pcfich(enbConfigRx, subframe_rx);
|
||||
decoded_cfi_srslte(snr_idx) = decoded_cfi_srslte(snr_idx) + (rxCFI_srslte == txCFI);
|
||||
enbConfigRx.CFI = rxCFI_srslte;
|
||||
enbConfigRx.CFI = rxCFI;
|
||||
[found_srslte, pdcchBits2, pdcchRx2, pdcchSymbols2, hest2] = srslte_pdcch(enbConfigRx, ueConfig.RNTI, subframe_rx, hest, nest);
|
||||
decoded_srslte(snr_idx) = decoded_srslte(snr_idx)+found_srslte;
|
||||
end
|
||||
|
@ -172,12 +172,6 @@ if (Npackets>1)
|
|||
axis([min(SNR_values) max(SNR_values) 1/Npackets/10 1])
|
||||
else
|
||||
|
||||
%scatter(real(pdcchSymbols2),imag(pdcchSymbols2))
|
||||
%hold on
|
||||
%scatter(real(pdcchSymbols),imag(pdcchSymbols))
|
||||
%axis([-1.5 1.5 -1.5 1.5])
|
||||
%hold off
|
||||
|
||||
n=min(length(pdcchSymbols),length(pdcchSymbols2));
|
||||
subplot(2,1,1)
|
||||
plot(abs(pdcchSymbols(1:n)-pdcchSymbols2(1:n)))
|
||||
|
@ -185,6 +179,9 @@ else
|
|||
subplot(2,1,2)
|
||||
pdcchBitsTx(pdcchBitsTx==-1)=0;
|
||||
plot(abs((pdcchBitsTx(1:n)>0.1)-(pdcchBits2(1:n)>0.1)))
|
||||
|
||||
subplot(1,1,1)
|
||||
plot(1:180,real(hest(:,1,1,1)),1:180,real(hest2(1:180)))
|
||||
|
||||
disp(decoded)
|
||||
disp(decoded_srslte)
|
||||
|
|
|
@ -53,7 +53,7 @@ char *mexutils_get_char_struct(const mxArray *ptr, const char *field_name) {
|
|||
mxArray *p;
|
||||
p = mxGetField(ptr, 0, field_name);
|
||||
if (!p) {
|
||||
return NULL;
|
||||
return "";
|
||||
}
|
||||
|
||||
if (mxIsCell(p)) {
|
||||
|
|
|
@ -40,10 +40,10 @@
|
|||
#include "srslte/rf/rf_utils.h"
|
||||
|
||||
cell_search_cfg_t cell_detect_config = {
|
||||
5000, // maximum number of frames to receive for MIB decoding
|
||||
50, // maximum number of frames to receive for PSS correlation
|
||||
10.0,
|
||||
50.0
|
||||
500,
|
||||
50,
|
||||
10,
|
||||
0
|
||||
};
|
||||
|
||||
/**********************************************************************
|
||||
|
@ -153,6 +153,7 @@ int main(int argc, char **argv) {
|
|||
int sfn_offset;
|
||||
float rssi_utra=0,rssi=0, rsrp=0, rsrq=0, snr=0;
|
||||
cf_t *ce[SRSLTE_MAX_PORTS];
|
||||
float cfo = 0;
|
||||
|
||||
if (parse_args(&prog_args, argc, argv)) {
|
||||
exit(-1);
|
||||
|
@ -191,7 +192,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
uint32_t ntrial=0;
|
||||
do {
|
||||
ret = rf_search_and_decode_mib(&rf, &cell_detect_config, prog_args.force_N_id_2, &cell);
|
||||
ret = rf_search_and_decode_mib(&rf, &cell_detect_config, prog_args.force_N_id_2, &cell, &cfo);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error searching for cell\n");
|
||||
exit(-1);
|
||||
|
@ -267,6 +268,9 @@ int main(int argc, char **argv) {
|
|||
|
||||
float rx_gain_offset = 0;
|
||||
|
||||
// Set initial CFO for ue_sync
|
||||
srslte_ue_sync_set_cfo(&ue_sync, cfo);
|
||||
|
||||
/* Main loop */
|
||||
while ((sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1) && !go_exit) {
|
||||
|
||||
|
|
|
@ -55,12 +55,13 @@
|
|||
int band = -1;
|
||||
int earfcn_start=-1, earfcn_end = -1;
|
||||
|
||||
cell_search_cfg_t config = {
|
||||
50, // maximum number of 5ms frames to capture for MIB decoding
|
||||
50, // maximum number of 5ms frames to capture for PSS correlation
|
||||
4.0, // early-stops cell detection if mean PSR is above this value
|
||||
0 // 0 or negative to disable AGC
|
||||
};
|
||||
|
||||
cell_search_cfg_t cell_detect_config = {
|
||||
500,
|
||||
50,
|
||||
10,
|
||||
0
|
||||
};
|
||||
|
||||
struct cells {
|
||||
srslte_cell_t cell;
|
||||
|
@ -80,13 +81,12 @@ void usage(char *prog) {
|
|||
printf("\t-s earfcn_start [Default All]\n");
|
||||
printf("\t-e earfcn_end [Default All]\n");
|
||||
printf("\t-n nof_frames_total [Default 100]\n");
|
||||
printf("\t-t threshold [Default %.2f]\n",config.threshold);
|
||||
printf("\t-v [set srslte_verbose to debug, default none]\n");
|
||||
}
|
||||
|
||||
void parse_args(int argc, char **argv) {
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "agsendtvb")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "agsendvb")) != -1) {
|
||||
switch(opt) {
|
||||
case 'a':
|
||||
rf_args = argv[optind];
|
||||
|
@ -101,10 +101,7 @@ void parse_args(int argc, char **argv) {
|
|||
earfcn_end = atoi(argv[optind]);
|
||||
break;
|
||||
case 'n':
|
||||
config.max_frames_pss = atoi(argv[optind]);
|
||||
break;
|
||||
case 't':
|
||||
config.threshold = atof(argv[optind]);
|
||||
cell_detect_config.max_frames_pss = atoi(argv[optind]);
|
||||
break;
|
||||
case 'g':
|
||||
rf_gain = atof(argv[optind]);
|
||||
|
@ -159,7 +156,7 @@ int main(int argc, char **argv) {
|
|||
fprintf(stderr, "Error opening rf\n");
|
||||
exit(-1);
|
||||
}
|
||||
if (!config.init_agc) {
|
||||
if (!cell_detect_config.init_agc) {
|
||||
srslte_rf_set_rx_gain(&rf, rf_gain);
|
||||
} else {
|
||||
printf("Starting AGC thread...\n");
|
||||
|
@ -203,19 +200,16 @@ int main(int argc, char **argv) {
|
|||
|
||||
bzero(found_cells, 3*sizeof(srslte_ue_cellsearch_result_t));
|
||||
|
||||
if (srslte_ue_cellsearch_init(&cs, srslte_rf_recv_wrapper, (void*) &rf)) {
|
||||
if (srslte_ue_cellsearch_init(&cs, cell_detect_config.max_frames_pss, srslte_rf_recv_wrapper, (void*) &rf)) {
|
||||
fprintf(stderr, "Error initiating UE cell detect\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (config.max_frames_pss) {
|
||||
srslte_ue_cellsearch_set_nof_frames_to_scan(&cs, config.max_frames_pss);
|
||||
if (cell_detect_config.max_frames_pss) {
|
||||
srslte_ue_cellsearch_set_nof_valid_frames(&cs, cell_detect_config.nof_valid_pss_frames);
|
||||
}
|
||||
if (config.threshold) {
|
||||
srslte_ue_cellsearch_set_threshold(&cs, config.threshold);
|
||||
}
|
||||
if (config.init_agc) {
|
||||
srslte_ue_sync_start_agc(&cs.ue_sync, srslte_rf_set_rx_gain_wrapper, config.init_agc);
|
||||
if (cell_detect_config.init_agc) {
|
||||
srslte_ue_sync_start_agc(&cs.ue_sync, srslte_rf_set_rx_gain_wrapper, cell_detect_config.init_agc);
|
||||
}
|
||||
|
||||
INFO("Setting sampling frequency %.2f MHz for PSS search\n", SRSLTE_CS_SAMP_FREQ/1000000);
|
||||
|
@ -229,11 +223,11 @@ int main(int argc, char **argv) {
|
|||
exit(-1);
|
||||
} else if (n > 0) {
|
||||
for (int i=0;i<3;i++) {
|
||||
if (found_cells[i].psr > config.threshold/2) {
|
||||
if (found_cells[i].psr > 10.0) {
|
||||
srslte_cell_t cell;
|
||||
cell.id = found_cells[i].cell_id;
|
||||
cell.cp = found_cells[i].cp;
|
||||
int ret = rf_mib_decoder(&rf, &config, &cell);
|
||||
int ret = rf_mib_decoder(&rf, &cell_detect_config, &cell, NULL);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error decoding MIB\n");
|
||||
exit(-1);
|
||||
|
|
|
@ -39,15 +39,20 @@
|
|||
|
||||
#include "srslte/srslte.h"
|
||||
|
||||
// From srsLTE 1.2, AGC is disabled by default
|
||||
//#define ENABLE_AGC_DEFAULT
|
||||
|
||||
#ifndef DISABLE_RF
|
||||
#include "srslte/rf/rf.h"
|
||||
#include "srslte/rf/rf_utils.h"
|
||||
|
||||
cell_search_cfg_t cell_detect_config = {
|
||||
5000,
|
||||
200, // nof_frames_total
|
||||
10.0 // threshold
|
||||
500,
|
||||
50,
|
||||
10,
|
||||
0
|
||||
};
|
||||
|
||||
#else
|
||||
#warning Compiling pdsch_ue with no RF support
|
||||
#endif
|
||||
|
@ -110,7 +115,11 @@ void args_default(prog_args_t *args) {
|
|||
args->file_offset_freq = 0;
|
||||
args->rf_args = "";
|
||||
args->rf_freq = -1.0;
|
||||
#ifdef ENABLE_AGC_DEFAULT
|
||||
args->rf_gain = -1.0;
|
||||
#else
|
||||
args->rf_gain = 50.0;
|
||||
#endif
|
||||
args->net_port = -1;
|
||||
args->net_address = "127.0.0.1";
|
||||
args->net_port_signal = -1;
|
||||
|
@ -277,6 +286,7 @@ int main(int argc, char **argv) {
|
|||
int n;
|
||||
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
|
||||
int sfn_offset;
|
||||
float cfo = 0;
|
||||
|
||||
parse_args(&prog_args, argc, argv);
|
||||
|
||||
|
@ -332,7 +342,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
uint32_t ntrial=0;
|
||||
do {
|
||||
ret = rf_search_and_decode_mib(&rf, &cell_detect_config, prog_args.force_N_id_2, &cell);
|
||||
ret = rf_search_and_decode_mib(&rf, &cell_detect_config, prog_args.force_N_id_2, &cell, &cfo);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error searching for cell\n");
|
||||
exit(-1);
|
||||
|
@ -439,7 +449,10 @@ int main(int argc, char **argv) {
|
|||
#endif
|
||||
|
||||
ue_sync.correct_cfo = !prog_args.disable_cfo;
|
||||
|
||||
|
||||
// Set initial CFO for ue_sync
|
||||
srslte_ue_sync_set_cfo(&ue_sync, cfo);
|
||||
|
||||
INFO("\nEntering main loop...\n\n", 0);
|
||||
/* Main loop */
|
||||
while (!go_exit && (sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1)) {
|
||||
|
@ -478,7 +491,7 @@ int main(int argc, char **argv) {
|
|||
decode_pdsch = true;
|
||||
} else {
|
||||
/* We are looking for SIB1 Blocks, search only in appropiate places */
|
||||
if ((srslte_ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%2)==0)) {
|
||||
if ((srslte_ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%8)==0)) {
|
||||
decode_pdsch = true;
|
||||
} else {
|
||||
decode_pdsch = false;
|
||||
|
@ -486,6 +499,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
if (decode_pdsch) {
|
||||
INFO("Attempting DL decode SFN=%d\n", sfn);
|
||||
if (prog_args.rnti != SRSLTE_SIRNTI) {
|
||||
n = srslte_ue_dl_decode(&ue_dl, &sf_buffer[prog_args.time_offset], data, srslte_ue_sync_get_sfidx(&ue_sync));
|
||||
} else {
|
||||
|
@ -495,7 +509,14 @@ int main(int argc, char **argv) {
|
|||
n = srslte_ue_dl_decode_rnti_rv(&ue_dl, &sf_buffer[prog_args.time_offset], data,
|
||||
srslte_ue_sync_get_sfidx(&ue_sync),
|
||||
SRSLTE_SIRNTI, rv);
|
||||
srslte_ue_dl_save_signal(&ue_dl, &ue_dl.softbuffer, sfn*10+srslte_ue_sync_get_sfidx(&ue_sync), rv);
|
||||
|
||||
/*
|
||||
if (!n) {
|
||||
printf("Saving signal...\n");
|
||||
srslte_ue_dl_save_signal(&ue_dl, &ue_dl.softbuffer, sfn*10+srslte_ue_sync_get_sfidx(&ue_sync), rv);
|
||||
exit(-1);
|
||||
}
|
||||
*/
|
||||
}
|
||||
if (n < 0) {
|
||||
// fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);
|
||||
|
|
|
@ -45,37 +45,17 @@
|
|||
*/
|
||||
|
||||
|
||||
typedef struct {
|
||||
cf_t *h_mod;
|
||||
cf_t *tmp1;
|
||||
cf_t *tmp2;
|
||||
cf_t *tmp3;
|
||||
float *y_mod;
|
||||
float *z_real;
|
||||
float *z_imag;
|
||||
uint32_t max_frame_len;
|
||||
} srslte_precoding_t;
|
||||
|
||||
|
||||
SRSLTE_API int srslte_precoding_init(srslte_precoding_t *q,
|
||||
uint32_t max_frame_len);
|
||||
|
||||
SRSLTE_API void srslte_precoding_free(srslte_precoding_t *q);
|
||||
|
||||
/* Generates the vector "y" from the input vector "x"
|
||||
*/
|
||||
SRSLTE_API int srslte_precoding_single(srslte_precoding_t *q,
|
||||
cf_t *x,
|
||||
SRSLTE_API int srslte_precoding_single(cf_t *x,
|
||||
cf_t *y,
|
||||
int nof_symbols);
|
||||
|
||||
SRSLTE_API int srslte_precoding_diversity(srslte_precoding_t *q,
|
||||
cf_t *x[SRSLTE_MAX_LAYERS],
|
||||
SRSLTE_API int srslte_precoding_diversity(cf_t *x[SRSLTE_MAX_LAYERS],
|
||||
cf_t *y[SRSLTE_MAX_PORTS],
|
||||
int nof_ports, int nof_symbols);
|
||||
|
||||
SRSLTE_API int srslte_precoding_type(srslte_precoding_t *q,
|
||||
cf_t *x[SRSLTE_MAX_LAYERS],
|
||||
SRSLTE_API int srslte_precoding_type(cf_t *x[SRSLTE_MAX_LAYERS],
|
||||
cf_t *y[SRSLTE_MAX_PORTS],
|
||||
int nof_layers,
|
||||
int nof_ports,
|
||||
|
@ -90,16 +70,13 @@ SRSLTE_API int srslte_predecoding_single(cf_t *y,
|
|||
int nof_symbols,
|
||||
float noise_estimate);
|
||||
|
||||
SRSLTE_API int srslte_predecoding_diversity(srslte_precoding_t *q,
|
||||
cf_t *y,
|
||||
SRSLTE_API int srslte_predecoding_diversity(cf_t *y,
|
||||
cf_t *h[SRSLTE_MAX_PORTS],
|
||||
cf_t *x[SRSLTE_MAX_LAYERS],
|
||||
int nof_ports,
|
||||
int nof_symbols,
|
||||
float noise_estimate);
|
||||
int nof_symbols);
|
||||
|
||||
SRSLTE_API int srslte_predecoding_type(srslte_precoding_t *q,
|
||||
cf_t *y,
|
||||
SRSLTE_API int srslte_predecoding_type(cf_t *y,
|
||||
cf_t *h[SRSLTE_MAX_PORTS],
|
||||
cf_t *x[SRSLTE_MAX_LAYERS],
|
||||
int nof_ports,
|
||||
|
|
|
@ -79,7 +79,6 @@ typedef struct SRSLTE_API {
|
|||
srslte_viterbi_t decoder;
|
||||
srslte_crc_t crc;
|
||||
srslte_convcoder_t encoder;
|
||||
srslte_precoding_t precoding;
|
||||
bool search_all_ports;
|
||||
|
||||
} srslte_pbch_t;
|
||||
|
|
|
@ -73,8 +73,7 @@ typedef struct SRSLTE_API {
|
|||
/* tx & rx objects */
|
||||
srslte_modem_table_t mod;
|
||||
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
|
||||
srslte_precoding_t precoding;
|
||||
|
||||
|
||||
} srslte_pcfich_t;
|
||||
|
||||
SRSLTE_API int srslte_pcfich_init(srslte_pcfich_t *q,
|
||||
|
|
|
@ -80,8 +80,7 @@ typedef struct SRSLTE_API {
|
|||
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
|
||||
srslte_viterbi_t decoder;
|
||||
srslte_crc_t crc;
|
||||
srslte_precoding_t precoding;
|
||||
|
||||
|
||||
} srslte_pdcch_t;
|
||||
|
||||
SRSLTE_API int srslte_pdcch_init(srslte_pdcch_t *q,
|
||||
|
|
|
@ -67,8 +67,7 @@ typedef struct SRSLTE_API {
|
|||
srslte_modem_table_t mod[4];
|
||||
|
||||
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
|
||||
srslte_precoding_t precoding;
|
||||
|
||||
|
||||
srslte_sch_t dl_sch;
|
||||
|
||||
} srslte_pdsch_t;
|
||||
|
|
|
@ -80,8 +80,7 @@ typedef struct SRSLTE_API {
|
|||
/* tx & rx objects */
|
||||
srslte_modem_table_t mod;
|
||||
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
|
||||
srslte_precoding_t precoding;
|
||||
|
||||
|
||||
} srslte_phich_t;
|
||||
|
||||
SRSLTE_API int srslte_phich_init(srslte_phich_t *q,
|
||||
|
|
|
@ -73,8 +73,6 @@ typedef struct SRSLTE_API {
|
|||
|
||||
srslte_dft_precoding_t dft_precoding;
|
||||
|
||||
srslte_precoding_t equalizer;
|
||||
|
||||
/* buffers */
|
||||
// void buffers are shared for tx and rx
|
||||
cf_t *ce;
|
||||
|
|
|
@ -29,31 +29,34 @@
|
|||
#include "srslte/rf/rf.h"
|
||||
|
||||
typedef struct SRSLTE_API {
|
||||
uint32_t max_frames_pbch; // maximum number of 5ms frames to capture for MIB decoding
|
||||
uint32_t max_frames_pss; // maximum number of 5ms frames to capture for PSS correlation
|
||||
float threshold; // early-stops cell detection if mean PSR is above this value
|
||||
uint32_t max_frames_pbch; // timeout in number of 5ms frames for MIB decoding
|
||||
uint32_t max_frames_pss; // timeout in number of 5ms frames for synchronization
|
||||
uint32_t nof_valid_pss_frames; // number of required synchronized frames
|
||||
float init_agc; // 0 or negative to disable AGC
|
||||
} cell_search_cfg_t;
|
||||
|
||||
SRSLTE_API int rf_rssi_scan(srslte_rf_t *rf,
|
||||
float *freqs,
|
||||
float *rssi,
|
||||
int nof_bands,
|
||||
double fs,
|
||||
int nsamp);
|
||||
float *freqs,
|
||||
float *rssi,
|
||||
int nof_bands,
|
||||
double fs,
|
||||
int nsamp);
|
||||
|
||||
SRSLTE_API int rf_mib_decoder(srslte_rf_t *rf,
|
||||
cell_search_cfg_t *config,
|
||||
srslte_cell_t *cell);
|
||||
cell_search_cfg_t *config,
|
||||
srslte_cell_t *cell,
|
||||
float *cfo);
|
||||
|
||||
SRSLTE_API int rf_cell_search(srslte_rf_t *rf,
|
||||
cell_search_cfg_t *config,
|
||||
int force_N_id_2,
|
||||
srslte_cell_t *cell);
|
||||
cell_search_cfg_t *config,
|
||||
int force_N_id_2,
|
||||
srslte_cell_t *cell,
|
||||
float *cfo);
|
||||
|
||||
SRSLTE_API int rf_search_and_decode_mib(srslte_rf_t *rf,
|
||||
cell_search_cfg_t *config,
|
||||
int force_N_id_2,
|
||||
srslte_cell_t *cell);
|
||||
cell_search_cfg_t *config,
|
||||
int force_N_id_2,
|
||||
srslte_cell_t *cell,
|
||||
float *cfo);
|
||||
|
||||
|
||||
|
|
|
@ -68,7 +68,6 @@ typedef struct SRSLTE_API {
|
|||
|
||||
float threshold;
|
||||
float peak_value;
|
||||
float mean_peak_value;
|
||||
uint32_t N_id_2;
|
||||
uint32_t N_id_1;
|
||||
uint32_t sf_idx;
|
||||
|
@ -97,6 +96,13 @@ typedef struct SRSLTE_API {
|
|||
|
||||
}srslte_sync_t;
|
||||
|
||||
typedef enum {
|
||||
SRSLTE_SYNC_FOUND = 1,
|
||||
SRSLTE_SYNC_FOUND_NOSPACE = 2,
|
||||
SRSLTE_SYNC_NOFOUND = 0,
|
||||
SRSLTE_SYNC_ERROR = -1
|
||||
} srslte_sync_find_ret_t;
|
||||
|
||||
|
||||
SRSLTE_API int srslte_sync_init(srslte_sync_t *q,
|
||||
uint32_t frame_size,
|
||||
|
@ -108,10 +114,10 @@ SRSLTE_API void srslte_sync_free(srslte_sync_t *q);
|
|||
SRSLTE_API void srslte_sync_reset(srslte_sync_t *q);
|
||||
|
||||
/* Finds a correlation peak in the input signal around position find_offset */
|
||||
SRSLTE_API int srslte_sync_find(srslte_sync_t *q,
|
||||
cf_t *input,
|
||||
uint32_t find_offset,
|
||||
uint32_t *peak_position);
|
||||
SRSLTE_API srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q,
|
||||
cf_t *input,
|
||||
uint32_t find_offset,
|
||||
uint32_t *peak_position);
|
||||
|
||||
/* Estimates the CP length */
|
||||
SRSLTE_API srslte_cp_t srslte_sync_detect_cp(srslte_sync_t *q,
|
||||
|
|
|
@ -57,12 +57,6 @@
|
|||
* TODO: Check also peak offset
|
||||
*/
|
||||
|
||||
#define SRSLTE_CS_DEFAULT_MAXFRAMES_TOTAL 500
|
||||
#define SRSLTE_CS_DEFAULT_MAXFRAMES_DETECTED 50
|
||||
|
||||
#define SRSLTE_CS_DEFAULT_NOFFRAMES_TOTAL 50
|
||||
#define SRSLTE_CS_DEFAULT_NOFFRAMES_DETECTED 10
|
||||
|
||||
#define SRSLTE_CS_NOF_PRB 6
|
||||
#define SRSLTE_CS_SAMP_FREQ 1920000.0
|
||||
|
||||
|
@ -80,8 +74,7 @@ typedef struct SRSLTE_API {
|
|||
srslte_ue_sync_t ue_sync;
|
||||
|
||||
uint32_t max_frames;
|
||||
uint32_t nof_frames_to_scan; // number of 5 ms frames to scan
|
||||
float detect_threshold; // early-stops scan if mean PSR above this threshold
|
||||
uint32_t nof_valid_frames; // number of 5 ms frames to scan
|
||||
|
||||
uint32_t *mode_ntimes;
|
||||
uint8_t *mode_counted;
|
||||
|
@ -89,16 +82,11 @@ typedef struct SRSLTE_API {
|
|||
srslte_ue_cellsearch_result_t *candidates;
|
||||
} srslte_ue_cellsearch_t;
|
||||
|
||||
|
||||
SRSLTE_API int srslte_ue_cellsearch_init(srslte_ue_cellsearch_t *q,
|
||||
uint32_t max_frames_total,
|
||||
int (recv_callback)(void*, void*, uint32_t,srslte_timestamp_t*),
|
||||
void *stream_handler);
|
||||
|
||||
SRSLTE_API int srslte_ue_cellsearch_init_max(srslte_ue_cellsearch_t *q,
|
||||
uint32_t max_frames_total,
|
||||
int (recv_callback)(void*, void*, uint32_t,srslte_timestamp_t*),
|
||||
void *stream_handler);
|
||||
|
||||
SRSLTE_API void srslte_ue_cellsearch_free(srslte_ue_cellsearch_t *q);
|
||||
|
||||
SRSLTE_API int srslte_ue_cellsearch_scan_N_id_2(srslte_ue_cellsearch_t *q,
|
||||
|
@ -109,11 +97,8 @@ SRSLTE_API int srslte_ue_cellsearch_scan(srslte_ue_cellsearch_t * q,
|
|||
srslte_ue_cellsearch_result_t found_cells[3],
|
||||
uint32_t *max_N_id_2);
|
||||
|
||||
SRSLTE_API int srslte_ue_cellsearch_set_nof_frames_to_scan(srslte_ue_cellsearch_t *q,
|
||||
uint32_t nof_frames);
|
||||
|
||||
SRSLTE_API void srslte_ue_cellsearch_set_threshold(srslte_ue_cellsearch_t *q,
|
||||
float threshold);
|
||||
SRSLTE_API int srslte_ue_cellsearch_set_nof_valid_frames(srslte_ue_cellsearch_t *q,
|
||||
uint32_t nof_frames);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -41,8 +41,9 @@
|
|||
|
||||
#define ESTIMATE_NOISE_LS_PSS
|
||||
|
||||
#define DEFAULT_FILTER_LEN 3
|
||||
//#define DEFAULT_FILTER_LEN 3
|
||||
|
||||
#ifdef DEFAULT_FILTER_LEN
|
||||
static void set_default_filter(srslte_chest_dl_t *q, int filter_len) {
|
||||
|
||||
float fil[SRSLTE_CHEST_DL_MAX_SMOOTH_FIL_LEN];
|
||||
|
@ -63,6 +64,7 @@ static void set_default_filter(srslte_chest_dl_t *q, int filter_len) {
|
|||
|
||||
srslte_chest_dl_set_smooth_filter(q, fil, filter_len);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** 3GPP LTE Downlink channel estimator and equalizer.
|
||||
* Estimates the channel in the resource elements transmitting references and interpolates for the rest
|
||||
|
@ -124,9 +126,13 @@ int srslte_chest_dl_init(srslte_chest_dl_t *q, srslte_cell_t cell)
|
|||
}
|
||||
|
||||
q->smooth_filter_len = 0;
|
||||
|
||||
#ifdef DEFAULT_FILTER_LEN
|
||||
set_default_filter(q, DEFAULT_FILTER_LEN);
|
||||
#else
|
||||
float fil[3] = {0.1, 0.8, 0.1};
|
||||
srslte_chest_dl_set_smooth_filter(q, fil, 3);
|
||||
//set_default_filter(q, DEFAULT_FILTER_LEN);
|
||||
#endif
|
||||
|
||||
q->cell = cell;
|
||||
}
|
||||
|
|
|
@ -82,7 +82,6 @@ void parse_args(int argc, char **argv) {
|
|||
|
||||
int main(int argc, char **argv) {
|
||||
srslte_chest_dl_t est;
|
||||
srslte_precoding_t cheq;
|
||||
cf_t *input = NULL, *ce = NULL, *h = NULL, *output = NULL;
|
||||
int i, j, n_port=0, sf_idx=0, cid=0, num_re;
|
||||
int ret = -1;
|
||||
|
@ -129,8 +128,6 @@ int main(int argc, char **argv) {
|
|||
cid = cell.id;
|
||||
max_cid = cell.id;
|
||||
}
|
||||
|
||||
srslte_precoding_init(&cheq, num_re);
|
||||
|
||||
while(cid <= max_cid) {
|
||||
cell.id = cid;
|
||||
|
@ -227,8 +224,6 @@ int main(int argc, char **argv) {
|
|||
|
||||
do_exit:
|
||||
|
||||
srslte_precoding_free(&cheq);
|
||||
|
||||
if (output) {
|
||||
free(output);
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
int i;
|
||||
srslte_cell_t cell;
|
||||
srslte_chest_dl_t chest;
|
||||
srslte_precoding_t cheq;
|
||||
|
||||
cf_t *input_signal = NULL, *output_signal[SRSLTE_MAX_LAYERS];
|
||||
cf_t *output_signal2 = NULL;
|
||||
cf_t *ce[SRSLTE_MAX_PORTS];
|
||||
|
@ -114,8 +114,6 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
}
|
||||
output_signal2 = srslte_vec_malloc(nof_re * sizeof(cf_t));
|
||||
|
||||
srslte_precoding_init(&cheq, nof_re);
|
||||
|
||||
/* Create output values */
|
||||
if (nlhs >= 1) {
|
||||
plhs[0] = mxCreateDoubleMatrix(nof_re * nsubframes, cell.nof_ports, mxCOMPLEX);
|
||||
|
@ -161,7 +159,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
if (cell.nof_ports == 1) {
|
||||
srslte_predecoding_single(input_signal, ce[0], output_signal2, nof_re, srslte_chest_dl_get_noise_estimate(&chest));
|
||||
} else {
|
||||
srslte_predecoding_diversity(&cheq, input_signal, ce, output_signal, cell.nof_ports, nof_re, srslte_chest_dl_get_noise_estimate(&chest));
|
||||
srslte_predecoding_diversity(input_signal, ce, output_signal, cell.nof_ports, nof_re);
|
||||
srslte_layerdemap_diversity(output_signal, output_signal2, cell.nof_ports, nof_re/cell.nof_ports);
|
||||
}
|
||||
|
||||
|
@ -205,7 +203,6 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
}
|
||||
|
||||
srslte_chest_dl_free(&chest);
|
||||
srslte_precoding_free(&cheq);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include "srslte/common/phy_common.h"
|
||||
#include "srslte/common/sequence.h"
|
||||
|
||||
#define FORCE_STANDARD_RATE
|
||||
#ifdef FORCE_STANDARD_RATE
|
||||
static bool use_standard_rates = true;
|
||||
#else
|
||||
|
|
|
@ -204,11 +204,11 @@ int main(int argc, char **argv) {
|
|||
for (j = 0; j < coded_length; j++) {
|
||||
llr[j] = symbols[j] ? sqrt(2) : -sqrt(2);
|
||||
}
|
||||
|
||||
|
||||
srslte_ch_awgn_f(llr, llr, var[i], coded_length);
|
||||
|
||||
srslte_vec_quant_fuc(llr, llr_c, Gain, 127.5, 255, coded_length);
|
||||
|
||||
|
||||
struct timeval t[3];
|
||||
gettimeofday(&t[1], NULL);
|
||||
int M = 1;
|
||||
|
@ -264,8 +264,7 @@ int main(int argc, char **argv) {
|
|||
free(data_rx);
|
||||
|
||||
if (snr_points == 1) {
|
||||
int expected_errors = get_expected_errors(nof_frames,
|
||||
seed, frame_length, tail_biting, ebno_db);
|
||||
int expected_errors = get_expected_errors(nof_frames, seed, frame_length, tail_biting, ebno_db);
|
||||
if (expected_errors == -1) {
|
||||
fprintf(stderr, "Test parameters not defined in test_results.h\n");
|
||||
exit(-1);
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <xmmintrin.h>
|
||||
#include <pmmintrin.h>
|
||||
int srslte_predecoding_single_sse(cf_t *y, cf_t *h, cf_t *x, int nof_symbols, float noise_estimate);
|
||||
int srslte_predecoding_diversity2_sse(cf_t *y, cf_t *h[SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], int nof_symbols);
|
||||
#endif
|
||||
|
||||
#ifdef LV_HAVE_AVX
|
||||
|
@ -53,81 +54,6 @@ int srslte_predecoding_single_avx(cf_t *y, cf_t *h, cf_t *x, int nof_symbols, fl
|
|||
*
|
||||
**************************************************/
|
||||
|
||||
int srslte_precoding_init(srslte_precoding_t *q, uint32_t max_frame_len) {
|
||||
if (q) {
|
||||
bzero(q, sizeof(srslte_precoding_t));
|
||||
|
||||
q->h_mod = srslte_vec_malloc(sizeof(cf_t) * max_frame_len);
|
||||
if (!q->h_mod) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
q->tmp1 = srslte_vec_malloc(sizeof(cf_t) * max_frame_len);
|
||||
if (!q->tmp1) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
q->tmp2 = srslte_vec_malloc(sizeof(cf_t) * max_frame_len);
|
||||
if (!q->tmp2) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
q->tmp3 = srslte_vec_malloc(sizeof(cf_t) * max_frame_len);
|
||||
if (!q->tmp3) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
q->y_mod = srslte_vec_malloc(sizeof(float) * max_frame_len);
|
||||
if (!q->y_mod) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
q->z_real = srslte_vec_malloc(sizeof(float) * max_frame_len);
|
||||
if (!q->z_real) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
q->z_imag = srslte_vec_malloc(sizeof(float) * max_frame_len);
|
||||
if (!q->z_imag) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
q->max_frame_len = max_frame_len;
|
||||
return SRSLTE_SUCCESS;
|
||||
} else {
|
||||
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
clean_exit:
|
||||
srslte_precoding_free(q);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
void srslte_precoding_free(srslte_precoding_t *q) {
|
||||
|
||||
if (q->tmp1) {
|
||||
free(q->tmp1);
|
||||
}
|
||||
if (q->tmp2) {
|
||||
free(q->tmp2);
|
||||
}
|
||||
if (q->tmp3) {
|
||||
free(q->tmp3);
|
||||
}
|
||||
if (q->h_mod) {
|
||||
free(q->h_mod);
|
||||
}
|
||||
if (q->y_mod) {
|
||||
free(q->y_mod);
|
||||
}
|
||||
if (q->z_real) {
|
||||
free(q->z_real);
|
||||
}
|
||||
if (q->z_imag) {
|
||||
free(q->z_imag);
|
||||
}
|
||||
bzero(q, sizeof(srslte_precoding_t));
|
||||
}
|
||||
|
||||
#ifdef LV_HAVE_SSE
|
||||
|
||||
#define PROD(a,b) _mm_addsub_ps(_mm_mul_ps(a,_mm_moveldup_ps(b)),_mm_mul_ps(_mm_shuffle_ps(a,a,0xB1),_mm_movehdup_ps(b)))
|
||||
|
@ -262,83 +188,37 @@ int srslte_predecoding_single(cf_t *y, cf_t *h, cf_t *x, int nof_symbols, float
|
|||
#endif
|
||||
}
|
||||
|
||||
/* ZF/MMSE STBC equalizer x=y(H'H+n0·I)^(-1)H' (ZF is n0=0.0)
|
||||
*/
|
||||
int srslte_predecoding_diversity(srslte_precoding_t *q, cf_t *y, cf_t *h[SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS],
|
||||
int nof_ports, int nof_symbols, float noise_estimate)
|
||||
/* C implementatino of the SFBC equalizer */
|
||||
int srslte_predecoding_diversity_gen_(cf_t *y, cf_t *h[SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS],
|
||||
int nof_ports, int nof_symbols, int symbol_start)
|
||||
{
|
||||
int i;
|
||||
if (nof_ports == 2) {
|
||||
|
||||
#define new
|
||||
#ifdef new
|
||||
|
||||
// reuse buffers
|
||||
cf_t *r0 = q->tmp3;
|
||||
cf_t *r1 = &q->tmp3[nof_symbols/2];
|
||||
cf_t *h0 = q->h_mod;
|
||||
cf_t *h1 = &q->h_mod[nof_symbols/2];
|
||||
|
||||
float *modhh = q->y_mod;
|
||||
float *modh0 = q->z_real;
|
||||
float *modh1 = q->z_imag;
|
||||
|
||||
// prepare buffers
|
||||
for (i=0;i<nof_symbols/2;i++) {
|
||||
h0[i] = h[0][2*i]; // h0
|
||||
h1[i] = h[1][2*i+1]; // h1
|
||||
r0[i] = y[2*i]; // r0
|
||||
r1[i] = y[2*i+1]; // r1
|
||||
}
|
||||
|
||||
// Compute common dividend and store in y_mod
|
||||
srslte_vec_abs_square_cf(h0, modh0, nof_symbols/2);
|
||||
srslte_vec_abs_square_cf(h1, modh1, nof_symbols/2);
|
||||
srslte_vec_sum_fff(modh0, modh1, modhh, nof_symbols/2);
|
||||
//if (noise_estimate > 0.0) {
|
||||
// (H'H + n0)
|
||||
//srslte_vec_sc_add_fff(modhh, noise_estimate, modhh, nof_symbols/2);
|
||||
//}
|
||||
|
||||
srslte_vec_sc_prod_fff(modhh, 1/sqrt(2), modhh, nof_symbols/2);
|
||||
|
||||
// x[0] = r0·h0*/(|h0|+|h1|)+r1*·h1/(|h0|+|h1|)
|
||||
srslte_vec_prod_conj_ccc(r0,h0,q->tmp1, nof_symbols/2);
|
||||
srslte_vec_prod_conj_ccc(h1,r1,q->tmp2, nof_symbols/2);
|
||||
srslte_vec_sum_ccc(q->tmp1, q->tmp2, x[0], nof_symbols/2);
|
||||
srslte_vec_div_cfc(x[0], modhh, x[0], q->z_real, q->z_imag, nof_symbols/2);
|
||||
cf_t h00, h01, h10, h11, r0, r1;
|
||||
float hh;
|
||||
|
||||
// x[1] = r1·h0*/(|h0|+|h1|)-r0*·h1/(|h0|+|h1|)
|
||||
srslte_vec_prod_conj_ccc(r1,h0,q->tmp1, nof_symbols/2);
|
||||
srslte_vec_prod_conj_ccc(h1,r0,q->tmp2, nof_symbols/2);
|
||||
srslte_vec_sub_ccc(q->tmp1, q->tmp2, x[1], nof_symbols/2);
|
||||
srslte_vec_div_cfc(x[1], modhh, x[1], q->z_real, q->z_imag, nof_symbols/2);
|
||||
|
||||
#else
|
||||
cf_t h0, h1, h2, h3, r0, r1, r2, r3;
|
||||
float hh, hh02, hh13;
|
||||
|
||||
for (i = 0; i < nof_symbols / 2; i++) {
|
||||
h0 = h[0][2 * i];
|
||||
h1 = h[1][2 * i];
|
||||
hh = crealf(h0) * crealf(h0) + cimagf(h0) * cimagf(h0)
|
||||
+ crealf(h1) * crealf(h1) + cimagf(h1) * cimagf(h1) + noise_estimate;
|
||||
for (i = symbol_start/2; i < nof_symbols / 2; i++) {
|
||||
h00 = h[0][2 * i];
|
||||
h01 = h[0][2 * i+1];
|
||||
h10 = h[1][2 * i];
|
||||
h11 = h[1][2 * i+1];
|
||||
hh = crealf(h00) * crealf(h00) + cimagf(h00) * cimagf(h00)
|
||||
+ crealf(h11) * crealf(h11) + cimagf(h11) * cimagf(h11);
|
||||
r0 = y[2 * i];
|
||||
r1 = y[2 * i + 1];
|
||||
if (hh == 0) {
|
||||
hh = 1e-2;
|
||||
hh = 1e-4;
|
||||
}
|
||||
x[0][i] = (conjf(h0) * r0 + h1 * conjf(r1)) / hh * sqrt(2);
|
||||
x[1][i] = (-h1 * conj(r0) + conj(h0) * r1) / hh * sqrt(2);
|
||||
x[0][i] = (conjf(h00) * r0 + h11 * conjf(r1)) / hh * sqrt(2);
|
||||
x[1][i] = (-h10 * conj(r0) + conj(h01) * r1) / hh * sqrt(2);
|
||||
}
|
||||
#endif
|
||||
return i;
|
||||
} else if (nof_ports == 4) {
|
||||
cf_t h0, h1, h2, h3, r0, r1, r2, r3;
|
||||
float hh02, hh13;
|
||||
|
||||
int m_ap = (nof_symbols % 4) ? ((nof_symbols - 2) / 4) : nof_symbols / 4;
|
||||
for (i = 0; i < m_ap; i++) {
|
||||
for (i = symbol_start; i < m_ap; i++) {
|
||||
h0 = h[0][4 * i];
|
||||
h1 = h[1][4 * i + 2];
|
||||
h2 = h[2][4 * i];
|
||||
|
@ -365,8 +245,88 @@ int srslte_predecoding_diversity(srslte_precoding_t *q, cf_t *y, cf_t *h[SRSLTE_
|
|||
}
|
||||
}
|
||||
|
||||
int srslte_predecoding_diversity_gen(cf_t *y, cf_t *h[SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS],
|
||||
int nof_ports, int nof_symbols) {
|
||||
return srslte_predecoding_diversity_gen_(y, h, x, nof_ports, nof_symbols, 0);
|
||||
}
|
||||
|
||||
/* SSE implementation of the 2-port SFBC equalizer */
|
||||
#ifdef LV_HAVE_SSE
|
||||
int srslte_predecoding_diversity2_sse(cf_t *y, cf_t *h[SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], int nof_symbols)
|
||||
{
|
||||
float *x0Ptr = (float*) x[0];
|
||||
float *x1Ptr = (float*) x[1];
|
||||
const float *h0Ptr = (const float*) h[0];
|
||||
const float *h1Ptr = (const float*) h[1];
|
||||
const float *yPtr = (const float*) y;
|
||||
|
||||
__m128 conjugator = _mm_setr_ps(0, -0.f, 0, -0.f);
|
||||
__m128 sqrt2 = _mm_setr_ps(sqrt(2), sqrt(2), sqrt(2), sqrt(2));
|
||||
|
||||
__m128 h0Val_0, h0Val_1, h1Val_0, h1Val_1, h00, h00conj, h01, h01conj, h10, h11, hh, hhshuf, hhsum, hhadd;
|
||||
__m128 r0Val, r1Val, r0, r1, r0conj, r1conj;
|
||||
__m128 x0, x1;
|
||||
|
||||
for (int i=0;i<nof_symbols/4;i++) {
|
||||
|
||||
h0Val_0 = _mm_load_ps(h0Ptr); h0Ptr+=4; h0Val_1 = _mm_load_ps(h0Ptr); h0Ptr+=4;
|
||||
h1Val_0 = _mm_load_ps(h1Ptr); h1Ptr+=4; h1Val_1 = _mm_load_ps(h1Ptr); h1Ptr+=4;
|
||||
|
||||
h00 = _mm_shuffle_ps(h0Val_0, h0Val_1, _MM_SHUFFLE(1, 0, 1, 0));
|
||||
h01 = _mm_shuffle_ps(h0Val_0, h0Val_1, _MM_SHUFFLE(3, 2, 3, 2));
|
||||
|
||||
h10 = _mm_shuffle_ps(h1Val_0, h1Val_1, _MM_SHUFFLE(1, 0, 1, 0));
|
||||
h11 = _mm_shuffle_ps(h1Val_0, h1Val_1, _MM_SHUFFLE(3, 2, 3, 2));
|
||||
|
||||
r0Val = _mm_load_ps(yPtr); yPtr+=4;
|
||||
r1Val = _mm_load_ps(yPtr); yPtr+=4;
|
||||
r0 = _mm_shuffle_ps(r0Val, r1Val, _MM_SHUFFLE(1, 0, 1, 0));
|
||||
r1 = _mm_shuffle_ps(r0Val, r1Val, _MM_SHUFFLE(3, 2, 3, 2));
|
||||
|
||||
/* Compute channel gain */
|
||||
hhadd = _mm_hadd_ps(_mm_mul_ps(h00, h00), _mm_mul_ps(h11, h11));
|
||||
hhshuf = _mm_shuffle_ps(hhadd, hhadd, _MM_SHUFFLE(3, 1, 2, 0));
|
||||
hhsum = _mm_hadd_ps(hhshuf, hhshuf);
|
||||
hh = _mm_shuffle_ps(hhsum, hhsum, _MM_SHUFFLE(1, 1, 0, 0)); // h00^2+h11^2
|
||||
|
||||
// Conjugate value
|
||||
h00conj = _mm_xor_ps(h00, conjugator);
|
||||
h01conj = _mm_xor_ps(h01, conjugator);
|
||||
r0conj = _mm_xor_ps(r0, conjugator);
|
||||
r1conj = _mm_xor_ps(r1, conjugator);
|
||||
|
||||
// Multiply by channel matrix
|
||||
x0 = _mm_add_ps(PROD(h00conj, r0), PROD(h11, r1conj));
|
||||
x1 = _mm_sub_ps(PROD(h01conj, r1), PROD(h10, r0conj));
|
||||
|
||||
x0 = _mm_mul_ps(_mm_div_ps(x0, hh), sqrt2);
|
||||
x1 = _mm_mul_ps(_mm_div_ps(x1, hh), sqrt2);
|
||||
|
||||
_mm_store_ps(x0Ptr, x0); x0Ptr+=4;
|
||||
_mm_store_ps(x1Ptr, x1); x1Ptr+=4;
|
||||
}
|
||||
// Compute remaining symbols using generic implementation
|
||||
srslte_predecoding_diversity_gen_(y, h, x, 2, nof_symbols, 4*(nof_symbols/4));
|
||||
return nof_symbols;
|
||||
}
|
||||
#endif
|
||||
|
||||
int srslte_predecoding_diversity(cf_t *y, cf_t *h[SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS],
|
||||
int nof_ports, int nof_symbols)
|
||||
{
|
||||
#ifdef LV_HAVE_SSE
|
||||
if (nof_symbols > 32 && nof_ports == 2) {
|
||||
return srslte_predecoding_diversity2_sse(y, h, x, nof_symbols);
|
||||
} else {
|
||||
return srslte_predecoding_diversity_gen(y, h, x, nof_ports, nof_symbols);
|
||||
}
|
||||
#else
|
||||
return srslte_predecoding_diversity_gen(y, h, x, nof_ports, nof_symbols);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 36.211 v10.3.0 Section 6.3.4 */
|
||||
int srslte_predecoding_type(srslte_precoding_t *q, cf_t *y, cf_t *h[SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS],
|
||||
int srslte_predecoding_type(cf_t *y, cf_t *h[SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS],
|
||||
int nof_ports, int nof_layers, int nof_symbols, srslte_mimo_type_t type, float noise_estimate) {
|
||||
|
||||
if (nof_ports > SRSLTE_MAX_PORTS) {
|
||||
|
@ -392,7 +352,7 @@ int srslte_predecoding_type(srslte_precoding_t *q, cf_t *y, cf_t *h[SRSLTE_MAX_P
|
|||
break;
|
||||
case SRSLTE_MIMO_TYPE_TX_DIVERSITY:
|
||||
if (nof_ports == nof_layers) {
|
||||
return srslte_predecoding_diversity(q, y, h, x, nof_ports, nof_symbols, noise_estimate);
|
||||
return srslte_predecoding_diversity(y, h, x, nof_ports, nof_symbols);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Error number of layers must equal number of ports in transmit diversity\n");
|
||||
|
@ -417,11 +377,11 @@ int srslte_predecoding_type(srslte_precoding_t *q, cf_t *y, cf_t *h[SRSLTE_MAX_P
|
|||
*
|
||||
**************************************************/
|
||||
|
||||
int srslte_precoding_single(srslte_precoding_t *q, cf_t *x, cf_t *y, int nof_symbols) {
|
||||
int srslte_precoding_single(cf_t *x, cf_t *y, int nof_symbols) {
|
||||
memcpy(y, x, nof_symbols * sizeof(cf_t));
|
||||
return nof_symbols;
|
||||
}
|
||||
int srslte_precoding_diversity(srslte_precoding_t *q, cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PORTS], int nof_ports,
|
||||
int srslte_precoding_diversity(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PORTS], int nof_ports,
|
||||
int nof_symbols) {
|
||||
int i;
|
||||
if (nof_ports == 2) {
|
||||
|
@ -467,7 +427,7 @@ int srslte_precoding_diversity(srslte_precoding_t *q, cf_t *x[SRSLTE_MAX_LAYERS]
|
|||
}
|
||||
|
||||
/* 36.211 v10.3.0 Section 6.3.4 */
|
||||
int srslte_precoding_type(srslte_precoding_t *q, cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PORTS], int nof_layers,
|
||||
int srslte_precoding_type(cf_t *x[SRSLTE_MAX_LAYERS], cf_t *y[SRSLTE_MAX_PORTS], int nof_layers,
|
||||
int nof_ports, int nof_symbols, srslte_mimo_type_t type) {
|
||||
|
||||
if (nof_ports > SRSLTE_MAX_PORTS) {
|
||||
|
@ -484,7 +444,7 @@ int srslte_precoding_type(srslte_precoding_t *q, cf_t *x[SRSLTE_MAX_LAYERS], cf_
|
|||
switch (type) {
|
||||
case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA:
|
||||
if (nof_ports == 1 && nof_layers == 1) {
|
||||
return srslte_precoding_single(q, x[0], y[0], nof_symbols);
|
||||
return srslte_precoding_single(x[0], y[0], nof_symbols);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Number of ports and layers must be 1 for transmission on single antenna ports\n");
|
||||
|
@ -493,7 +453,7 @@ int srslte_precoding_type(srslte_precoding_t *q, cf_t *x[SRSLTE_MAX_LAYERS], cf_
|
|||
break;
|
||||
case SRSLTE_MIMO_TYPE_TX_DIVERSITY:
|
||||
if (nof_ports == nof_layers) {
|
||||
return srslte_precoding_diversity(q, x, y, nof_ports, nof_symbols);
|
||||
return srslte_precoding_diversity(x, y, nof_ports, nof_symbols);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Error number of layers must equal number of ports in transmit diversity\n");
|
||||
|
|
|
@ -61,6 +61,8 @@ ADD_TEST(precoding_diversity2 precoding_test -n 1000 -m diversity -l 2 -p 2)
|
|||
ADD_TEST(precoding_diversity4 precoding_test -n 1024 -m diversity -l 4 -p 4)
|
||||
|
||||
|
||||
# MEX file for predecoding and layer demapping test
|
||||
BuildMex(MEXNAME diversitydecode SOURCES diversitydecode_mex.c LIBRARIES srslte srslte_mex)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2015 Software Radio Systems Limited
|
||||
*
|
||||
* \section LICENSE
|
||||
*
|
||||
* This file is part of the srsLTE library.
|
||||
*
|
||||
* srsLTE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsLTE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero General Public License can be found in
|
||||
* the LICENSE file in the top-level directory of this distribution
|
||||
* and at http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "srslte/srslte.h"
|
||||
#include "srslte/mex/mexutils.h"
|
||||
|
||||
/** MEX function to be called from MATLAB to test the predecoder
|
||||
*/
|
||||
|
||||
#define INPUT prhs[0]
|
||||
#define HEST prhs[1]
|
||||
#define NOF_INPUTS 2
|
||||
|
||||
|
||||
void help()
|
||||
{
|
||||
mexErrMsgTxt
|
||||
("[output] = srslte_predecoder(input, hest, nest)\n\n");
|
||||
}
|
||||
|
||||
/* the gateway function */
|
||||
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
||||
{
|
||||
cf_t *input = NULL;
|
||||
cf_t *hest = NULL;
|
||||
cf_t *output = NULL;
|
||||
uint32_t nof_symbols = 0;
|
||||
|
||||
if (nrhs < NOF_INPUTS) {
|
||||
help();
|
||||
return;
|
||||
}
|
||||
|
||||
// Read input symbols
|
||||
nof_symbols = mexutils_read_cf(INPUT, &input);
|
||||
if (nof_symbols < 0) {
|
||||
mexErrMsgTxt("Error reading input\n");
|
||||
return;
|
||||
}
|
||||
// Read channel estimates
|
||||
uint32_t nof_symbols2 = mexutils_read_cf(HEST, &hest);
|
||||
if (nof_symbols < 0) {
|
||||
mexErrMsgTxt("Error reading hest\n");
|
||||
return;
|
||||
}
|
||||
if ((nof_symbols2 % nof_symbols) != 0) {
|
||||
mexErrMsgTxt("Hest size must be multiple of input size\n");
|
||||
return;
|
||||
}
|
||||
// Calculate number of ports
|
||||
uint32_t nof_ports = nof_symbols2/nof_symbols;
|
||||
|
||||
cf_t *x[8];
|
||||
cf_t *h[4];
|
||||
|
||||
/* Allocate memory */
|
||||
output = srslte_vec_malloc(sizeof(cf_t)*nof_symbols);
|
||||
int i;
|
||||
for (i = 0; i < nof_ports; i++) {
|
||||
x[i] = srslte_vec_malloc(sizeof(cf_t)*nof_symbols);
|
||||
h[i] = &hest[i*nof_symbols];
|
||||
}
|
||||
for (;i<8;i++) {
|
||||
x[i] = NULL;
|
||||
}
|
||||
for (i=nof_ports;i<4;i++) {
|
||||
h[i] = NULL;
|
||||
}
|
||||
|
||||
srslte_predecoding_diversity(input, h, x, nof_ports, nof_symbols);
|
||||
srslte_layerdemap_diversity(x, output, nof_ports, nof_symbols / nof_ports);
|
||||
|
||||
|
||||
if (nlhs >= 1) {
|
||||
mexutils_write_cf(output, &plhs[0], nof_symbols, 1);
|
||||
}
|
||||
|
||||
if (input) {
|
||||
free(input);
|
||||
}
|
||||
if (output) {
|
||||
free(output);
|
||||
}
|
||||
for (i=0;i<8;i++) {
|
||||
if (x[i]) {
|
||||
free(x[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -81,7 +81,6 @@ int main(int argc, char **argv) {
|
|||
cf_t *x[SRSLTE_MAX_LAYERS], *r[SRSLTE_MAX_PORTS], *y[SRSLTE_MAX_PORTS], *h[SRSLTE_MAX_PORTS],
|
||||
*xr[SRSLTE_MAX_LAYERS];
|
||||
srslte_mimo_type_t type;
|
||||
srslte_precoding_t precoding;
|
||||
|
||||
parse_args(argc, argv);
|
||||
|
||||
|
@ -135,13 +134,8 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
if (srslte_precoding_init(&precoding, nof_symbols * nof_layers)) {
|
||||
fprintf(stderr, "Error initializing precoding\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* precoding */
|
||||
if (srslte_precoding_type(&precoding, x, y, nof_layers, nof_ports, nof_symbols, type) < 0) {
|
||||
if (srslte_precoding_type(x, y, nof_layers, nof_ports, nof_symbols, type) < 0) {
|
||||
fprintf(stderr, "Error layer mapper encoder\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
@ -152,7 +146,7 @@ int main(int argc, char **argv) {
|
|||
h[i][nof_layers*j] = (float) rand()/RAND_MAX+((float) rand()/RAND_MAX)*_Complex_I;
|
||||
// assume the channel is time-invariant in nlayer consecutive symbols
|
||||
for (int k=0;k<nof_layers;k++) {
|
||||
h[i][nof_layers*j+k] = h[i][nof_layers*j];
|
||||
h[i][nof_layers*j+k] = h[i][nof_layers*j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -168,11 +162,11 @@ int main(int argc, char **argv) {
|
|||
r[0][j] += y[i][j] * h[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* predecoding / equalization */
|
||||
struct timeval t[3];
|
||||
gettimeofday(&t[1], NULL);
|
||||
if (srslte_predecoding_type(&precoding, r[0], h, xr, nof_ports, nof_layers,
|
||||
if (srslte_predecoding_type(r[0], h, xr, nof_ports, nof_layers,
|
||||
nof_symbols * nof_layers, type, 0) < 0) {
|
||||
fprintf(stderr, "Error layer mapper encoder\n");
|
||||
exit(-1);
|
||||
|
@ -204,8 +198,6 @@ int main(int argc, char **argv) {
|
|||
|
||||
free(r[0]);
|
||||
|
||||
srslte_precoding_free(&precoding);
|
||||
|
||||
printf("Ok\n");
|
||||
exit(0);
|
||||
}
|
||||
|
|
|
@ -151,10 +151,6 @@ int srslte_pbch_init(srslte_pbch_t *q, srslte_cell_t cell) {
|
|||
q->cell = cell;
|
||||
q->nof_symbols = (SRSLTE_CP_ISNORM(q->cell.cp)) ? PBCH_RE_CP_NORM : PBCH_RE_CP_EXT;
|
||||
|
||||
if (srslte_precoding_init(&q->precoding, SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp))) {
|
||||
fprintf(stderr, "Error initializing precoding\n");
|
||||
}
|
||||
|
||||
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) {
|
||||
goto clean;
|
||||
}
|
||||
|
@ -239,7 +235,6 @@ void srslte_pbch_free(srslte_pbch_t *q) {
|
|||
if (q->rm_b) {
|
||||
free(q->rm_b);
|
||||
}
|
||||
srslte_precoding_free(&q->precoding);
|
||||
srslte_sequence_free(&q->seq);
|
||||
srslte_modem_table_free(&q->mod);
|
||||
srslte_viterbi_free(&q->decoder);
|
||||
|
@ -373,8 +368,6 @@ int decode_frame(srslte_pbch_t *q, uint32_t src, uint32_t dst, uint32_t n,
|
|||
uint32_t nof_bits, uint32_t nof_ports) {
|
||||
int j;
|
||||
|
||||
DEBUG("Trying to decode PBCH %d bits, %d ports, src: %d, dst: %d, n=%d\n", nof_bits, nof_ports, src, dst, n);
|
||||
|
||||
memcpy(&q->temp[dst * nof_bits], &q->llr[src * nof_bits],
|
||||
n * nof_bits * sizeof(float));
|
||||
|
||||
|
@ -392,6 +385,9 @@ int decode_frame(srslte_pbch_t *q, uint32_t src, uint32_t dst, uint32_t n,
|
|||
/* unrate matching */
|
||||
srslte_rm_conv_rx(q->temp, 4 * nof_bits, q->rm_f, SRSLTE_BCH_ENCODED_LEN);
|
||||
|
||||
/* Normalize LLR */
|
||||
srslte_vec_sc_prod_fff(q->rm_f, 1.0/((float) 2*n), q->rm_f, SRSLTE_BCH_ENCODED_LEN);
|
||||
|
||||
/* decode */
|
||||
srslte_viterbi_decode_f(&q->decoder, q->rm_f, q->data, SRSLTE_BCH_PAYLOADCRC_LEN);
|
||||
|
||||
|
@ -471,8 +467,8 @@ int srslte_pbch_decode(srslte_pbch_t *q, cf_t *slot1_symbols, cf_t *ce_slot1[SRS
|
|||
/* no need for layer demapping */
|
||||
srslte_predecoding_single(q->symbols[0], q->ce[0], q->d, q->nof_symbols, noise_estimate);
|
||||
} else {
|
||||
srslte_predecoding_diversity(&q->precoding, q->symbols[0], q->ce, x, nant,
|
||||
q->nof_symbols, noise_estimate);
|
||||
srslte_predecoding_diversity(q->symbols[0], q->ce, x, nant,
|
||||
q->nof_symbols);
|
||||
srslte_layerdemap_diversity(x, q->d, nant, q->nof_symbols / nant);
|
||||
}
|
||||
|
||||
|
@ -482,17 +478,14 @@ int srslte_pbch_decode(srslte_pbch_t *q, cf_t *slot1_symbols, cf_t *ce_slot1[SRS
|
|||
/* We don't know where the 40 ms begin, so we try all combinations. E.g. if we received
|
||||
* 4 frames, try 1,2,3,4 individually, 12, 23, 34 in pairs, 123, 234 and finally 1234.
|
||||
* We know they are ordered.
|
||||
*
|
||||
* FIXME: There are unnecessary checks because 2,3,4 have already been processed in the previous
|
||||
* calls.
|
||||
*/
|
||||
for (nb = 0; nb < q->frame_idx && !ret; nb++) {
|
||||
for (dst = 0; (dst < 4 - nb) && !ret; dst++) {
|
||||
for (src = 0; src < q->frame_idx - nb && !ret; src++) {
|
||||
for (nb = 0; nb < q->frame_idx; nb++) {
|
||||
for (dst = 0; (dst < 4 - nb); dst++) {
|
||||
for (src = 0; src < q->frame_idx - nb; src++) {
|
||||
ret = decode_frame(q, src, dst, nb + 1, nof_bits, nant);
|
||||
if (ret == 1) {
|
||||
if (sfn_offset) {
|
||||
*sfn_offset = (int) dst - src;
|
||||
*sfn_offset = (int) dst - src + q->frame_idx - 1;
|
||||
}
|
||||
if (nof_tx_ports) {
|
||||
*nof_tx_ports = nant;
|
||||
|
@ -500,13 +493,15 @@ int srslte_pbch_decode(srslte_pbch_t *q, cf_t *slot1_symbols, cf_t *ce_slot1[SRS
|
|||
if (bch_payload) {
|
||||
memcpy(bch_payload, q->data, sizeof(uint8_t) * SRSLTE_BCH_PAYLOAD_LEN);
|
||||
}
|
||||
INFO("Decoded PBCH: src=%d, dst=%d, nb=%d, sfn_offset=%d\n", src, dst, nb+1, (int) dst - src + q->frame_idx - 1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
nant++;
|
||||
} while(nant <= q->cell.nof_ports && !ret);
|
||||
} while(nant <= q->cell.nof_ports);
|
||||
|
||||
/* If not found, make room for the next packet of radio frame symbols */
|
||||
if (q->frame_idx == 4) {
|
||||
|
@ -561,7 +556,7 @@ int srslte_pbch_encode(srslte_pbch_t *q, uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_
|
|||
/* layer mapping & precoding */
|
||||
if (q->cell.nof_ports > 1) {
|
||||
srslte_layermap_diversity(q->d, x, q->cell.nof_ports, q->nof_symbols);
|
||||
srslte_precoding_diversity(&q->precoding, x, q->symbols, q->cell.nof_ports,
|
||||
srslte_precoding_diversity(x, q->symbols, q->cell.nof_ports,
|
||||
q->nof_symbols / q->cell.nof_ports);
|
||||
} else {
|
||||
memcpy(q->symbols[0], q->d, q->nof_symbols * sizeof(cf_t));
|
||||
|
|
|
@ -74,10 +74,6 @@ int srslte_pcfich_init(srslte_pcfich_t *q, srslte_regs_t *regs, srslte_cell_t ce
|
|||
q->regs = regs;
|
||||
q->nof_symbols = PCFICH_RE;
|
||||
|
||||
if (srslte_precoding_init(&q->precoding, SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp))) {
|
||||
fprintf(stderr, "Error initializing precoding\n");
|
||||
}
|
||||
|
||||
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) {
|
||||
goto clean;
|
||||
}
|
||||
|
@ -110,7 +106,6 @@ void srslte_pcfich_free(srslte_pcfich_t *q) {
|
|||
srslte_sequence_free(&q->seq[ns]);
|
||||
}
|
||||
srslte_modem_table_free(&q->mod);
|
||||
srslte_precoding_free(&q->precoding);
|
||||
|
||||
bzero(q, sizeof(srslte_pcfich_t));
|
||||
}
|
||||
|
@ -194,8 +189,8 @@ int srslte_pcfich_decode(srslte_pcfich_t *q, cf_t *slot_symbols, cf_t *ce[SRSLTE
|
|||
/* no need for layer demapping */
|
||||
srslte_predecoding_single(q->symbols[0], q->ce[0], q->d, q->nof_symbols, noise_estimate);
|
||||
} else {
|
||||
srslte_predecoding_diversity(&q->precoding, q->symbols[0], ce_precoding, x,
|
||||
q->cell.nof_ports, q->nof_symbols, noise_estimate);
|
||||
srslte_predecoding_diversity(q->symbols[0], ce_precoding, x,
|
||||
q->cell.nof_ports, q->nof_symbols);
|
||||
srslte_layerdemap_diversity(x, q->d, q->cell.nof_ports,
|
||||
q->nof_symbols / q->cell.nof_ports);
|
||||
}
|
||||
|
@ -253,7 +248,7 @@ int srslte_pcfich_encode(srslte_pcfich_t *q, uint32_t cfi, cf_t *slot_symbols[SR
|
|||
/* layer mapping & precoding */
|
||||
if (q->cell.nof_ports > 1) {
|
||||
srslte_layermap_diversity(q->d, x, q->cell.nof_ports, q->nof_symbols);
|
||||
srslte_precoding_diversity(&q->precoding, x, symbols_precoding, q->cell.nof_ports,
|
||||
srslte_precoding_diversity(x, symbols_precoding, q->cell.nof_ports,
|
||||
q->nof_symbols / q->cell.nof_ports);
|
||||
} else {
|
||||
memcpy(q->symbols[0], q->d, q->nof_symbols * sizeof(cf_t));
|
||||
|
|
|
@ -67,10 +67,6 @@ int srslte_pdcch_init(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell
|
|||
q->cell = cell;
|
||||
q->regs = regs;
|
||||
|
||||
if (srslte_precoding_init(&q->precoding, SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp))) {
|
||||
fprintf(stderr, "Error initializing precoding\n");
|
||||
}
|
||||
|
||||
/* Allocate memory for the maximum number of PDCCH bits (CFI=3) */
|
||||
q->max_bits = (srslte_regs_pdcch_nregs(q->regs, 3) / 9) * 72;
|
||||
|
||||
|
@ -166,7 +162,6 @@ void srslte_pdcch_free(srslte_pdcch_t *q) {
|
|||
srslte_sequence_free(&q->seq[i]);
|
||||
}
|
||||
|
||||
srslte_precoding_free(&q->precoding);
|
||||
srslte_modem_table_free(&q->mod);
|
||||
srslte_viterbi_free(&q->decoder);
|
||||
|
||||
|
@ -280,7 +275,10 @@ static int dci_decode(srslte_pdcch_t *q, float *e, uint8_t *data, uint32_t E, ui
|
|||
|
||||
/* unrate matching */
|
||||
srslte_rm_conv_rx(e, E, q->rm_f, 3 * (nof_bits + 16));
|
||||
|
||||
|
||||
/* Normalize LLR */
|
||||
srslte_vec_sc_prod_fff(q->rm_f, (float) 3 * nof_bits/E, q->rm_f, 3*(nof_bits+16));
|
||||
|
||||
/* viterbi decoder */
|
||||
srslte_viterbi_decode_f(&q->decoder, q->rm_f, data, nof_bits + 16);
|
||||
|
||||
|
@ -406,7 +404,7 @@ int srslte_pdcch_extract_llr(srslte_pdcch_t *q, cf_t *sf_symbols, cf_t *ce[SRSLT
|
|||
/* no need for layer demapping */
|
||||
srslte_predecoding_single(q->symbols[0], q->ce[0], q->d, nof_symbols, noise_estimate);
|
||||
} else {
|
||||
srslte_predecoding_diversity(&q->precoding, q->symbols[0], q->ce, x, q->cell.nof_ports, nof_symbols, noise_estimate);
|
||||
srslte_predecoding_diversity(q->symbols[0], q->ce, x, q->cell.nof_ports, nof_symbols);
|
||||
srslte_layerdemap_diversity(x, q->d, q->cell.nof_ports, nof_symbols / q->cell.nof_ports);
|
||||
}
|
||||
|
||||
|
@ -532,7 +530,7 @@ int srslte_pdcch_encode(srslte_pdcch_t *q, srslte_dci_msg_t *msg, srslte_dci_loc
|
|||
/* layer mapping & precoding */
|
||||
if (q->cell.nof_ports > 1) {
|
||||
srslte_layermap_diversity(q->d, x, q->cell.nof_ports, nof_symbols);
|
||||
srslte_precoding_diversity(&q->precoding, x, q->symbols, q->cell.nof_ports, nof_symbols / q->cell.nof_ports);
|
||||
srslte_precoding_diversity(x, q->symbols, q->cell.nof_ports, nof_symbols / q->cell.nof_ports);
|
||||
} else {
|
||||
memcpy(q->symbols[0], q->d, nof_symbols * sizeof(cf_t));
|
||||
}
|
||||
|
|
|
@ -216,11 +216,6 @@ int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell) {
|
|||
INFO("Init PDSCH: %d ports %d PRBs, max_symbols: %d\n", q->cell.nof_ports,
|
||||
q->cell.nof_prb, q->max_re);
|
||||
|
||||
if (srslte_precoding_init(&q->precoding, SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp))) {
|
||||
fprintf(stderr, "Error initializing precoding\n");
|
||||
goto clean;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (srslte_modem_table_lte(&q->mod[i], modulations[i])) {
|
||||
goto clean;
|
||||
|
@ -295,7 +290,7 @@ void srslte_pdsch_free(srslte_pdsch_t *q) {
|
|||
for (i = 0; i < 4; i++) {
|
||||
srslte_modem_table_free(&q->mod[i]);
|
||||
}
|
||||
srslte_precoding_free(&q->precoding);
|
||||
|
||||
srslte_sch_free(&q->dl_sch);
|
||||
|
||||
bzero(q, sizeof(srslte_pdsch_t));
|
||||
|
@ -409,8 +404,8 @@ int srslte_pdsch_decode_rnti(srslte_pdsch_t *q,
|
|||
/* no need for layer demapping */
|
||||
srslte_predecoding_single(q->symbols[0], q->ce[0], q->d, cfg->nbits.nof_re, noise_estimate);
|
||||
} else {
|
||||
srslte_predecoding_diversity(&q->precoding, q->symbols[0], q->ce, x, q->cell.nof_ports,
|
||||
cfg->nbits.nof_re, noise_estimate);
|
||||
srslte_predecoding_diversity(q->symbols[0], q->ce, x, q->cell.nof_ports,
|
||||
cfg->nbits.nof_re);
|
||||
srslte_layerdemap_diversity(x, q->d, q->cell.nof_ports,
|
||||
cfg->nbits.nof_re / q->cell.nof_ports);
|
||||
}
|
||||
|
@ -541,7 +536,7 @@ int srslte_pdsch_encode_rnti(srslte_pdsch_t *q,
|
|||
/* TODO: only diversity supported */
|
||||
if (q->cell.nof_ports > 1) {
|
||||
srslte_layermap_diversity(q->d, x, q->cell.nof_ports, cfg->nbits.nof_re);
|
||||
srslte_precoding_diversity(&q->precoding, x, q->symbols, q->cell.nof_ports,
|
||||
srslte_precoding_diversity(x, q->symbols, q->cell.nof_ports,
|
||||
cfg->nbits.nof_re / q->cell.nof_ports);
|
||||
} else {
|
||||
memcpy(q->symbols[0], q->d, cfg->nbits.nof_re * sizeof(cf_t));
|
||||
|
|
|
@ -82,10 +82,6 @@ int srslte_phich_init(srslte_phich_t *q, srslte_regs_t *regs, srslte_cell_t cell
|
|||
q->cell = cell;
|
||||
q->regs = regs;
|
||||
|
||||
if (srslte_precoding_init(&q->precoding, SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp))) {
|
||||
fprintf(stderr, "Error initializing precoding\n");
|
||||
}
|
||||
|
||||
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_BPSK)) {
|
||||
goto clean;
|
||||
}
|
||||
|
@ -109,7 +105,6 @@ void srslte_phich_free(srslte_phich_t *q) {
|
|||
srslte_sequence_free(&q->seq[ns]);
|
||||
}
|
||||
srslte_modem_table_free(&q->mod);
|
||||
srslte_precoding_free(&q->precoding);
|
||||
|
||||
bzero(q, sizeof(srslte_phich_t));
|
||||
|
||||
|
@ -217,8 +212,8 @@ int srslte_phich_decode(srslte_phich_t *q, cf_t *slot_symbols, cf_t *ce[SRSLTE_M
|
|||
/* no need for layer demapping */
|
||||
srslte_predecoding_single(q->symbols[0], q->ce[0], q->d0, SRSLTE_PHICH_MAX_NSYMB, noise_estimate);
|
||||
} else {
|
||||
srslte_predecoding_diversity(&q->precoding, q->symbols[0], ce_precoding, x,
|
||||
q->cell.nof_ports, SRSLTE_PHICH_MAX_NSYMB, noise_estimate);
|
||||
srslte_predecoding_diversity(q->symbols[0], ce_precoding, x,
|
||||
q->cell.nof_ports, SRSLTE_PHICH_MAX_NSYMB);
|
||||
srslte_layerdemap_diversity(x, q->d0, q->cell.nof_ports,
|
||||
SRSLTE_PHICH_MAX_NSYMB / q->cell.nof_ports);
|
||||
}
|
||||
|
@ -382,7 +377,7 @@ int srslte_phich_encode(srslte_phich_t *q, uint8_t ack, uint32_t ngroup, uint32_
|
|||
/* layer mapping & precoding */
|
||||
if (q->cell.nof_ports > 1) {
|
||||
srslte_layermap_diversity(q->d0, x, q->cell.nof_ports, SRSLTE_PHICH_MAX_NSYMB);
|
||||
srslte_precoding_diversity(&q->precoding, x, symbols_precoding, q->cell.nof_ports,
|
||||
srslte_precoding_diversity(x, symbols_precoding, q->cell.nof_ports,
|
||||
SRSLTE_PHICH_MAX_NSYMB / q->cell.nof_ports);
|
||||
/**FIXME: According to 6.9.2, Precoding for 4 tx ports is different! */
|
||||
} else {
|
||||
|
|
|
@ -218,12 +218,6 @@ int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) {
|
|||
goto clean;
|
||||
}
|
||||
|
||||
/* This is for equalization at receiver */
|
||||
if (srslte_precoding_init(&q->equalizer, SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp))) {
|
||||
fprintf(stderr, "Error initializing precoding\n");
|
||||
goto clean;
|
||||
}
|
||||
|
||||
q->rnti_is_set = false;
|
||||
|
||||
// Allocate floats for reception (LLRs). Buffer casted to uint8_t for transmission
|
||||
|
@ -281,8 +275,6 @@ void srslte_pusch_free(srslte_pusch_t *q) {
|
|||
|
||||
srslte_dft_precoding_free(&q->dft_precoding);
|
||||
|
||||
srslte_precoding_free(&q->equalizer);
|
||||
|
||||
for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
|
||||
srslte_sequence_free(&q->seq[i]);
|
||||
}
|
||||
|
|
|
@ -50,9 +50,11 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
srslte_pbch_t pbch;
|
||||
srslte_chest_dl_t chest;
|
||||
srslte_ofdm_t ofdm_rx;
|
||||
cf_t *input_fft;
|
||||
cf_t *input_fft = NULL;
|
||||
cf_t *ce[SRSLTE_MAX_PORTS], *ce_slot[SRSLTE_MAX_PORTS];
|
||||
|
||||
srslte_verbose = SRSLTE_VERBOSE_DEBUG;
|
||||
|
||||
if (nrhs < NOF_INPUTS) {
|
||||
help();
|
||||
return;
|
||||
|
@ -62,7 +64,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
help();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Allocate memory
|
||||
for (i=0;i<SRSLTE_MAX_PORTS;i++) {
|
||||
ce[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
|
||||
|
@ -78,59 +80,80 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
return;
|
||||
}
|
||||
|
||||
uint32_t nof_ports = cell.nof_ports;
|
||||
//cell.nof_ports = 0;
|
||||
if (srslte_pbch_init(&pbch, cell)) {
|
||||
fprintf(stderr, "Error initiating PBCH\n");
|
||||
return;
|
||||
}
|
||||
cell.nof_ports = nof_ports;
|
||||
|
||||
|
||||
// Read input signal
|
||||
cf_t *input_signal = NULL;
|
||||
int insignal_len = mexutils_read_cf(INPUT, &input_signal);
|
||||
if (insignal_len < 0) {
|
||||
mexErrMsgTxt("Error reading input signal\n");
|
||||
return;
|
||||
}
|
||||
if (insignal_len == SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)) {
|
||||
input_fft = input_signal;
|
||||
} else {
|
||||
input_fft = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
|
||||
srslte_ofdm_rx_sf(&ofdm_rx, input_signal, input_fft);
|
||||
free(input_signal);
|
||||
}
|
||||
|
||||
if (nrhs > NOF_INPUTS) {
|
||||
cf_t *cearray = NULL;
|
||||
mexutils_read_cf(prhs[NOF_INPUTS], &cearray);
|
||||
cf_t *cearray_ptr = cearray;
|
||||
for (i=0;i<cell.nof_ports;i++) {
|
||||
for (int j=0;j<SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);j++) {
|
||||
ce[i][j] = *cearray_ptr;
|
||||
cearray_ptr++;
|
||||
}
|
||||
}
|
||||
if (cearray) {
|
||||
free(cearray);
|
||||
}
|
||||
} else {
|
||||
srslte_chest_dl_estimate(&chest, input_fft, ce, 0);
|
||||
}
|
||||
float noise_power;
|
||||
if (nrhs > NOF_INPUTS + 1) {
|
||||
noise_power = mxGetScalar(prhs[NOF_INPUTS+1]);
|
||||
} else if (nrhs > NOF_INPUTS) {
|
||||
noise_power = 0;
|
||||
} else {
|
||||
noise_power = srslte_chest_dl_get_noise_estimate(&chest);
|
||||
}
|
||||
|
||||
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
|
||||
ce_slot[i] = &ce[i][SRSLTE_SLOT_LEN_RE(cell.nof_prb, cell.cp)];
|
||||
}
|
||||
|
||||
uint32_t nof_ports;
|
||||
int n = srslte_pbch_decode(&pbch, &input_fft[SRSLTE_SLOT_LEN_RE(cell.nof_prb, cell.cp)],
|
||||
ce_slot, noise_power,
|
||||
NULL, &nof_ports, NULL);
|
||||
int nof_subframes=1;
|
||||
if (mexutils_isCell(INPUT)) {
|
||||
nof_subframes = mexutils_getLength(INPUT);
|
||||
mexPrintf("input is cell. %d subframes\n", nof_subframes);
|
||||
}
|
||||
|
||||
nof_ports = 0;
|
||||
int sfn_offset = 0;
|
||||
int n = -1;
|
||||
for (int s=0;s<nof_subframes;s++) {
|
||||
|
||||
mxArray *tmp = (mxArray*) INPUT;
|
||||
if (mexutils_isCell(INPUT)) {
|
||||
tmp = mexutils_getCellArray(INPUT, s);
|
||||
}
|
||||
|
||||
// Read input signal
|
||||
cf_t *input_signal = NULL;
|
||||
int insignal_len = mexutils_read_cf(tmp, &input_signal);
|
||||
if (insignal_len < 0) {
|
||||
mexErrMsgTxt("Error reading input signal\n");
|
||||
return;
|
||||
}
|
||||
if (insignal_len == SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)) {
|
||||
input_fft = input_signal;
|
||||
} else {
|
||||
input_fft = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
|
||||
srslte_ofdm_rx_sf(&ofdm_rx, input_signal, input_fft);
|
||||
free(input_signal);
|
||||
}
|
||||
|
||||
if (nrhs > NOF_INPUTS) {
|
||||
cf_t *cearray = NULL;
|
||||
mexutils_read_cf(prhs[NOF_INPUTS], &cearray);
|
||||
cf_t *cearray_ptr = cearray;
|
||||
for (i=0;i<cell.nof_ports;i++) {
|
||||
for (int j=0;j<SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);j++) {
|
||||
ce[i][j] = *cearray_ptr;
|
||||
cearray_ptr++;
|
||||
}
|
||||
}
|
||||
if (cearray) {
|
||||
free(cearray);
|
||||
}
|
||||
} else {
|
||||
srslte_chest_dl_estimate(&chest, input_fft, ce, 0);
|
||||
}
|
||||
float noise_power;
|
||||
if (nrhs > NOF_INPUTS + 1) {
|
||||
noise_power = mxGetScalar(prhs[NOF_INPUTS+1]);
|
||||
} else if (nrhs > NOF_INPUTS) {
|
||||
noise_power = 0;
|
||||
} else {
|
||||
noise_power = srslte_chest_dl_get_noise_estimate(&chest);
|
||||
}
|
||||
|
||||
n = srslte_pbch_decode(&pbch, &input_fft[SRSLTE_SLOT_LEN_RE(cell.nof_prb, cell.cp)],
|
||||
ce_slot, noise_power,
|
||||
NULL, &nof_ports, &sfn_offset);
|
||||
}
|
||||
|
||||
if (nlhs >= 1) {
|
||||
if (n == 1) {
|
||||
|
@ -143,7 +166,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
mexutils_write_cf(pbch.d, &plhs[1], pbch.nof_symbols, 1);
|
||||
}
|
||||
if (nlhs >= 3) {
|
||||
mexutils_write_f(pbch.llr, &plhs[2], 2*pbch.nof_symbols, 1);
|
||||
mexutils_write_f(pbch.temp, &plhs[2], 4*2*pbch.nof_symbols, 1);
|
||||
}
|
||||
if (nlhs >= 4) {
|
||||
mexutils_write_cf(ce[0], &plhs[3], SRSLTE_SF_LEN_RE(cell.nof_prb,cell.cp)/14, 14);
|
||||
|
@ -157,6 +180,12 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
if (nlhs >= 7) {
|
||||
mexutils_write_cf(pbch.ce[0], &plhs[6], pbch.nof_symbols, 1);
|
||||
}
|
||||
if (nlhs >= 8) {
|
||||
plhs[7] = mxCreateDoubleScalar(sfn_offset);
|
||||
}
|
||||
if (nlhs >= 9) {
|
||||
mexutils_write_f(pbch.rm_f, &plhs[8], 120, 1);
|
||||
}
|
||||
|
||||
srslte_chest_dl_free(&chest);
|
||||
srslte_ofdm_rx_free(&ofdm_rx);
|
||||
|
@ -165,8 +194,9 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
for (i=0;i<cell.nof_ports;i++) {
|
||||
free(ce[i]);
|
||||
}
|
||||
free(input_fft);
|
||||
|
||||
if(input_fft) {
|
||||
free(input_fft);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -152,6 +152,9 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
if (nlhs >= 3) {
|
||||
mexutils_write_cf(pcfich.symbols[0], &plhs[2], 16, 1);
|
||||
}
|
||||
if (nlhs >= 4) {
|
||||
mexutils_write_cf(ce[0], &plhs[3], SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp), 1);
|
||||
}
|
||||
|
||||
srslte_chest_dl_free(&chest);
|
||||
srslte_ofdm_rx_free(&ofdm_rx);
|
||||
|
|
|
@ -95,7 +95,7 @@ double srslte_rf_set_rx_gain_th_wrapper(void *h, double f) {
|
|||
/** This function is simply a wrapper to the ue_cell_search module for rf devices
|
||||
* Return 1 if the MIB is decoded, 0 if not or -1 on error.
|
||||
*/
|
||||
int rf_mib_decoder(srslte_rf_t *rf, cell_search_cfg_t *config, srslte_cell_t *cell) {
|
||||
int rf_mib_decoder(srslte_rf_t *rf, cell_search_cfg_t *config, srslte_cell_t *cell, float *cfo) {
|
||||
int ret = SRSLTE_ERROR;
|
||||
srslte_ue_mib_sync_t ue_mib;
|
||||
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
|
||||
|
@ -116,6 +116,11 @@ int rf_mib_decoder(srslte_rf_t *rf, cell_search_cfg_t *config, srslte_cell_t *ce
|
|||
INFO("Starting receiver...\n", 0);
|
||||
srslte_rf_start_rx_stream(rf);
|
||||
|
||||
// Set CFO if available
|
||||
if (cfo) {
|
||||
srslte_ue_sync_set_cfo(&ue_mib.ue_sync, *cfo);
|
||||
}
|
||||
|
||||
/* Find and decody MIB */
|
||||
ret = srslte_ue_mib_sync_decode(&ue_mib, config->max_frames_pss, bch_payload, &cell->nof_ports, NULL);
|
||||
if (ret < 0) {
|
||||
|
@ -131,6 +136,11 @@ int rf_mib_decoder(srslte_rf_t *rf, cell_search_cfg_t *config, srslte_cell_t *ce
|
|||
config->init_agc = srslte_agc_get_gain(&ue_mib.ue_sync.agc);
|
||||
}
|
||||
|
||||
// Save CFO
|
||||
if (cfo) {
|
||||
*cfo = srslte_ue_sync_get_cfo(&ue_mib.ue_sync);
|
||||
}
|
||||
|
||||
clean_exit:
|
||||
|
||||
srslte_rf_stop_rx_stream(rf);
|
||||
|
@ -142,7 +152,7 @@ clean_exit:
|
|||
/** This function is simply a wrapper to the ue_cell_search module for rf devices
|
||||
*/
|
||||
int rf_cell_search(srslte_rf_t *rf, cell_search_cfg_t *config,
|
||||
int force_N_id_2, srslte_cell_t *cell)
|
||||
int force_N_id_2, srslte_cell_t *cell, float *cfo)
|
||||
{
|
||||
int ret = SRSLTE_ERROR;
|
||||
srslte_ue_cellsearch_t cs;
|
||||
|
@ -150,18 +160,14 @@ int rf_cell_search(srslte_rf_t *rf, cell_search_cfg_t *config,
|
|||
|
||||
bzero(found_cells, 3*sizeof(srslte_ue_cellsearch_result_t));
|
||||
|
||||
if (srslte_ue_cellsearch_init(&cs, srslte_rf_recv_wrapper_cs, (void*) rf)) {
|
||||
if (srslte_ue_cellsearch_init(&cs, config->max_frames_pss, srslte_rf_recv_wrapper_cs, (void*) rf)) {
|
||||
fprintf(stderr, "Error initiating UE cell detect\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
if (config->max_frames_pss) {
|
||||
srslte_ue_cellsearch_set_nof_frames_to_scan(&cs, config->max_frames_pss);
|
||||
if (config->nof_valid_pss_frames) {
|
||||
srslte_ue_cellsearch_set_nof_valid_frames(&cs, config->nof_valid_pss_frames);
|
||||
}
|
||||
if (config->threshold) {
|
||||
srslte_ue_cellsearch_set_threshold(&cs, config->threshold);
|
||||
}
|
||||
|
||||
if (config->init_agc > 0) {
|
||||
srslte_ue_sync_start_agc(&cs.ue_sync, srslte_rf_set_rx_gain_th_wrapper, config->init_agc);
|
||||
}
|
||||
|
@ -206,6 +212,11 @@ int rf_cell_search(srslte_rf_t *rf, cell_search_cfg_t *config,
|
|||
cell->cp = found_cells[max_peak_cell].cp;
|
||||
}
|
||||
|
||||
// Save CFO
|
||||
if (cfo) {
|
||||
*cfo = found_cells[max_peak_cell].cfo;
|
||||
}
|
||||
|
||||
// Save AGC value for MIB decoding
|
||||
if (config->init_agc > 0) {
|
||||
config->init_agc = srslte_agc_get_gain(&cs.ue_sync.agc);
|
||||
|
@ -223,15 +234,15 @@ int rf_cell_search(srslte_rf_t *rf, cell_search_cfg_t *config,
|
|||
* 0 if no cell was found or MIB could not be decoded,
|
||||
* -1 on error
|
||||
*/
|
||||
int rf_search_and_decode_mib(srslte_rf_t *rf, cell_search_cfg_t *config, int force_N_id_2, srslte_cell_t *cell)
|
||||
int rf_search_and_decode_mib(srslte_rf_t *rf, cell_search_cfg_t *config, int force_N_id_2, srslte_cell_t *cell, float *cfo)
|
||||
{
|
||||
int ret = SRSLTE_ERROR;
|
||||
|
||||
printf("Searching for cell...\n");
|
||||
ret = rf_cell_search(rf, config, force_N_id_2, cell);
|
||||
ret = rf_cell_search(rf, config, force_N_id_2, cell, cfo);
|
||||
if (ret > 0) {
|
||||
printf("Decoding PBCH for cell %d (N_id_2=%d)\n", cell->id, cell->id%3);
|
||||
ret = rf_mib_decoder(rf, config, cell);
|
||||
ret = rf_mib_decoder(rf, config, cell, cfo);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Could not decode PBCH from CELL ID %d\n", cell->id);
|
||||
return SRSLTE_ERROR;
|
||||
|
|
|
@ -51,21 +51,20 @@ void srslte_cp_synch_free(srslte_cp_synch_t *q)
|
|||
|
||||
uint32_t srslte_cp_synch(srslte_cp_synch_t *q, cf_t *input, uint32_t max_offset, uint32_t nof_symbols, uint32_t cp_len)
|
||||
{
|
||||
if (max_offset <= q->symbol_sz) {
|
||||
for (int i=0;i<max_offset;i++) {
|
||||
q->corr[i] = 0;
|
||||
cf_t *inputPtr = input;
|
||||
for (int n=0;n<nof_symbols;n++) {
|
||||
uint32_t cplen = (n%7)?cp_len:cp_len+1;
|
||||
q->corr[i] += srslte_vec_dot_prod_conj_ccc(&inputPtr[i], &inputPtr[i+q->symbol_sz], cplen)/nof_symbols;
|
||||
inputPtr += q->symbol_sz+cplen;
|
||||
}
|
||||
}
|
||||
uint32_t max_idx = srslte_vec_max_abs_ci(q->corr, max_offset);
|
||||
return max_idx;
|
||||
} else {
|
||||
return 0;
|
||||
if (max_offset > q->symbol_sz) {
|
||||
max_offset = q->symbol_sz;
|
||||
}
|
||||
for (int i=0;i<max_offset;i++) {
|
||||
q->corr[i] = 0;
|
||||
cf_t *inputPtr = input;
|
||||
for (int n=0;n<nof_symbols;n++) {
|
||||
uint32_t cplen = (n%7)?cp_len:cp_len+1;
|
||||
q->corr[i] += srslte_vec_dot_prod_conj_ccc(&inputPtr[i], &inputPtr[i+q->symbol_sz], cplen)/nof_symbols;
|
||||
inputPtr += q->symbol_sz+cplen;
|
||||
}
|
||||
}
|
||||
uint32_t max_idx = srslte_vec_max_abs_ci(q->corr, max_offset);
|
||||
return max_idx;
|
||||
}
|
||||
|
||||
cf_t srslte_cp_synch_corr_output(srslte_cp_synch_t *q, uint32_t offset)
|
||||
|
|
|
@ -70,11 +70,14 @@ static void corr_all_sz_partial(cf_t z[SRSLTE_SSS_N], float s[SRSLTE_SSS_N][SRSL
|
|||
|
||||
static void extract_pair_sss(srslte_sss_synch_t *q, cf_t *input, cf_t *ce, cf_t y[2][SRSLTE_SSS_N]) {
|
||||
cf_t input_fft[SRSLTE_SYMBOL_SZ_MAX];
|
||||
|
||||
float ce_mod[2*SRSLTE_SSS_N], z_real[2*SRSLTE_SSS_N], z_imag[2*SRSLTE_SSS_N];
|
||||
|
||||
srslte_dft_run_c(&q->dftp_input, input, input_fft);
|
||||
|
||||
if (ce) {
|
||||
srslte_vec_prod_conj_ccc(&input_fft[q->fft_size/2-SRSLTE_SSS_N], ce, &input_fft[q->fft_size/2-SRSLTE_SSS_N], 2*SRSLTE_SSS_N);
|
||||
srslte_vec_div_ccc(&input_fft[q->fft_size/2-SRSLTE_SSS_N], ce, ce_mod,
|
||||
&input_fft[q->fft_size/2-SRSLTE_SSS_N], z_real, z_imag,
|
||||
2*SRSLTE_SSS_N);
|
||||
}
|
||||
|
||||
for (int i = 0; i < SRSLTE_SSS_N; i++) {
|
||||
|
|
|
@ -101,7 +101,7 @@ int srslte_pss_synch_init_fft_offset(srslte_pss_synch_t *q, uint32_t frame_size,
|
|||
q->N_id_2 = 10;
|
||||
q->fft_size = fft_size;
|
||||
q->frame_size = frame_size;
|
||||
q->ema_alpha = 0.1;
|
||||
q->ema_alpha = 0.2;
|
||||
|
||||
buffer_size = fft_size + frame_size + 1;
|
||||
|
||||
|
|
|
@ -35,9 +35,9 @@
|
|||
#include "srslte/utils/vector.h"
|
||||
#include "srslte/sync/cfo.h"
|
||||
|
||||
#define MEANPEAK_EMA_ALPHA 0.2
|
||||
#define CFO_EMA_ALPHA 0.9
|
||||
#define CP_EMA_ALPHA 0.2
|
||||
#define MEANPEAK_EMA_ALPHA 0.1
|
||||
#define CFO_EMA_ALPHA 0.1
|
||||
#define CP_EMA_ALPHA 0.1
|
||||
|
||||
static bool fft_size_isvalid(uint32_t fft_size) {
|
||||
if (fft_size >= SRSLTE_SYNC_FFT_SZ_MIN && fft_size <= SRSLTE_SYNC_FFT_SZ_MAX && (fft_size%64) == 0) {
|
||||
|
@ -59,7 +59,6 @@ int srslte_sync_init(srslte_sync_t *q, uint32_t frame_size, uint32_t max_offset,
|
|||
|
||||
bzero(q, sizeof(srslte_sync_t));
|
||||
q->detect_cp = true;
|
||||
q->mean_peak_value = 0.0;
|
||||
q->sss_en = true;
|
||||
q->mean_cfo = 0;
|
||||
q->N_id_2 = 1000;
|
||||
|
@ -72,7 +71,15 @@ int srslte_sync_init(srslte_sync_t *q, uint32_t frame_size, uint32_t max_offset,
|
|||
q->frame_size = frame_size;
|
||||
q->max_offset = max_offset;
|
||||
q->sss_alg = SSS_FULL;
|
||||
|
||||
q->enable_cfo_corr = true;
|
||||
if (srslte_cfo_init(&q->cfocorr, q->frame_size)) {
|
||||
fprintf(stderr, "Error initiating CFO\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
// Set a CFO tolerance of approx 100 Hz
|
||||
srslte_cfo_set_tol(&q->cfocorr, 100/(15000*q->fft_size));
|
||||
|
||||
for (int i=0;i<2;i++) {
|
||||
q->cfo_i_corr[i] = srslte_vec_malloc(sizeof(cf_t)*q->frame_size);
|
||||
|
@ -93,11 +100,6 @@ int srslte_sync_init(srslte_sync_t *q, uint32_t frame_size, uint32_t max_offset,
|
|||
goto clean_exit;
|
||||
}
|
||||
|
||||
if (srslte_cfo_init(&q->cfocorr, frame_size)) {
|
||||
fprintf(stderr, "Error initiating CFO\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
if (srslte_cp_synch_init(&q->cp_synch, fft_size)) {
|
||||
fprintf(stderr, "Error initiating CFO\n");
|
||||
goto clean_exit;
|
||||
|
@ -207,7 +209,7 @@ float srslte_sync_get_last_peak_value(srslte_sync_t *q) {
|
|||
}
|
||||
|
||||
float srslte_sync_get_peak_value(srslte_sync_t *q) {
|
||||
return q->mean_peak_value;
|
||||
return q->peak_value;
|
||||
}
|
||||
|
||||
void srslte_sync_cp_en(srslte_sync_t *q, bool enabled) {
|
||||
|
@ -245,45 +247,58 @@ void srslte_sync_set_sss_algorithm(srslte_sync_t *q, sss_alg_t alg) {
|
|||
*/
|
||||
srslte_cp_t srslte_sync_detect_cp(srslte_sync_t *q, cf_t *input, uint32_t peak_pos)
|
||||
{
|
||||
float R_norm, R_ext, C_norm, C_ext;
|
||||
float R_norm=0, R_ext=0, C_norm=0, C_ext=0;
|
||||
float M_norm=0, M_ext=0;
|
||||
|
||||
uint32_t cp_norm_len = SRSLTE_CP_LEN_NORM(7, q->fft_size);
|
||||
uint32_t cp_ext_len = SRSLTE_CP_LEN_EXT(q->fft_size);
|
||||
|
||||
uint32_t nof_symbols = peak_pos/(q->fft_size+cp_ext_len);
|
||||
|
||||
if (nof_symbols > 3) {
|
||||
nof_symbols = 3;
|
||||
}
|
||||
|
||||
if (nof_symbols > 0) {
|
||||
|
||||
cf_t *input_cp_norm = &input[peak_pos-2*(q->fft_size+cp_norm_len)];
|
||||
cf_t *input_cp_ext = &input[peak_pos-2*(q->fft_size+cp_ext_len)];
|
||||
cf_t *input_cp_norm = &input[peak_pos-nof_symbols*(q->fft_size+cp_norm_len)];
|
||||
cf_t *input_cp_ext = &input[peak_pos-nof_symbols*(q->fft_size+cp_ext_len)];
|
||||
|
||||
for (int i=0;i<2;i++) {
|
||||
R_norm = crealf(srslte_vec_dot_prod_conj_ccc(&input_cp_norm[q->fft_size], input_cp_norm, cp_norm_len));
|
||||
C_norm = cp_norm_len * srslte_vec_avg_power_cf(input_cp_norm, cp_norm_len);
|
||||
input_cp_norm += q->fft_size+cp_norm_len;
|
||||
M_norm += R_norm/C_norm;
|
||||
}
|
||||
|
||||
q->M_norm_avg = SRSLTE_VEC_EMA(M_norm/2, q->M_norm_avg, CP_EMA_ALPHA);
|
||||
|
||||
for (int i=0;i<2;i++) {
|
||||
R_ext = crealf(srslte_vec_dot_prod_conj_ccc(&input_cp_ext[q->fft_size], input_cp_ext, cp_ext_len));
|
||||
C_ext = cp_ext_len * srslte_vec_avg_power_cf(input_cp_ext, cp_ext_len);
|
||||
input_cp_ext += q->fft_size+cp_ext_len;
|
||||
for (int i=0;i<nof_symbols;i++) {
|
||||
R_norm += crealf(srslte_vec_dot_prod_conj_ccc(&input_cp_norm[q->fft_size], input_cp_norm, cp_norm_len));
|
||||
C_norm += cp_norm_len * srslte_vec_avg_power_cf(input_cp_norm, cp_norm_len);
|
||||
input_cp_norm += q->fft_size+cp_norm_len;
|
||||
}
|
||||
if (C_norm > 0) {
|
||||
M_norm = R_norm/C_norm;
|
||||
}
|
||||
|
||||
q->M_norm_avg = SRSLTE_VEC_EMA(M_norm/nof_symbols, q->M_norm_avg, CP_EMA_ALPHA);
|
||||
|
||||
for (int i=0;i<nof_symbols;i++) {
|
||||
R_ext += crealf(srslte_vec_dot_prod_conj_ccc(&input_cp_ext[q->fft_size], input_cp_ext, cp_ext_len));
|
||||
C_ext += cp_ext_len * srslte_vec_avg_power_cf(input_cp_ext, cp_ext_len);
|
||||
input_cp_ext += q->fft_size+cp_ext_len;
|
||||
}
|
||||
if (C_ext > 0) {
|
||||
M_ext += R_ext/C_ext;
|
||||
M_ext = R_ext/C_ext;
|
||||
}
|
||||
}
|
||||
|
||||
q->M_ext_avg = SRSLTE_VEC_EMA(M_ext/2, q->M_ext_avg, CP_EMA_ALPHA);
|
||||
q->M_ext_avg = SRSLTE_VEC_EMA(M_ext/nof_symbols, q->M_ext_avg, CP_EMA_ALPHA);
|
||||
|
||||
if (q->M_norm_avg > q->M_ext_avg) {
|
||||
return SRSLTE_CP_NORM;
|
||||
} else if (q->M_norm_avg < q->M_ext_avg) {
|
||||
return SRSLTE_CP_EXT;
|
||||
} else {
|
||||
if (R_norm > R_ext) {
|
||||
return SRSLTE_CP_NORM;
|
||||
} else {
|
||||
if (q->M_norm_avg > q->M_ext_avg) {
|
||||
return SRSLTE_CP_NORM;
|
||||
} else if (q->M_norm_avg < q->M_ext_avg) {
|
||||
return SRSLTE_CP_EXT;
|
||||
} else {
|
||||
if (R_norm > R_ext) {
|
||||
return SRSLTE_CP_NORM;
|
||||
} else {
|
||||
return SRSLTE_CP_EXT;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return SRSLTE_CP_NORM;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -333,6 +348,44 @@ srslte_pss_synch_t* srslte_sync_get_cur_pss_obj(srslte_sync_t *q) {
|
|||
return pss_obj[q->cfo_i+1];
|
||||
}
|
||||
|
||||
static float cfo_estimate(srslte_sync_t *q, cf_t *input) {
|
||||
uint32_t cp_offset = 0;
|
||||
cp_offset = srslte_cp_synch(&q->cp_synch, input, q->max_offset, q->nof_symbols, SRSLTE_CP_LEN_NORM(1,q->fft_size));
|
||||
cf_t cp_corr_max = srslte_cp_synch_corr_output(&q->cp_synch, cp_offset);
|
||||
float cfo = -carg(cp_corr_max) / M_PI / 2;
|
||||
return cfo;
|
||||
}
|
||||
|
||||
static int cfo_i_estimate(srslte_sync_t *q, cf_t *input, int find_offset, int *peak_pos) {
|
||||
float peak_value;
|
||||
float max_peak_value = -99;
|
||||
int max_cfo_i = 0;
|
||||
srslte_pss_synch_t *pss_obj[3] = {&q->pss_i[0], &q->pss, &q->pss_i[1]};
|
||||
for (int cfo_i=0;cfo_i<3;cfo_i++) {
|
||||
srslte_pss_synch_set_N_id_2(pss_obj[cfo_i], q->N_id_2);
|
||||
int p = srslte_pss_synch_find_pss(pss_obj[cfo_i], &input[find_offset], &peak_value);
|
||||
if (peak_value > max_peak_value) {
|
||||
max_peak_value = peak_value;
|
||||
if (peak_pos) {
|
||||
*peak_pos = p;
|
||||
}
|
||||
q->peak_value = peak_value;
|
||||
max_cfo_i = cfo_i-1;
|
||||
}
|
||||
}
|
||||
return max_cfo_i;
|
||||
}
|
||||
|
||||
float srslte_sync_cfo_estimate(srslte_sync_t *q, cf_t *input, int find_offset) {
|
||||
float cfo_f = cfo_estimate(q, input);
|
||||
|
||||
int cfo_i = 0;
|
||||
if (q->find_cfo_i) {
|
||||
cfo_i = cfo_i_estimate(q, input, find_offset, NULL);
|
||||
}
|
||||
return (float) cfo_i + cfo_f;
|
||||
}
|
||||
|
||||
/** Finds the PSS sequence previously defined by a call to srslte_sync_set_N_id_2()
|
||||
* around the position find_offset in the buffer input.
|
||||
* Returns 1 if the correlation peak exceeds the threshold set by srslte_sync_set_threshold()
|
||||
|
@ -340,17 +393,17 @@ srslte_pss_synch_t* srslte_sync_get_cur_pss_obj(srslte_sync_t *q) {
|
|||
*
|
||||
* The maximum of the correlation peak is always stored in *peak_position
|
||||
*/
|
||||
int srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32_t *peak_position)
|
||||
srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32_t *peak_position)
|
||||
{
|
||||
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
srslte_sync_find_ret_t ret = SRSLTE_SYNC_ERROR;
|
||||
|
||||
if (q != NULL &&
|
||||
input != NULL &&
|
||||
srslte_N_id_2_isvalid(q->N_id_2) &&
|
||||
fft_size_isvalid(q->fft_size))
|
||||
{
|
||||
int peak_pos;
|
||||
int peak_pos = 0;
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
|
||||
|
@ -358,44 +411,20 @@ int srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32
|
|||
*peak_position = 0;
|
||||
}
|
||||
|
||||
/* Estimate CFO using CP before computing the PSS correlation as in:
|
||||
* Shoujun Huang, et al, "Joint Time and Frequency Offset Estimation in LTE Downlink"
|
||||
*/
|
||||
uint32_t cp_offset = 0;
|
||||
if (q->enable_cfo_corr) {
|
||||
cp_offset = srslte_cp_synch(&q->cp_synch, input, q->max_offset, q->nof_symbols, SRSLTE_CP_LEN_NORM(1,q->fft_size));
|
||||
cf_t cp_corr_max = srslte_cp_synch_corr_output(&q->cp_synch, cp_offset);
|
||||
float cfo = -carg(cp_corr_max) / M_PI / 2;
|
||||
float cfo = cfo_estimate(q, input);
|
||||
|
||||
/* compute cumulative moving average CFO */
|
||||
DEBUG("cp_offset_pos=%d, abs=%f, cfo=%f, mean_cfo=%f, nof_symb=%d\n",
|
||||
cp_offset, cabs(cp_corr_max), cfo, q->mean_cfo, q->nof_symbols);
|
||||
if (q->mean_cfo) {
|
||||
q->mean_cfo = SRSLTE_VEC_EMA(cfo, q->mean_cfo, q->cfo_ema_alpha);
|
||||
} else {
|
||||
q->mean_cfo = cfo;
|
||||
}
|
||||
/* compute exponential moving average CFO */
|
||||
q->mean_cfo = SRSLTE_VEC_EMA(cfo, q->mean_cfo, q->cfo_ema_alpha);
|
||||
|
||||
/* Correct CFO with the averaged CFO estimation */
|
||||
srslte_cfo_correct(&q->cfocorr, input, input, -q->mean_cfo / q->fft_size);
|
||||
|
||||
}
|
||||
|
||||
/* If integer CFO is enabled, find max PSS correlation for shifted +1/0/-1 integer versions */
|
||||
if (q->find_cfo_i && q->enable_cfo_corr) {
|
||||
float peak_value;
|
||||
float max_peak_value = -99;
|
||||
peak_pos = 0;
|
||||
srslte_pss_synch_t *pss_obj[3] = {&q->pss_i[0], &q->pss, &q->pss_i[1]};
|
||||
for (int cfo_i=0;cfo_i<3;cfo_i++) {
|
||||
srslte_pss_synch_set_N_id_2(pss_obj[cfo_i], q->N_id_2);
|
||||
int p = srslte_pss_synch_find_pss(pss_obj[cfo_i], &input[find_offset], &peak_value);
|
||||
if (peak_value > max_peak_value) {
|
||||
max_peak_value = peak_value;
|
||||
peak_pos = p;
|
||||
q->peak_value = peak_value;
|
||||
q->cfo_i = cfo_i-1;
|
||||
}
|
||||
}
|
||||
q->cfo_i = cfo_i_estimate(q, input, find_offset, &peak_pos);
|
||||
if (q->cfo_i != 0) {
|
||||
srslte_vec_prod_ccc(input, q->cfo_i_corr[q->cfo_i<0?0:1], input, q->frame_size);
|
||||
INFO("Compensating cfo_i=%d\n", q->cfo_i);
|
||||
|
@ -409,8 +438,6 @@ int srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32
|
|||
}
|
||||
}
|
||||
|
||||
q->mean_peak_value = SRSLTE_VEC_EMA(q->peak_value, q->mean_peak_value, MEANPEAK_EMA_ALPHA);
|
||||
|
||||
if (peak_position) {
|
||||
*peak_position = (uint32_t) peak_pos;
|
||||
}
|
||||
|
@ -436,13 +463,16 @@ int srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32
|
|||
}
|
||||
}
|
||||
|
||||
// Return 1 (peak detected) even if we couldn't estimate CFO and SSS
|
||||
ret = 1;
|
||||
if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) {
|
||||
ret = SRSLTE_SYNC_FOUND;
|
||||
} else {
|
||||
ret = SRSLTE_SYNC_FOUND_NOSPACE;
|
||||
}
|
||||
} else {
|
||||
ret = 0;
|
||||
ret = SRSLTE_SYNC_NOFOUND;
|
||||
}
|
||||
|
||||
DEBUG("SYNC ret=%d N_id_2=%d find_offset=%d frame_len=%d, pos=%d peak=%.2f threshold=%.2f sf_idx=%d, CFO=%.3f KHz\n",
|
||||
INFO("SYNC ret=%d N_id_2=%d find_offset=%d frame_len=%d, pos=%d peak=%.2f threshold=%.2f sf_idx=%d, CFO=%.3f KHz\n",
|
||||
ret, q->N_id_2, find_offset, q->frame_size, peak_pos, q->peak_value,
|
||||
q->threshold, q->sf_idx, 15*(q->cfo_i+q->mean_cfo));
|
||||
|
||||
|
|
|
@ -259,23 +259,23 @@ int main(int argc, char **argv) {
|
|||
// Find SSS
|
||||
int sss_idx = peak_idx-2*fft_size-(SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN(fft_size, SRSLTE_CP_NORM_LEN):SRSLTE_CP_LEN(fft_size, SRSLTE_CP_EXT_LEN));
|
||||
if (sss_idx >= 0 && sss_idx < flen-fft_size) {
|
||||
INFO("Full N_id_1: %d\n", srslte_sss_synch_N_id_1(&sss, m0, m1));
|
||||
srslte_sss_synch_m0m1_partial(&sss, &buffer[sss_idx], 1, ce, &m0, &m0_value, &m1, &m1_value);
|
||||
if (srslte_sss_synch_N_id_1(&sss, m0, m1) != N_id_1) {
|
||||
sss_error2++;
|
||||
}
|
||||
INFO("Partial N_id_1: %d\n", srslte_sss_synch_N_id_1(&sss, m0, m1));
|
||||
srslte_sss_synch_m0m1_diff(&sss, &buffer[sss_idx], &m0, &m0_value, &m1, &m1_value);
|
||||
srslte_sss_synch_m0m1_diff_coh(&sss, &buffer[sss_idx], ce, &m0, &m0_value, &m1, &m1_value);
|
||||
if (srslte_sss_synch_N_id_1(&sss, m0, m1) != N_id_1) {
|
||||
sss_error3++;
|
||||
}
|
||||
INFO("Diff N_id_1: %d\n", srslte_sss_synch_N_id_1(&sss, m0, m1));
|
||||
srslte_sss_synch_m0m1_partial(&sss, &buffer[sss_idx], 1, NULL, &m0, &m0_value, &m1, &m1_value);
|
||||
if (srslte_sss_synch_N_id_1(&sss, m0, m1) != N_id_1) {
|
||||
sss_error1++;
|
||||
}
|
||||
INFO("Full N_id_1: %d\n", srslte_sss_synch_N_id_1(&sss, m0, m1));
|
||||
}
|
||||
|
||||
srslte_sss_synch_m0m1_partial(&sss, &buffer[sss_idx], 1, NULL, &m0, &m0_value, &m1, &m1_value);
|
||||
if (srslte_sss_synch_N_id_1(&sss, m0, m1) != N_id_1) {
|
||||
sss_error1++;
|
||||
}
|
||||
|
||||
// Estimate CP
|
||||
if (peak_idx > 2*(fft_size + SRSLTE_CP_LEN_EXT(fft_size))) {
|
||||
srslte_cp_t cp = srslte_sync_detect_cp(&ssync, buffer, peak_idx);
|
||||
|
@ -300,7 +300,6 @@ int main(int argc, char **argv) {
|
|||
nof_nodet++;
|
||||
}
|
||||
|
||||
|
||||
printf("[%5d]: Pos: %5d (%d-%d), PSR: %4.1f (~%4.1f) Pdet: %4.2f, "
|
||||
"FA: %4.2f, CFO: %+4.1f KHz, SFO: %+.2f Hz SSSmiss: %4.2f/%4.2f/%4.2f CPNorm: %.0f%%\r",
|
||||
frame_cnt,
|
||||
|
@ -310,7 +309,6 @@ int main(int argc, char **argv) {
|
|||
(float) nof_nopeakdet/frame_cnt, mean_cfo*15, sfo,
|
||||
(float) sss_error1/nof_det,(float) sss_error2/nof_det,(float) sss_error3/nof_det,
|
||||
(float) cp_is_norm/nof_det * 100);
|
||||
|
||||
|
||||
if (frame_cnt > 100) {
|
||||
if (abs(last_peak-peak_idx) > 4) {
|
||||
|
|
|
@ -35,12 +35,7 @@
|
|||
#include "srslte/utils/debug.h"
|
||||
#include "srslte/utils/vector.h"
|
||||
|
||||
int srslte_ue_cellsearch_init(srslte_ue_cellsearch_t * q, int (recv_callback)(void*, void*, uint32_t,srslte_timestamp_t*), void *stream_handler)
|
||||
{
|
||||
return srslte_ue_cellsearch_init_max(q, SRSLTE_CS_DEFAULT_MAXFRAMES_TOTAL, recv_callback, stream_handler);
|
||||
}
|
||||
|
||||
int srslte_ue_cellsearch_init_max(srslte_ue_cellsearch_t * q, uint32_t max_frames,
|
||||
int srslte_ue_cellsearch_init(srslte_ue_cellsearch_t * q, uint32_t max_frames,
|
||||
int (recv_callback)(void*, void*, uint32_t,srslte_timestamp_t*), void *stream_handler)
|
||||
{
|
||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||
|
@ -77,8 +72,7 @@ int srslte_ue_cellsearch_init_max(srslte_ue_cellsearch_t * q, uint32_t max_frame
|
|||
}
|
||||
|
||||
q->max_frames = max_frames;
|
||||
q->nof_frames_to_scan = SRSLTE_CS_DEFAULT_NOFFRAMES_TOTAL;
|
||||
q->detect_threshold = 1.0;
|
||||
q->nof_valid_frames = max_frames;
|
||||
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
|
@ -107,15 +101,10 @@ void srslte_ue_cellsearch_free(srslte_ue_cellsearch_t * q)
|
|||
|
||||
}
|
||||
|
||||
void srslte_ue_cellsearch_set_threshold(srslte_ue_cellsearch_t * q, float threshold)
|
||||
{
|
||||
q->detect_threshold = threshold;
|
||||
}
|
||||
|
||||
int srslte_ue_cellsearch_set_nof_frames_to_scan(srslte_ue_cellsearch_t * q, uint32_t nof_frames)
|
||||
int srslte_ue_cellsearch_set_nof_valid_frames(srslte_ue_cellsearch_t * q, uint32_t nof_frames)
|
||||
{
|
||||
if (nof_frames <= q->max_frames) {
|
||||
q->nof_frames_to_scan = nof_frames;
|
||||
q->nof_valid_frames = nof_frames;
|
||||
return SRSLTE_SUCCESS;
|
||||
} else {
|
||||
return SRSLTE_ERROR;
|
||||
|
@ -233,23 +222,20 @@ int srslte_ue_cellsearch_scan_N_id_2(srslte_ue_cellsearch_t * q,
|
|||
} else if (ret == 1) {
|
||||
/* This means a peak was found and ue_sync is now in tracking state */
|
||||
ret = srslte_sync_get_cell_id(&q->ue_sync.strack);
|
||||
if (ret >= 0) {
|
||||
if (srslte_sync_get_peak_value(&q->ue_sync.strack) > q->detect_threshold) {
|
||||
/* Save cell id, cp and peak */
|
||||
q->candidates[nof_detected_frames].cell_id = (uint32_t) ret;
|
||||
q->candidates[nof_detected_frames].cp = srslte_sync_get_cp(&q->ue_sync.strack);
|
||||
q->candidates[nof_detected_frames].peak = q->ue_sync.strack.pss.peak_value;
|
||||
q->candidates[nof_detected_frames].psr = srslte_sync_get_peak_value(&q->ue_sync.strack);
|
||||
q->candidates[nof_detected_frames].cfo = srslte_ue_sync_get_cfo(&q->ue_sync);
|
||||
DEBUG
|
||||
("CELL SEARCH: [%3d/%3d/%d]: Found peak PSR=%.3f, Cell_id: %d CP: %s\n",
|
||||
nof_detected_frames, nof_scanned_frames, q->nof_frames_to_scan,
|
||||
q->candidates[nof_detected_frames].psr, q->candidates[nof_detected_frames].cell_id,
|
||||
srslte_cp_string(q->candidates[nof_detected_frames].cp));
|
||||
|
||||
nof_detected_frames++;
|
||||
if (ret >= 0) {
|
||||
/* Save cell id, cp and peak */
|
||||
q->candidates[nof_detected_frames].cell_id = (uint32_t) ret;
|
||||
q->candidates[nof_detected_frames].cp = srslte_sync_get_cp(&q->ue_sync.strack);
|
||||
q->candidates[nof_detected_frames].peak = q->ue_sync.strack.pss.peak_value;
|
||||
q->candidates[nof_detected_frames].psr = srslte_sync_get_peak_value(&q->ue_sync.strack);
|
||||
q->candidates[nof_detected_frames].cfo = srslte_ue_sync_get_cfo(&q->ue_sync);
|
||||
DEBUG
|
||||
("CELL SEARCH: [%3d/%3d/%d]: Found peak PSR=%.3f, Cell_id: %d CP: %s\n",
|
||||
nof_detected_frames, nof_scanned_frames, q->nof_valid_frames,
|
||||
q->candidates[nof_detected_frames].psr, q->candidates[nof_detected_frames].cell_id,
|
||||
srslte_cp_string(q->candidates[nof_detected_frames].cp));
|
||||
|
||||
}
|
||||
nof_detected_frames++;
|
||||
}
|
||||
} else if (ret == 0) {
|
||||
/* This means a peak is not yet found and ue_sync is in find state
|
||||
|
@ -259,7 +245,7 @@ int srslte_ue_cellsearch_scan_N_id_2(srslte_ue_cellsearch_t * q,
|
|||
|
||||
nof_scanned_frames++;
|
||||
|
||||
} while (nof_scanned_frames < q->nof_frames_to_scan);
|
||||
} while (nof_scanned_frames < q->max_frames && nof_detected_frames < q->nof_valid_frames);
|
||||
|
||||
/* In either case, check if the mean PSR is above the minimum threshold */
|
||||
if (nof_detected_frames > 0) {
|
||||
|
|
|
@ -102,6 +102,8 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q,
|
|||
fprintf(stderr, "Error initiating SFO correct\n");
|
||||
goto clean_exit;
|
||||
}
|
||||
srslte_cfo_set_tol(&q->sfo_correct, 0);
|
||||
|
||||
q->sf_symbols = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
|
||||
if (!q->sf_symbols) {
|
||||
perror("malloc");
|
||||
|
|
|
@ -142,10 +142,10 @@ int srslte_ue_mib_decode(srslte_ue_mib_t * q, cf_t *input,
|
|||
|
||||
/* Decode PBCH */
|
||||
ret = srslte_pbch_decode(&q->pbch, &q->sf_symbols[SRSLTE_SLOT_LEN_RE(q->chest.cell.nof_prb, q->chest.cell.cp)],
|
||||
ce_slot1, 0,
|
||||
ce_slot1, srslte_chest_dl_get_noise_estimate(&q->chest),
|
||||
bch_payload, nof_tx_ports, sfn_offset);
|
||||
|
||||
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error decoding PBCH (%d)\n", ret);
|
||||
} else if (ret == 1) {
|
||||
|
@ -153,10 +153,11 @@ int srslte_ue_mib_decode(srslte_ue_mib_t * q, cf_t *input,
|
|||
srslte_ue_mib_reset(q);
|
||||
ret = SRSLTE_UE_MIB_FOUND;
|
||||
} else {
|
||||
ret = SRSLTE_UE_MIB_NOTFOUND;
|
||||
INFO("MIB not decoded: %u\n", q->frame_cnt);
|
||||
q->frame_cnt++;
|
||||
ret = SRSLTE_UE_MIB_NOTFOUND;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,9 +43,9 @@ cf_t dummy[MAX_TIME_OFFSET];
|
|||
|
||||
#define TRACK_MAX_LOST 4
|
||||
#define TRACK_FRAME_SIZE 32
|
||||
#define FIND_NOF_AVG_FRAMES 2
|
||||
#define DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD 20
|
||||
#define DEFAULT_SFO_EMA_COEFF 0.1
|
||||
#define FIND_NOF_AVG_FRAMES 4
|
||||
#define DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD 10
|
||||
#define DEFAULT_SFO_EMA_COEFF 0.1
|
||||
|
||||
cf_t dummy_offset_buffer[1024*1024];
|
||||
|
||||
|
@ -171,17 +171,17 @@ int srslte_ue_sync_init(srslte_ue_sync_t *q,
|
|||
|
||||
if (cell.id == 1000) {
|
||||
/* If the cell id is unknown, enable CP detection on find */
|
||||
srslte_sync_cp_en(&q->sfind, true);
|
||||
srslte_sync_cp_en(&q->strack, true);
|
||||
// FIXME: CP detection not working very well. Not supporting Extended CP right now
|
||||
srslte_sync_cp_en(&q->sfind, false);
|
||||
srslte_sync_cp_en(&q->strack, false);
|
||||
|
||||
srslte_sync_set_cfo_ema_alpha(&q->sfind, 0.9);
|
||||
srslte_sync_set_cfo_ema_alpha(&q->strack, 0.4);
|
||||
srslte_sync_set_cfo_ema_alpha(&q->sfind, 0.8);
|
||||
srslte_sync_set_cfo_ema_alpha(&q->strack, 0.1);
|
||||
|
||||
srslte_sync_cfo_i_detec_en(&q->sfind, true);
|
||||
srslte_sync_cfo_i_detec_en(&q->strack, true);
|
||||
srslte_sync_cfo_i_detec_en(&q->sfind, false);
|
||||
|
||||
srslte_sync_set_threshold(&q->sfind, 1.5);
|
||||
q->nof_avg_find_frames = FIND_NOF_AVG_FRAMES;
|
||||
srslte_sync_set_threshold(&q->sfind, 2.0);
|
||||
srslte_sync_set_threshold(&q->strack, 1.0);
|
||||
|
||||
} else {
|
||||
|
@ -192,10 +192,9 @@ int srslte_ue_sync_init(srslte_ue_sync_t *q,
|
|||
srslte_sync_cp_en(&q->sfind, false);
|
||||
srslte_sync_cp_en(&q->strack, false);
|
||||
|
||||
srslte_sync_cfo_i_detec_en(&q->sfind, true);
|
||||
srslte_sync_cfo_i_detec_en(&q->strack, true);
|
||||
srslte_sync_cfo_i_detec_en(&q->sfind, false);
|
||||
|
||||
srslte_sync_set_cfo_ema_alpha(&q->sfind, 0.9);
|
||||
srslte_sync_set_cfo_ema_alpha(&q->sfind, 0.01);
|
||||
srslte_sync_set_cfo_ema_alpha(&q->strack, 0.01);
|
||||
|
||||
/* In find phase and if the cell is known, do not average pss correlation
|
||||
|
@ -203,10 +202,10 @@ int srslte_ue_sync_init(srslte_ue_sync_t *q,
|
|||
*/
|
||||
q->nof_avg_find_frames = 1;
|
||||
srslte_sync_set_em_alpha(&q->sfind, 1);
|
||||
srslte_sync_set_threshold(&q->sfind, 4.0);
|
||||
srslte_sync_set_threshold(&q->sfind, 3.0);
|
||||
|
||||
srslte_sync_set_em_alpha(&q->strack, 0.2);
|
||||
srslte_sync_set_threshold(&q->strack, 1.0);
|
||||
srslte_sync_set_threshold(&q->strack, 1.2);
|
||||
|
||||
}
|
||||
|
||||
|
@ -273,7 +272,8 @@ float srslte_ue_sync_get_cfo(srslte_ue_sync_t *q) {
|
|||
return 15000 * srslte_sync_get_cfo(&q->strack);
|
||||
}
|
||||
|
||||
void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q, float cfo) {
|
||||
void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q, float cfo) {
|
||||
srslte_sync_set_cfo(&q->sfind, cfo/15000);
|
||||
srslte_sync_set_cfo(&q->strack, cfo/15000);
|
||||
}
|
||||
|
||||
|
@ -330,7 +330,7 @@ static int find_peak_ok(srslte_ue_sync_t *q, cf_t *input_buffer) {
|
|||
if (q->recv_callback(q->stream, input_buffer, q->peak_idx+q->sf_len/2, &q->last_timestamp) < 0) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/* Reset variables */
|
||||
q->frame_ok_cnt = 0;
|
||||
q->frame_no_cnt = 0;
|
||||
|
@ -346,7 +346,6 @@ static int find_peak_ok(srslte_ue_sync_t *q, cf_t *input_buffer) {
|
|||
q->strack.cfo_i = q->sfind.cfo_i;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -397,7 +396,7 @@ static int track_peak_ok(srslte_ue_sync_t *q, uint32_t track_idx) {
|
|||
}
|
||||
q->mean_sfo = SRSLTE_VEC_EMA(q->mean_sample_offset, q->mean_sfo, q->sfo_ema);
|
||||
|
||||
INFO("\n\nTime offset adjustment: %d samples (%.2f), mean SFO: %.2f Hz, %.5f samples/5-sf, ema=%f, length=%d\n",
|
||||
INFO("Time offset adjustment: %d samples (%.2f), mean SFO: %.2f Hz, %.5f samples/5-sf, ema=%f, length=%d\n",
|
||||
q->next_rf_sample_offset, q->mean_sample_offset,
|
||||
srslte_ue_sync_get_sfo(q),
|
||||
q->mean_sfo, q->sfo_ema, q->sample_offset_correct_period);
|
||||
|
@ -433,6 +432,12 @@ static int track_peak_no(srslte_ue_sync_t *q) {
|
|||
} else {
|
||||
INFO("Tracking peak not found. Peak %.3f, %d lost\n",
|
||||
srslte_sync_get_last_peak_value(&q->strack), (int) q->frame_no_cnt);
|
||||
/*
|
||||
printf("Saving files: pss_corr (%d), input (%d)\n", q->strack.pss.frame_size, SRSLTE_SF_LEN_PRB(q->cell.nof_prb));
|
||||
srslte_vec_save_file("pss_corr", q->strack.pss.conv_output_avg, q->strack.pss.frame_size*sizeof(float));
|
||||
srslte_vec_save_file("input", q->input_buffer, SRSLTE_SF_LEN_PRB(q->cell.nof_prb)*sizeof(cf_t));
|
||||
exit(-1);
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -512,19 +517,28 @@ int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer) {
|
|||
return SRSLTE_ERROR;
|
||||
}
|
||||
switch (q->state) {
|
||||
case SF_FIND:
|
||||
ret = srslte_sync_find(&q->sfind, input_buffer, 0, &q->peak_idx);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error finding correlation peak (%d)\n", ret);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
case SF_FIND:
|
||||
switch(srslte_sync_find(&q->sfind, input_buffer, 0, &q->peak_idx)) {
|
||||
case SRSLTE_SYNC_ERROR:
|
||||
ret = SRSLTE_ERROR;
|
||||
fprintf(stderr, "Error finding correlation peak (%d)\n", ret);
|
||||
return SRSLTE_ERROR;
|
||||
case SRSLTE_SYNC_FOUND:
|
||||
ret = find_peak_ok(q, input_buffer);
|
||||
break;
|
||||
case SRSLTE_SYNC_FOUND_NOSPACE:
|
||||
/* If a peak was found but there is not enough space for SSS/CP detection, discard a few samples */
|
||||
q->recv_callback(q->stream, dummy_offset_buffer, q->frame_len/2, NULL);
|
||||
srslte_sync_reset(&q->sfind);
|
||||
ret = SRSLTE_SUCCESS;
|
||||
break;
|
||||
default:
|
||||
ret = SRSLTE_SUCCESS;
|
||||
break;
|
||||
}
|
||||
if (q->do_agc) {
|
||||
srslte_agc_process(&q->agc, input_buffer, q->sf_len);
|
||||
}
|
||||
|
||||
if (ret == 1) {
|
||||
ret = find_peak_ok(q, input_buffer);
|
||||
}
|
||||
break;
|
||||
case SF_TRACK:
|
||||
ret = 1;
|
||||
|
@ -552,12 +566,26 @@ int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer) {
|
|||
/* Track PSS/SSS around the expected PSS position
|
||||
* In tracking phase, the subframe carrying the PSS is always the last one of the frame
|
||||
*/
|
||||
ret = srslte_sync_find(&q->strack, input_buffer,
|
||||
q->frame_len - q->sf_len/2 - q->fft_size - q->strack.max_offset/2,
|
||||
&track_idx);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error tracking correlation peak\n");
|
||||
return SRSLTE_ERROR;
|
||||
switch(srslte_sync_find(&q->strack, input_buffer,
|
||||
q->frame_len - q->sf_len/2 - q->fft_size - q->strack.max_offset/2,
|
||||
&track_idx))
|
||||
{
|
||||
case SRSLTE_SYNC_ERROR:
|
||||
ret = SRSLTE_ERROR;
|
||||
fprintf(stderr, "Error tracking correlation peak\n");
|
||||
return SRSLTE_ERROR;
|
||||
case SRSLTE_SYNC_FOUND:
|
||||
ret = track_peak_ok(q, track_idx);
|
||||
break;
|
||||
case SRSLTE_SYNC_FOUND_NOSPACE:
|
||||
// It's very very unlikely that we fall here because this event should happen at FIND phase only
|
||||
ret = 0;
|
||||
q->state = SF_FIND;
|
||||
printf("Warning: No space for SSS/CP while in tracking phase\n");
|
||||
break;
|
||||
case SRSLTE_SYNC_NOFOUND:
|
||||
ret = track_peak_no(q);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef MEASURE_EXEC_TIME
|
||||
|
@ -566,11 +594,6 @@ int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer) {
|
|||
q->mean_exec_time = (float) SRSLTE_VEC_CMA((float) t[0].tv_usec, q->mean_exec_time, q->frame_total_cnt);
|
||||
#endif
|
||||
|
||||
if (ret == 1) {
|
||||
ret = track_peak_ok(q, track_idx);
|
||||
} else {
|
||||
ret = track_peak_no(q);
|
||||
}
|
||||
if (ret == SRSLTE_ERROR) {
|
||||
fprintf(stderr, "Error processing tracking peak\n");
|
||||
q->state = SF_FIND;
|
||||
|
@ -579,16 +602,14 @@ int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer) {
|
|||
|
||||
q->frame_total_cnt++;
|
||||
} else {
|
||||
/* Do CFO Correction if not in 0 or 5 subframes */
|
||||
if (q->correct_cfo) {
|
||||
srslte_cfo_correct(&q->sfind.cfocorr,
|
||||
input_buffer,
|
||||
input_buffer,
|
||||
-srslte_sync_get_cfo(&q->strack) / q->fft_size);
|
||||
-srslte_sync_get_cfo(&q->sfind) / q->fft_size);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -704,14 +704,14 @@ uint32_t srslte_vec_max_abs_ci(cf_t *x, uint32_t len) {
|
|||
void srslte_vec_quant_fuc(float *in, uint8_t *out, float gain, float offset, float clip, uint32_t len) {
|
||||
int i;
|
||||
int tmp;
|
||||
|
||||
for (i=0;i<len;i++) {
|
||||
tmp = (int) (offset + gain * in[i]);
|
||||
if (tmp < 0)
|
||||
tmp = 0;
|
||||
if (tmp > clip)
|
||||
tmp = clip;
|
||||
out[i] = (uint8_t) tmp;
|
||||
out[i] = (uint8_t) tmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue