% AGC.m - script to demonstrate AGC for HW problem
%
% This script demonstrates an iterative automatic gain control (AGC)
% algorithm. The algorithm processes blocks of samples. In each of these
% blocks, we measure the power of the output signal and compare it to the
% target power. Based on this comparison, the gain is adjusted with the
% objective to make the measured power equal to the target power.
%
% The output signal is plotted to verify that the amplitude reaches the
% desired level sqrt(P_target). Similarly, the measured power is plotted.
%
% Usage:
%   AGC

%% Parameters that control the simulation
mu = 0.5;       % step size parameter
P_target = 1;   % target power
P_in = 0.1;     % input power

N_avg = 10;     % length of block to measure power
N_blocks = 1000; % number of blocks to simulate
NN = N_avg*N_blocks;

% storage for gains during adaptation; initial gain = 1
G = zeros(1,N_blocks+1);
G(1) = 1;

% input signal
% constant amplitude input - simple case
%r_in = sqrt(P_in)*ones(1, NN)
% time-varying input power - more interesting
r_in = sqrt(P_in)*ones(1, NN).*(1+0.5*cos(2*pi*(0:NN-1)/NN));

% storage for output signal and measured power
r_out = zeros(size(r_in));
P_measured = zeros(1,N_blocks);

%% main loop
for nn = 1:N_blocks
    % grab consecutive blocks of input samples
    thisBlock = ((nn-1)*N_avg+1):(nn*N_avg);
    
    % apply current gain to produce output signal
    r_out(thisBlock) = G(nn)*r_in(thisBlock);
    
    % measure power
    P_measured(nn) = 1/N_avg * sum( r_out(thisBlock).^2 );
    
    % adapt gain
    G(nn+1) = G(nn) + mu*4*(P_target - P_measured(nn))*P_measured(nn)/G(nn);
end

figure(1)
% plot input and output signal
plot(0:NN-1, r_in, 'b', 0:NN-1, r_out, 'r', ...
    [0,NN-1], sqrt(P_target)*ones(1,2), 'r--');
grid on
xlabel( 'Sample Number')
ylabel( 'Amplitude' )
legend( 'input signal', 'output signal', 'target amplitude', 'Location','SouthEast')

figure(2)
% plot input and output signal
plot((0:NN-1), 10*log10(r_in.^2), 'b', ...
    (0:N_blocks-1)*N_avg, 10*log10(P_measured), 'r', ...
    [0,NN-1], 10*log10(P_target*ones(1,2)), 'r--');
grid on
xlabel( 'Sample Number')
ylabel( 'Power (dB)' )
legend( 'input power', 'measured power', 'target power', 'Location','SouthEast')