/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
::   Module      :   Framework Scheduler
::   Copyright   :   (C)2003-2009 Woodward
::   Platform(s) :   MPC5xx
::   Limitations :   MPC5xx OS
::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*! \file Resource_Scheduler.h
    \brief Applications using the Framework are expected to be event driven. The framework scheduler manages
           the issuing of the events and the passing of execution control to the application so that it may
           act upon them.

           Tasks execute when events are detected. The Framework provides the event detection mechanism and
           provides the methods necessary to communicate the occurrence of these events to the application.
           It also controls when tasks execute and which types of task can be pre-empted by others.

           The framework passes execution control to the application through the use of a callback that is
           defined when the scheduling resource is created. A callback takes the form of a C function which
           has a prototype definition defined within the Framework's scope and has its implementation defined
           within the scope of the application software. The Framework executes the callback, thereby passing
           control to the application software. It can then execute the tasks related to the detected event.

           Also see \ref eventpriority, \ref openapp, \ref appevents
*/

#ifndef __RESOURCE_SCHEDULER_H
#define __RESOURCE_SCHEDULER_H

/*----- INCLUDES ------------------------------------------------------------------------------------------*/
#include <typedefn.h>
#include <NativeError.h>
#include <Resource.h>

/*----- DEFINES -------------------------------------------------------------------------------------------*/

/*----- TYPEDEFS ------------------------------------------------------------------------------------------*/
#pragma pack(1)

typedef void* SchedulerHandle;

