function varargout = commblkuniformsrc2(block, action, varargin)
%COMMBLKUNIFORMSRC2 Mask dynamic dialog function for uniform noise generator
% block.

%   Copyright 1996-2017 The MathWorks, Inc.

switch action
  case 'init'
    
    low  = varargin{1};
    up   = varargin{2};
    seed = varargin{3};

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

    [idxFrameBased,idxOrient] = ...
        dspGetMaskParamIdx(block,'frameBased','orient');

    vLen = [length(low) length(up) length(seed)];
    vSize = {size(low) size(up) size(seed)};

    lenmax = max(vLen);         % Largest of all the parameter lengths
    dimcomp = find(vLen~=1,1);  % Index of the first vector parameter
                                % used for comparison with dimensions of other parameters

    % --- Exit code and error message definitions
    eStr.ecode = 0;
    eStr.eID   = '';
    eStr.emsg  = '';
    
    % Check for consistency among vector parameter lengths
    if ~isequal(lenmax,1)   % if there exist vector parameters
        
        % Check if vector lengths (if any) agree
        if any(find(vLen(vLen~=1)~=lenmax))
            eStr.ecode = 1;
            eStr.eID   = 'comm:commblkuniformsrc2:InvalidParamDims';
            eStr.emsg  = 'Noise lower bound, Noise upper bound and Initial seed must be either all scalars, or if more than one of them is a vector, their vector sizes should agree.';
            varargout{1}=eStr;
            return
            % If dimensions are to be preserved, check if they agree
        elseif strcmp(Vals{idxOrient},'off') && strcmp(Vals{idxFrameBased},'off')  
            for idx = find(vLen~=1)
                if ~isequal(vSize{idx},vSize{dimcomp})
                    eStr.ecode = 1;
                    eStr.eID   = 'comm:commblkuniformsrc2:InconsistentParamDims';
                    eStr.emsg  = ['Dimensions of parameter values in ', block, ' are inconsistent.'];
                end
            end         
        end
    end
    
    cbFrameBased(block);
    cbOrient(block);
    setOutDataType(block);
    updateBlocks(block,Vals{idxFrameBased},Vals{idxOrient},vLen,vSize);
    
    varargout{1}=eStr;
    
  case 'cbFrameBased'
    cbFrameBased(block);
    
  case 'cbOrient'
    cbOrient(block);
end


%----------------------------------------------------------------------
%	Subfunctions
%----------------------------------------------------------------------
%*********************************************************************
% Function Name :   updateBlocks
% - Set the simulink blocks as required
%********************************************************************
function updateBlocks(block,frameBased,orient,vLen,vSize)

if(strcmp(frameBased,'off'))
    % Sample-based case
    
    set_param([block, '/Frame Status Conversion'],'outframe','Sample-based');   
    set_param([block, '/Random Source'],'SampFrame','1');
    
    % Interpret as 1-D; OR scalar output
    if(strcmp(orient,'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 dimensions of 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
    
else
    % Frame-based case
    set_param([block, '/Frame Status Conversion'],'outframe','Frame-based');   
    set_param([block, '/Random Source'],'SampFrame','sampPerFrame');
    set_param([block, '/Reshape'],'OutputDimensionality','Customize');
end


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

[idxFrameBased,idxSampPerFrame,idxOrient] = ...
    dspGetMaskParamIdx(block,'frameBased','sampPerFrame','orient');

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{idxFrameBased}) || ...
        ~strcmp(oldEnOrient, En{idxFrameBased}) 
    set_param(block,'MaskEnables',En,'MaskVisibilities',Vis);
end


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

[idxFrameBased,idxOrient] = ...
    dspGetMaskParamIdx(block,'frameBased','orient');

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)

idxOutDataType = dspGetMaskParamIdx(block,'outDataType');
Vals           = get_param(block, 'maskvalues');

% Set the Gaussian Noise Generator blocks' output types, which governs the 
% datatype of the output of the Rician Source block
switch (Vals{idxOutDataType})
  case 'double'
    set_param([block, '/Random Source'], 'DataType', 'double');   
  case 'single'
    set_param([block, '/Random Source'], 'DataType', 'single');  
end

% [EOF]
