I have created a FSE with LMS algorithm. The problem I am facing is related to the Symbol Error Rate (SER). I want it to be as small as possibile, the value that i have found is around 0.4, but i prefered to be close to 0.01.
I have tried different ways, but I falled in all of them.
I expected lower value for SER, but I have found a high value.
clear all
close all
clc
% Root of raised cosine filter parameters
alpha = 0.35; % Rolloff factor
L = 24; % Truncated impulse length (-L/2:L/2)
Nc = 12; % Number of samples per symbol
% Tx filter design
istrt = floor(L/2);
n = -istrt:1/Nc:istrt; %(-L/2:1/Nc:L/2)
pt = truncRRC(n, alpha,0);
pt_delay=0.5*pt+0.2*truncRRC(n, alpha, 1)+0.2*truncRRC(n, alpha, 2)+0.1*truncRRC(n, alpha, -2);
figure
subplot(2,1,1)
stem((-L/2:1/Nc:L/2),pt);
xlim([-5 5]);
title('No ISI');
subplot(2,1,2)
stem((-L/2:1/Nc:L/2),pt_delay);
xlim([-5 5]);
title('ISI');
M = 2;
mb = log2(M);
nFrm = 1; % num di frames
nSym = 1000; % length of the data sequence (num di simboli)
nSFrm = nSym;
data_seq = sign(randn(1,nSym)); % Generate BPSK data
figure
scatter(real(data_seq), imag(data_seq),'red')
title('Ideal BPSK symbols');
pairs = [1 2; 3 4; 5 6; 7 8; 9 10; 11 12; 13 14;
15 16; 17 18; 19 20; 21 22; 23 24; 25 26;
27 28 ;29 30; 31 32; 33 34; 35 36; 37 38;
39 40; 41 42; 43 44; 45 46; 47 48; 49 50;
51 52; 53 54; 55 56; 57 58; 59 60; 61 62; 63 64];
% Generate Barker sequence
barker = ones(1, 16);
for i = 1:size(pairs, 1)
barker(pairs(i, 1)) = -1;
barker(pairs(i, 2)) = 1;
end
barker_len = size(barker);
trainSymtx_len = nSym; % sceglila tu!
trainSymtx = sign(randn(1, trainSymtx_len));
ReadySignal = [barker, trainSymtx, data_seq];
% Transmission filtering: upsample and filter
txSig_up = upsample(ReadySignal, Nc);
txSig = filter(pt_delay, 1, txSig_up);
SampleRate = 1e6; % SampleRate ~ rate the device is configured to collect data
SamplesPerRXFrame = length(txSig); % SamplesPerRXFrame ~ size of the buffer/ frame transfer from PlutoSDR to MATLAB
FramesToCollect = 10; % Frame exchanged between Adalm Pluto and MATLAB
FrequencyOffset = 0; % Frequency Error (Hz)
rx = sdrrx('Pluto','SamplesPerFrame',SamplesPerRXFrame,...
'BasebandSampleRate',SampleRate,'OutputDataType','double');
tx = sdrtx('Pluto','Gain',-20,...
'BasebandSampleRate',SampleRate);
tx.CenterFrequency = tx.CenterFrequency + FrequencyOffset; % Correction of the Rotation introduced by the Frequency Error
txSig = complex(txSig,0);
tx.transmitRepeat(txSig');
% Get data from radio --> Checking Overflow Conditions
sa=dsp.SpectrumAnalyzer();
saved = zeros(FramesToCollect*SamplesPerRXFrame,1);
ofe = 0;
for g = 1 : SamplesPerRXFrame : FramesToCollect * SamplesPerRXFrame
[sig_rx, ~, of] = rx();
saved(g : g+SamplesPerRXFrame - 1) = sig_rx;
% Checking and counting overflows events
if of
ofe = ofe + 1;
end
end
% Visualize
for g=1:SamplesPerRXFrame:FramesToCollect*SamplesPerRXFrame
sa(saved(g:g+SamplesPerRXFrame-1));
end
clear rx tx;
%% Set up radio and capture some data
rx = sdrrx('Pluto','SamplesPerFrame',SamplesPerRXFrame,...
'BasebandSampleRate',SampleRate);
tx = sdrtx('Pluto','Gain',-20,...
'BasebandSampleRate',SampleRate);
tx.transmitRepeat(txSig');
% Get data from radio
sa = dsp.SpectrumAnalyzer();
sa(complex(zeros(SamplesPerRXFrame,1,'int16')));
ofe = 0;
for g=1:FramesToCollect
[sig_rx,~,of] = rx();
if of
ofe = ofe + 1;
end
sa(sig_rx);
end
clear rx tx;
% Receiver filtering
rxSig = filter(pt, 1, txSig)./Nc;
figure;
scatter(real(rxSig), imag(rxSig),'red')
title('seq rx con ISI Filtrata')
ylim([-0.5 0.5])
preamble_up = upsample(barker, Nc);
[r,lags] = xcorr(rxSig,preamble_up);
[~, idx] = max(real(r));
start_preamble_idx = lags(idx);
%% 1) Estrazione del Preambolo dal Frame
% PREAMBOLO inizia da start_preamble_idx+1 in avanti
preamble_syms = rxSig(start_preamble_idx+1:start_preamble_idx+length(preamble_up));
preamble_syms_ds = downsample(preamble_syms,Nc)
preamble_syms_ds = 2*double(preamble_syms_ds>0)-1
okey_preambolo = 0;
for ii=1:length(barker)
if preamble_syms_ds(ii) == barker(ii)
okey_preambolo = okey_preambolo+1;
end
end
if okey_preambolo == length(barker) % esce 38 = 39 ..
disp('Il preambolo è stato stimato correttamente');
end
% 2) Estrazione della Training_Seq dal Frame
training_seq = rxSig(start_preamble_idx+length(preamble_up)+1:start_preamble_idx+length(preamble_up)+Nc*trainSymtx_len);
training_seq_ds = downsample(training_seq,Nc)
% 3) Estrazione dei Dati (payload) dal Frame .. cioè separo _data(payload)_ da _training_ e da _preambolo_
data_seq_rx = rxSig(start_preamble_idx+length(preamble_up)+Nc*trainSymtx_len+1:end);
data_seq_rx_ds = downsample(data_seq_rx,Nc)
% FSE and LMS parameters
N = 22;
numTaps = 2 * N + 1;
stepSize = 0.01;
is_training = 1;
% Initialize tap weights
tapWeights = zeros(1, numTaps);
for k = 1:2*length(trainSymtx)
for i = N+1:length(trainSymtx)-N
% Current received symbol
currSymbols = training_seq_ds(i-N:i+N);
% L'output dell'equalizzatore
y(k) = tapWeights * currSymbols';
if mod(k, 2) == 0
a = k/2;
% L'errore tra l'output e il simbolo di training
error = y(k) - trainSymtx(a);
% Update tap weights
tapWeights = tapWeights - stepSize * error * conj(training_seq_ds(i-N:i+N));
end
end
end
tapWeights_tracking = tapWeights;
% Decision Device
estimated_symbols = zeros(size(data_seq_rx_ds));
dist_vec = zeros(size(data_seq_rx_ds));
for b = N+1:length(data_seq_rx_ds)-N
% Current received symbol
currSym = data_seq_rx_ds(b-N:b+N);
% L'output dell'equalizzatore
eq_out(b) = tapWeights_tracking * currSym';
estimated_symbols = 2*double(eq_out>0)-1;
% Error between equalizer output and estimated symbol
error = eq_out(b) - estimated_symbols(b);
% Update tap weights
tapWeights_tracking = tapWeights_tracking - stepSize * error * conj(currSym);
end
final_estSym = downsample(estimated_symbols, 2);
figure, scatter(real(final_estSym), imag(final_estSym), '*r'), title('Estimated symbols')
xlim([-1.1 1.1])
ylim([-0.4 0.4])
% Symbol Error Rate (SER)
num_errors_symbol = sum(final_estSym ~= data_seq(1:length(final_estSym)));
SER = num_errors_symbol / length(final_estSym);
fprintf('Symbol Error Rate (SER): %.4f\n', SER);