/*! \brief Software execution event definitions. Application defined scheduler tasks are called with a
           value from this enumeration list by the framework when it observes the associated event

           Event handlers for the event enumerations that contain \c PERIODIC can use GetProcessPeriodTime_ms()
           or GetProcessPeriodTime_us() to calculate the event period. Using such a method allows generic
           handlers to coded that offer invariant operation regardless of the actual event being handled
*/
typedef enum
{
    FGND_720 = 0,            /*!< Event occurs every 720 degCA with foreground priority. The percentage of time spent
                                 servicing this event is included in the \b CPUTime_FgndAngle variable */
    FGND_360 = 1,            /*!< Event occurs every 360 degCA with foreground priority. The percentage of time spent
                                 servicing this event is included in the \b CPUTime_FgndAngle variable */
    FGND_180 = 2,            /*!< Event occurs every 180 degCA with foreground priority. The percentage of time spent
                                 servicing this event is included in the \b CPUTime_FgndAngle variable */
    FGND_120 = 3,            /*!< Event occurs every 120 degCA with foreground priority. The accuracy of the
                                 event is based upon the number of teeth on the encoder. The percentage of time spent
                                 servicing this event is included in the \b CPUTime_FgndAngle variable */
    FGND_90 = 4,             /*!< Event occurs every 90 degCA with foreground priority. The accuracy of the
                                 event is based upon the number of teeth on the encoder. The percentage of time spent
                                 servicing this event is included in the \b CPUTime_FgndAngle variable */
    FGND_60 = 5,             /*!< Event occurs every 60 degCA with foreground priority. The accuracy of the
                                 event is based upon the number of teeth on the encoder. The percentage of time spent
                                 servicing this event is included in the \b CPUTime_FgndAngle variable */
    FGND_30 = 6,             /*!< Event occurs approximately every 30 degCA with foreground priority. The accuracy of the
                                 event is based upon the number of teeth on the encoder. The percentage of time spent
                                 servicing this event is included in the \b CPUTime_FgndAngle variable */
    FGND_HIRES = 7,          /*!< Event occurs on each detected encoder tooth with foreground priority. Caution
                                 should be used when enabling this event as it could swamp the available CPU
                                 bandwidth. The percentage of time spent servicing this event is included in the
                                 \b CPUTime_FgndAngle variable */
    BGND_720 = 8,            /*!< Event occurs every 720 degCA with background priority. The percentage of time spent
                                 servicing this event is included in the \b CPUTime_Bgnd variable */
    BGND_360 = 9,            /*!< Event occurs every 360 degCA with background priority. The percentage of time spent
                                 servicing this event is included in the \b CPUTime_Bgnd variable */
    BGND_180 = 10,            /*!< Event occurs every 180 degCA with background priority. The percentage of time spent
                                 servicing this event is included in the \b CPUTime_Bgnd variable */
    BGND_120 = 11,            /*!< Event occurs every 120 degCA with background priority. The accuracy
                                 of the event is based upon the number of teeth on the encoder. The
                                 percentage of time spent servicing this event is included in the
                                 \b CPUTime_Bgnd variable */
    BGND_90 = 12,             /*!< Event occurs every 90 degCA with background priority. The accuracy
                                 of the event is based upon the number of teeth on the encoder. The
                                 percentage of time spent servicing this event is included in the
                                 \b CPUTime_Bgnd variable */
    BGND_60 = 13,             /*!< Event occurs every 60 degCA with background priority. The accuracy
                                 of the event is based upon the number of teeth on the encoder. The
                                 percentage of time spent servicing this event is included in the
                                 \b CPUTime_Bgnd variable */
    BGND_30 = 14,             /*!< Event occurs approximately every 30 degCA with background priority. The accuracy
                                 of the event is based upon the number of teeth on the encoder. The
                                 percentage of time spent servicing this event is included in the
                                 \b CPUTime_Bgnd variable */
    BGND_HIRES = 15,          /*!< Event occurs on each detected encoder tooth with background priority. This event
                                 may suffer from overrun if too many encoder tooth events are detected. The
                                 percentage of time spent servicing this event is included in the
                                 \b CPUTime_Bgnd variable */

    FGND_RTI_PERIODIC,      /*!< Real Time Interrupt event. Occurs each time RTI period timeout expires. The percentage
                                 of time spent servicing this event is included in the CPUTime_FgndTime */
    FGND_2XRTI_PERIODIC,    /*!< Occurs on even RTI period timeouts The percentage
                                 of time spent servicing this event is included in the CPUTime_FgndTime */
    FGND_5XRTI_PERIODIC,    /*!< Occurs on every fifth RTI period timeout. The percentage
                                 of time spent servicing this event is included in the CPUTime_FgndTime */
    FGND_10XRTI_PERIODIC,   /*!< Occurs on every tenth RTI period timeout.  The percentage
                                 of time spent servicing this event is included in the CPUTime_FgndTime */
    FGND_20XRTI_PERIODIC,   /*!< Occurs on every twentieth RTI period timeout.  The percentage
                                 of time spent servicing this event is included in the CPUTime_FgndTime */
    BGND_BASE_PERIODIC,     /*!< Periodic background event. Occurs every \ref BgndPeriodicBaseRTIMultiple x RTI. The
                                 percentage of time spent servicing this event is included in \b CPUTime_Bgnd */
    BGND_BASEx2_PERIODIC,   /*!< Periodic background event. Occurs at 1/2 \ref BGND_BASE_PERIODIC. The
                                 percentage of time spent servicing this event is included in \b CPUTime_Bgnd */
    BGND_BASEx10_PERIODIC,  /*!< Periodic background event. Occurs at 1/10 \ref BGND_BASE_PERIODIC. The
                                 percentage of time spent servicing this event is included in \b CPUTime_Bgnd */
    BGND_BASEx20_PERIODIC,  /*!< Periodic background event. Occurs at 1/20 \ref BGND_BASE_PERIODIC. The
                                 percentage of time spent servicing this event is included in \b CPUTime_Bgnd */
    BGND_BASEx40_PERIODIC,  /*!< Periodic background event. Occurs at 1/40 \ref BGND_BASE_PERIODIC. The
                                 percentage of time spent servicing this event is included in \b CPUTime_Bgnd */
    BGND_BASEx80_PERIODIC,  /*!< Periodic background event. Occurs at 1/80 \ref BGND_BASE_PERIODIC. The
                                 percentage of time spent servicing this event is included in \b CPUTime_Bgnd */
    BGND_BASEx1200_PERIODIC,/*!< Periodic background event. Occurs at 1/1200 \ref BGND_BASE_PERIODIC. The
                                 percentage of time spent servicing this event is included in \b CPUTime_Bgnd */
    FGND_TDC1_EVENT,        /*!< Periodic event that occurs once per cycle on TDC#1 with foreground priority. The
                                 percentage of time spent servicing this event is included in \b CPUTime_FgndAngle */
    FGND_TDC_EVENT,         /*!< Periodic event that occurs on each firing TDC with foreground priority.
                                 Use GetTDCOfLastTDCEvent() to identify what TDC issued the message. The
                                 percentage of time spent servicing this event is included in \b CPUTime_FgndAngle */
    BGND_TDC_EVENT,         /*!< Periodic event that occurs on each firing TDC with background priority
                                 Use GetTDCOfLastTDCEvent() to identify what TDC issued the message. The
                                 percentage of time spent servicing this event is included in \b CPUTime_Bgnd */
    BGND_TDC1_EVENT,        /*!< Periodic event that occurs once per cycle on TDC#1 with background priority. The
                                 percentage of time spent servicing this event is included in \b CPUTime_Bgnd */

    FW_CLOSED,              /*!< Issued when the framework has finished closing. It is the last event
                                 that will be issued by the framework until OpenApplication() next executes */
    IDLE_EVENT,             /*!< Issued when the framework detects an idle condition. Background can pre-empt
                                 this task. The percentage of time spent idle or executing idle taks (and the
                                 best measure of system load) is the \b CPUIdlePcent parameter. */
    FGND_MID_TDC_EVENT,     /*!< Periodic event that occurs mid way between each firing TDC. Thus if each firing
                                 TDC was displaced by 180degCA then an event would occur at 90degAfTDC#1,
                                 270degAfTDC#1 and so on. This event will not occur unless TDC scheduling is
                                 enabled. See S_EncoderCreateResourceAttributes::ps2TDCOfsArr */
    ONE_SECOND_EVENT,       /*!< Issued every second, regardless of base rate settings. That is, \ref BgndPeriodicBaseRTIMultiple
                                 does not affect the interval of this event */
    ONE_MINUTE_EVENT,       /*!< Issued every minute, regardless of base rate settings. That is, \ref BgndPeriodicBaseRTIMultiple
                                 does not affect the interval of this event */
    FGND_TIMER_ISR_EVENT,   /*!< Timer Interrupt event. Occurs every time \ref PITCBaseRate period timeout expires. */
	FW_MASKABLE_EVENTS,
    FW_TPU_EVENT = FW_MASKABLE_EVENTS,
    FW_MIOS_EVENT,
    FW_SERIAL_EVENT,
    FW_CAN_EVENT,
    FW_TIMER_EVENT,
    FW_SOFTWARE_ISR_EVENT,
    FW_BACKGROUND_EVENT,
    FW_FGND_ANGLE_EVENT,
    APPLICATION_SWITCH,     /*!< This event is issued when a switch to a different application is imminent. The application is
                                 unlikely to see any further execution once this event has been serviced because the framework will
                                 pass execution control to a new application. For example, this event would be issued prior to
                                 starting an on-the-fly programming session. The application should use this event to save important
                                 non-volatile information, flush caches etc */
    BASE_APP_EVENT,         /*!< This defines the base event number for the application specific events. */

} E_FWExecutionEvent;

