/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
::  Module      :   Encoder Resource Framework API Header File
::  Copyright   :   (C)2003-2009 Woodward
::  Platform(s) :   MPC5xx
::  Limitations :   MPC5xx OS
::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*! \file Resource_Encoder.h
    \brief The Framework is responsible for analysing the crank angle position information made available to
           it by the crank position sensor (CPS) or sensors, which are often referred to as the encoder. The
           BEHAVIOUR_ENCODER provides functions to configure the Framework's detection of crank position, to
           allow task scheduling and to provide the application software with information like engine speed.
    
           See \ref encoderattributes for further summary detail on the attributes and operation of the encoder
*/
#ifndef __RESOURCE_ENCODER_H
#define __RESOURCE_ENCODER_H

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

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

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

/*! The Crank Encoder refers to the pattern fitted to the system's crank shaft. This would be the only supported
    target in a 2-stroke appliction. A 4-stroke system may also have a Cam encoder like those described by the
    \ref E_CamEncoder enumeration */

/* Name: E_CrankEncoder ClassID:ENUMDEC EnumDflt:"Unknown Crank Encoder" */
typedef enum
{
/*! 60 tooth encoder pattern that is suitable for use with VR type and digital type encoders. Each missing
    tooth pair describes a synchronisation point. Engine position can be determined after two missing teeth
    have been observed. Two standard teeth must preceed the missing tooth before that tooth will be detected. */
    ENC_60_MINUS_6     = 0, /* EnumTxt:"60 minus 6" */
/*! 24 tooth encoder pattern that is only suitable for use with digital type encoders. The pattern uses pulse
    width to determine synchronisation. Each 6 teeth describe a unique pattern that allows synchrnoisation to
    occur at the 6th tooth in each pattern. */
    ENC_GM24XE         = 1, /* EnumTxt:"24 GM24Xe" */
/*! A 4-stroke pattern with 4 teeth. The pattern does not allow complete engine synchronisation by itself. Each
    tooth represents an engine TDC. */
    ENC_4X             = 2, /* EnumTxt:"4 TDC Teeth" */
/*! A 4-stroke pattern with 3 teeth. The pattern does not allow complete engine synchronisation by itself. Each
    tooth represents an engine TDC. */
    ENC_3X             = 3, /* EnumTxt:"3 TDC Teeth" */
/*! 60 tooth encoder pattern that is suitable for use with VR type and digital type encoders. The double missing
    tooth pair describes the synchronisation point. Synchronisation is achieved each time this double missing
    tooth is observed. The double missing tooth will not be detected unless two standard teeth are observed prior
    to the missing tooth region occurring */
    ENC_58X            = 4, /* EnumTxt:"58X: 60T, Missing 2" */
/*! 36 tooth encoder pattern that is suitable for use with VR type and digital type encoders. The single missing
    tooth describes the synchronisation point. Synchronisation is achieved each time this missing tooth is
    observed. The missing tooth will not be detected unless two standard teeth are observed prior to the missing
    tooth occurring */
    ENC_36_MINUS_1     = 5, /* EnumTxt:"36 minus 1" */
/*! 24 tooth encoder pattern that is suitable for use with VR type and digital type encoders. The double missing
    tooth pair describes the synchronisation point. Synchronisation is achieved each time this double missing
    tooth is observed. The double missing tooth will not be detected unless two standard teeth are observed prior
    to the missing tooth region occurring */
    ENC_24_MINUS_2     = 6, /* EnumTxt:"24 minus 2" */
/*! A 30 tooth pattern with the same characteristics as the \ref ENC_60_MINUS_6 encoder pattern except that it
    has 5 missing teeth.
    <IMG src="30Minus5.wmf" alt="30 Tooth With 5 Missing Figure" align="middle" border=0> */
    ENC_30_MINUS_5     = 7, /* EnumTxt:"30 minus 5" */
/*! A 60 tooth proprietary Hyundai encoder pattern */
    ENC_60_HYUNDAI     = 8, /* EnumTxt:"60 Hyundai" */
/*! A 24 tooth pattern with one of those teeth advanced to allow for synchronisation detection. Pattern suitable
    for use with a VR or digital type encoder.
    <IMG src="24With1Shifted.wmf" alt="24 Tooth With 1 Shifted Figure" align="middle" border=0> */
    ENC_24_SHIFTED_1   = 9, /* EnumTxt:"24 with 1 shifted" */

/*! 32 tooth encoder pattern that is suitable for use with VR type and digital type encoders. The two missing
    teeth describes the synchronisation point. Synchronisation is achieved each time thses missing teeth are
    observed. The missing teeth will not be detected unless two standard teeth are observed prior to the missing
    tooth occurring */
    ENC_32_MINUS_2   = 10, /* EnumTxt:"32 minus 2" */

/*! A 36 tooth encoder that does not have a synchronisation tooth. A single tooth cam provides the synchronisation */
    ENC_36_CAMSYNC   = 11, /* EnumTxt:"36 sync on cam" */

/*! A 8 pulse pattern that uses a narrow/wide pulse to distinguish it from the other 50% dutycycle pulses */
    ENC_8X_PW_SYNC   = 12, /* EnumTxt:"8 Pulse Width Sync" */
/*! 24 tooth encoder pattern that is suitable for use with VR type and digital type encoders. The single missing
    tooth describes the synchronisation point. Synchronisation is achieved each time this missing tooth is
    observed. The missing tooth will not be detected unless two standard teeth are observed prior to the missing
    tooth region occurring */
    ENC_24_MINUS_1   = 13, /* EnumTxt:"24 minus 1" */

/*! One Tooth pattern implements a single strobe per engine revolution. Such a pattern is susceptable to pulse
    scheduling errors on large accelerations. The Framework will issue encoder errors when such strong transients
    are detected. */
    ENC_1X           = 14, /* EnumTxt:"1 Tooth" */

/*! 34 tooth encoder pattern that is suitable for use with VR type and digital type encoders. The two missing
    teeth describes the synchronisation point. Synchronisation is achieved each time thses missing teeth are
    observed. The missing teeth will not be detected unless two standard teeth are observed prior to the missing
    tooth occurring */
    ENC_34_MINUS_2   = 15, /* EnumTxt:"34 minus 2" */

/*! 12 tooth encoder pattern that is suitable for use with VR type and digital type encoders. The single missing
    tooth describes the synchronisation point. Synchronisation is achieved each time this missing tooth is
    observed. The missing tooth will not be detected unless two standard teeth are observed prior to the missing
    tooth occurring */
    ENC_12_MINUS_1   = 16, /* EnumTxt:"12 minus 1" */

/*! 36 tooth pattern with that is suitable for use with VR type and digital type encoders. The additional tooth
    provides the synchronisation point, but is not used for scheduling */ 
    ENC_36_PLUS_1    = 17, /* EnumTxt:"36 plus 1" */

/*! A 360Degree 4-stroke pattern with 6 teeth. Sychronisation is via a CAM pulse that occurs ever 360 Deg. */
    ENC_6X_360       = 18, /* EnumTxt:"6 TDC Teeth - 360Deg Encoder" */

/*! A 4-stroke pattern with 12 teeth. Sychronisation is via a CAM pulse that occurs ever 720 Deg. */
    ENC_12X          = 19, /* EnumTxt:"12 Equal Teeth per Rev" */

/*! 4-stroke pattern with 6 teeth. Sychronisation is via a CAM pulse every 720 Deg. */
    ENC_6X           = 20, /* EnumTxt:"6 TDC Teeth - 360Deg Encoder" */

/*! 4-stroke pattern with 6 teeth. Crank Sychronisation is via a CAM pulse that occurs ever 360 Deg. */
    ENC_6X_CAM2X     = 21, /* EnumTxt:"6X Teeth - CrankSync via CAM input - SetPhase capable" */

/*! 4-stroke pattern 36-6 teeth. (3x (10Teeth 2 Missing)) NissanZ. Crank Sychronisation is via HalfMoon Compatible CAM */
    ENC_36_MINUS_6   = 22, /* EnumTxt:"NissanZ 36-6 Sync Via CAM" */

/*! 12 tooth pattern with that is suitable for use with VR type and digital type encoders. The additional tooth
    provides the synchronisation point, but is not used for scheduling */ 
    ENC_12_PLUS_1    = 23, /* EnumTxt:"12 plus 1" */

/*! 6 tooth pattern with that is suitable for use with VR type and digital type encoders. The additional tooth
    provides the synchronisation point, but is not used for scheduling */ 
    ENC_6_PLUS_1     = 24, /* EnumTxt:"6 plus 1" */

/*! 20 tooth pattern arranged as 5 groups of 4 teeth with 2 missing.  Ie. 5*(2Teeth, 2Miss)
    Halfmoon compatible CAM provides synchronisation */ 
    ENC_20_MINUS_10  = 25, /* EnumTxt:"5 Groups of 4 minus 2" */ /* Search for ENC_4S_20M10 in code */

/*! 2 tooth pattern equally spaced per rev. 4X per cycle.  Halfmoon compatible CAM provides synchronisation */ 
    ENC_2X           = 26, /* EnumTxt:"2 Teeth per Rev" */
/*! 36 tooth encoder pattern that is suitable for use with VR type and digital type encoders. The double missing
    tooth describes the synchronisation point. Synchronisation is achieved each time the missing tooth pair are
    observed. The missing teeth will not be detected unless two standard teeth are observed prior to the missing
    tooth pair occurring */
    ENC_36_MINUS_2   = 27, /* EnumTxt:"36 minus 2" */

/*! 36 tooth encoder pattern that is suitable for use with VR type and digital type encoders. Has 2 sets of double missing
    teeth per revolution. Utilizes a cam to provide synchronization */
    ENC_2N18M2       = 28, /* EnumTxt:"36 as 2x 18 minus 2" */

/*! 60 tooth encoder pattern that is suitable for use with VR type and digital type encoders. The missing tooth
    region describes the synchronisation point. Synchronisation is achieved each time sufficient missing teeth are
    observed. The missing teeth will not be detected unless two standard teeth are observed prior to the missing
    tooth region occurring */
    ENC_60_MINUS_4   = 29, /* EnumTxt:"60 minus 4" */
    NUM_CRANK_ENCODERS,
} E_CrankEncoder;

