classdef helperBluetoothSlotTimer < handle
%helperBluetoothSlotTimer Create a Bluetooth slot-timer object
%   SLOTTIMER = helperBluetoothSlotTimer creates a Bluetooth timer object
%   for maintaining a slot duration of 625 microseconds.

%   Copyright 2020 The MathWorks, Inc.

%#codegen

% Constant, Hidden properties
properties (Constant, Hidden)
    %SlotDuration Duration of a slot in microseconds
    SlotDuration = 625
end

% Private properties with get access
properties (SetAccess = private)
    %NumSlots Number of slots elapsed
    NumSlots = 0
    
    %Clock Native clock of the Bluetooth device
    % Each tick is 312.5 microseconds of duration. 1 slot = 2 clock ticks.
    % For every slot, clock is incremented by 2.
    Clock = 0
end

% Private properties
properties (Access = private)
    %pTimer Timer for slot duration in microseconds
    pTimer = 0
    
    %pSlotsUpdated Flag to identify that the number of slots are updated
    pSlotsUpdated = true
end

% Public methods
methods
    % Run the slot timer
    function [nextInvokeTime, slotStart] = runSlotTimer(obj, elapsedTime)
        %runSlotTimer Runs the slot timer
        %
        %   This function maintains the timer for the duration of a slot
        %   (625 microseconds). The function returns the remaining time,
        %   NEXTINVOKETIME, to complete the slot duration and a flag,
        %   SLOTSTART, to identify whether a new slot is started or not.
        %
        %   [NEXTINVOKETIME, SLOTSTART] = run(OBJ, ELAPSEDTIME) runs the
        %   slot timer by updating the elapsed time, ELAPSEDTIME.
        %
        %   NEXTINVOKETIME is the time (in microseconds) after which the
        %   runSlotTimer function is invoked again.
        %
        %   SLOTSTART is a boolean value representing whether a new slot is
        %   started or not. A true value indicates the start of a new slot.
        %
        %   ELAPSEDTIME is the time elapsed in microseconds between the
        %   previous and current call of this function.
        
        % Initialize
        slotStart = false;
        
        % Calculate the number of slots for the given elapsed time
        numSlots = floor(elapsedTime/obj.SlotDuration);
        
        if numSlots ~= 0
            obj.pSlotsUpdated = true;
        end
        
        % Update the total number of slots and the clock elapsed
        obj.NumSlots = obj.NumSlots + numSlots;
        obj.Clock = obj.NumSlots * 2; % 1 slot = 2 clock ticks
        
        obj.pTimer = mod(obj.pTimer + elapsedTime, obj.SlotDuration); % microseconds
        
        % New slot start
        if (obj.pTimer == 0)    
            % Update number of slots
            if (elapsedTime ~= 0) && (rem(elapsedTime, obj.SlotDuration) ~= 0)
                obj.NumSlots = obj.NumSlots + 1;
                obj.Clock = obj.NumSlots * 2; % 1 slot = 2 clock ticks
                obj.pSlotsUpdated = true;
            end
            
            % Check whether the number of slots are updated or not
            if obj.pSlotsUpdated
                slotStart = true;
                obj.pSlotsUpdated = false;
            end
        end
        
        % Update the next invoke time
        nextInvokeTime = obj.SlotDuration - obj.pTimer;
    end
end
end