/*! \brief Type used to define the size of the execution event for which the \ref E_FWExecutionEvent enumeration forms a subset.

  An enumeration is not explicitly used because all events after \ref BASE_APP_EVENT represent legal application defined events
  that are not known by the API at compile time. If an enumeration were used then explcit casting would be required to use the
  user defined events */
typedef uint1 E_ExecutionEvent;

/*!
\brief Describes how the framework opened

The framework can open in a number of ways depending upon whether it suffered a normal or abnormal reset
condition. A COLD open refers to an open due to a power on condition. A WARM open is typically the result of
an unexpected reset. This enumeration allows the application to detect the difference and handle its
initialisation as is appropriate for that condition */
/* Name: E_OpenEventType ClassID:ENUMDEC EnumDflt:"Illegal" */
typedef enum
{
/*! Framework open from a power-on condition */
    COLD_OPEN,  /* EnumTxt:"COLD Open" */
/*! Framework open because of an unexpected reset */
    WARM_OPEN   /* EnumTxt:"WARM Open" */
} E_OpenEventType;

/*! \brief Type that describes the prototype for an application defined task scheduler callback function.

    A function of this type is the hook that the framework executes when the associated scheduler has an event.
    Hooks to all of the application's tasks would be placed within this function. The code example illustrates.

    The task scheduler callback function has used a switch to allow for inline optimisation to occur. Switching
    on the supplied event and then executing that task by supplying the event ID as a constant allows an
    inlining compiler to optimse the task based upon the constant. In effect only those tasks that actually
    perform work on the event will have code inserted into the AppTaskScheduler's case.

    \code
    void AppTaskScheduler(E_ExecutionEvent in_eEvent)
    {
        switch(in_eEvent)
        {
            case BGND_BASE_PERIODIC:
                ExecuteTask1(BGND_BASE_PERIODIC);   // Will optimise out when inlined
                ExecuteTask2(BGND_BASE_PERIODIC);
                break;
            case FGND_RTI_PERIODIC:
                ExecuteTask1(FGND_RTI_PERIODIC);    // Inline optimisation will put OnRTI_ExecuteTask1() in here
                ExecuteTask2(FGND_RTI_PERIODIC);
                break;
            ...
        }
    }

    INLINE void ExecuteTask1(E_ExecutionEvent in_eEvent)
    {
        switch(in_eEvent)
        {
            case BGND_BASE_PERIODIC:
                break;  // Do nothing.
            case FGND_RTI_PERIODIC:
                OnRTI_ExecuteTask1();
                ...
        }
    }
    \endcode
*/
typedef void (*SchedulerEventHandlerFuncPtrType)(E_ExecutionEvent);