/*! The Cam Encoder refers to the pattern fitted to the system's cam shaft. Some systems support only this target
    while others support this in conjunction with the crank encoder described by \ref E_CrankEncoder */

/* Name: E_CamEncoder ClassID:ENUMDEC EnumDflt:"Unknown Cam Encoder" */
typedef enum
{
/*! Selected when a cam encoder is not defined */
    CAM_UNUSED          = 0, /* EnumTxt:"No Cam Encoder" */
/*! Half moon cam encoder. The lobe describes 360 degCA */
    CAM_HALFMOON        = 1, /* EnumTxt:"Halfmoon" */
/*! Proprietary hyundai cam encoder pattern */
    CAM_HYUNDAI         = 2, /* EnumTxt:"Hyundai 7 Tooth" */
/*! A single tooth cam that provides cycle synchronisation each time it is observed */
    CAM_1X              = 3, /* EnumTxt:"Single Tooth" */
/*! Halfmoon cam encoder used in a variable cam phaser arrangement */
    CAM_HALFMOON_VCAM   = 4, /* EnumTxt:"Halfmoon variable cam" */
/*! A variable cam phaser pattern that is constructed from X teeth. Half the teeth are narrow and the other
    half are wide. Narrow teeth represent one half of the engine cycle and wide teeth represent the other
    half of the cycle. The width of the cam pulse observed just prior to observing a synchronisation point on
    a crank encoder (like a pair of missing teeth) will communicate the engine halfcycle information to the
    crank encoder process. */
    CAM_X_PW_VCAM       = 5, /* EnumTxt:"X PW sync variable cam" */
/*! Similar to halfmoon, but with short pulse inversion during each half. ----_----____-____ */ 
    CAM_DURAMAX         = 6, /* EnumTxt:"Duramax CAM" */

    CAM_HCAM4T          = 7, /* EnumTxt:"Hyundai 4 Tooth CAM with one wide" */

    CAM_NISSANZ         = 8, /* EnumTxt:"NissanZ CAM - Output is Halfmoon Compatible" */

    CAM_COYOTE          = 9, /* EnumTxt:"Coyote CAM - Output is ToothCam Compatible" */

    CAM_T6M2P2_VCAM    = 10, /* EnumTxt:"6 Teeth Minus 2 Plus 2 (NissanZ) Variable CAM - Output is Halfmoon Compatible" */

    CAM_1XP1_EVO9      = 11, /* EnumTxt:"Single Tooth, Plus 1 (EVO9) CAM - Output is Halfmoon Compatible" */

    CAM_KOHKI          = 12, /* EnumTxt:"24 teeth. 4T, 2M, 2T, 4M, 1T, 5M, 3T, 3M" */

    CAM_WINSYNC_VCAM_3X = 13, /* EnumTxt:"3 Teeth VCam, looks for sync by detecting presence or absence of edge within crank tooth window" */

    CAM_WINSYNC_VCAM_4M1 = 14, /* EnumTxt:"4 Minus 1 Teeth VCam, looks for sync by detecting presence or absence of edge within crank tooth window" */

	CAM_PLUS1            = 15, /* EnumTxt:"Any +1 Style cam combined with CRANK that has at least 4* number of normal CAM teeth" */
    NUM_CAM_ENCODERS
} E_CamEncoder;

