function exportcoeffgen(e,fdafid, tbx)
% EXPORTCOEFFGEN generates C-code coefficients from the FDATool.
%   EXPORTCOEFFGEN(E,FDAFID) generates C-code coefficients where E is
%   a structure which stores filter information and FDAFID is the file
%   identifier where the C-code will be stored

%   Author(s): A. Dowd
%   Copyright 1988-2004 The MathWorks, Inc.
%   $Revision: 1.11.4.5 $  $Date: 2004/07/28 04:39:03 $

if nargin < 3,
    tbx = 'signal';
end

e.info = cellstr([repmat(' * ', size(e.info,1), 1), e.info]);

header = cellstr(sptfileheader('', tbx, ' *'));

strpreamble = { ...
    '/*', ...
    ' * Filter Coefficients (C Source) generated by the Filter Design and Analysis Tool', ...
    header{:}, ...
    ' */', ...
    '', ...
    '/*', ...
    e.info{:}, ...
    ' */', ...
    '', ...
    '/* General type conversion for MATLAB generated C-code  */', ...
    '#include "tmwtypes.h"', ...
    };

coeffprec = e.DataType;
if strcmpi(coeffprec, 'single')
    coeffprec = sprintf('%s-precision', coeffprec);
end

strquantwarning = {
    '/*', ...
    ' * Warning - Filter coefficients were truncated to fit specified data type.  ', ...
    ' *   The resulting response may not match generated theoretical response.', ...
    ' *   Use the Filter Design & Analysis Tool to design accurate', ...
    sprintf(' *   %s filter coefficients.', coeffprec), ...
    ' */', ...
    };

cellprintf(fdafid,strpreamble);
fprintf(fdafid,'/* \n * Expected path to tmwtypes.h \n * %s \n */\n',fullfile(matlabroot,'extern','include','tmwtypes.h'));

if e.isTrunc,
    cellprintf(fdafid,strquantwarning);
end

dtype = {'int8'  ,'int16'  ,'int32'  ,'uint8'  ,'uint16'  ,'uint32'  , 'single'  , 'double'  };
ctype = {'int8_T','int16_T','int32_T','uint8_T','uint16_T','uint32_T', 'real32_T', 'real64_T'};
dfmt =  {'%5d,'  ,'%7d,'   ,'%12d,'   ,'%5u,'   ,'%7u,'    ,'%12u,'    ,'%15.10g,'  ,'%18.13g,'  };

itype = find(strcmpi(e.DataType,dtype));
if isempty(itype),
    error(['Data type: ' e.DataType ' Not supported']);
end

% Let's assume the worst case, sections have different lengths!
% so for each variable, we need to determine the MAX length