/*! \brief Scheduler event condition.

Condition is altered via a call to SetResourceAttributesBEHAVIOUR_SCHEDULER() or SetSchedulerEventCond(). Use
the generic resource attributes set when the condition of multiple events needs to be set as this function
can cater for this through a single call */
typedef struct
{
    E_ExecutionEvent eEventToAffect;    /*!< The event to be affected by the condition described by S_EventCond::eCondToApply */
    E_ResourceCond   eCondToApply;      /*!< The condition to apply to S_EventCond::eEventToAffect. An event is blocked by the
                                             framework when set to \ref RES_DISABLED and passed onto the application when set to
                                             \ref RES_ENABLED. */
} S_EventCond;

/*! The operational condition of an event can be altered on a per event basis. This data structure allows the
    state of multiple events to be defined and then applied through a single call to SetResourceAttributesBEHAVIOUR_SCHEDULER(). */
typedef struct
{
/*! The number of event condition objects pointed to be the S_MultiEventCond::pEventCondObjArr member */
    NativeVar_U uNumEventsInArray;
/*! Pointer to an array of event condition objects. The size of the array is described by the
    S_MultiEventCond::uNumEventsInArray member */
    S_EventCond const* pEventCondObjArr;
} S_MultiEventCond;

/*! \brief Enumeration describes the set of mask definitions that are used to identify the valid scheduler
           attributes in the S_ScheduleResourceAttributes and S_ScheduleCreateResourceAttributes data structures.

Each mask definition applies to a particular member of one of the data structures.
\code
    ...
    S_ScheduleResourceAttributes AttribsObj;
    S_EventCond MyEventObj;

    MyEventObj.eEventToAffect = FGND_MID_TDC_EVENT;
    MyEventObj.eCondToApply = RES_ENABLED;
    // Want to enable the FGND_MID_TDC_EVENT event
    AttribsObj.uValidAttributesMask = USE_SCHD_CONDITION;
    AttribsObj.EventCondObj.uNumEventsInArray = 1;
    AttribsObj.EventCondObj.pEventCondObjArr = &MyEventObj;
    // The remainder of the data structure can be left undefined since the uValidAttributesMask
    //   indicates that the members are not valid
    ... \endcode */
typedef enum
{
    USE_SCHD_DEFAULTS = 0,
    USE_SCHD_CONDITION = 0x01,          /*!< Selects S_ScheduleResourceAttributes::EventCondObj */
    USE_SCHD_TASK_MANAGER = 0x02,       /*!< Selects S_ScheduleCreateResourceAttributes::pfAppCback */
    USE_SCHD_DYNAMIC_ON_CREATE = 0x04,  /*!< Selects S_ScheduleCreateResourceAttributes::DynamicObj */

/* IF THIS TYPE EXCEEDS 0x80 THEN ALTER THE TYPE OF THE uValidAttributesMask MEMBER(S) ACCORDINGLY */

} E_SchedulerAttributeMask;

