function outData = forwardGaussianFilterToDiscreteFIRFilter(inData)
% Transformation function in commobslib to forward Gaussian Filter to
% Discrete FIR Filter 
%
% INDATA is a structure with fields ForwardingTableEntry and InstanceData,
% and ForwardingTableEntry is also a structure. 
%
% OUTDATA is a structure with fields NewInstanceData and NewBlockPath.

% Copyright 2019 The MathWorks, Inc.

%#ok<*AGROW>
% Get old instance data
oldInstanceData = inData.InstanceData;
oldBlockParams = {oldInstanceData.Name};

% Set new param values where there is a one-to-one mapping
count = 1;
for p = 1 : length(oldBlockParams)
  switch oldBlockParams{p}
    case 'N'
      sampPerSym = slResolve(oldInstanceData(p).Value, gcs);
    case 'BT'
      BT = slResolve(oldInstanceData(p).Value, gcs);
    case 'D'
      grpDelay = slResolve(oldInstanceData(p).Value, gcs); % in symbols
    case 'normMode'
      normMode = oldInstanceData(p).Value; % normalization mode
    case 'InputProcessing'
      newInstanceData(count) = struct( ...
        'Name', 'InputProcessing', ...
        'Value', oldInstanceData(p).Value);
      count = count + 1;
    case 'filterGain'
      gain = slResolve(oldInstanceData(p).Value, gcs); % linear gain
    case 'roundingMode'
      newInstanceData(count) = struct( ...
        'Name', 'RndMeth', ...
        'Value', oldInstanceData(p).Value);
      count = count + 1;
    case 'overflowMode'
      newInstanceData(count) = struct( ...
        'Name', 'SaturateOnIntegerOverflow', ...
        'Value', oldInstanceData(p).Value);
      count = count + 1;      
    case 'coeffMode'
      newInstanceData(count) = struct( ...
        'Name', 'CoefDataTypeStr', ...
        'Value', oldInstanceData(p).Value);
      cDTMode = oldInstanceData(p).Value;
      count = count + 1;      
    case 'coeffWordLength'
      cWordLength = slResolve(oldInstanceData(p).Value, gcs);
    case 'coeffFracLength'
      cFracLength = slResolve(oldInstanceData(p).Value, gcs);
    case 'prodOutputMode'
      newInstanceData(count) = struct( ...
        'Name', 'ProductDataTypeStr', ...
        'Value', oldInstanceData(p).Value);
      pDTMode = oldInstanceData(p).Value;
      count = count + 1;      
    case 'prodOutputWordLength'
      pWordLength = slResolve(oldInstanceData(p).Value, gcs);
    case 'prodOutputFracLength'
      pFracLength = slResolve(oldInstanceData(p).Value, gcs);
    case 'accumMode'      
      newInstanceData(count) = struct( ...
        'Name', 'AccumDataTypeStr', ...
        'Value', oldInstanceData(p).Value);
      aDTMode = oldInstanceData(p).Value;
      count = count + 1;      
    case 'accumWordLength'
      aWordLength = slResolve(oldInstanceData(p).Value, gcs);
    case 'accumFracLength'
      aFracLength = slResolve(oldInstanceData(p).Value, gcs);
    case 'outputMode'
      newInstanceData(count) = struct( ...
        'Name', 'OutDataTypeStr', ...
        'Value', oldInstanceData(p).Value);
      oDTMode = oldInstanceData(p).Value;
      count = count + 1;      
    case 'outputWordLength'
      oWordLength = slResolve(oldInstanceData(p).Value, gcs);
    case 'outputFracLength'
      oFracLength = slResolve(oldInstanceData(p).Value, gcs);
    case 'LockScale'
      newInstanceData(count) = struct( ...
        'Name', 'LockScale', ...
        'Value', oldInstanceData(p).Value);
      count = count + 1;      
  end
end

% Calculate coefficients and add to new block param structure
coeffs = gaussdesign(BT, 2*grpDelay, sampPerSym);
switch normMode
  case 'Sum of coefficients'
    % No normalization
  case 'Filter energy'
    coeffs = coeffs * sum(coeffs)/norm(coeffs);
  case 'Peak amplitude'
    coeffs = coeffs * sum(coeffs)/max(coeffs);
end
coeffs = gain * coeffs;
newInstanceData(end+1) = struct( ...
  'Name', 'Coefficients', ...
  'Value', ['[' num2str(coeffs) ']']);

% Set data type fields as necessary
% Coefficient data type
switch cDTMode
  case 'Same word length as input'
    newInstanceData(end+1) = struct( ...
      'Name', 'CoefDataTypeStr', ...
      'Value', 'Inherit: Same word length as input');
  case 'Specify word length'
    newInstanceData(end+1) = struct( ...
      'Name', 'CoefDataTypeStr', ...
      'Value', ['fixdt(1,' cWordLength ')']);   
  case 'Binary point scaling'
    newInstanceData(end+1) = struct( ...
      'Name', 'CoefDataTypeStr', ...
      'Value', ...
      ['fixdt(1,' num2str(cWordLength) ',' num2str(cFracLength) ')']);
end

% Product output data type
switch pDTMode
  case 'Same as input'
    newInstanceData(end+1) = struct( ...
      'Name', 'ProductDataTypeStr', ...
      'Value', 'Inherit: Same as input');
  case 'Binary point scaling'
    newInstanceData(end+1) = struct( ...
      'Name', 'ProductDataTypeStr', ...
      'Value', ...
      ['fixdt(1,' num2str(pWordLength) ',' num2str(pFracLength) ')']);
end

% Accumulator data type
switch aDTMode
  case 'Same as product output'
    newInstanceData(end+1) = struct( ...
      'Name', 'AccumDataTypeStr', ...
      'Value', 'Inherit: Same as product output');
  case 'Same as input'
    newInstanceData(end+1) = struct( ...
      'Name', 'AccumDataTypeStr', ...
      'Value', 'Inherit: Same as input');
  case 'Binary point scaling'
    newInstanceData(end+1) = struct( ...
      'Name', 'AccumDataTypeStr', ...
      'Value', ...
      ['fixdt(1,' num2str(aWordLength) ',' num2str(aFracLength) ')']);
end

% Output data type
switch oDTMode
  case'Same as accumulator'
    newInstanceData(end+1) = struct( ...
      'Name', 'OutDataTypeStr', ...
      'Value', 'Inherit: Same as accumulator');
  case 'Same as input'
    newInstanceData(end+1) = struct( ...
      'Name', 'OutDataTypeStr', ...
      'Value', 'Inherit: Same as input');  
  case 'Binary point scaling'
    newInstanceData(end+1) = struct( ...
      'Name', 'OutDataTypeStr', ...
      'Value', ...
      ['fixdt(1,' num2str(oWordLength) ',' num2str(oFracLength) ')']);
end

outData.NewBlockPath = 'dsparch4/Discrete FIR Filter';
outData.NewInstanceData = newInstanceData;

% EOF