if e.nsecs > 1,

    % Multi-Section, assume anything !
    nSect = length(e.coeffs);
    fprintf(fdafid,'#define MWSPT_NSEC %d\n',nSect);
    nVars = length(e.coeffvars);
    for iV = 1:nVars
        MaxEl = 1;
        % [Section][Elements] C 2-D order
        fprintf(fdafid,'const int %s[MWSPT_NSEC] = {',e.coefflengthvars{iV});
        tempStr = ' ';
        fromLastcr = 0;
        isimag = false;
        for tempA = 1:length(e.coeffs),

            if ~isreal(e.coeffs{tempA}{iV})
                isimag = true;
            end
            
            % Check for the "scalar" case, which only needs 1 space
            if length(e.coeffs{tempA}) > 1 | iV == 1,
                tempLen = length(e.coeffs{tempA}{iV});
            else
                tempLen = 1;
            end
            if (length(tempStr) - fromLastcr) > 70,
                tempStr = [tempStr '\n'];
                fromLastcr = length(tempStr);
            end
            tempStr = [tempStr sprintf('%d,',tempLen)];
            if tempLen > MaxEl, MaxEl = tempLen; end
        end

        % This backup of 1 space is to avoid printing extra commas
        tempStr = [tempStr(1:end-1) ' };\n'];
        fprintf(fdafid,tempStr);

        if isimag, suffix = '_re';
        else,      suffix = ''; end
        
        fprintf(fdafid,'const %s %s%s[MWSPT_NSEC][%d] = {\n',ctype{itype},e.coeffvars{iV},suffix,MaxEl);
        tempStr = '';
        fromLastcr = 0;
        for tempA = 1:length(e.coeffs),
            tempStr = [tempStr '  {\n  '];
            fromLastcr = length(tempStr);

            % Check for the scalar case (this occurs when we attempt to query the denominator)
            % which should always be [1 0 ... 0]
            if length(e.coeffs{tempA}) > 1 | iV == 1,
                dataA = padarray(e.coeffs{tempA}{iV},MaxEl);  % Pad to Max size (C can't handle non-rect arrays)
            else
                dataA = padarray(1, MaxEl);
            end
            for data = dataA;
                if (length(tempStr) - fromLastcr) > 70,
                    tempStr = [tempStr '\n  '];
                    fromLastcr = length(tempStr);
                end
                tempStr = [tempStr sprintf(dfmt{itype},real(double(data)))];
            end

            % This backup of 1 space is to avoid printing extra commas
            tempStr = [tempStr(1:end-1) ' \n  },\n'];
            fromLastcr = length(tempStr);
        end
        tempStr = [tempStr(1:end-3) '\n};\n'];
        fprintf(fdafid,tempStr);

        
        if isimag
            fprintf(fdafid,'const %s %s_im[MWSPT_NSEC][%d] = {\n',ctype{itype},e.coeffvars{iV},MaxEl);
            tempStr = '';
            fromLastcr = 0;
            for tempA = 1:length(e.coeffs),
                tempStr = [tempStr '  {\n  '];
                fromLastcr = length(tempStr);

                % Check for the scalar case (this occurs when we attempt to query the denominator)
                % which should always be [1 0 ... 0]
                if length(e.coeffs{tempA}) > 1 | iV == 1,
                    dataA = padarray(e.coeffs{tempA}{iV},MaxEl);  % Pad to Max size (C can't handle non-rect arrays)
                else
                    dataA = padarray(1, MaxEl);
                end
                for data = dataA;
                    if (length(tempStr) - fromLastcr) > 70,
                        tempStr = [tempStr '\n  '];
                        fromLastcr = length(tempStr);
                    end
                    tempStr = [tempStr sprintf(dfmt{itype},imag(double(data)))];
                end

                % This backup of 1 space is to avoid printing extra commas
                tempStr = [tempStr(1:end-1) ' \n  },\n'];
                fromLastcr = length(tempStr);
            end
            tempStr = [tempStr(1:end-3) '\n};\n'];
            fprintf(fdafid,tempStr);
        end
    end
else
    % Single Section, generate a slightly simpler file
    nVars = length(e.coeffs{1});
    for iV = 1:nVars
        
        isimag = ~isreal(e.coeffs{1}{iV});
        
        if isimag, suffix = '_re';
        else,      suffix = ''; end

        MaxEl = 1;

        [row,col] = size(e.coeffs{1}{iV});
        isNxM = row>1 && col>1; % assume 2-D
        
        if isNxM, % 2d matrix
            fprintf(fdafid,'const int %s[2] = {%d,%d};\n',e.coefflengthvars{iV},row,col);
            fprintf(fdafid,'const %s %s%s[%d][%d] = ',ctype{itype},e.coeffvars{iV},suffix,row,col);
        else % 1xN: vector and scalar
            fprintf(fdafid,'const int %s = %d;\n',e.coefflengthvars{iV},length(e.coeffs{1}{iV}));
            fprintf(fdafid,'const %s %s%s[%d] = ',ctype{itype},e.coeffvars{iV},suffix,length(e.coeffs{1}{iV}));
        end

        tmpcoefs = e.coeffs{1}{iV}; % used for real and imag
        
        % Make sure all vectors are of 1xN format
        if row>1 && col==1, % if Nx1, change to 1xN
            tmpcoefs = tmpcoefs';
            col = row; row = 1;
        end

        if row>1,
            ismatrix = true;
            indentBrkt = ' '; % amount of indention for internal curly braces
            fprintf(fdafid,'{\n'); % add an extra { outside
        else
            ismatrix = false;
            indentBrkt = '';
        end

        for itR = 1:row
            fprintf(fdafid,'%s{\n  ',indentBrkt);
            tempStr = '';
            fromLastcr = 0;
            for itC = 1:col,
                % Check if str is more than 70 characters, go to next line
                if (length(tempStr) - fromLastcr) > 70,
                    tempStr = [tempStr '\n  '];
                    fromLastcr = length(tempStr);
                end
                tempStr = [tempStr sprintf(dfmt{itype},real(double(tmpcoefs(itR,itC))))];
            end

            % This backup of 1 space is to avoid printing extra commas
            tempStr = [tempStr(1:end-1) sprintf('\n%s}',indentBrkt)];
            % Append comma, semi-colon, or none
            if ismatrix
                if itR==row,  tempStr = [tempStr '\n'];
                else          tempStr = [tempStr ',\n'];
                end
            else
                tempStr = [tempStr ';\n'];
            end
            fprintf(fdafid,tempStr);

        end
        if ismatrix, fprintf(fdafid,'};\n'); end % add an extra } outside

        if isimag
            if isNxM, % NxM: 2d array
                fprintf(fdafid,'const %s %s_im[%d][%d] = ',ctype{itype},e.coeffvars{iV},row,col);
            else % 1xN: vector and scalar
                fprintf(fdafid,'const %s %s_im[%d] = ',ctype{itype},e.coeffvars{iV},length(e.coeffs{1}{iV}));
            end

            if ismatrix,  fprintf(fdafid,'{\n'); end; % add an extra { outside
            
            for itR = 1:row
                fprintf(fdafid,'%s{\n  ',indentBrkt);
                tempStr = '';
                fromLastcr = 0;
                for itC = 1:col,
                    % Check if str is more than 70 characters, go to next line
                    if (length(tempStr) - fromLastcr) > 70,
                        tempStr = [tempStr '\n  '];
                        fromLastcr = length(tempStr);
                    end
                    tempStr = [tempStr sprintf(dfmt{itype},imag(double(tmpcoefs(itR,itC))))];
                end

                % This backup of 1 space is to avoid printing extra commas
                tempStr = [tempStr(1:end-1) sprintf('\n%s}',indentBrkt)];
                % Append comma, semi-colon, or none
                if ismatrix
                    if itR==row,  tempStr = [tempStr '\n'];
                    else          tempStr = [tempStr ',\n'];
                    end
                else
                    tempStr = [tempStr ';\n'];
                end
                fprintf(fdafid,tempStr);

            end
            if ismatrix, fprintf(fdafid,'};\n'); end % add an extra } outside
        end
    end
end


% --------------------------------------------------------
function ap = padarray(a,n)
% Pads input a array to length n.
% Note - ONLY works on 1D arrays, either row or column vector
if n == length(a)
    % Don't bother with padding, already to desired size!
    ap = a;
    return;
elseif n < length(a),
    error('Truncation of Coefficent Array not allowed');
end
if ~isnumeric(a)
    error('Coefficient Array must be numeric!');
end
classname = class(a);
[r,c] = size(a);
if r > 1,
    pn = n - r;
    ap = [a; feval(classname,zeros(pn,c))];
else
    % By default, make a column vector
    pn = n - c;
    ap = [a feval(classname,zeros(r,pn))];
end

% --------------------------------------------------------
function cellprintf(fid,cell)
% Cell Array printf
fprintf(fid,'%s\n',cell{1:end});

% EOF
