Eb_No_linear = db2pow(Eb_No); 
error_awgn = zeros(length(Eb_No), N_iterations);
error_rayleigh_awgn = zeros(length(Eb_No), N_iterations);
BER_awgn = zeros(size(Eb_No));
BER_rayleigh_awgn = zeros(size(Eb_No));
BER_theoretical_awgn = qfunc(sqrt(2 * Eb_No_linear)); 
BER_theoretical_fading = 0.5 * (1 - sqrt(Eb_No_linear ./ (1 + Eb_No_linear))); 
    Es_No = Eb_No(n) + 10*log10(Im); 
    total_bit_errors_awgn = 0;
    total_bit_errors_rayleigh = 0;
        data = randi([0 1], Nb, 1);
        data_symbols = bi2de(reshape(data, Im, []).', 'left-msb');
        x = pskmod(data_symbols, M, pi/M, 'gray');
        h = 1/sqrt(2) * (randn(N, 1) + 1i * randn(N, 1)); 
        y = awgn(x, Es_No, "measured");
        yf = awgn(xf, Es_No, "measured");
        y_est = pskdemod(y, M, pi/M, 'gray');
        yf_est = pskdemod(yf_equalized, M, pi/M, 'gray');
        y_est_bits = de2bi(y_est, Im, 'left-msb').';
        yf_est_bits = de2bi(yf_est, Im, 'left-msb').';
        y_est_bits = y_est_bits(:);
        yf_est_bits = yf_est_bits(:);
        total_bit_errors_awgn = total_bit_errors_awgn + nnz(data ~= y_est_bits);
        total_bit_errors_rayleigh = total_bit_errors_rayleigh + nnz(data ~= yf_est_bits);
    BER_awgn(n) = total_bit_errors_awgn / (Nb * N_iterations);
    BER_rayleigh_awgn(n) = total_bit_errors_rayleigh / (Nb * N_iterations);
semilogy(Eb_No, BER_theoretical_awgn, 'r-', 'LineWidth', 1.5); hold on;
semilogy(Eb_No, BER_awgn, 'r-o', 'LineWidth', 1);
semilogy(Eb_No, BER_theoretical_fading, 'b-', 'LineWidth', 1.5);
semilogy(Eb_No, BER_rayleigh_awgn, 'b-o', 'LineWidth', 1);
title('QPSK BER curves for AWGN and Rayleigh');
legend('AWGN_{theory}', 'AWGN_{simulation}', 'Rayleigh_{theory}', 'Rayleigh_{simulation}', 'location', 'best');