/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
::   Module      :   Sequence Output Resource Framework API Header File
::   Copyright   :   (C)2002-2009 Woodward
::   Platform(s) :   MPC5xx
::   Limitations :   Dependant upon MPC5xx OS sub-project
::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*! \file Resource_SequenceOut.h
    \brief A Sequenced Output is an output resource that is capable of automatically generating a periodic
           pulse using crank angle domain information supplied to the Framework by an encoder resource (see
           \ref Resource_Encoder.c). Typically such an output is used to control an injector or an ignition
           coil. Each defined pulse repeats once per engine cycle. Most of the sequence output behaviours
           support the definition of multiple pulses, which allows the generation of multiple pulses per
           engine cycle. Useful topics \ref pulseevents, \ref pulsecontrolconcepts, \ref enablingpulses
           and \ref sequenceoutbehaviours.
*/

#ifndef __RESOURCE_SEQUENCEOUT_H
#define __RESOURCE_SEQUENCEOUT_H

/*----- INCLUDES ------------------------------------------------------------------------------------------*/
#include <typedefn.h>
#include <resource.h>

/*----- DEFINES -------------------------------------------------------------------------------------------*/
/* Set to zero if the input data verification should be limited */
#define DO_SEQ_OUT_DATA_VERIFICATION 0

/*! Multiplexed sequence outputs can only support a finite number of pulses which is captured by this define */
#define MAX_MUX_PULSES_SUPPORTED 8

/*! Defines the crank angle degree resolution (0.0625)  */
#define CRANK_ANGLE_PRECISION ((NativeVar_U) 16)

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

/*! \brief Enumeration that describes the set of mask definitions that are used to identify the valid sequence
           Ooutput attributes in the various data structures that are valid. */
typedef enum
{
    USE_SEQ_MULTI_STRIKE = 0x0001,          /*!< Selects S_SeqOutAttributes::MultiStrikeObj */
    USE_SEQ_PULSE_COND = 0x0002,            /*!< Selects S_SeqOutAttributes::eResourceCondition */
    USE_SEQ_TIMING = 0x0004,                /*!< Selects S_SeqOutAttributes::TimingObj */
    USE_SEQ_PEAK = 0x0008,                  /*!< Selects S_SeqOutAttributes::u2PeakTimeInMicroSecs */
    USE_SEQ_DIAG_REPORT_COND = 0x0010,      /*!< Selects S_SeqOutAttributes::eDiagCond */
    USE_SEQ_ENDEVENT_REPORT_COND = 0x0020,  /*!< Selects S_SeqOutAttributes::eReportCond */
    USE_SEQ_MAX_DURATION = 0x0040,          /*!< Selects S_SeqOutAttributes::u4MaxDurationInMicroSecs */
    USE_SEQ_UPDATE_MODE = 0x0080,           /*!< Selects S_SeqOutAttributes::eUpdateMode */
    USE_SEQ_GRANULARITY = 0x0100,           /*!< Selects S_TranInjSeqCreateAttributes::eGranularity,
                                                         S_BankedESTSeqCreateAttributes::eGranularity,
                                                         S_InjSeqCreateAttributes::eGranularity,
                                                         S_ESTSeqCreateAttributes::eGranularity, 
                                                         S_MuxESTSeqCreateAttributes::eGranularity */
    USE_SEQ_MIN_DURATION = 0x0200,          /*!< Selects S_SeqOutAttributes::uMinPulseDurationInMicroSecs */
    USE_SEQ_CTRLMODE     = 0x0400,          /*!< Selects S_MuxESTSeqCreateAttributes::eCtrlMode */
    USE_SEQ_POLARITY     = 0x0800,          /*!< Selects S_MuxESTSeqCreateAttributes::ePolarity */
/* IF THIS TYPE EXCEEDS 0x8000 THEN ALTER THE TYPE OF THE uValidAttributesMask MEMBERS ACCORDINGLY */

} E_SeqOutAttributes;

/*! \brief Sequence output pulse condition, which is used to enable and disable a sequence output's pulses.

    The framework actively attempts to schedule an enabled pulse while ignoring disabled pulses. Thus the
    timing and other attributes of a disabled pulse can be altered without affecting the output. The attribute
    is generally applied on a per pulse basis and thus allows one pulse to be disabled while continuing to
    allow other pulses to be scheduled. */
typedef enum 
{
/*! The sequence/channel is deactivated immediately. If a sequenced output is currently ON then it will be
    turned OFF immediately. The pulse will not participate in pulse scheduling off its start event once
    the pulse has turned OFF until the \ref SEQ_ENABLED is again assigned to it */
    SEQ_DISABLED = RES_DISABLED,
/*! The pulse is enabled and actively participates in pulse generation */
    SEQ_ENABLED  = RES_ENABLED,
/*! The sequence output is deactivated immediately after the pulse has finished. A sequenced output that is
    OFF will remain OFF. However, a sequenced output that is currently ON will remain ON until its duration
    has elapsed or the stop event occurs (which ever is appropriate for that sequenced output). Once the
    sequenced output is OFF it will automatically take on the SEQ_DISABLED condition and operate in the
    manner appropriate for this condition. */
    SEQ_DISNEXT
} E_SeqOutCond;