/*! The signal interface refers to the type of sensor(s) fitted to the system. */

/* Name: E_EncoderSignalInterface ClassID:ENUMDEC EnumDflt:"Illegal Configuration" */
typedef enum
{
/*! Digital Crank, Digital CAM or Unused */
    CNK_DG_CAM_DG      = 0, /* EnumTxt:"Digital Crank, Digital CAM or Unused" */
/*! VR Crank, Digital CAM or Unused */
    CNK_VR_CAM_DG      = 1, /* EnumTxt:"VR Crank, Digital CAM or Unused" */
/*! Digital Crank, VR CAM */
    CNK_DG_CAM_VR      = 2, /* EnumTxt:"Digital Crank, VR CAM" */
/*! VR Crank, VR CAM. Not all Woodward modules support this capability */
    CNK_VR_CAM_VR      = 3  /* EnumTxt:"VR Crank, VR CAM" */
} E_EncoderSignalInterface;

/*! The possible encoder errors that are reported through the application supplied error notification callback function */

/* Name: E_EncoderError ClassID:ENUMDEC EnumDflt:"Unknown encoder error" */
typedef enum
{
/*! Describes an encoder synchronisation error. This occurs when the internal tooth number that is incremented
    each time a tooth is detected and initialised when position is first found does not match the absolute tooth
    number that is calculated when a pattern sychronisation point is detected.
    
    In a dual redundant encoder system this fault refers to a synchronisation fault that is detected on the
    master */
    ENC_SYNC_FLT       = 0, /* EnumTxt:"Encoder Sync error on master" */

/*! The encoder pattern has been observed as rotating in reverse. This fault applies to the master channel when
    more than one primary source is available, such as in a dual redundant system. */
    ENC_REV_ROT_FLT    = 1, /* EnumTxt:"Reverse rotation on master" */

/*! The primary encoder source is not detecting encoder teeth when it is known that is should be. Possible to detect
    when either a CAM encoder exists (as it can be used to confirm whether engine speed is non-zero) or a dual redundant
    encoder is in use. When this fault is issued in a dual redundant encoder system it infers that the master channel
    has failed. */
    ENC_NO_EDGES_FLT   = 2, /* EnumTxt:"Primary Master Encoder loss" */
/*! The cam signal being observed is such that is can't be trusted */
    ENC_NO_CAM_FLT     = 3, /* EnumTxt:"Cam fault such that cam can't be trusted" */
/*! Cam encoder error. */
    ENC_CAM_FLT        = 4, /* EnumTxt:"Cam fault" */

/*! Only available in a dual redundant encoder system. This error is issued when a synchronisation fault, as
    detailed by \ref ENC_SYNC_FLT is detected on the slave encoder channel */
    ENC_SYNC_FLT_SLAVE = 5, /* EnumTxt:"Encoder Sync error on Slave" */

/*! Only available in a dual redundant encoder system. This error is issued when the primary encoder source of
    the slave channel is indicating reverse rotation */
    ENC_REV_ROT_SLAVE = 6,  /* EnumTxt:"Reverse rotation on Slave" */
/*! Only available in a dual redundant encoder system. This error is issued when no encoder edges are observed
    on the slave encoder */
    ENC_NO_EDGES_SLAVE = 7, /*EnumTxt:"Primary Slave Encoder Loss" */
} E_EncoderError;

