/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
::  Module      :   TransCount Resource Framework API Header File
::  Copyright   :   (C)2006-2009 Woodward
::  Platform(s) :   MPC5xx
::  Limitations :   MPC5xx OS
::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*! \file Resource_TransCount.h
    \brief \ref BEHAVIOUR_TRANSCOUNT provides the capability to support \ref TransCountPattern and 
           \ref QuadratureDecoderPattern.
    
    It has four modes of operation: <br>
    - Transition counter (One Resource)
    - Quadrature decoder (Two Resources)
    - Transition counter with HW synchronisation (Two Resources)
    - Quadrature decoder with HW synchronisation (Three Resources)

    Usage of a combined resource Eg. RES_ENCODER implies two channels and therefore Quadrature decoder.
    
    The separate \ref BEHAVIOUR_TRANSCOUNT is used rather than \ref BEHAVIOUR_ENCODER
    because it was deemed that the Quadrature decoder was not required to drive angular function.
    Also the Quadrature decoder has special features Eg. Able to measure position in both directions
    that are not supported in \ref BEHAVIOUR_ENCODER.

    The user may request at any time current position and last edge period.

    See also \ref TransCountattributes
*/
#ifndef __RESOURCE_TRANSCOUNT_H
#define __RESOURCE_TRANSCOUNT_H

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

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

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

/*! \brief Function pointer type that defines the prototype of Modulus wrap notification function.

    The framework will call this function when the specified event is detected.
    
    The function can call GetResourceAttributesBEHAVIOUR_TRANSCOUNT to obtain current data.
    The function pointer can be set dynamically using SetResourceAttributesBEHAVIOUR_TRANSCOUNT and 
    when set to NULL disabled the callback.
    See \ref transcountcallbacks for an example. */
typedef void (*TransCountModulusNotifyFuncPtrType)(NativeVar_U);

/*! \brief Function pointer type that defines the prototype of Hardware Sync occurred notification function.

    The framework will call this function when the specified event is detected.

    The function pointer can be set dynamically using SetResourceAttributesBEHAVIOUR_TRANSCOUNT and 
    when set to NULL it disables the callback.
    See \ref transcountcallbacks for an example. */
typedef void (*TransCountSyncNotifyFuncPtrType)(NativeVar_U);

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

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

    TransCountAttribObj.uValidAttributesMask = USE_TRANSCOUNT_CONDITION;
    TransCountAttribObj.eResourceCondition = RES_ENABLED;
    ... \endcode */
typedef enum
{
    USE_TRANSCOUNT_CONDITION            = 0x0001, /*!< Selects S_TransCountResourceAttributes::eResourceCond. 
                                                     See \ref TransCountSetPosition.  */
    USE_TRANSCOUNT_POSITION             = 0x0002, /*!< \b Write: SetResourceAttributesBEHAVIOUR_TRANSCOUNT()<br>
                                                     Selects S_TransCountResourceAttributes::s2Edge <br>
                                                     Selects S_TransCountResourceAttributes::s4EdgeModulusCount <br>
                                                     \b Read: GetResourceAttributesBEHAVIOUR_TRANSCOUNT() <br>
                                                     Selects S_TransCountResourceAttributes::s2Edge <br>
                                                     Selects S_TransCountResourceAttributes::u4EdgePeriod <br>
                                                     Selects S_TransCountResourceAttributes::s4EdgeModulusCount <br>
                                                     Selects S_TransCountResourceAttributes::bSynchronised  
                                                     See \ref TransCountSetPosition,\ref TransCountGetPosition and
                                                     \ref TransCountTestSyncEx */

    USE_TRANSCOUNT_SECONDARY            = 0x0004, /*!< Selects S_TransCountCreateResourceAttributes::eSecondaryResource */
    USE_TRANSCOUNT_SYNCCHAN             = 0x0008, /*!< Selects S_TransCountCreateResourceAttributes::eSyncResource, <br>
                                                       Selects S_TransCountCreateResourceAttributes::eSyncEdge and <br>
                                                       Selects S_TransCountCreateResourceAttributes::eSyncType */
    USE_TRANSCOUNT_PRIM_PULLUP_STRENGTH = 0x0010, /*!< Select S_TransCountCreateResourceAttributes::ePrimPullUp */
    USE_TRANSCOUNT_SEC_PULLUP_STRENGTH  = 0x0020, /*!< Select S_TransCountCreateResourceAttributes::eSecPullUp */
    USE_TRANSCOUNT_SYNC_PULLUP_STRENGTH = 0x0040, /*!< Select S_TransCountCreateResourceAttributes::eSyncPullUp */

    USE_TRANSCOUNT_SYNC_POSITION        = 0x0080, /*!< Edge count value to apply on sync (write) <br>
                                                       Select S_TransCountResourceAttributes::s2Edge <br> 
                                                       Selects S_TransCountResourceAttributes::s4EdgeModulusCount <br> */

    USE_TRANSCOUNT_PERIOD_OPTION        = 0x0100, /*!< Select S_TransCountCreateResourceAttributes::ePeriodOptionType */
    USE_TRANSCOUNT_MODULUS              = 0x0200, /*!< Selects S_TransCountCreateResourceAttributes::s2EdgeModulus <br>
                                                       Selects S_TransCountCreateResourceAttributes::s4EdgeModulusCountModulus*/
    USE_TRANSCOUNT_MODULUS_NOTIFY       = 0x0400, /*!< Selects S_TransCountResourceAttributes::pfModulusNotify <br>
                                                       Selects S_TransCountResourceAttributes::uModulusNotifyData */
    USE_TRANSCOUNT_SYNC_CONDITION       = 0x0800, /*!< Selects S_TransCountResourceAttributes::eSyncResourceCond */

    USE_TRANSCOUNT_SYNC_NOTIFY          = 0x1000, /*!< Selects S_TransCountResourceAttributes::pfSyncNotify <br>
                                                       Selects S_TransCountResourceAttributes::uSyncNotifyData */

    USE_TRANSCOUNT_DYNAMIC_ON_CREATE    = 0x8000, /*!< Selects S_TransCountCreateResourceAttributes::DynamicObj */
/* IF THIS TYPE EXCEEDS 0x80 THEN ALTER THE TYPE OF THE TransCountAttributesMask_U ACCORDINGLY */

} E_TransCountAttributesMask;

