function [NumErrors, ResultsStruct] = MCVA( ParametersStruct )
% MCNarrowBand - Monte Carlo Simulation of a WideBand System with
% Multi-path and Viterbi Equalizer
%
% Simulate a simple communication system in a time-varying multi-path
% environment and measure the symbol error rate.
%
% Inputs:
%   ParametersStruct - a structure containing system parameters ( see
%   MCNarrowBandDriver for details) 
%
% Output:
%   NumErrors     - number of errors
%   ResultsStruct - return complete results in a structure; look at
%                   fieldnames for details.
%
% Example:
%   NumErrors = MCNarrowBand( ParametersStruct )

%% Parameters
% unpack parameters structure - convert to local variables
Fields = fieldnames( ParametersStruct );
for kk = 1:length(Fields)
    if ( isstruct(ParametersStruct.(Fields{kk})) )
        eval([Fields{kk} '= ParametersStruct.' Fields{kk} ';' ]);
    else
    eval([ Fields{kk} ...
        '= [' num2str( ParametersStruct.( Fields{kk} ) ) '];' ]);
    end
end

%% derived parameters
A        = sqrt(Es/T);    % transmitter gain
N0       = Es/EsOverN0;   % noise PSD (complex noise)
NoiseVar = N0/T*fsT;      % corresponding noise variance N0/Ts
Scale    = A*hh*hh';      % gain through signal chain
fs       = fsT/T;         % sampling rate
ChannelParams.fd = fd;    % add Doppler to Channel model

%% simulate discrete-time equivalent system
% transmitter and channel via toolbox functions
InfoSymbols = RandomSymbols( NSymbols, Alphabet, Priors );
% insert training sequence
Symbols = [ InfoSymbols(1:TrainLoc) TrainingSeq ...
    InfoSymbols(TrainLoc+1:end)];
% linear modulation
Signal = A * LinearModulation( Symbols, hh, fsT );

% time-varying multi-path channels and additive noise
Received = SimulateCOSTChannel( Signal, ChannelParams, fs);
Received = addNoise( Received, NoiseVar );

% digital matched filter(downsample to 2 samples per symbol), ensure MFOut
% is long enough so that VA below produces the right number of symbols.
MFOut     = zeros( 1, 2*length(Symbols)+L-1 );
Temp      = DMF( Received, hh, fsT/2 );
MFOut( 1:length(Temp) ) = Temp;

% channel estimation
MFOutTraining = MFOut( 2*TrainLoc+1 : 2*(TrainLoc+TrainLength) );
ChannelEst = EstChannel( MFOutTraining, TrainingSeq, L, 2);

% VA over MFOut using ChannelEst
Decisions = va( MFOut, ChannelEst, Alphabet, 2);
% strip training sequence and possible extra symbols
Decisions( TrainLoc+1 : TrainLoc+TrainLength ) = [ ];
Decisions = Decisions(1:NSymbols);

%% Count errors
NumErrors = sum( Decisions ~= InfoSymbols );

%% Return results in a structure, if needed
if (nargout > 1)
    ResultsStruct.NumErrors  = NumErrors;
    ResultsStruct.NumSymbols = length( Symbols );
    ResultsStruct.Received   = Received;
    ResultsStruct.MFOut      = MFOut;
    ResultsStruct.Symbols    = Symbols;
    ResultsStruct.Decisions  = Decisions;
    ResultsStruct.Scale      = Scale;
end

