% Problem 3

close all; 
clear all;

% Load the various files
load('training_symbols.mat');
load('received_OFDM_symbols.mat');
load('lambdas.mat');


% Using the first column of the received symbols matrix and the training
% sequence, estimate the noise variance. The noise is assumed to have
% independent and identically distributed components.

noise_var = var(received_OFDM_symbols(:,1).' - training_symbols.*lambdas)


% If you do not manage to compute the noise variance, you can use a value
% of 0.01 for it in the following.

% Compute the LS estimate of the transmitted data symbols
D = diag(lambdas);
% Since D is diagonal, any of the following will work, they are the same.
data_LS_estim1 = received_OFDM_symbols(:,2:end)./(lambdas.');
data_LS_estim2 = pinv(D)*received_OFDM_symbols(:,2:end);
data_LS_estim3 = D\received_OFDM_symbols(:,2:end);


% Plot the estimated data symbols. You should get a noisy 4-QAM
% constellation.
suf_data = data_LS_estim1(:).';
figure; plot(suf_data, '*b'); xlabel('Re'); ylabel('Im'); grid on;
title('The constellation of the estimated data symbols (LS)');


% Compute the LMMSE estimate of the transmitted data symbols
D1 = D*D' + noise_var*eye(length(lambdas));
data_LMMSE_estim = D'*(D1\received_OFDM_symbols(:,2:end));


% Plot the estimated data symbols. You should get a noisy 4-QAM
% constellation.
suf_data = data_LMMSE_estim(:).';
figure; plot(suf_data, '*b'); xlabel('Re'); ylabel('Im'); grid on;
title('The constellation of the estimated data symbols (LMMSE)');


% Compare the values of the estimated symbols obtained with the two methods
% above. For example, compute something like
% mean(abs(data_LS_estim - data_LMMSE_estim)).
% If your estimates were correct, the value above should be around 0.0077.
avg_diff_abs = mean(abs(data_LS_estim1(:) - data_LMMSE_estim(:)))