/*! Specifies the sync behaviour. Selected by S_TransCountCreateResourceAttributes::eSyncType  */
typedef enum
{
    TRANSCOUNT_SYNC_ALWAYS   = 0,  /*!< Synchronise on edge of sync pulse always */
    TRANSCOUNT_SYNC_ONCE,          /*!< Synchronise only once on sync pulse */
} E_TransCountSyncType;

/*! \brief Specify on which edge of sync pulse does count reset occur. Selected by S_TransCountCreateResourceAttributes::eSyncEdge */
typedef enum
{
    TRANSCOUNT_SYNC_RISING   = 0,  /*!< Synchronise on Rising edge */
    TRANSCOUNT_SYNC_FALLING,       /*!< Synchronise on Falling edge */
} E_TransCountSyncEdge;

/*! \brief Specify between which edge(s) to measure period. Selected by S_TransCountCreateResourceAttributes::ePeriodOptionType */
typedef enum
{
    TRANSCOUNT_PERIOD_ALL_EDGES = 0,           /*!< Measure period between primary and secondary edges - Default */
    TRANSCOUNT_PERIOD_PRIMARY_EDGES = 1,       /*!< Measure period between primary edges */
    TRANSCOUNT_PERIOD_PRIMARY_RISING_EDGE = 3, /*!< Measure period between primary rising edges */
} E_TransCountPeriodOptionType;

/*! Unsigned integer type of sufficient size to hold the attribute masks for an encoder described by \ref E_TransCountAttributesMask */
typedef uint2 TransCountAttributesMask_U;

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

    Attributes are applied using with the SetResourceAttributesBEHAVIOUR_TRANSCOUNT() function. Not all the 
    available attributes need to be set by a single call. Each attribute has a mask associated with it.
    Some attributes may be read using GetResourceAttributesBEHAVIOUR_TRANSCOUNT()
    Logic-OR this mask into the \ref S_TransCountResourceAttributes::uValidAttributesMask member to enable an
    attribute. */
