%% Create CIC Decimation Filter for HDL Code Generation
%
% This example shows how to use a |dsp.HDLCICDecimation| System object(TM)
% to filter and downsample the data. This object supports scalar and vector
% inputs. In this example, two functions are provided to work with scalar
% and vector input data separately. You can generate the HDL code from
% these functions.
%
% Copyright 2019 The MathWorks, Inc.

%% Generate Frames of Random Input Samples
% Set up these workspace variables for the object to use. The object
% supports fixed and variable decimation rates for scalar inputs and only a
% fixed decimation rate for vector inputs. The example runs the
% |HDLCIC_maxR8| function when you set the scalar variable to |true| and
% runs the |HDLCIC_vec| function when you set the scalar variable to
% |false|. For scalar inputs, choose a range of the input varRValue values
% and set the decimation factor value, R, to the maximum expected
% decimation factor. For vector inputs, the input data must be a column
% vector of size 1 to 64 and R must be an integer multiple of the input
% frame size.

R = 8; % decimation factor
M = 1; % differential delay
N = 3; % number of sections
scalar = false; % true for scalar; false for vector
if scalar
    varRValue = [4, 5, 6, 7, 8];
    vecSize = 1;
else
    varRValue = R;
    vecSize = randsrc(1,1,factor(R));
end

numFrames = length(varRValue);
dataSamples = cell(1,numFrames);
varRtemp = cell(1,numFrames);
framesize = zeros(1,numFrames);
refOutput = [];
WL = 0; % Word length
FL = 0; % Fraction length

%% Generate Reference Output from |dsp.CICDecimation| System Object(TM)
% Generate frames of random input samples and apply the samples to the
% |dsp.CICDecimation| System object. The output generated from this System
% object is used as a reference data for comparison. The System object does
% not support a variable decimation rate, so you must create and release
% the object for each change in decimation factor value.

totalsamples = 0;
for i = 1:numFrames
    framesize(i) = varRValue(i)*randi([5 20],1,1);
    dataSamples{i} = fi(randn(vecSize,framesize(i)),1,16,8);
    ref_cic = dsp.CICDecimator('DifferentialDelay',M,...
        'NumSections',N,...
        'DecimationFactor',varRValue(i));
    refOutput = [refOutput,ref_cic(dataSamples{i}(:)).'];
    release(ref_cic);
end
%% Run a Function that contains |dsp.HDLCICDecimation| System Object
% Set the properties of the System object to match the input data
% parameters and run the respective function based on the input type. These
% functions operate on a stream of data samples rather than a frame. You
% can generate HDL code from these functions.
% 
%
% The example uses the |HDLCIC_maxR8| function for a scalar input.
%
%
% <include>HDLCIC_maxR8.m</include> 
%
% The example uses the |HDLCIC_vec| function for a vector input.
%
%
% <include>HDLCIC_vec.m</include>
%
%
% To flush remaining data, run the object by inserting the required number
% of idle cycles after each frame through |latency| variable. For more
% information, see <docid:dsp_ref#mw_da293f3a-8d63-440e-a2b2-28ad7d601056
% GainCorrection> property.
%
% Initialize the output to a size large enough to accommodate the output
% data. The final size is expected to be smaller than |totalsamples| due to
% decimation.

latency = floor((vecSize - 1)*(N/vecSize))+ 1+ N +(2+(vecSize + 1)*N)+ 9;
dataOut = zeros(1,totalsamples+numFrames*latency);
validOut = zeros(1,totalsamples+numFrames*latency);
idx=0;
for ij = 1:numFrames
    if scalar
        % scalar input with variable decimation
        for ii = 1:length(dataSamples{ij})
            idx = idx+1;
            [dataOut(idx),validOut(idx)] = HDLCIC_maxR8(...
                dataSamples{ij}(ii),...
                true,...
                fi(varRValue(ij),0,12,0));
        end
        for ii = 1:latency
            idx = idx+1;
            [dataOut(idx),validOut(idx)] = HDLCIC_maxR8(...
                fi(0,1,16,8),...
                false,...
                fi(varRValue(ij),0,12,0));
        end
        
    else
        % vector input with fixed decimation
        for ii = 1:size(dataSamples{ij},2)
            idx = idx+1;
            [dataOut(idx),validOut(idx)] = HDLCIC_vec(...
                dataSamples{ij}(:,ii),...
                true);
        end
        for ii = 1:latency
            idx = idx+1;
            [dataOut(idx),validOut(idx)] = HDLCIC_vec(...
                fi(zeros(vecSize,1),1,16,8),...
                false);
        end
    end
end


%% Compare the Function Output with the Reference Data
% Compare the function results against the output from the
% |dsp.CICDecimation| object.

cicOutput = dataOut(validOut==1);

fprintf('\nHDL CIC Decimation\n');
difference = (abs(cicOutput-refOutput(1:length(cicOutput)))>0);
fprintf('\nTotal number of samples differed between Behavioral and HDL simulation: %d \n',sum(difference));

