I am doing a project about the fractionally spaced equalizers on matlab. The goal is to mitigate ISI on the signal using the LMS algorithm to update the tap weights of the FSE. Below i have uploaded the whole code. I have done most of the project but have some problems on the final part. When i try to write the LMS algorithm part it seems to always have some problems (below i've put 2 versions of it, one is commented %%). I don't know what might be the problem. Since i'm using a BPSK modulated signal the final result should be a graph with points scattered around -1 and 1 forming 2 clouds arond these 2 values. Can you help me understand where does my error lies and how to fix it? The help will be very much appreciated.
Below i have explained all the code to make it easier for everyone to follow:
Channel impulse response creation. (RRC channel impulse response).
% 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); % Plot Tx/Rx impulse response figure, stem(n, pt), title('RRC filter impulse response')
Insertion of ISI in the channel impulse response. Since i have to have ISI in my channel impulse response (otherwise i wouldn't need equalization) i have created an identical copy of "pt" called "pt_delay" that is just shifted in time. After that i have used this method to insert ISI "pt_delay = 0.7pt+0.3pt_delay;"
pt_delay = truncRRC(n, alpha,1/3); pt_delay = 0.7*pt+0.3*pt_delay; figure, stem(n, pt_delay), title('RRC filter impulse response with delay')
Here the BPSK modulated signal is created.
% M-PSK consellation M = 2; % Number of PSK levels mb = log2(M); % Number of bits psklev = exp(1j*2*pi*(0:M-1)/M); % M-PSK levels nSym = 1000; % Number of symbols symtx = randi([0,M-1], nSym, 1); % Generate random M-ary symbols [symtxg, ~] = togray(symtx, mb); % Gray mapping ci = psklev(symtxg+1); % Symbol selection
After that i have created my packet that consists of a Barker preamble, training sequence and the BPSK symbols. Upsample the signal and then filter it.
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); % Generate training sequence trainSymtx = randi([0, M-1], 1, nSym); % Random M-ary symbols ReadySignal = [barker,trainSymtx, ci]; % Transmission filtering: upsample and filter txSig_up = upsample(ReadySignal, Nc); txSig = filter(pt_delay, 1, txSig_up);
SNR = 30; % SNR in dB SNRlin = 10^(SNR/10); % SNR linear scale swn = sqrt(0.5*Nc/(SNRlin*mb)); % Noise variance rxSig = txSig + swn*(randn(size(txSig)) + 1j*randn(size(txSig))); figure, scatter(real(rxSig), imag(rxSig)), title('Received constellation') % Receiver filtering rxSig2 = filter(pt, 1, rxSig);
After adding noise and filtering it's time for cross correlation to find where does my "useful" signal starts.
preamble_up = upsample(barker, Nc); [r,lags] = xcorr(rxSig2,preamble_up); [~, idx] = max(abs(r)); start_preamble_idx = lags(idx); % start_preamble_idx is the index of the symbol that precedes the first of the preamble
I have downsampled to pass from 12 samples per symbol to only 2 samples per symbol
% downsampling rxSig_ds = downsample(rxSig2(start_preamble_idx+1:end), Nc/2); figure, scatter(real(rxSig_ds), imag(rxSig_ds)), title('Received constellation downsampled')
Here i have divided my received packet into its 3 parts
% ML detection (minimum distance) dist_vec = abs(psklev.' - rxSig_ds) .^ 2; [~, sym_idx] = min(dist_vec); det_symg = sym_idx - 1; % Gray-coded detected symbol [detected_syms, ~] = fromgray(det_symg, mb); % Detected symbol selected_syms = psklev(detected_syms + 1); % Symbol selection % select only the preamble preamble_syms = selected_syms(1:2*barker_len(2)); % select only the training sequence trainseq_syms = selected_syms(2*barker_len(2)+1:2*barker_len(2)+2*nSym); % select only the payload payload_syms = selected_syms(2*barker_len(2)+2*nSym+1:end); figure, scatter(real(payload_syms), imag(payload_syms)), title('Received payload') ylim([-0.5 0.5])
Now we can check if the vector 'preamble_syms' contains the initial preamble 'barker'.
preamble_syms_real = real(preamble_syms); preamble_syms_real = downsample(preamble_syms_real, 2); if preamble_syms_real == barker disp('The vectors are equal.'); else disp('The vectors are not equal.'); end
% FSE parameters tapSpacing = 1/Nc; % Fractional tap spacing numTaps = L*Nc; % Number of taps % LMS algorithm parameters stepSize = 0.01; % Initialize tap weights tapWeights = zeros(1, numTaps); train_syms_real = real(trainseq_syms); error = zeros(1, numTaps); train_syms_real_ds = downsample(train_syms_real, 2);
This is where LMS algorithm is applied and where my problems start. As you can see i have tried 2 different approaches but nothing seems to work.
% % Perform equalization for each symbol in the training signal % for i = 1:2*length(trainSymtx) % % % Extract the current training symbol % currentSymbol = train_syms_real(i); % % % Convolve the tap weights with the received training seq using the fractional tap positions % convOutput = conv(tapWeights, currentSymbol); % % % Calculate the error % error = trainSymtx(i) - convOutput; % % % Update the tap weights using the LMS update rule % tapWeights = tapWeights + stepSize * conj(currentSymbol) * error; % % end for i = 1:nSym convOutput(i) = tapWeights * train_syms_real_ds'; %convOutput(i) = conv(tapWeights, train_syms_real_ds); error(i) = trainSymtx(i)-convOutput(i); for m = 1:nSym tapWeights(m) = tapWeights(m) + stepSize * error(i) * train_syms_real_ds(m); end end % % Use the trained tap weights to equalize the received signal % equalizedSignal = conv(tapWeights, payload_syms); % %Downsample to have 1 sample per symbol % equalizedSignal_ds = downsample(equalizedSignal,2); figure, scatter(real(equalizedSignal_ds), imag(equalizedSignal_ds)), title('Constellation after equalization')
function pRRC=truncRRC(x,a,tau) %truncRRC: Truncated raised root cosine impulse %Use: pRRC=truncRRC(x,a,tau) % x: normalised time % a: rolloff, within [0,1] % tau: input delay % truncRRC(x,a)= (1-a) sinc( (1-a) x) + % a( sinc(ax + 1/4) cos(pi (x+1/4)) + sinc(ax - 1/4) cos(pi (x-1/4)) x = x - tau; % delayed time pRRC = (1-a)*sinc(x*(1-a)); pRRC = pRRC + a* sinc(a*x + 0.25).*cos(pi * (x + 0.25)); pRRC = pRRC + a* sinc(a*x - 0.25).*cos(pi * (x - 0.25)); end function [gd, gb] = togray(in, len) if ischar(in) in = bin2dec(in); end gd = bitxor(in, bitshift(in,-1)); gb = dec2bin(gd, len); end function [de, bi] = fromgray(in, len) if ischar(in) in = bin2dec(in); end in = in(:); n_syms = length(in); b = zeros(n_syms,len); % get MSB of in b(:,1) = bitget(in, repmat(len,[n_syms,1])); for sh = 2 : len in_loc = bitget(in, repmat(len-sh+1,[n_syms,1])); b(:,sh) = bitxor(b(:,sh-1), in_loc); end bi = num2str(b); de = bin2dec(bi); end