/*! \brief This data structure describes all of the Scheduler resource's runtime configuration attributes.

    The attributes are altered through the use of SetResourceAttributesBEHAVIOUR_SCHEDULER(). The data structure
    does not need to be completely filled inorder to be used. The \c uValidAttributesMask is a bit field
    member that is used to identify which attributes are valid. Each attribute is identified with a separate
    bit mask that is logic-ORed into the a mask when an attribute is to be used.
\code
    ...
    S_ScheduleResourceAttributes AttribsObj;
    S_EventCond MyEventObj;

    MyEventObj.eEventToAffect = FGND_MID_TDC_EVENT;
    MyEventObj.eCondToApply = RES_ENABLED;
    // Want to enable the FGND_MID_TDC_EVENT event
    AttribsObj.uValidAttributesMask = USE_SCHD_CONDITION;
    AttribsObj.EventCondObj.uNumEventsInArray = 1;
    AttribsObj.EventCondObj.pEventCondObjArr = &MyEventObj;
    // The remainder of the data structure can be left undefined since the uValidAttributesMask
    //   indicates that the members are not valid
    ... \endcode */
typedef struct
{
/*! Logic-OR the attributes [\ref USE_SCHD_CONDITION] that are valid for this instance of the data structure */
    uint1 uValidAttributesMask;
/*! This object allows the condition of multiple events to be altered. Select with the \ref USE_SCHD_CONDITION
    bit mask */
    S_MultiEventCond EventCondObj;
} S_ScheduleResourceAttributes;

typedef S_ScheduleResourceAttributes const* S_ScheduleResourceAttributesPtr;

/*! Describes the creation attributes for a resource with the \c BEHAVIOUR_SCHEDULER */
typedef struct
{
/*! Logic-OR the attributes [\ref USE_SCHD_TASK_MANAGER, \ref USE_SCHD_DYNAMIC_ON_CREATE] that are valid for
    this instance of the data structure. The framework will employ the creation defaults for those attributes
    that are left undefined. */
    uint1 uValidAttributesMask;
/*! The application callback function that should execute each time the Framework issues an execution event.
    Creation will fail if an application callback is not defined. Select with \ref USE_SCHD_TASK_MANAGER bit mask */
    SchedulerEventHandlerFuncPtrType pfAppCback;
/*! Initial values of the runtime attributes, which can be later altered through with
    SetResourceAttributesBEHAVIOUR_SCHEDULER(). Select with the \ref USE_SCHD_DYNAMIC_ON_CREATE bit mask */
    S_ScheduleResourceAttributes DynamicObj;
} S_ScheduleCreateResourceAttributes;

typedef S_ScheduleCreateResourceAttributes const* S_ScheduleCreateResourceAttributesPtr;

/*! Defines the Data structure to access a 64bit free running counter. Coherency may not be guaranteed 
    due to the native register size of the target.   */ 
typedef struct
{
    uint4 u4Upper32Bits;     /*!< The upper 32bits. */
    uint4 u4Lower32Bits;     /*!< The lower 32bits. */

} S_FreeRunningCounter64Bit;


/*! \brief This data structure describes how to configure the operating system's defaults.

    Before the OS is opened, a call to the application supplied \ref PreStartOS(S_PreStartConfig *inout_pPreStartConfig)
    is made. See \ref prestartos.

Example:

\code
    void PreStartOS(S_PreStartConfig *inout_pPreStartConfig)
    {
        inout_pPreStartConfig->uCamDelay = 5;
        inout_pPreStartConfig->uPITCBaseRate = 5000;
        inout_pPreStartConfig->uFgndPeriodicBaseRTIMultiple = 2;
        inout_pPreStartConfig->uBgndPeriodicBaseRTIMultiple = 5;

        inout_pPreStartConfig->pInterruptStack     = (NativeVar_U *)&InterruptStack[0];
        inout_pPreStartConfig->uInterruptStackSize = sizeof(InterruptStack);

        inout_pPreStartConfig->pBgndStack          = (NativeVar_U *)&BgndStack[0];
        inout_pPreStartConfig->uBgndStackSize      = sizeof(BgndStack);

        inout_pPreStartConfig->pIdleStack          = (NativeVar_U *)&IdleStack[0];
        inout_pPreStartConfig->uIdleStackSize      = sizeof(IdleStack);

        inout_pPreStartConfig->pFgndTimeStack      = NULL;  // Allocate stack on heap
        input_pPreStartConfig->uFgndTimeStackSize  = 1728;

        inout_pPreStartConfig->pFgndAngleStack     = NULL;
        // Allocate non-zero size when the task is required
        inout_pPreStartConfig->uFgndAngleStackSize = 1728;
        // OR set to zero if task is not required. When not used all FgndAngle tasks
        // will execute using the FgndTime task (and stack)
        inout_pPreStartConfig->uFgndAngleStackSize  = 0;
        ...
    }
    \endcode */

