classdef TaskCounterOffsetData < rtw.pil.NonCodeInfoData
    % XIL data to be transferred between host and target to initialize task
    % counter offsets for model reference, single tasking, rate based
    % models.

    % Copyright 2024 The MathWorks, Inc.

    properties(Constant)
        IsProtocolData = false;
        XILTargetVariableString = "InitialTaskCounterOffset";
    end

    properties(SetAccess = private, GetAccess = public)
        TID (1,1) {mustBeInteger, mustBeNonnegative}
    end

    methods
        function this = TaskCounterOffsetData(tid, mf0ModelInstance)
            % call superclass constructor
            dType = rtw.connectivity.CodeInfoTypeEnum.TypeUInt32;
            dimensions = 1;
            this@rtw.pil.NonCodeInfoData(dType, dimensions, mf0ModelInstance);
            this.getType().Identifier = ...
                rtw.connectivity.TypeUtils.builtinToHostCType(dType);

            this.TID = tid;
        end

        function targetBaseTypeIdentifier = getTargetBaseTypeIdentifier(~, dataElement)
            targetBaseTypeIdentifier = dataElement.getType().Identifier;
        end

        function writePILIODataTableEntry(this, dataElement, tableName, writer, ~)
            targetBaseTypeIdentifier = this.getTargetBaseTypeIdentifier(dataElement);
            targetVariable = sprintf('%s[%d]', this.XILTargetVariableString, this.TID);
            writer.wLine('void * dataAddress = (void *) &(%s);', targetVariable);
            memUnitLength = sprintf('%d * sizeof(%s)', dataElement.getNumElements(), targetBaseTypeIdentifier);
            writer.writeLine([tableName '[tableIdx].memUnitLength = ' memUnitLength ';']);
            writer.writeLine([tableName '[tableIdx++].address = (MemUnit_T *) dataAddress;']);
        end

        function string = getString(~, ~) %#ok<STOUT>
            assert(false, 'Should never call getString for TaskCounterOffsetData');
        end
    end

    methods (Static)
        function writeHostSideTaskOffsetFunction(writer)
            % This function can be factored out into a static location and
            % linked as a library during mex - g3222858.
            writer.wBlockStart('static uint32_T computeTaskTickOffset(SimStruct *S, int_T tidIdx)');
            writer.writeLine('uint32_T nOffsetTicks = 0;');
            writer.wComment('No task counter required for base rate');
            writer.wBlockStart('if (tidIdx>0)');
            writer.writeLine('time_T stepSize = ssGetFixedStepSize(S);');
            writer.writeLine('time_T period = ssGetSampleTime(S, tidIdx);');
            writer.writeLine('time_T simulationTime = ssGetT(S);');
            writer.writeLine('time_T offset = period*floor(simulationTime/period);');
            writer.writeLine('nOffsetTicks = round((simulationTime-offset)/stepSize);');
            writer.wBlockEnd();
            writer.writeLine('return nOffsetTicks;');
            writer.wBlockEnd();
        end
    end
end