/* Name: E_SeqOutCtrlMode ClassID:ENUMDEC EnumDflt:"Unknown Option" */
/*! \brief Enumeration describes the pulse control modes supported by the framework. */
typedef enum
{
    /*! See \ref angleanglepulsecontrol */
    ANGLE_CTRL = 0, /* EnumTxt:"ANGLE_CTRL" */    
    /*! See \ref angletimepulsecontrol */
    DURATION_CTRL = 1, /* EnumTxt:"DURATION_CTRL" */  
    /*! See \ref angletimehardstopcontrol */ 
    DURATION_CTRL_HARDSTOP = 2 /* EnumTxt:"DURATION_CTRL_HARDSTOP" */ 
} E_SeqOutCtrlMode;

/* Name: E_SeqGranularity ClassID:ENUMDEC EnumDflt:"Unknown Option" */
/*! \brief Pulse scheduling granularity.

 Pulses that use interpolation for their angle domain events are said to have a fine granularity. Fine
 granularity has an approximate pulse precision of 0.0625geCA. See \ref pulsegenerationprinciples for
 further information on interpolation in angle domain pulse scheduling. Those pulses that do not use
 interpolation are said to have coarse granularity. Effectively such pulses have the same resolution as the
 encoder pattern used by the system. */
typedef enum
{
/*! Fine granularity where interpolation is used to achieve high precision angle domain events */
    FINE_GRANULARITY,   /* EnumTxt:"Fine"   */
/*! Coarse granularity where no interpolation is performed. This results in the timing being rounded to the
    resolution offered by the encoder. */
    COARSE_GRANULARITY  /* EnumTxt:"Coarse" */
} E_SeqGranularity;

/*! \brief Describes the output type of a sequence output resource.

    This attribute is used to discern the type of diagnostic report issed by the framework since that report
    type uses a union to combine the data, thus allowing for a common prototype. */
typedef enum
{
    SQ_INJECTOR,    /*!< Sequence output is on an injector driver */
    SQ_EST          /*!< Sequence output is on an low current, push-pull style driver most commonly used for
                         Electronic Spark Tuiming (EST) */
} E_SeqOutType;

/*! \brief Injector report */
typedef struct
{
    uint4 u4TXTimeInMicroSecs;  /*!< The approximate time in microseconds until the injector driver's current
                                     threshold was first reached. If this value is too small then the driver
                                     has a shorted load (assumes an inductive load is connected) */
    uint1 u1TXCnt;              /*!< The approximate number of current switching transitions that occurred
                                     combined with the count of inductive turn-offs. A value of zero indicates
                                     that there is no load connected to the driver. */
} S_SeqOutInjDiagReport;

/*! \brief Ignition report that can be used to diagnose a short circuit.

 Short circuits can only be diagnosed when the driver is being actively switched on and off and so is generally
 only performed when the driver is in use and there is engine speed. The framework detects when the conditions
 are sufficient to allow diagnosis and will only issue the report in this circumstance. */
typedef struct
{
/*! The approximate dwell time of the last event. This value will not be accurate if the coil is employing
    multi-strike and should be ignored in this circumstance */
    uint2 u2OnTimeInMicroSecs;
/*! Boolean that indicates whether a pulse was generated. The load is shorted if this report is received
    with this member set to \c FALSE. */
    bool1 b1Occurred;
} S_SeqOutESTShortDiagReport;

/*! \brief Ignition report that can be used to diagnose an open circuit.

 The open circuit diagnostic can only be performed while the driver is OFF and it's low side has been disconnected
 from the load. Hardware exists to achive such a condition. However the report is only issued when the framework
 detects a zero engine speed condition because of the requirement to only perform the test while the driver is OFF.

 An open circuit is detected if the \p uADCSample is too high (indicating that an implicit pull-down within the
 nominal load is not present) */
typedef struct
{
    NativeADC_U uADCSample;     /*!< ADC Sample used to detect open circuit. A too high reading indicates an open circuit */
} S_SeqOutESTOpenDiagReport;

#define HAS_SHORT_CCT_EST_DIAG ((uint1)(1))
#define HAS_OPEN_CCT_EST_DIAG  ((uint1)(2))