typedef struct
{
/*! Pointer to allocated memory for IdleStack. If NULL, the system alocate a stack on the heap
    of the size specified by \ref uIdleStackSize */
    NativeVar_U* pIdleStack;
/*! Pointer to allocated memory for BgndStack. If NULL, the system alocate a stack on the heap
    of the size specified by \ref uBgndStackSize */
    NativeVar_U* pBgndStack;
/*! Pointer to allocated memory for FgndTimeStack. If NULL, the system alocate a stack on the heap
    of the size specified by \ref uFgndTimeStackSize */
    NativeVar_U* pFgndTimeStack;
/*! Pointer to allocated memory for FgndAngleStack. If NULL, the system alocate a stack on the heap
    of the size specified by \ref uFgndAngleSize */
    NativeVar_U* pFgndAngleStack;
/*! Pointer to allocated memory for InterruptStack. If NULL, the system alocate a stack on the heap
    of the size specified by  \ref uInterruptStackSize */
    NativeVar_U* pInterruptStack;

/*! Size of IdleStack. */
    uint4 uIdleStackSize;
/*! Size of BgndStack. */
    uint4 uBgndStackSize;
/*! Size of FgndTimeStack. */
    uint4 uFgndTimeStackSize;
/*! Size of FgndAngleStack. If Zero, FgndAngle Events will be pushed to the FngdTime stack for processing,
    and there will be no FgndAngle stack allocated */
    uint4 uFgndAngleStackSize;
/*! Size of InterruptStack. */
    uint4 uInterruptStackSize;

/*! This is the rate at which the Periodic Interrupt timer (PIT) is executing in MicroSeconds.
    The PIT rate is the fundemental scheduling unit for time based events. Care should be used when
    setting this value as too low a value will over tax the application with interrupts.  The
    default value can be set in calibration */
    uint2 uPITCBaseRate;
/*! This value, when multipled by the \ref PITCBaseRate, determines the base period of execution for the
    foreground periodic time events. The default value can be set in calibration */
    uint2 uFgndPeriodicBaseRTIMultiple;
/*! This value, when multipled by the foreground RTI process period (see \ref FgndPeriodicBaseRTIMultiple ) determines
    the base period of execution for the background periodic time events. The default value can be set in calibration */
    uint2 uBgndPeriodicBaseRTIMultiple;

/*! The cam delay to be applied (\ref camdelay ). Describes the angular delay between the rising edge of the
    actual cam signal and the rising edge of the ideal cam signal. If the cam leads the ideal cam by one tooth
    in a 60 minus 6 system then the cam Delay would be 6 degCA. If it lagged it would be 714 degCA. The cam
    delay is only applicable to those 4-strokes that use a cam and the crank encoder pattern has more than one
    synchronisation point. */
    uint2 uCamDelay;

/*! If the Idle task does not get to run during this length of time, starvation has occured and the
    watchdog will reset.  Typically a task has got into an endless loop */
    uint2 u2COPStarvationTimeInMilliSecs;

/*! Maximum number of FgndAngle Events that the queue can grow */
    uint1 u1FgndAngleMaxAllowedQueueGrowSize; 

/*! Maximum number of FgndTime Events that the queue can grow */
    uint1 u1FgndTimeMaxAllowedQueueGrowSize;  

/*! Maximum number of SWISR Events that the queue can grow */
    uint1 u1SWISRMaxAllowedQueueGrowSize;   
    
/*! See \ref encodertoothratio entry.  Some encoders support configurable missing tooth detection ratio.
    Typical value is 1.5 - Changes clipped between 1.2 to 1.8. - ALTER WITH CARE - SYSTEM ANALYSIS REQUIRED
    Storage is fixed point integer. Value = (Ratio * 128)  */
    uint1 uEncoderToothRatio;

/*! Some encoders can be configured to ignore a number of teeth before rotation is recognized and attempts to
    synchronize can begin. The default value is zero. The encoder will ignore the supplied value of teeth
    before it will allow synchronization to occur. Entering the speed zero condition resets the number of
    teeth that the Encoder has ignored so far back to zero */
    uint1 u8EncoderIgnoreTeeth;
} S_PreStartConfig;

