function varargout = commblkrayleighsrc2(block, varargin)
%COMMBLKRAYLEIGHSRC2 Mask dynamic dialog function for Rayleigh noise 
% generator block.

%   Copyright 1996-2016 The MathWorks, Inc.

% --- Exit code and error message definitions
eStr.ecode = 0;
eStr.eID   = '';
eStr.emsg  = '';

% --- Parse inputs
nvarargin = nargin - 1;
switch nvarargin
  case 0
    action = '';
  case 1
    action = varargin{1};
    Args = {}; %#ok
  otherwise
    action = varargin{1};
    Args = varargin{2:end};
    
    if(~strcmpi(action,'backprop'))
        % --- Breakout the arguments if required
        if((nvarargin > 1) && (isa(Args,'cell')))
            Mask_alpha        = Args{1};
            Mask_seed         = Args{2};
            Mask_sampPerFrame = Args{3};
            Mask_Ts           = Args{4};
        end
    end
end

% --- Field data
Vals  = get_param(block, 'maskvalues');

% --- Set Field index numbers
[idxSampPerFrame,idxOrient,idxFrameBased,idxOutDataType] = ...
    dspGetMaskParamIdx( block,'sampPerFrame','orient','frameBased',...
                        'outDataType'); 


%*********************************************************************
% Function:			initialize
% Description:		Set the dialogs up based on the parameter values.
%                   MaskEnables/MaskVisibles are not saved in reference 
%                   blocks.
% Inputs:			current block
% Return Values:	none
%********************************************************************
if(strcmp(action,'init'))
    
    vLen = [length(Mask_alpha) length(Mask_seed)];
    vSize = {size(Mask_alpha) size(Mask_seed)};

    lenmax = max(vLen);            % Largest of all the parameter lengths

    % --- Return in case of early exit
    varargout = {Mask_alpha, Mask_seed, eStr};
    
    % Check for sample time parameter
    if (~isscalar(Mask_Ts))
        eStr.eID   = 'comm:commblkrayleighsrc2:NonScalarSampleTime';
        eStr.emsg  = 'The sample time parameter must be a real scalar.';
        eStr.ecode = 1; varargout{3} = eStr; return;
    end    
    
    if ((Mask_Ts <= 0) && (Mask_Ts ~= -1))
        eStr.eID   = 'comm:commblkrayleighsrc2:ContSampleTime';
        eStr.emsg  = 'Continuous sample times are not allowed.';
        eStr.ecode = 1; varargout{3} = eStr; return;
    end

    % Check for consistency among vector parameter lengths
    if ~isequal(lenmax,1)   % there exist vector parameters
        
        vSizeAlpha = vSize{1};
        vSizeSeed  = vSize{2};
        
        % Check if vector lengths (if any) agree
        if any(find(vLen(vLen~=1)~=lenmax))
            eStr.eID   = 'comm:commblkrayleighsrc2:InvalidParamDims';
            eStr.emsg  = ['Sigma and Initial seed must be either all scalars,',...
                          ' or if more than one of them is a vector, their',...
                          ' vector sizes should agree.'];
            eStr.ecode = 1; varargout{3} = eStr; return;
            
            % If dimensions are to be preserved, check if they agree
        elseif strcmp(Vals{idxOrient},'off') && strcmp(Vals{idxFrameBased},'off') ...
                && ~isequal(vSizeAlpha(1),vSizeSeed(1)) && ~isequal(vSizeAlpha(2),vSizeSeed(2)) ...
                && ~isequal(vSize{1},vSize{2})
            eStr.eID   = 'comm:commblkrayleighsrc2:InconsistentParamDims';
            eStr.emsg  = ['Dimensions of parameter values in ', block, ' are inconsistent.'];
            eStr.ecode = 1; varargout{3} = eStr; return;
        end
        
    end     
    
    [varargout{1:2}] = updateWS(Mask_alpha,Mask_seed);
    
    cbFrameBased(block,idxSampPerFrame,idxOrient,idxFrameBased);
    cbOrient(block,idxFrameBased,idxOrient);
    setOutDataType(block,Vals{idxOutDataType});    
    updateBlocks(block,lenmax,Vals{idxFrameBased},Vals{idxOrient},...
                 vLen,vSize,Mask_sampPerFrame);
    
    varargout{3} = eStr;
    
end

if(strcmp(action,'cbFrameBased'))
    cbFrameBased(block,idxSampPerFrame,idxOrient,idxFrameBased);
end

if(strcmp(action,'cbOrient'))
    cbOrient(block,idxFrameBased,idxOrient);
end

%----------------------------------------------------------------------
%	Block specific update functions
%----------------------------------------------------------------------
%*********************************************************************
% Function:			UpdateIc
% Description:		Set the initial frame for buffer
% Inputs:			current block
% Return Values:	values set in the workspace (buffic)
%********************************************************************
if(strcmp(action,'UpdateIc'))
    
    vLen   = [length(Mask_alpha) length(Mask_seed)];
    lenmax = max(vLen);            % Largest of all the parameter lengths
    
    % Check for samples per frame parameter
    if (~isscalar(Mask_sampPerFrame) || ~is(Mask_sampPerFrame, 'integer') || ...
        Mask_sampPerFrame < 1 )
        error(message('comm:commblkrayleighsrc2:InvalidSamplesPerFrame'));         
    end    
    
    alpha = Mask_alpha(:)'.*ones(1,lenmax); 
    seed  = Mask_seed;
    sampnum = Mask_sampPerFrame;
    
    % Calculate initial frame for buffer
    varargout{1} = abs( complex( wgn( sampnum, lenmax, 1, 1, seed(1) ) ...
        .*(ones(sampnum,1)*alpha ), wgn( sampnum, lenmax, 1, 1, seed(1) ...
        + max(seed) ).*(ones(sampnum,1)*alpha) ) );