/*! \brief EST diagnostic report data that is supplied with each \ref SeqOutDiagCbackFuncPtrType diagnostic
           report that corresponds to an EST sequence output (\ref SQ_EST).

 EST sequence output pulses can only be diagnosed when certain conditions are TRUE. The framework detects when
 conditions are correct and constructs a report. The S_SeqOutESTDiagReport::u1ValidDataMask is set to indicate
 what report information is valid. If the open circuit test conditions have been met then \c HAS_OPEN_CCT_EST_DIAG
 will exist in the mask while \c HAS_SHORT_CCT_EST_DIAG will exist in the mask when the short circuit conditions
 have been met.
 \code
void ProcessESTDiagnostics(S_SeqOutESTDiagReport const* in_pESTDiagReportObj, S_AppSeqOutDefn const* in_pResourceObjPtr)
{
   if ((in_pESTDiagReportObj->u1ValidDataMask & HAS_SHORT_CCT_EST_DIAG) != 0)
   {
       // Handle the Short Circuit Condition
       if (in_pESTDiagReportObj->ShortDataObj.b1Occurred == FALSE)
       {   // Fault condition detected
           ...
       }
   }

   if ((in_pESTDiagReportObj->u1ValidDataMask & HAS_OPEN_CCT_EST_DIAG) != 0)
   {
       if (in_pESTDiagReportObj->OpenDataObj.uADCSample > g_u2ESTOpenTestThreshold)
       {    // Fault condition
            ...
        }
    }
} \endcode */
typedef struct
{
/*! Mask indicating which reports in the structure are valid */
    uint1 u1ValidDataMask;
/*! Short circuit data that is valid when S_SeqOutESTDiagReport::u1ValidDataMask & HAS_SHORT_CCT_EST_DIAG != 0 */
    S_SeqOutESTShortDiagReport ShortDataObj;    
/*! Open circuit data that is valid when S_SeqOutESTDiagReport::u1ValidDataMask & HAS_OPEN_CCT_EST_DIAG != 0 */
    S_SeqOutESTOpenDiagReport  OpenDataObj;
} S_SeqOutESTDiagReport;

/*! Union that mixes the mutually exclusive report information of an injector and ignition resource so that
    the same data prototype can be used for both driver types */
typedef union
{
    S_SeqOutInjDiagReport Inj;  /*!< Rpeort contains injector information */
    S_SeqOutESTDiagReport EST;  /*!< Report contains ignition information */
} U_SeqDiagReport;

/*! \brief Sequence output diagnostic report. */
typedef struct
{
    E_ModuleResource eOwningResource;   /*!< The sequence output resource that issued the report */
    E_SeqOutType eOutputType;           /*!< The type of output that issued the report. Allows the
                                             S_SeqOutDiagReport::DiagReportObj to be interpreted */
    U_SeqDiagReport DiagReportObj;      /*!< The report. Use S_SeqOutDiagReport::eOutputType to interepret the union */
} S_SeqOutDiagReport;

/*! Read only pointer type for the \ref S_SeqOutDiagReport report data that is issued on sequence output diagnostic events */
typedef S_SeqOutDiagReport const* S_SeqOutDiagReportPtr;

/*! Describes the end of event report for an injector control pulse */
typedef struct
{
    E_ModuleResource eOwningResource;   /*!< The sequence output resource that issued the report */
    uint1 u1OwningPulseNum;             /*!< The pulse number that issued the report. Some sequence outputs
                                             can have more than one pulse associated to them. */
    uint4 u4PulseDurationInMicroSecs;   /*!< Describes the duration of the pulse that just completed. This value
                                             is only meaning ful when the control mode is \ref DURATION_CTRL. <br>
                                             If in ANGLE_CTRL or DURATION_CTRL_HARDSTOP with hardstop active, 
                                             The reported duration is calculated based on the last period. */
} S_SeqOutInjEndEventReport;
 
/*! Read only pointer type for the \ref S_SeqOutInjEndEventReport report data that is issued on an injector end of event */
typedef S_SeqOutInjEndEventReport const* S_SeqOutInjEndEventReportPtr;

/*! \brief Describes the prototype for a sequence output diagnostic report.

    The \p in_uNotificationData parameter is the data that was supplied by the S_InjectorReports::uDiagCbackUserData
    or S_SparkReports::uDiagCbackUserData members.

    \p in_pDiagReportObj describes the diagnostic report. Spark and injector information are different and so the
    application must first interrogate the report to learn how to interpret the data.
    \code
 void OnSequenceOutDiagReport(S_SeqOutDiagReportPtr in_pDiagReportObj, NativePtrSizedInt_U in_uNotificationData)
 {
     switch(in_pDiagReportObj->eOutputType)
     {
         case SQ_INJECTOR:
             // A S_AppSeqOutDefn const* pointer was supplied as the application data when the report was created
             ProcessInjectorDiagnostics(&in_pDiagReportObj->DiagReportObj.Inj, (S_AppSeqOutDefn const*)in_uNotificationData);
             break;

         case SQ_EST:
             // A S_AppSeqOutDefn const* pointer was supplied as the application data when the report was created
             ProcessESTDiagnostics(&in_pDiagReportObj->DiagReportObj.EST, (S_AppSeqOutDefn const*)in_uNotificationData);
             break;
     }
 } \endcode */