/*! \brief  The status of the encoder.

    Events are sent each time there is a state change and fill a FIFO so that status events can be processed
    in the order that they are issued. The following state machine describes how the status changes:

    <IMG src="EncoderStatusFig.wmf" alt="Encoder Status Figure" align="middle" border=0>
*/

/* Name: E_EncoderStatus ClassID:ENUMDEC EnumDflt:"Unknown State" */
typedef enum
{
    NOT_CREATED             = 0, /* Keep this entry free to catch Zero Speed Entry from init */
/*! Zero speed */
    ZERO_SPEED              = 1, /* EnumTxt:"No Encoder Activity" */
/*! Waiting for encoder synchronisation */
    POSN_UNKNOWN            = 2, /* EnumTxt:"Encoder Edges without sync" */

/*! Encoder synchronised, waiting for cam synchronisation. Won't leave this state if there is no cam encoder. */
    ENC_SYNC_CAM_UNKNOWN    = 3, /* EnumTxt:"Encoder Sync, CAM unknown or does not exist" */

/*! Encoder synchronised, Cam synchronised */
    ENC_SYNC_CAM_SYNC       = 4, /* EnumTxt:"Encoder and CAM Sync" */

/*! A dual redundant encoder is in use. Only the master half of the redundant system is synchronised and operating.
    The slave half of the system may have failed or is yet to synchronise. Only the Odd injector and EST resources
    will operate reliably in this condition. The slave (even) resources should be disabled while this state is TRUE.
    The state of the cam (if one exists) is unknown */
    ENC_SYNC_MASTER_ONLY    = 5, /* EnumTxt:"Master Sync Only (Odd INJs/ESTs)" */

/*! A dual redundant encoder is in use. Only the slave half of the redundant system is synchronised and operating.
    The master half of the system may have failed or is yet to synchronise. Only the even injector and EST resources
    will operate reliably in this condition. The master (odd) resources should be disabled while this state is TRUE.
    The state of the cam (if one exists) is unknown */
    ENC_SYNC_SLAVE_ONLY     = 6, /* EnumTxt:"Slave Sync Only (Even INJs/ESTs)" */

/*! When a dual redundant encoder is in use this state implies that the primary encoder source of both the
    master and the slave channel have achieved synchronisation (without cam synchronisation). */
    ENC_SYNC_DUAL           = 7, /* EnumTxt:"Dual Sync" */

/*! A dual redundant encoder is in use and both halves (master and slave) have achieved synchronisation */
} E_EncoderStatus;

/*! The condition of the encoder. Disabling the encoder will force encoder activity to stop. Commonly this
    attribute is used to switch between Pseudo Encoder and standard Encoder operation. */
typedef enum 
{ 
    ENCODER_DISABLED = RES_DISABLED,         /*!< Allows no encoder activity */
    ENCODER_ENABLE_EXTERNAL = RES_ENABLED,   /*!< Encoder activity allowed. Uses the CPS sensors */
    ENCODER_ENABLED_INTERNAL                 /*!< Encoder activity allowed. External encoder signals ignored
                                                  and the activity is simulated */
} E_EncoderCond;

/*! Encoder phase describes whether the encoder sub-system is in phase with the actual engine position. */

/* Name: E_EncoderPhaseState ClassID:ENUMDEC EnumDflt:"Unknown State" */
typedef enum
{
/*! The encoder sub-system is in phase with the engine */
    ENC_PHASE_0 = 0,    /* EnumTxt:"Phase 0" */
/*! The encoder sub-system is 360degCA out of phase with actual engine position */
    ENC_PHASE_1 = 1     /* EnumTxt:"Phase 1" */
} E_EncoderPhaseState;

/*! The allowed firing TDCs. Upto \ref MAX_NUM_TDCS_SUPPORTED TDCs can be supported by the framework */
/* Name: E_FireTDC ClassID:ENUMDEC EnumDflt:"Illegal TDC" */
typedef enum
{
    FIRE_TDC1               = 0,  /* EnumTxt:"TDC#1"  */
    FIRE_TDC2               = 1,  /* EnumTxt:"TDC#2"  */
    FIRE_TDC3               = 2,  /* EnumTxt:"TDC#3"  */
    FIRE_TDC4               = 3,  /* EnumTxt:"TDC#4"  */
    FIRE_TDC5               = 4,  /* EnumTxt:"TDC#5"  */
    FIRE_TDC6               = 5,  /* EnumTxt:"TDC#6"  */
    FIRE_TDC7               = 6,  /* EnumTxt:"TDC#7"  */
    FIRE_TDC8               = 7,  /* EnumTxt:"TDC#8"  */
    FIRE_TDC9               = 8,  /* EnumTxt:"TDC#9"  */
    FIRE_TDC10              = 9,  /* EnumTxt:"TDC#10" */
    FIRE_TDC11              = 10, /* EnumTxt:"TDC#11" */
    FIRE_TDC12              = 11, /* EnumTxt:"TDC#12" */
    FIRE_TDC13              = 12, /* EnumTxt:"TDC#13" */
    FIRE_TDC14              = 13, /* EnumTxt:"TDC#14" */
    FIRE_TDC15              = 14, /* EnumTxt:"TDC#15" */
    FIRE_TDC16              = 15, /* EnumTxt:"TDC#16" */

/*! The maximum number of TDCs that the framework supports. */
    MAX_NUM_TDCS_SUPPORTED  = 16
} E_FireTDC;