typedef struct
{
/*! Logic-OR the attributes Eg: \ref USE_TRANSCOUNT_CONDITION, \ref USE_TRANSCOUNT_POSITION, 
    that are valid for this this instance of the data structure.

    \code
    ...
    S_TransCountResourceAttributes EncAttribObj;

    EncAttribObj.uValidAttributesMask = USE_TRANSCOUNT_CONDITION | USE_TRANSCOUNT_POSITION;
    EncAttribObj.eResourceCondition = RES_ENABLED;
    EncAttribObj.s2Edge = 534;           // Edge Number
    EncAttribObj.s4EdgeModulusCount = 0; // EdgeModulus Rollovers counter

    SetResourceAttributesBEHAVIOUR_TRANSCOUNT(RES_ENCODER, &EncAttribObj);  
    \endcode */

    TransCountAttributesMask_U uValidAttributesMask;
/*! The condition of the TransCount. Disabling the encoder will force TransCount activity to stop. 
    Select this attribute with the \ref USE_TRANSCOUNT_CONDITION bit mask. */
    E_ResourceCond eResourceCond;

/*! The condition of the Sync Channel. Disabling the sync will stop automatic synchronisation
    and disable any notification. Select this attribute with the \ref USE_TRANSCOUNT_SYNC_CONDITION bit mask. */
    E_ResourceCond eSyncResourceCond;

/*! Indicates if HW synchronisation has occured, Read with GetResourceAttributesBEHAVIOUR_TRANSCOUNT() and 
    \ref USE_TRANSCOUNT_CONDITION bit mask. Returns FALSE if synchronisation not configured.  Note: if
    You re-enable the sync channel, this flag becomes FALSE until a sync edge occurs. */
    NativeBool bSynchronised;

/*! Current edge number.  Increments or decrements on each edge seen on primary or secondary channel, 
    depending on phase of inputs. Wraps at +- s2EdgeModulus (Default 32767). Read and write this
    attribute with the \ref USE_TRANSCOUNT_POSITION bit mask. */
    sint2 s2Edge;

/*! Stores last period between edges seen when using GetResourceAttributesBEHAVIOUR_TRANSCOUNT() and 
    \ref USE_TRANSCOUNT_POSITION bit mask. */
    uint4 u4EdgePeriod;

/*! Counts the number of times s2Edge has wrapped by s2EdgeModulus. Counts in both directions. Read
    and write with \ref USE_TRANSCOUNT_POSITION */
    sint4 s4EdgeModulusCount;

/*! Edge number to apply when sync occurs. Write this
    attribute with the \ref USE_TRANSCOUNT_SYNC_POSITION bit mask. */
    sint2 s2EdgeOnSync;

/*! Modulus count to apply when sync occurs. Write this 
    attribute with the \ref USE_TRANSCOUNT_SYNC_POSITION bit mask. */
    sint4 s4EdgeModulusCountOnSync;

/*! The notification function that is to be called by the framework when the requested event is observed. Use the
    \ref USE_TRANSCOUNT_MODULUS_NOTIFY mask to enable this attribute. This value defaults to NULL on creation. */
    TransCountModulusNotifyFuncPtrType pfModulusNotify;

/*! Modulus notification callback will return this supplied data field. Set using \ref USE_TRANSCOUNT_MODULUS_NOTIFY 
    on creation. */
    NativeVar_U uModulusNotifyData;

/*! The notification function that is to be called by the framework when the requested event is observed. Use the
    \ref USE_TRANSCOUNT_SYNC_NOTIFY mask to enable this attribute. This value defaults to NULL on creation. */
    TransCountSyncNotifyFuncPtrType pfSyncNotify;

/*! Sync notification callback will return this supplied data field. Set using \ref USE_TRANSCOUNT_SYNC_NOTIFY 
    on creation. */
    NativeVar_U uSyncNotifyData;

} S_TransCountResourceAttributes;

typedef S_TransCountResourceAttributes const* S_TransCountResourceAttributesPtr;

/*! \brief Structure describes the attributes of the TransCount behaviour that is to be assigned to the
           module resource during creation.
    
 Use CreateResourceBEHAVIOUR_TRANSCOUNT() to create an Transition Counter / Quadrature decoder. 
 The data structure has some attributes that are optional
 or support defaults. An attribute mask S_TransCountCreateResourceAttributes::uValidAttributesMask is used to identify
 these attributes by logic-ORing those attributes into the mask. */