typedef void (*SeqOutDiagCbackFuncPtrType)(S_SeqOutDiagReportPtr in_pDiagReportObj, NativePtrSizedInt_U in_uNotificationData);

/*! Describes the prototype of the end of pulse event for an injector sequence output. The \p in_uNotificationData
    parameter is the data that was supplied when the report was created. See S_InjectorReports::uReportCbackUserData. */
typedef void (*SeqOutInjEndEventCbackFuncPtrType)(S_SeqOutInjEndEventReportPtr in_pReportObj, NativePtrSizedInt_U in_uNotificationData);

/*! \brief The type describes the report setup attributes for a sequence output being used on a injector resource */
typedef struct
{
/*! The notification function that the framework will execute when an injector diagnostic event has occurred, provided
    that report has been enabled. See S_SeqOutAttributes::eDiagCond. */
    SeqOutDiagCbackFuncPtrType pfDiagCback;
/*! Application data to be supplied when the diagnostic report is issued. This type is sufficiently sized to
    allow the storage of a pointer type. */
    NativePtrSizedInt_U uDiagCbackUserData;
/*! The end of pulse event notification function. This function will be executed by the framework for end of event
    detected on the associated sequence output provided that has been enabled. See S_SeqOutAttributes::eReportCond */
    SeqOutInjEndEventCbackFuncPtrType pfReportCback;
/*! Application data to be supplied when the end of event report is issued. This type is sufficiently sized to
    allow the storage of a pointer type. */
    NativePtrSizedInt_U uReportCbackUserData;
} S_InjectorReports;

/*! Describes the end of event report for a spark (EST) pulse */
typedef struct
{
    E_ModuleResource eOwningResource;   /*!< The sequence output resource that issued the report */
    uint1 u1OwningPulseNum;             /*!< The pulse number that issued the report. Some sequence outputs
                                             can have more than one pulse associated to them. */
} S_SeqOutESTEndEventReport;

/*! Read only pointer type for the \ref S_SeqOutESTEndEventReport report data that is issued with a spark end of event */
typedef S_SeqOutESTEndEventReport const* S_SeqOutESTEndEventReportPtr;

/*! Describes the prototype of the end of pulse event for a spark (EST) sequence output. The \p in_uUserData
    parameter is the data that was supplied when the report was created. See S_SparkReports::uReportCbackUserData. */
typedef void (*SeqOutESTEndEventCbackFuncPtrType)(S_SeqOutESTEndEventReportPtr, NativePtrSizedInt_U in_uUserData);

/*! \brief The type describes the report setup attributes for a sequence output being used on a spark resource */
typedef struct
{
/*! The notification function that the framework will execute when a spark diagnostic event has occurred, provided
    that report has been enabled. See S_SeqOutAttributes::eDiagCond. */
    SeqOutDiagCbackFuncPtrType pfDiagCback;
/*! Application data to be supplied when the diagnostic report is issued. This type is sufficiently sized to
    allow the storage of a pointer type. */
    NativePtrSizedInt_U uDiagCbackUserData;
/*! The end of pulse event notification function. This function will be executed by the framework for end of event
    detected on the associated sequence output provided that has been enabled. See S_SeqOutAttributes::eReportCond */
    SeqOutESTEndEventCbackFuncPtrType pfReportCback;
/*! Application data to be supplied when the end of event report is issued. This type is sufficiently sized to
    allow the storage of a pointer type. */
    NativePtrSizedInt_U uReportCbackUserData;
} S_SparkReports;

/*! \brief Describes how the Framework should process a timing attribute update with respect to the management
           of missing pulse and double pulse generation.  */
typedef enum
{
/*! The OS performs the management, which is the default */
    SEQ_UPDATE_OS_PROTECTED,
/*! The application performs the management. Here the framework can assume that the pulse timing attributes
    are applied directly and will not take any action to protect against unexpected pulse behaviour. For
    example, the application is using an end of event report to allow multiple, non-overlapping pulses to be
    generated over the course of one engine cycle. Framework protection is not warrented here and could even
    be of detriment because the framework may incorrectly attempt to protect against application desired
    behaviour. */
    SEQ_UPDATE_APP_PROTECTED
} E_SeqOutUpdateMode;

/*! \brief Type describes the pulse event attributes that control the position and duration of an output pulse.

    Only one of S_SeqOutPulseTiming::s2StopAngle or S_SeqOutPulseTiming::u4Duration need be valid in this data
    structure (dependant upon the control mode described by S_SeqOutPulseTiming::eCtrlMode). */