#pragma pack()
/*----- EXTERNALS -----------------------------------------------------------------------------------------*/
    
/*----- PROTOTYPES ----------------------------------------------------------------------------------------*/

/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: PreStartOS   (hook implemented in the Application)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*! \brief  Application hook that is executed by the Framework before opening. This function must exist within
            the scope of the application.

            This function is used by the application to initialise options that need to be set before the
            OS opens. (Eg. Stacks, Timer rates etc) It may choose to do nothing and defaults will be used.

    \param   in_pPreStartConfigObj Pointer to S_PreStartConfig containg modifiable configuration
    \remarks Must be implemented within the scope of the application
*/

void PreStartOS(S_PreStartConfig *inout_pPreStartConfig);

/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: OpenApplication   (hook implemented in the Application)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*! \brief  Application hook that is exeucted by the Framework upon opening. This function must exist within
            the scope of the application.

            This function is used by the application to initialise itself. One key initialisation that should
            occur would be the creation (or installation) of a scheduler.
    \code
    void OpenApplication(E_OpenEventType in_eOpenType)
    {
        S_ScheduleCreateResourceAttributes SchedulerCreateAttribObj;

        SchedulerCreateAttribObj.pfAppCback = &AppSchdTaskCback;
        // CreateResource( , ,BEHAVIOUR_SCHEDULER) is equivelent to CreateResourceBEHAVIOUR_SCHEDULER( , )
        CreateResource(RES_SCHEDULER, &SchedulerCreateAttribObj, BEHAVIOUR_SCHEDULER);

        ...
    \endcode

    \param   in_eOpenType Describes how the Framework opened
    \remarks Must be implemented within the scope of the application
*/

void OpenApplication(E_OpenEventType in_eOpenType);

uint2 GetProcessPeriod(void);
uint2 GetRTIPeriod(void);
uint4 GetProcessPeriodTime_ms(void);
uint4 GetProcessPeriodTime_us(void);
void SendCloseOSMessage(void);
NativeError_S SendEvent(E_ExecutionEvent in_eAppEventToSend);
NativeError_S PostEvent(E_ExecutionEvent in_eAppEventToPost);

uint4 SleepTask(sint4 time_in_us);

NativeError_S GetFreeRunningCounter32Bits(uint4* inout_pCounter);
NativeError_S GetFreeRunningCounter64Bits(S_FreeRunningCounter64Bit* inout_pCounterobj);
NativeError_S ResetFreeRunningCounter64Bits(void);

NativeVar_U GetTDCOfLastTDCEvent(void);
NativeVar_U GetNextTDC(NativeVar_U in_uRelativeToThisTDC);

NativeError_S SetSchedulerEventCond(E_ModuleResource in_eResource, E_ExecutionEvent in_eEvent, E_ResourceCond in_eCond);

NativeError_S CreateResourceBEHAVIOUR_SCHEDULER(E_ModuleResource in_eResource, S_ScheduleCreateResourceAttributes const* in_pAttribObj);
NativeError_S CreateScheduler(SchedulerHandle* out_pHandle, S_ScheduleCreateResourceAttributes const* in_pAttribObj);
NativeError_S SetResourceAttributesBEHAVIOUR_SCHEDULER(E_ModuleResource in_eResource, S_ScheduleResourceAttributes const* in_pAttribObj);
NativeError_S SetSchedulerAttributes(SchedulerHandle in_Handle, S_ScheduleResourceAttributes const* in_pAttribObj);

#endif /* __RESOURCE_SCHEDULER_H */

/*----- END OF FILE ---------------------------------------------------------------------------------------*/