/*! \brief Enumeration describes the set of mask definitions that are used to identify the valid discrete
           output attributes in the S_EncoderResourceAttributes and S_EncoderCreateResourceAttributes data
           structures.

    Each mask definition applies to a particular member of one of the data structures.
    \code
    ...
    S_EncoderResourceAttributes EncAttribObj;

    EncAttribObj.uValidAttributesMask = USE_ENC_CONDITION | USE_ENC_TDC_OFFSET;
    EncAttribObj.eResourceCondition = RES_ENABLED;
    // Offset is x16 deg
    EncAttribObj.s2TDCOffset = 30*16;
    // The remainder of the data structure can be left undefined since the uValidAttributesMask
    //   indicates that the members are not valid
    ... \endcode */
typedef enum
{
    USE_ENC_CONDITION = 0x01,           /*!< Selects S_EncoderResourceAttributes::eResourceCond */
    USE_ENC_TEETH_AFTER_CAM = 0x01,    /*!< Selects S_EncoderCreateResourceAttributes::uTeethAfterCam */
    USE_ENC_TDC_OFFSET = 0x02,          /*!< Selects S_EncoderResourceAttributes::s2TDCOffset */
    USE_ENC_PSEUDO_RPM = 0x04,          /*!< Selects S_EncoderResourceAttributes::u2PseudoRPM */
    USE_ENC_PHASE = 0x08,               /*!< Selects S_EncoderResourceAttributes::ePhaseState */
    USE_ENC_REPORT = 0x10,              /*!< Selects S_EncoderCreateResourceAttributes::pfReportCback */
    USE_ENC_DIAG_REPORT = 0x20,         /*!< Selects S_EncoderCreateResourceAttributes::pfDiagCback */
    USE_ENC_TDC_EVENTS = 0x40,          /*!< Selects S_EncoderCreateResourceAttributes::ps2TDCOfsArr */
    USE_ENC_DYNAMIC_ON_CREATE = 0x80,   /*!< Selects S_EncoderCreateResourceAttributes::DynamicObj */
    USE_ENC_CRANK_VR_THRESH = 0x100,    /*!< Selects S_EncoderCreateResourceAttributes::eCrankThreshMode */
    USE_ENC_CAM_VR_THRESH = 0x200,      /*!< Selects S_EncoderCreateResourceAttributes::eCamThreshMode */
    USE_ENC_CAM_SYNC_POL = 0x400,       /*!< Selects S_EncoderCreateResourceAttributes::eCamSyncPolarity */
    USE_ENC_IGNORE_DELAY = 0x800,       /*!< Selects S_EncoderResourceAttributes::u2IgnoreDelay_ms */
    USE_ENC_CRANK_PULLUP_STRENGTH = 0x1000, /*!< Select S_EncoderCreateResourceAttributes::eCrankPullUp */
    USE_ENC_CAM_PULLUP_STRENGTH = 0x2000,   /*!< Select S_EncoderCreateResourceAttributes::eCamPullUp */
    USE_ENC_PRIMARY_ON_CAM = 0x4000,    /*!< Infers that the chosen crank encoder should use the Cam input */

/*! When this mask is applied to S_EncoderCreateResourceAttributes::uValidAttributesMask it implies that the
    pattern defined by S_EncoderCreateResourceAttributes::eCrankDefn is also used on the cam input to form a
    redundant system. The value of the S_EncoderCreateResourceAttributes::eCamDefn attribute is ignored
    if this setting has been selected. */
    USE_ENC_REDUNDANT_CRANK = 0x8000,
    /* Same value as above because the two attributes are applied mutually exclusively */
    USE_ENC_SLAVE_TDC_OFFSET = 0x8000,  /*!< Selects S_EncoderResourceAttributes::s2SlaveTDCOffset */

    USE_ENC_RPMVECTOR_REPORT     = 0x00010000,  /*!< Selects S_EncoderCreateResourceAttributes::pfRPMVector_ReportCback */
    USE_ENC_RPMVECTOR_RATE       = 0x00020000,  /*!< Selects S_EncoderCreateResourceAttributes::u1RPMVector_Rate (Default = 1 Every Tooth) */
    USE_ENC_RPMVECTOR_NUMVEC     = 0x00040000,  /*!< Selects S_EncoderCreateResourceAttributes::u1RPMVector_NumVec (Default = 2 Double Buffer)*/
    USE_ENC_RPMVECTOR_CONDITION  = 0x00080000,  /*!< Selects S_EncoderResourceAttributes::eRPMVectorCond (Default = RES_DISABLED) */

/* IF THIS TYPE EXCEEDS 0x80000000 THEN ALTER THE TYPE OF THE EncoderAttributesMask_U ACCORDINGLY */

} E_EncoderAttributesMask;

/*! Unsigned integer type of sufficient size to hold the attribute masks for an encoder described by \ref E_EncoderAttributesMask */
typedef uint4 EncoderAttributesMask_U;

/*! \brief Structure that describes the attributes of an encoder that are dynamic. These attributes can be
           altered as conditions change.

    Attributes are applied using with the SetResourceAttributesBEHAVIOUR_ENCODER() function. Not all the 
    available attributes need to be set by a single call. Each attribute has a mask associated with it.
    Logic-OR this mask into the \ref S_EncoderResourceAttributes::uValidAttributesMask member to enable an
    attribute. */