typedef struct
{
/*! The start event angle. Has units of crank angle degrees before firing TDC (degBfTDC). A negative value
    describes an after firing TDC event. The attribute has a gain of 0.0625 degCA. */
    sint2 s2StartAngle;             
/*! The stop event angle. Has units of crank angle degrees before firing TDC (degBfTDC). A negative value
    describes an after firing TDC event. The attribute has a gain of 0.0625 degCA. It need only be defined
    when the control mode (S_SeqOutPulseTiming::eCtrlMode) is \ref ANGLE_CTRL or \ref DURATION_CTRL_HARDSTOP. */
    sint2 s2StopAngle;
/*! The pulse on time in microseconds. It need only be defined when the control mode
    (S_SeqOutPulseTiming::eCtrlMode) is \ref DURATION_CTRL or \ref DURATION_CTRL_HARDSTOP. */
    uint4 u4Duration;
/*! Describes the control mode to be applied to the pulse. See \ref angleanglepulsecontrol and
    \ref angletimepulsecontrol */
    E_SeqOutCtrlMode eCtrlMode;
} S_SeqOutPulseTiming;

/*! Read only S_SeqOutPulseTiming pointer type */
typedef S_SeqOutPulseTiming const* S_SeqOutPulseTimingPtr;

/*! Data structure describes the multi-strike attributes that can be applied to spark capable drivers */
typedef struct
{
    uint1 u1NumPulsesToAppend;      /*!< The number of pulses to apply after the end event */
    sint2 s2DutyCycle;              /*! The duty-cycle that describes the portion of the
                                        S_MultiStrikeAttributes::u2PulsePeriodInMicroSecs time that the pulse
                                        is to be ON for. 4096 scales to 100%. */
    uint2 u2PulsePeriodInMicroSecs; /*!< The period of an appended pulse in microseconds. */
} S_MultiStrikeAttributes;

typedef S_MultiStrikeAttributes const* S_MultiStrikeAttributesPtr;

/*! \brief This data structure describes all of a sequence output pulse's runtime configuration attributes.

    The attributes are altered through the use of SetResourceAttributesSequenceOut(). The data structure
    does not need to be completely filled inorder to be used. The \p 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. Importantly, many attributes
    are applicable to one sequence output pulse, and so \p u1AffectedPulse must be set to identify the pulse.
    \code
    ...
    S_SeqOutAttributes SeqOutPulseObj;

    // Going to enable the pulse and its report
    SeqOutPulseObj.uValidAttributesMask = USE_SEQ_PULSE_COND | USE_SEQ_ENDEVENT_REPORT_COND;
    // Apply to pulse zero
    SeqOutPulseObj.u1AffectedPulse = 0;  \endcode
    Attempting to apply an unsupported attribute has no affect on the modification of any unrelated attributes. */
typedef struct
{
/*! Defines which sequence output pulse this attribute object is to be applied to. It \b MUST \b EXIST. */
    uint1 u1AffectedPulse;

/*! Logic-OR the attributes [\ref USE_SEQ_MULTI_STRIKE, \ref USE_SEQ_PULSE_COND, \ref USE_SEQ_TIMING,
    \ref USE_SEQ_PEAK, \ref USE_SEQ_DIAG_REPORT_COND, \ref USE_SEQ_ENDEVENT_REPORT_COND,
    \ref USE_SEQ_MAX_DURATION, \ref USE_SEQ_UPDATE_MODE] that are valid for this instance of the data structure */
    uint2 uValidAttributesMask;

/*! Defines the maximum allowable duration of a pulse in microseconds. A pulse is forcibly turned off if it
    has been on for longer than this time. Select with the \ref USE_SEQ_MAX_DURATION bit mask.
    
    This attribute is commonly used to protect ignition coils employing the \ref angleanglepulsecontrol from
    turning ON for too long (which can cause coil damage) should the system experience a temporary loss of
    encoder synchronisation.

    The attribute offers good precision, but the control is actually quite granule because it employs the system's
    real time interrupt as the secondary timing mechanism. Setting to zero, which is the default, disables this
    attribute from having any affect on the output. Minimising the use of this attribute will conserve CPU bandwidth. */
    uint4 u4MaxDurationInMicroSecs;

/*! The peaktime event in microseconds. Default value is zero, which disables the event. Select with the
    \ref USE_SEQ_PEAK bit mask. This attribute is applied to all pulses describes by the sequence output,
    regardless of the value or the \p u1AffectedPulse member. Also see \ref peakevent. */
    uint2 u2PeakTimeInMicroSecs;

/*! Describes the timing attributes to apply to the specified pulse. This attribute is selected with the
    \ref USE_SEQ_TIMING bit mask. */
    S_SeqOutPulseTiming TimingObj;
/*! This attribute describes the framework updatemode to apply to the specified pulse. This attribute is
    selected with the \ref USE_SEQ_UPDATE_MODE bit mask. */
    E_SeqOutUpdateMode eUpdateMode;
/*! Each sequence output pulse has the capability to issue an end of event report. This attribute is used to
    enable or disable those reports. This attribute is selected with the \ref USE_SEQ_ENDEVENT_REPORT_COND
    bit mask. The default value on creation is disabled. */
    E_ResourceCond eReportCond;
/*! Each sequence output has the capability to issue a diagnostic report that provides event based information
    on the health of the hardware driver associated with the output. The report is attached to the output rather
    than the pulse so the S_SeqOutAttributes::u1AffectedPulse is ignored. This attribute is selected with the 
    \ref USE_SEQ_DIAG_REPORT_COND bit mask. Its initial value is disabled. */
    E_ResourceCond eDiagCond;
/*! Describes the multi-strike attributes that can be applied to some sequence outputs. This attribute is
    selected with the \ref USE_SEQ_MULTI_STRIKE bit mask. SetResourceAttributesSequenceOut() will error if
    this attribute is applied to a resource that is incapable of multi-strike functionality. */
    S_MultiStrikeAttributes MultiStrikeObj;
/*! The pulse condition, this attribute is primarily used to enable or disable a pulse. Select attribute
    with the \ref USE_SEQ_PULSE_COND bit mask. The attributes of a pulse can be altered without having it
    affect the output while the pulse is disabled. Can also be achieved through the use of the SetSeqOutCond().
    
    The order in which a pulse is enabled can be important, see \ref enablingmuxpulses and \ref enablingdualpulses */
    E_SeqOutCond eResourceCondition;

/*! Defines what the minimum allowed pulse duration for this output can be. This attribute is applied to all pulses
    associated with the Sequence Output. This attribute is selected with the \ref USE_SEQ_MIN_DURATION bit mask.
    Time domain controlled pulses that are altered by the Framework to allow for scheduling (like the make-up fuel
    pulse in the transient behaviour) shall use this value to determine whether the pulse should be scheduled. */
    uint4 uMinPulseDurationInMicroSecs;
} S_SeqOutAttributes;