typedef struct
{
/*! Logic-OR the attributes [\ref USE_TRANSCOUNT_DYNAMIC_ON_CREATE, ]
    that are valid for this this instance of the data structure. Those values

    \code
    ...
    S_TransCountCreateResourceAttributes QuadratureCreateInfo;

    QuadratureCreateInfo.uValidAttributesMask = USE_TRANSCOUNT_DYNAMIC_ON_CREATE;
    QuadratureCreateInfo.DynamicObj.uValidAttributesMask = USE_TRANSCOUNT_CONDITION;
    QuadratureCreateInfo.DynamicObj.eResourceCond = RES_ENABLED;

    // Create the Quadrature input 
    sError = CreateResourceBEHAVIOUR_TRANSCOUNT(RES_ENCODER, &QuadratureCreateInfo); 
    if (FAILED(sError))
    {
        g_u2CreateErrors++;
    }

    See \ref TransCountExamples for more.
    
    \endcode */

    TransCountAttributesMask_U uValidAttributesMask;

/*! Defines Resource that provides the Secondary Resource (When Primary and Secondary are separately defined, unlike RES_ENCODER) */
    E_ModuleResource eSecondaryResource;

/*! Defines Resource that provides the sync edge, that resets \ref S_TransCountResourceAttributes::s2Edge to specified value on edge occurance. */
    E_ModuleResource eSyncResource;

/*! Defines the strength of the software selectable pull-up on the primary input. Select this attribute
    with \ref USE_TRANSCOUNT_PRIM_PULLUP_STRENGTH mask. Pin \ref PULLUP_R_WEAK is assumed if undefined on 
    encoder input, PULLUP_R_NONE (Pull down) is assumed if on Switch input, 
    and is ignored by those systems that are not able to set the strength of the pull-up */
    E_EncoderPullUp ePrimPullUp;

/*! Defines the strength of the software selectable pull-up on the secondary input. Select this attribute
    with \ref USE_TRANSCOUNT_SEC_PULLUP_STRENGTH mask.  Pin \ref PULLUP_R_WEAK is assumed if undefined on 
    encoder input, PULLUP_R_NONE (Pull down) is assumed if on Switch input, 
    and is ignored by those systems that are not able to set the strength of the pull-up */
    E_EncoderPullUp eSecPullUp;

/*! Defines the strength of the software selectable pull-up on the sync input. Select this attribute
    with \ref USE_TRANSCOUNT_SYNC_PULLUP_STRENGTH mask.  Pin \ref PULLUP_R_WEAK is assumed if undefined on 
    encoder input, PULLUP_R_NONE (Pull down) is assumed if on Switch input, 
    and is ignored by those systems that are not able to set the strength of the pull-up */
    E_EncoderPullUp eSyncPullUp;

/*! Defines the type of synchronisation signal. Select this attribute
    with \ref USE_TRANSCOUNT_SYNCCHAN mask. */ 
    E_TransCountSyncType eSyncType;

/*! Defines which edge to synchronise on. Select this attribute
    with \ref USE_TRANSCOUNT_SYNCCHAN mask. */ 
    E_TransCountSyncEdge eSyncEdge;

/*! Defines when to read period. Select this attribute
    with \ref USE_TRANSCOUNT_PERIOD_OPTION mask. */ 
    E_TransCountPeriodOptionType ePeriodOptionType;

/*! Defines how s2Edge count will wrap.  The wrap is done +- This modulus value.  Eg Modulus = 4, 
    Counting forward 9 then counting back 15.  <br>
    \code
    | Count Forwards           | Count Backwards                            |
    | 1| 2| 3| 4| 5| 6| 7| 8| 9| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14|15|
    -------------------------------------------------------------------------
    | 0| 1| 2| 3| 4| 0| 1| 2| 3| 2| 1| 0|-1|-2|-3|-4| 0|-1|-2|-3|-4| 0|-1|-2| s2Edges
    |      0       |                  1             |      0       |   -1   | s4EdgeModulusCount

Note: AbsoluteEdgeNum = s2Edges + (s4EdgeModulusCount * s2EdgeModulus)
      So -3 + (1 * 5) = 2 + (0 * 5)
    \endcode 
    Set on create set with /ref USE_TRANSCOUNT_MODULUS */
    sint2 s2EdgeModulus;

/*! Defines Modulus wrap of the ModulusCounter.  When +- this value is reached, s4EdgeModulusCount is
    reset to zero. Eg When s4EdgeModulusCountModulus = 3, s4EdgeModulusCount will count 0,1,2,0,1,2...
    Set on create using /ref USE_TRANSCOUNT_MODULUS */
    sint4 s4EdgeModulusCountModulus;

/*! Dynamic attributes to initialise the encoder with. These can be subsequently changed with a call to
    SetResourceAttributesBEHAVIOUR_TRANSCOUNT(). Use the \ref USE_TRANSCOUNT_DYNAMIC_ON_CREATE bit mask 
    if the application wants to initialise some of the runtime attributes. */
    S_TransCountResourceAttributes DynamicObj;

} S_TransCountCreateResourceAttributes;

typedef S_TransCountCreateResourceAttributes const* S_TransCountCreateResourceAttributesPtr;

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

/*----- PROTOTYPES ----------------------------------------------------------------------------------------*/
NativeError_S CreateResourceBEHAVIOUR_TRANSCOUNT(E_ModuleResource, S_TransCountCreateResourceAttributes const*);
NativeError_S DestroyResourceBEHAVIOUR_TRANSCOUNT(E_ModuleResource);
NativeError_S SetResourceAttributesBEHAVIOUR_TRANSCOUNT(E_ModuleResource, S_TransCountResourceAttributes const*);
NativeError_S GetResourceAttributesBEHAVIOUR_TRANSCOUNT(E_ModuleResource, S_TransCountResourceAttributes *);

#endif /* __RESOURCE_TRANSCOUNT_H */

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