% clc;
% clear;
% close all;

%% =====================================================
% TEST SIGNAL GENERATION: OFDM + LPF (FINAL VERSION)
% =====================================================

%% PARAMETERS
FS        = 2e9;     % Sampling frequency (Hz)
M         = 16;        % QAM order

% OFDM parameters
Nfft      = 1024;
Nsc       = 50;        % ~10–12 MHz BW 
cp_len    = 72;

f_offset  = 0;         % Crosstalk case (same frequency)

rng(42);

%% =====================================================
% LIMIT TOTAL SAMPLES (<= 1e5)
%% =====================================================
max_samples = 1e5;
samples_per_symbol = Nfft + cp_len;
Nsym = floor(max_samples / samples_per_symbol);

fprintf('Using Nsym = %d (Total samples ≈ %d)\n', ...
    Nsym, Nsym*samples_per_symbol);

%% =====================================================
% DESIRED SIGNAL (OFDM)
%% =====================================================
data_x = randi([0 M-1], Nsc, Nsym);
qam_x  = qammod(data_x, M, 'UnitAveragePower', true);

Xk = zeros(Nfft, Nsym);
start = floor(Nfft/2 - Nsc/2) + 1;
Xk(start:start+Nsc-1, :) = qam_x;

x_time = ifft(ifftshift(Xk,1), Nfft, 1);
x_cp = [x_time(end-cp_len+1:end,:); x_time];
x = x_cp(:);
win = hann(length(x));
x = x .* win;
x = x / rms(x);

%% =====================================================
% INTERFERER SIGNAL
%% =====================================================
data_i = randi([0 M-1], Nsc, Nsym);
qam_i  = qammod(data_i, M, 'UnitAveragePower', true);

Ik = zeros(Nfft, Nsym);
Ik(start:start+Nsc-1, :) = qam_i;

i_time = ifft(ifftshift(Ik,1), Nfft, 1);
i_cp   = [i_time(end-cp_len+1:end,:); i_time];
i_sig = i_cp(:);
win = hann(length(i_sig));
i_sig =i_sig .* win;
i_sig = i_sig / rms(i_sig);


%% =====================================================
% FREQUENCY SHIFT (OPTIONAL)
%% =====================================================
N = length(x);
t = (0:N-1)' / FS;

i_shifted = i_sig .* exp(1j * 2*pi * f_offset * t);

%% =====================================================
% SAVE SIGNALS
%% =====================================================
save('desired_signal.mat', 'x','FS');
save('interferer_signal.mat', 'i_shifted','FS');

%% =====================================================
% PAPR CALCULATION
%% =====================================================
papr_x = 10*log10(max(abs(x).^2) / mean(abs(x).^2));
papr_i = 10*log10(max(abs(i_shifted).^2) / mean(abs(i_shifted).^2));

fprintf('PAPR (Desired)    = %.2f dB\n', papr_x);
fprintf('PAPR (Interferer) = %.2f dB\n', papr_i);

%% =====================================================
% PSD (WELCH)
%% =====================================================
nfft = 4096;
window = hamming(1024);
noverlap = 512;

%% =====================================================
% SEPARATE PSD PLOTS
%% =====================================================
[p1, f1] = pwelch(x, window, noverlap, nfft, FS, 'centered');
[p2, f2] = pwelch(i_shifted, window, noverlap, nfft, FS, 'centered');

figure;
plot(f1/1e6, 10*log10(p1), 'LineWidth', 1.2);
grid on;
xlabel('Frequency (MHz)');
ylabel('PSD (dB/Hz)');
title('PSD of Desired Signal');

figure;
plot(f2/1e6, 10*log10(p2), 'LineWidth', 1.2);
grid on;
xlabel('Frequency (MHz)');
ylabel('PSD (dB/Hz)');
title('PSD of Interferer');


%% =====================================================
% EXPORT IQ DATA
%% =====================================================
x_export = x / max(abs(x));
i_export = i_shifted / max(abs(i_shifted));