/*! Read only pointer type for a \ref S_SeqOutAttributes data structre */
typedef S_SeqOutAttributes const* S_SeqOutAttributesPtr;

/*! \brief The creation attributes for a transient injector sequence.

 A transient injector sequence is created with CreateResourceBEHAVIOUR_TRAN_FUEL_SEQ(). See \ref transientfuelseqout */
typedef struct
{
/*! Describes which optional attributes within the structure are valid. Logic-OR those attributes
    [\ref USE_SEQ_GRANULARITY, \ref USE_SEQ_DIAG_REPORT_COND, \ref USE_SEQ_ENDEVENT_REPORT_COND] which are valid */
    uint2 uValidAttributesMask;
/*! Defines the report hooks used by the application for the output. The defaults are to not provide application
    reports. Select with the \ref USE_SEQ_DIAG_REPORT_COND and \ref USE_SEQ_ENDEVENT_REPORT_COND bit masks */
    S_InjectorReports ReportsObj;   /*!< Report information that is applied during creation */
/*! Defines the granularity. Default value is \ref FINE_GRANULARITY. Select with the \ref USE_SEQ_GRANULARITY bit mask */ 
    E_SeqGranularity eGranularity;
    sint2 s2OffsetDegATDC1;         /*!< The global offset that is applied to both the primary and make-up fuel pulse */

} S_TranInjSeqCreateAttributes;

typedef S_TranInjSeqCreateAttributes const* S_TranInjSeqCreateAttributesPtr;

/*! \brief Banked EST sequence output creation attributes */
typedef struct
{
/*! Describes which optional attributes within the structure are valid. Logic-OR those attributes [\ref USE_SEQ_MULTI_STRIKE,
    \ref USE_SEQ_GRANULARITY, \ref USE_SEQ_DIAG_REPORT_COND, \ref USE_SEQ_ENDEVENT_REPORT_COND] which are valid */
    uint2 uValidAttributesMask;
/*! Defines the report hooks used by the application for the output. The defaults are to not provide application
    reports. Select with the \ref USE_SEQ_DIAG_REPORT_COND and \ref USE_SEQ_ENDEVENT_REPORT_COND bit masks */
    S_SparkReports ReportsObj;
/*! Defines the granularity. Default value is \ref FINE_GRANULARITY. Select with the \ref USE_SEQ_GRANULARITY bit mask */ 
    E_SeqGranularity eGranularity;
/*! The encoder offset that is applied to pulse zero. The second pulse shall use an offset of this value plus 360 degCA */
    sint2 s2OffsetDegATDC1;

} S_BankedESTSeqCreateAttributes;

typedef S_BankedESTSeqCreateAttributes const* S_BankedESTSeqCreateAttributesPtr;

