%% Code to generate Fig6a

% This code plots beampatterns of stage-2 of the proposed codebook as seen
% at the receiver for different voltage levels with and without angle
% steering.

% In case of any queries, please contact R.S. Prasobh Sankar (prasobhsankar1@gmail.com)

% Since this code does not involve monte-carlo runs, there is no
% corresponding code to plot Fig6a from data.

clear all
close all
clc

%%

OSR = 4;
N_t = 32;
N_r = (128/OSR)*OSR;
d_r = 0.5/OSR;
d_t = 0.5; % regular array at the transmitter

SNR_dB = 10;
SNR = 10.^(0.1.*SNR_dB);

aod_true = [5];
aoa_true = [30];
figure


a_steer_set = [0 aoa_true aoa_true];
lev_set = [3*sqrt((SNR(1)*N_t+1)/2) 1 3*sqrt((SNR(1)*N_t+1)/2)];
for loop_outer=1:length(a_steer_set) 
    
    a_steer = a_steer_set(loop_outer);  % we ignore angle steering here

L = length(aoa_true);
path_gain_angle = 2*pi*rand(L,1) - pi;
alpha = ones(L,1).*exp(1j.*path_gain_angle); 
A_RX = gen_a(N_r,d_r, aoa_true);


W_mrc_a = sqrt(1/N_r).*A_RX;
W_mrc_sd = sqrt(1/N_r).*A_RX;

Nsnap = 1;

M = 128;
K = 2; %  Beams per stage
s = 2; % Stage index
ncodes = K^s;
W = get_code_TX(N_t, d_t, M, K, s);


phi_d2 = 0:1:360;
cost_2 = zeros(K,length(phi_d2));
cost_2_sd = zeros(K,length(phi_d2));


lev_s2 = lev_set(loop_outer);
a_arg = 2*pi*d_r*sind(a_steer);
lev_corr_fact = 2 - abs(cos(a_arg)) -  abs(sin(a_arg));
b = lev_s2/lev_corr_fact;



for k =1:ncodes
    a_ref = W(:,k);
    for i=1:length(phi_d2)
        
        aod_true = phi_d2(i);
        A_TX = gen_a(N_t,d_t, aod_true);
        H_true = sqrt(1/L).*A_RX*diag(alpha)*A_TX';
        N_noise = sqrt(1/2).*(randn(N_r,Nsnap) + 1j.*randn(N_r,Nsnap));
        X = sqrt(SNR(1)).*H_true*repmat(a_ref,1,Nsnap) + N_noise;   
        
        Y = sigma_delta_ADC(X,a_steer,d_r,b);
        
        R_x_a = (1/Nsnap).*X*X';
        cost_2(k,i) = abs(W_mrc_a'*R_x_a*W_mrc_a);
        
        R_y = (1/Nsnap).*Y*Y';
        cost_2_sd(k,i) = abs(W_mrc_sd'*R_y*W_mrc_sd);
    end
end


subplot(1,4,loop_outer+1)
for k=1:ncodes
     polarplot(phi_d2*pi/180,cost_2_sd(k,:)./(sqrt(N_t)*N_r),'LineWidth',1.2);
    hold on;
end
grid on
if(loop_outer == 1)
    title(['\psi = ',num2str(a_steer),'^0, c=proposed']);
elseif(loop_outer == 2)
     title(['\psi = ',num2str(a_steer),'^0, c=1']);
 elseif(loop_outer == 3)
     title(['\psi = ',num2str(a_steer),'^0, c=proposed']);
end


end


s_index = [2];
for loop_outer=1:length(s_index) 
    
    a_steer = a_steer_set(loop_outer);  % we ignore angle steering here

L = length(aoa_true);
path_gain_angle = 2*pi*rand(L,1) - pi;
alpha = ones(L,1).*exp(1j.*path_gain_angle); 
A_RX = gen_a(N_r,d_r, aoa_true);

W_mrc_a = sqrt(1/N_r).*A_RX;
W_mrc_sd = sqrt(1/N_r).*A_RX;

Nsnap = 1;

M = 128;
K = 2; %  Beams per stage
s = s_index(loop_outer); % Stage index
ncodes = K^s;
W = get_code_TX(N_t, d_t, M, K, s);


phi_d2 = 0:1:360;
cost_2 = zeros(K,length(phi_d2));

for k =1:ncodes
    a_ref = W(:,k);
    for i=1:length(phi_d2)
        
        aod_true = phi_d2(i);
        A_TX = gen_a(N_t,d_t, aod_true);
        H_true = sqrt(1/L).*A_RX*diag(alpha)*A_TX';
        N_noise = sqrt(1/2).*(randn(N_r,Nsnap) + 1j.*randn(N_r,Nsnap));
        X = sqrt(SNR(1)).*H_true*repmat(a_ref,1,Nsnap) + N_noise;   
        
              
        R_x_a = (1/Nsnap).*X*X';
        cost_2(k,i) = abs(W_mrc_a'*R_x_a*W_mrc_a);
     
    end
end


subplot(1,4,1)
for k=1:ncodes
     polarplot(phi_d2*pi/180,cost_2(k,:)./(sqrt(N_t)*N_r),'LineWidth',1.2);
    hold on;
end
grid on
title('UQ');



end