end

%*********************************************************************
% Function:			UpDateBlocks
% Description:		Set the simulink blocks as required
% Inputs:			current block
% Return Values:	none
%********************************************************************
function updateBlocks(block,len,maskFrameBased,maskOrient,vLen,vSize,maskSampPerFrame)

% Sample-based case
if(strcmp(maskFrameBased,'off'))  % Sample-based
    set_param([block, '/Frame Status Conversion'],'outframe','Sample-based');   
    set_param([block, '/Buffer'],'N','1');   % Do not buffer up
    set_param([block, '/Buffer'],'ic','0');
    
    % Interpret as 1-D; OR scalar output
    if(strcmp(maskOrient,'on')) || ~any(vLen-1)
        set_param([block, '/Reshape'],'OutputDimensionality','1-D array');
        
        % 2-D vector output    
    else  
        dimcomp = find(vLen~=1, 1);    % Index of the first vector parameter
                                       % used for comparison with other
                                       % parameters
        vec = vSize{dimcomp};
        
        % Column vector
        if vec(1) > vec(2) 
            set_param([block, '/Reshape'],'OutputDimensionality','Column vector');
            % Row vector
        else
            set_param([block, '/Reshape'],'OutputDimensionality','Row vector');
        end            
    end
    
    % Frame-based case
else 
    set_param([block, '/Frame Status Conversion'],'outframe','Frame-based');   
    set_param([block, '/Buffer'],'N','sampPerFrame');   % Buffer up
    set_param([block, '/Reshape'],'OutputDimensionality','Customize');
    
    % Only need half the size of the seed, because size of seed has been doubled at this point
    set_param([block, '/Reshape'],'OutputDimensions',['[sampPerFrame, ',num2str(len), ']']);
    
    if maskSampPerFrame > 1
        set_param([block, '/Buffer'],'ic','buffic');
    else
        set_param([block, '/Buffer'],'ic','0');
    end
    
end

%*********************************************************************
% Function:			UpdateWs
% Description:		Set the simulink blocks as required
% Inputs:			current block
% Return Values:	values to be set in the workspace
%********************************************************************
function varargout = updateWS(Mask_alpha,Mask_seed)

alpha = Mask_alpha;
seed  = Mask_seed;

alpha=alpha.^2;
seed=[seed(:);seed(:)+max(seed)];
if length(alpha)>1
    alpha=[alpha(:);alpha(:)];
end

varargout(1:2) = {alpha,seed};


%*********************************************************************
% Function Name:	'cbFrameBased'
%  - Callback function for 'frameBased' parameter
%********************************************************************
function cbFrameBased(block,idxSampPerFrame,idxOrient,idxFrameBased)

Vals  = get_param(block, 'maskvalues');
En    = get_param(block, 'maskenables');
Vis   = get_param(block, 'maskvisibilities');
oldEnSamp   = En{idxSampPerFrame};
oldEnOrient = En{idxOrient};

if(strcmp(Vals{idxFrameBased},'off'))
    En{idxSampPerFrame}  = 'off';
    En{idxOrient}        = 'on';
    Vis{idxSampPerFrame} = 'off';
    Vis{idxOrient}       = 'on';
else % 'Frame-based'
    En{idxSampPerFrame}  = 'on';
    En{idxOrient}        = 'off';
    Vis{idxSampPerFrame} = 'on';
    Vis{idxOrient}       = 'off';
end

if ~strcmp(oldEnSamp, En{idxSampPerFrame}) || ...
        ~strcmp(oldEnOrient, En{idxOrient})
    set_param(block,'MaskEnables',En,'MaskVisibilities',Vis);
end

%*********************************************************************
% Function Name:	'cbOrient'
%  - Callback function for 'orient' parameter
%********************************************************************
function cbOrient(block,idxFrameBased,idxOrient)

Vals  = get_param(block, 'maskvalues');
En    = get_param(block, 'maskenables');
Vis   = get_param(block, 'maskvisibilities');
oldEnFrame = En{idxFrameBased};

if(strcmp(Vals{idxOrient},'on'))  % Interpret as 1-D
    En{idxFrameBased}  = 'off';
    Vis{idxFrameBased} = 'off';
else
    En{idxFrameBased}  = 'on';
    Vis{idxFrameBased} = 'on';
end

if ~strcmp(oldEnFrame, En{idxFrameBased})
    set_param(block,'MaskEnables',En,'MaskVisibilities',Vis);
end

%*********************************************************************
% Function Name:	'setOutDataType'
%  - Initialization function for 'outDataType' parameter
%********************************************************************
function setOutDataType(block,maskOutDataType)

% Set the Gaussian Noise Generator block's output type, which governs the 
% datatype of the output of the Rayleigh Source block
switch maskOutDataType
    case 'double'
        set_param([block, '/Gaussian Noise Generator'], 'outDataType', 'double');   
    case 'single'
        set_param([block, '/Gaussian Noise Generator'], 'outDataType', 'single');  
end

% [EOF]