/*! Standard injector sequence output creation attributes */
typedef struct
{
/*! Describes which optional attributes within the structure are valid. Logic-OR those attributes
    [\ref USE_SEQ_GRANULARITY, \ref USE_SEQ_DIAG_REPORT_COND, \ref USE_SEQ_ENDEVENT_REPORT_COND] which are valid */
    uint2 uValidAttributesMask;
/*! Defines the report hooks used by the application for the output. The defaults are to not provide application
    reports. Select with the \ref USE_SEQ_DIAG_REPORT_COND and \ref USE_SEQ_ENDEVENT_REPORT_COND bit masks */
    S_InjectorReports ReportsObj;
/*! Defines the granularity. Default value is \ref FINE_GRANULARITY. Select with the \ref USE_SEQ_GRANULARITY bit mask */ 
    E_SeqGranularity eGranularity;
/*! Required attribute that defines how many pulses are to be associated to this sequence output. Upto two
    pulses can be assigned to a sequence output of this type */
    uint1 u1NumPulsesToCreate;
/*! The global offset applied to each pulse relative to TDC #1. Has units of 0.0625 degAfTDC#1. */
    sint2 s2PulseOffsetDegATDC1Arr[2];

} S_InjSeqCreateAttributes;

typedef S_InjSeqCreateAttributes const* S_InjSeqCreateAttributesPtr;

/*! \brief EST sequence output creation attributes

 This output is principly the same as the injector sequence output described by \ref S_InjSeqCreateAttributes.
 The key differences are:
 - the output can have multi-strike capability assigned to it. Do not assign multi-strike capability to a
   sequence output that does not require it because it is mor CPU bandwidth intensive (even if the pulses
   are then disabled). Include the \c USE_SEQ_MULTI_STRIKE bit mask in \p uValidAttributesMask if multi-strike
   is a requirement.
 - it can only be assigned to sequence outputs that are of the \ref SQ_EST type. */
typedef struct
{
/*! Describes which optional attributes within the structure are valid. Logic-OR those attributes [\ref USE_SEQ_MULTI_STRIKE
    \ref USE_SEQ_GRANULARITY, \ref USE_SEQ_DIAG_REPORT_COND, \ref USE_SEQ_ENDEVENT_REPORT_COND] which are valid */
    uint2 uValidAttributesMask;
/*! Defines the report hooks used by the application for the output. The defaults are to not provide application
    reports. Select with the \ref USE_SEQ_DIAG_REPORT_COND and \ref USE_SEQ_ENDEVENT_REPORT_COND bit masks */
    S_SparkReports ReportsObj;
/*! Defines the granularity. Default value is \ref FINE_GRANULARITY. Select with the \ref USE_SEQ_GRANULARITY bit mask */ 
    E_SeqGranularity eGranularity;
/*! Required attribute that defines how many pulses are to be associated to this sequence output. Upto two
    pulses can be assigned to a sequence output of this type */
    uint1 u1NumPulsesToCreate;
/*! The global offset applied to each pulse relative to TDC #1. Has units of 0.0625 degAfTDC#1. */
    sint2 s2PulseOffsetDegATDC1Arr[2];

} S_ESTSeqCreateAttributes;

typedef S_ESTSeqCreateAttributes const* S_ESTSeqCreateAttributesPtr;

/*! \brief Multiplexed EST sequence output creation attributes

 This output is principly the same as the EST sequence output described by \ref S_ESTSeqCreateAttributes
 except it is designed to generate many more than two pulses per cycle. It is typically used for distributor
 based spark systems. It does not support multi-strike and can only be assigned to minimal set of sequence
 outputs. This set will nominally include SQ_EST1 and SQ_EST2. */
typedef struct
{
/*! Describes which optional attributes within the structure are valid. Logic-OR those attributes
    [\ref USE_SEQ_GRANULARITY, \ref USE_SEQ_DIAG_REPORT_COND, \ref USE_SEQ_ENDEVENT_REPORT_COND] which are valid */
    uint2 uValidAttributesMask;
/*! Defines the report hooks used by the application for the output. The defaults are to not provide application
    reports. Select with the \ref USE_SEQ_DIAG_REPORT_COND and \ref USE_SEQ_ENDEVENT_REPORT_COND bit masks */
    S_SparkReports ReportsObj;
/*! Defines the granularity. Default value is \ref FINE_GRANULARITY. Select with the \ref USE_SEQ_GRANULARITY bit mask */ 
    E_SeqGranularity eGranularity;
/*! The global offset applied to each pulse relative to TDC #1. Has units of 0.0625 degAfTDC#1. */
    sint2 s2PulseOffsetDegATDC1Arr[MAX_MUX_PULSES_SUPPORTED];
/*! Required attribute that defines how many pulses are to be associated to this sequence output. Upto
    \c MAX_MUX_PULSES_SUPPORTED pulses can be assigned to a sequence output of this type. */
    uint1 u1NumPulsesToCreate;
/*! Describes the control mode to be applied to all of the pulses. See \ref angleanglepulsecontrol and
    \ref angletimepulsecontrol. Select with the \ref USE_SEQ_CTRLMODE bit mask. When not selected the mode is set to ANGLE_CTRL. */
    E_SeqOutCtrlMode eCtrlMode;
/*! Describes the output polarity to be applied to all of the pulses. Select with the \ref USE_SEQ_POLARITY bit mask. When not
    selected this attribute defaults to RES_POL_ACTIVE_HIGH.  */ 
    E_ResourcePolarity ePolarity;

} S_MuxESTSeqCreateAttributes;