typedef struct
{
/*! Logic-OR the attributes [\ref USE_ENC_CONDITION, \ref USE_ENC_TDC_OFFSET, \ref USE_ENC_PHASE and \ref USE_ENC_PSEUDO_RPM ]
    that are valid for this this instance of the data structure.

    \code
    ...
    S_EncoderResourceAttributes EncAttribObj;

    EncAttribObj.uValidAttributesMask = USE_ENC_CONDITION | USE_ENC_TDC_OFFSET;
    EncAttribObj.eResourceCondition = RES_ENABLED;
    EncAttribObj.s2TDCOffset = 30*16;
    SetResourceAttributesBEHAVIOUR_ENCODER(RES_ENCODER, &EncAttribObj);  \endcode */
    EncoderAttributesMask_U uValidAttributesMask;
/*! The condition of the encoder. Disabling the encoder will force encoder activity to stop. Commonly this
    attribute is used to switch between Pseudo Encoder and standard Encoder operation. Select this attribute
    with the \ref USE_ENC_CONDITION bit mask. */
    E_EncoderCond eResourceCond;
/*! Encoder TDC offset in x16 degrees crank angle before firing TDC#1. A value of 16 = 1 degBfTDC#1. Select this
    attribute with the \ref USE_ENC_TDC_OFFSET bit mask. */
    sint2 s2TDCOffset;
/*! The RPM value to be applied to the pseudo encoder. Use \ref USE_ENC_PSEUDO_RPM to select this attribute. */
    uint2 u2PseudoRPM;
/*! The encoder phase attribute describes whether the underlying pulse generation system is in or out of
    phase with the actual engine. Camless 4-stroke crank encoder patterns do not allow, by themself, a means to
    determine what half-cycle an engine is operating in. When teeth are detected through rotation the underlying
    encoder sub-system makes a guess. The guess is either correct or off by 360degCA. Other systems, outside the
    encoder sub-system, can sometimes be used to determine whether the encoder sub-system has guessed correctly.
    Set this attribute to the alternate phase when the guess is incorrect. Thus set it to \ref ENC_PHASE_1 if the
    encoder sub-system's guess was found to be incorrect and \ref ENC_PHASE_0 was reported. Use the
    \ref USE_ENC_PHASE mask to select this attribute. */
    E_EncoderPhaseState ePhaseState;
/*! Defines how long the encoder system should delay attempting to synchronize once some encoder activity has
    been observed. Select with the \ref USE_ENC_IGNORE_DELAY create attribute. Defaults to zero (no impact)
    when not selected */
    uint2 u2IgnoreDelay_ms;
/*! The Encoder TDC offset in x16 degrees crank angle before firing TDC#1 for the slave input. A value of
    16 = 1 degBfTDC#1. The slave encoder uses the CAM input as a feed for a redundant encoder. Select this
    attribute with the \ref USE_ENC_SLAVE_TDC_OFFSET bit mask. This attribute serves no purpose if the encoder
    was not created with the \ref USE_ENC_REDUNDANT_CRANK setting. */
    sint2 s2SlaveTDCOffset;

/*! When the \ref RPMVector function is enabled by setting up \ref USE_ENC_RPMVECTOR_REPORT during create, 
    Vector capture can be enabled and disabled dynamically. Select this dynamic attribute
    with the \ref USE_ENC_RPMVECTOR_CONDITION bit mask. */
    E_ResourceCond eRPMVectorCond;

} S_EncoderResourceAttributes;

typedef S_EncoderResourceAttributes const* S_EncoderResourceAttributesPtr;

/*! \brief Prototype for an encoder report notification that is executed (when enabled) upon each change of
           encoder status.
    
 The \c in_uAppDataToSendOnNotify parameter is the S_EncoderCreateResourceAttributes::uReportCbackUserData data
 that was supplied by the application when this notification event was setup. The notification event is setup
 as part of the encoder's creation. See CreateResourceBEHAVIOUR_ENCODER(). */
typedef void (*EncoderReportCbackFuncPtrType)(E_EncoderStatus, NativePtrSizedInt_U in_uAppDataToSendOnNotify);

/*! \brief Prototype for an encoder diagnostic report notification that is executed (when enabled) upon each
           detection of an encoder error.
    
 The \c in_uAppDataToSendOnNotify parameter is the S_EncoderCreateResourceAttributes::uDiagCbackUserData data
 that was supplied by the application when this notification event was setup. The notification event is setup
 as part of the encoder's creation. See CreateResourceBEHAVIOUR_ENCODER(). */
typedef void (*EncoderDiagCbackFuncPtrType)(E_EncoderError, NativePtrSizedInt_U in_uAppDataToSendOnNotify);

/*! \brief Prototype for an encoder \ref RPMVector report notification.  This is executed (If RPMVector is created) 
           upon each fill of an vector (One Engine Cycle of RPM samples).
    
 The notification event is setup as part of the encoder's creation. See \ref CreateResourceBEHAVIOUR_ENCODER. 
 
 This is an \ref ANGLE_EVENT_CB priority event.  It will occur every cycle if enabled.
 Supplied data is one \ref RPMVector.  Each vector contains one  cycle of RPM measurements.  
 When processing is complete, you must call \ref RetireRPMVectorBEHAVIOUR_ENCODER with the vector number in
 order to free the Vector memory for further use.  \b in_uNumElements indicates the number of 2 byte RPM measurements
 in the array pointed to by \b in_pRPMArr.  <br>
 The value of \b in_uNumElements = \b u1RPMVector_NumVec * (\b NumTeethPerCycle / \b u1RPMVector_Rate)<br>
 If a vector is not available when required, the system will Log an OS error \ref OSERR_RPMVECTOR_OVERRUN. */
typedef void (*EncoderRPMVectorCbackFuncPtrType)(const NativeVar_U in_uVectorNum, const NativeVar_U in_uNumElements, const uint2* in_pRPMArr);

/*! Synchronisation polarity. Describes which edge of a digital signal represents the synchronous edge of the
    tooth. This edge describes the tooth event. The edge is relative to the signal as it enters the module.
    Any inversion that occurs within the module is automatically compensated for by the framework. It has no
    meaning for a variable reluctance type sensor */