typedef S_MuxESTSeqCreateAttributes const* S_MuxESTSeqCreateAttributesPtr;

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

/*----- PROTOTYPES ----------------------------------------------------------------------------------------*/
/* Optimised calls that can be applied to certain attribute sets                                           */

NativeError_S SetSeqOutTiming(E_ModuleResource in_eResource, NativeVar_U in_uPulseNum, S_SeqOutPulseTimingPtr in_pTimingObj);

NativeError_S SetSeqOutInjPeakTime(E_ModuleResource in_eResource, uint2 in_u2PeakTimeInMicroSecs);

/* The condition applies to all pulses when the sequence behaviour understands the pulse behaviour (Banked, Transient). */
/* It applies to the specific pulse when that behaviour allows it (Spark, Injection, Wasted Spark, Multiplexed Spark)   */
NativeError_S SetSeqOutCond(E_ModuleResource in_eResource, NativeVar_U in_uPulseNum, E_SeqOutCond in_eCond);
NativeError_S ReapplySeqOutCond(E_ModuleResource in_eResource);

NativeError_S SeqSeqOutUpdateMode(E_ModuleResource in_eResource, NativeVar_U in_uPulseNum, E_SeqOutUpdateMode in_eMode);

/* DO NOT use these functions directly. They are implicitly called through the use of the CreateResource() */
/*   and SetResourceAttributes() macro functions                                                           */
NativeError_S CreateResourceBEHAVIOUR_TRAN_FUEL_SEQ(E_ModuleResource in_eResource, S_TranInjSeqCreateAttributes const* in_pAttribsObj);
NativeError_S CreateResourceBEHAVIOUR_BANK_EST_SEQ(E_ModuleResource in_eResource, S_BankedESTSeqCreateAttributes const* in_pAttribsObj);
NativeError_S CreateResourceBEHAVIOUR_INJ_SEQ(E_ModuleResource in_eResource, S_InjSeqCreateAttributes const* in_pAttribsObj);
NativeError_S CreateResourceBEHAVIOUR_EST_SEQ(E_ModuleResource in_eResource, S_ESTSeqCreateAttributes const* in_pAttribsObj);
NativeError_S CreateResourceBEHAVIOUR_MUX_EST_SEQ(E_ModuleResource in_eResource, S_MuxESTSeqCreateAttributes const* in_pAttribsObj);

#define DestroyResourceBEHAVIOUR_TRAN_FUEL_SEQ(a)         DestroyResourceSequenceOut(a, BEHAVIOUR_TRAN_FUEL_SEQ);
#define DestroyResourceBEHAVIOUR_BANK_EST_SEQ(a)          DestroyResourceSequenceOut(a, BEHAVIOUR_BANK_EST_SEQ);
#define DestroyResourceBEHAVIOUR_INJ_SEQ(a)               DestroyResourceSequenceOut(a, BEHAVIOUR_INJ_SEQ);
#define DestroyResourceBEHAVIOUR_EST_SEQ(a)               DestroyResourceSequenceOut(a, BEHAVIOUR_EST_SEQ);
#define DestroyResourceBEHAVIOUR_MUX_EST_SEQ(a)           DestroyResourceSequenceOut(a, BEHAVIOUR_MUX_EST_SEQ);

NativeError_S DestroyResourceSequenceOut(E_ModuleResource in_eResource, E_ResourceBehaviour in_eSeqOutBehaviour);

#define SetResourceAttributesBEHAVIOUR_TRAN_FUEL_SEQ(a,b) SetResourceAttributesSequenceOut(a,b, BEHAVIOUR_TRAN_FUEL_SEQ)
#define SetResourceAttributesBEHAVIOUR_BANK_EST_SEQ(a,b)  SetResourceAttributesSequenceOut(a,b, BEHAVIOUR_BANK_EST_SEQ)
#define SetResourceAttributesBEHAVIOUR_INJ_SEQ(a,b)       SetResourceAttributesSequenceOut(a,b, BEHAVIOUR_INJ_SEQ)
#define SetResourceAttributesBEHAVIOUR_EST_SEQ(a,b)       SetResourceAttributesSequenceOut(a,b, BEHAVIOUR_EST_SEQ)
#define SetResourceAttributesBEHAVIOUR_MUX_EST_SEQ(a,b)   SetResourceAttributesSequenceOut(a,b, BEHAVIOUR_MUX_EST_SEQ)

NativeError_S SetResourceAttributesSequenceOut(E_ModuleResource in_eResource, S_SeqOutAttributesPtr in_pAttribsObj, E_ResourceBehaviour);

void PostMessageMultiplexedDiagnosticRefresh(void);
#endif /* __RESOURCE_SEQUENCEOUT_H */

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