/* Name: E_EncoderSyncPol ClassID:ENUMDEC EnumDflt:"Unknown Polarity" */
typedef enum
{
/*! Rising edge of the signal is the synchronous edge */
    ENC_SYNC_RISE_EDGE = 0, /* EnumTxt:"Rise Edge" */
/*! Falling edge of the signal is the synchronous edge */
    ENC_SYNC_FALL_EDGE = 1  /* EnumTxt:"Fall Edge" */
} E_EncoderSyncPol;

/*! \brief Structure describes the attributes of the encoder behaviour that is to be assigned to the \c RES_ENCODER
    module resource during creation.
    
 Use CreateResourceBEHAVIOUR_ENCODER() to create an encoder. The data structure has some attributes that are optional
 or support defaults. An attribute mask S_EncoderCreateResourceAttributes::uValidAttributesMask is used to identify
 these attributes by logic-ORing those attributes into the mask. */
typedef struct
{
/*! Logic-OR the attributes [\ref USE_ENC_DIAG_REPORT, \ref USE_ENC_REPORT, \ref USE_ENC_TDC_EVENTS,
    \ref USE_ENC_DYNAMIC_ON_CREATE, \ref USE_ENC_CRANK_PULLUP_STRENGTH, \ref USE_ENC_CAM_PULLUP_STRENGTH,
    \ref USE_ENC_REDUNDANT_CRANK ]
    that are valid for this this instance of the data structure. Those values

    \code
    ...
    S_EncoderCreateResourceAttributes EncCreateAttribObj;

    EncCreateAttribObj.uValidAttributesMask = USE_ENC_DIAG_REPORT | USE_ENC_DYNAMIC_ON_CREATE;
    EncCreateAttribObj.pfDiagCback = MyEncoderDiagnosticFunction;
    EncCreateAttribObj.uDiagCbackUserData = MY_DATA;
    EncCreateAttribObj.DynamicObj.uValidAttributesMask = USE_ENC_CONDITION | USE_ENC_TDC_OFFSET; 
    EncCreateAttribObj.DynamicObj.eResourceCondition = RES_ENABLED;
    EncCreateAttribObj.DynamicObj.s2TDCOffset = 30*16;
    CreateResourceBEHAVIOUR_ENCODER(RES_ENCODER, &EncCreateAttribObj);  \endcode */
    EncoderAttributesMask_U uValidAttributesMask;
/*! Encoder status report notification function. This function executes each time the status of the encoder
    changes. The framework will not issue reports if this value is set to \c NULL. Use the \ref USE_ENC_REPORT
    bit mask if the application sets this member. It's value defaults to \c NULL if not set by the application*/
    EncoderReportCbackFuncPtrType pfReportCback;
/*! Encoder status report notification function. This function executes each time the framework detects an encoder
    error. The framework will not issue this report if this value is set to \c NULL. Use the \ref USE_ENC_DIAG_REPORT
    bit mask if the application sets this member. It's value defaults to \c NULL if not set by the application*/
    EncoderDiagCbackFuncPtrType pfDiagCback;
/*! This user data is supplied as a parameter when the S_EncoderCreateResourceAttributes::pReportCbackFunc
    function executes. It is sized to hold a pointer. */
    NativePtrSizedInt_U uReportCbackUserData;
/*! This user data is supplied as a parameter when the S_EncoderCreateResourceAttributes::pDiagCbackFunc
    function executes. It is sized to hold a pointer. */
    NativePtrSizedInt_U uDiagCbackUserData;
/*! The Crank Encoder refers to the pattern fitted to the system's crank shaft. This would be the only supported
    target in a 2-stroke appliction. A 4-stroke system may also have a Cam encoder like those described by the
    \ref E_CamEncoder enumeration. Also see \ref encoderpattern */
    E_CrankEncoder eCrankDefn;
/*! The cam encoder pattern assigned to this encoder behaviour. Also see \ref encoderpattern */
    E_CamEncoder eCamDefn;
/*! The type of signals generating the crank and cam encoders patterns */
    E_EncoderSignalInterface eSignalInterface;
/*! The Synchronous edge of the crank encoder. Describes which edge of a digital signal represents the synchronous
    edge of the tooth. This edge describes the tooth event. The edge is relative to the signal as it enters the
    module. Any inversion that occurs within the module is automatically compensated for by the framework. It has no
    meaning for a variable reluctance type sensor. */
    E_EncoderSyncPol eSyncPolarity;
/*! Boolean that is set to \c TRUE if this encoder pattern describes a 4-stroke */
    bool1 b1Is4Stroke;
/*! Boolean that is set to \c TRUE if the Crank Pattern is driven/uses the Cam shaft. Such a pattern would only
    complete a single revolution in 720degCA. */
    bool1 b1Is720degCAPattern;
/*! The number of firing TDCs in this application. Also defines the number of elements in the array pointed
    to by S_EncoderCreateResourceAttributes::ps2TDCOfsArr */
    uint1 u1NumTDCs;
/*! Array describing the offset of each firing TDC relative to TDC#1 in units of 0.0625 degAfTDC#1.

    The framework will not support TDC events like \ref FGND_TDC_EVENT, even if enabled within the scheduler, if this
    value is set to \c NULL. Execution band width is saved if TDC events are not required. Use the \ref USE_ENC_TDC_EVENTS
    bit mask if the application sets this member. It's value defaults to \c NULL if not set by the application.
    
    Ensure that S_EncoderCreateResourceAttributes::eNumTDCs is set to describe the number of TDCs described by this array. */
    sint2 const* ps2TDCOfsArr;
/*! Dynamic attributes to initialise the encoder with. These can be subsequently changed with a call to
    SetResourceAttributesBEHAVIOUR_ENCODER(). Use the \ref USE_ENC_DYNAMIC_ON_CREATE bit mask if the application
    wants to initialise some of the runtime attributes. */
    S_EncoderResourceAttributes DynamicObj;

/*! Defines whether the crank encoder VR interface is to employ hardware adaptive thresholds or fixed thresholds.
    This attribute is selected with the \ref USE_ENC_CRANK_VR_THRESH and defaults to \ref THRESH_FIXED_HW when not
    selected. This attribute is ignored for digital crank encoders and by those modules whose hardware does not
    offer runtime configurable adaptive thresholds */
    E_DetectionThreshMode eCrankThreshMode;

/*! Defines whether the cam encoder VR interface is to employ hardware adaptive thresholds or fixed thresholds.
    This attribute is selected with the \ref USE_ENC_CAM_VR_THRESH and defaults to \ref THRESH_FIXED_HW when not
    selected. This attribute is ignored for digital crank encoders and by those modules whose hardware does not
    offer runtime configurable adaptive thresholds */
    E_DetectionThreshMode eCamThreshMode;
/*! The synchronous edge of the cam encoder. The attribute describes which edge of a digital signal represents the
    synchronous edge of the tooth and hence the tooth event. The edge is relative to the signal as it enters the
    module. Any inversion that occurs within the module is automatically compensated for by the framework. It has
    no meaning for a variable reluctance type sensor. This attribute is a don't care unless the cam sensor provides
    synchronisation information to the crank encoder that may be edge sensitive.
    
    Select this attribute using the \ref USE_ENC_CAM_SYNC_POL mask. \ref ENC_SYNC_FALL_EDGE is assumed if this attribute
    is left undefined. */
    E_EncoderSyncPol eCamSyncPolarity;

/*! Defines the strength of the software selectable pull-up on the crank encoder input. Select this attribute
    with \ref USE_ENC_CRANK_PULLUP_STRENGTH mask. \ref PULLUP_R_WEAK is assumed if this attribute is left undefined
    and is ignored by those systems that are not able to set the strength of the pull-up */
    E_EncoderPullUp eCrankPullUp;

/*! Defines the strength of the software selectable pull-up on the cam encoder input. Select this attribute
    with \ref USE_ENC_CAM_PULLUP_STRENGTH mask. \ref PULLUP_R_WEAK is assumed if this attribute is left undefined
    and is ignored by those systems that are not able to set the strength of the pull-up */
    E_EncoderPullUp eCamPullUp;

/*! Defines the number of teeth that would need to be observed prior to the synchronisation point on the primary
    encoder to guarentee that a cam edge would have been observed if the half cycle was such that the cam was due.
    For example, this attribute would have the value of 5 if there were 4 primary encoder teeth between the synchronous
    cam edge and the next missing tooth that was to be observed. That is by observing 5 teeth the system can know that
    the cam would have been observed if it had been present. This attribute is selected using the
    \ref USE_ENC_TEETH_AFTER_CAM bit mask. When not selected this value defaults to the number of teeth in one
    revolution. This attribute is ignored when a cam is not present */
    uint1 uTeethAfterCam;

/*! Encoder \ref RPMVector report notification function. This function is executed each time one cycle worth of data
    becomes available. \c NULL is not a valid value and the system will fail create.  
    Set this create attribute using \ref USE_ENC_RPMVECTOR_REPORT */
    EncoderRPMVectorCbackFuncPtrType pfRPMVector_ReportCback;

/*! Defines how many \ref RPMVector cycles of data will be buffered.  Default = 2.
    It is set using the \ref USE_ENC_RPMVECTOR_NUMVEC create atribute. <br> 
    0 = Illegal  <br>
    1 = Single buffered, each 2nd cycle can be captured. <br>
    2 = Double buffered, Process one cycle whilst capturing the next <br>
    n = n buffered, capture n cycles and process. <br>
        
    Each vector consumes \ref u1RPMVector_NumVec * ((2 * NumTeethPerCycle) / \ref u1RPMVector_Rate) bytes of RAM */
     
    uint1 u1RPMVector_NumVec;

/*! Defines how many teeth over which a \ref RPMVector RPM is calculated and stored. Default = 1 <br>
    0 = Illegal <br>
    1 = RPM is stored for every tooth <br>
    2 = RPM is calculated based on the average period of 2 teeth. <br>
    n = Reserved for future expansion <br> 
    Set using the \ref USE_ENC_RPMVECTOR_RATE create attribute. */
    uint1 u1RPMVector_Rate;

} S_EncoderCreateResourceAttributes;

typedef S_EncoderCreateResourceAttributes const* S_EncoderCreateResourceAttributesPtr;

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

/*----- PROTOTYPES ----------------------------------------------------------------------------------------*/
uint2 GetEncoderResourceInstantRPM(void);
uint2 GetEncoderResourceAverageRPM(void); 

uint4 GetEncoderRevPeriod(void);
E_EncoderPhaseState GetEncoderPhaseState(void);
sint2 GetEncoderEngAngle(void);

NativeError_S CreateResourceBEHAVIOUR_ENCODER(E_ModuleResource, S_EncoderCreateResourceAttributes const*);
NativeError_S DestroyResourceBEHAVIOUR_ENCODER(E_ModuleResource);
NativeError_S SetResourceAttributesBEHAVIOUR_ENCODER(E_ModuleResource, S_EncoderResourceAttributes const*);
NativeError_S RetireRPMVectorBEHAVIOUR_ENCODER(NativeVar_U in_uVectorNum);

#endif /* __RESOURCE_ENCODER_H */

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