/*******************************************************************
 *
 *  File: InnomatixCanAPI.h
 *
 *  Description: Simple CAN API for Innomatix Coprocessor applications 
 *
 *  Copyright 2015 Innomatix, LLC., All Rights Reserved
 *
 *  THIS DOCUMENT AND ITS CONTENTS ARE INTELLECTUAL PROPERTY
 *  OF INNOMATIX, LLC.  ANY DUPLICATION IN PART OR WHOLE
 *  WITHOUT PRIOR WRITTEN CONSENT IS STRICTLY PROHIBITED.
 *
 *******************************************************************/

#ifndef _INNOMATIX_CAN_API_H
#define _INNOMATIX_CAN_API_H

#ifdef __cplusplus
extern "C"
{
#endif
/*************************************************/

typedef enum
{
    canSuccess,				// 0
    canInvalidChannel,		// 1
    canInvalidSpeed,		// 2
    canInvalidIdentifier,	// 3
    canInvalidLength,		// 4
    canNoData,				// 5
    canNotInitialized,		// 6
    canGeneralError			// N
}CanResults_e;

typedef enum
{
    canChDAP3,	        // CAN 3 interface on the DAP connector or wiring harness
    canChDAP4	        // CAN 4 interface on the DAP connector or wiring harness
}CanChannel_e;
static const char *CanChannelName[] = {"CanChDAP3", "CanChDAP4"};


typedef enum
{
    canFormatStandard,     //	A standard, 11-bit identifier
    canFormatExtended,     //	An extended, 29-bit identifier
}CanFormat_e;

typedef struct
{
    int TxMessageCount;
    int RxMessageCount;

	// Increments when the internal message receive buffer is full and another message is received
    int OverflowCount;		
}StatisticsStruct_t, *StatisticsStruct_p;
  
  
typedef struct
{
    int Id;
    int DataLen;
	int Timestamp;
    CanFormat_e Format;
    unsigned char Data[ 8 ];
}CanMessage_t, *CanMessage_p;  


/**
 * These functions are the event handlers for incoming CAN messages.
 * They buffer the messages so they can be retrieved (by the application) later
 *
 * The mechanics of the API require that the application assign the event
 * handler rather than take care of it internally.
 * Example:
 *      CAN can0( p9, p10 );
 *      CAN can1( p30, p29 );
 *
 *      CanInit( &can0, &can1 );
 *      can0.attach( OnReceiveCanZero );
 *      Can1.attach( OnReceiveCanOne );
 *
 *      while( something )
 *          result = CanReceive( canChDAP3, ... )
 *
 ************************************************************************/
void OnReceiveCanZero( void );
void OnReceiveCanOne( void );


/**
 * This function initializes the API and the designated CAN interface.  
 * Return Values:
 * 	    Success - the API was initialized and the channel is ready to use.
 * 	    InvalidChannel - the specified channel is not supported
 * 	    InvalidSpeed - the specified network speed is not supported
 * 	    GeneralError - an unknown or unspecified error has occurred
 *************************************************************************/ 
CanResults_e CanInit( CAN *Can0, CAN *Can1 );

/**
 * This function opens the CAN channel at the specified baud rate and
 * begins receiving messages.
 * Return Values:
 * 	    Success - the API was initialized and the channel is ready to use.
 * 	    InvalidChannel - the specified channel is not supported
 * 	    InvalidSpeed - the specified network speed is not supported
 * 	    GeneralError - an unknown or unspecified error has occurred
 *************************************************************************/
CanResults_e CanOpen( CanChannel_e Channel, int Speed );


/**
 * This function disables the designated CAN interface. 
 *************************************************************************/ 
void CanClose( CanChannel_e Channel );


/**
 * Allow the client to send a message on the CAN bus.  
 * Return Values:
 * 	    Success - the message was sent
 * 	    InvalidChannel - the specified channel is not supported
 * 	    InvalidIdentifier - the provided message id is not a valid for the specified format 
 * 	    InvalidLength - more than 8 bytes of data were indicated
 *  	GeneralError - an unknown or unspecified error has occurred
 *************************************************************************/ 
CanResults_e CanSend( CanChannel_e Channel, unsigned long Id, CanFormat_e Format, const unsigned char *Data, char DLen );


/**
 * Allow the client to get a message from the CAN bus.  
 * Return Values:
 * 	    Success - a message was retrieved, the parameters hold the message values.
 * 	    InvalidChannel - the specified channel is not supported
 * 	    NoData - no message is available on the requested channel
 * 	    GeneralError - an unknown or unspecified error has occurred
 *************************************************************************/ 
CanResults_e CanReceive( CanChannel_e Channel, unsigned long *Timestamp, unsigned long *Id, CanFormat_e *Format, unsigned char *Data, char *DLen );


/**
 * Allow the client to retrieve statistics about the CAN interface.
 * 
 * Return Values:
 * 	    Success - statistics were retrieved
 * 	    InvalidChannel - the specified channel is not supported
 *  	GeneralError - an unknown or unspecified error has occurred
 *************************************************************************/ 
CanResults_e CanStatistics( CanChannel_e Channel, StatisticsStruct_t *Stats );


/**
 * Flush the Rx buffer - all messages are discarded, Rx and Overflow stats are cleared
 * 
 * Return Values:
 * 	    Success - statistics were retrieved
 * 	    InvalidChannel - the specified channel is not supported
 *  	GeneralError - an unknown or unspecified error has occurred
 *************************************************************************/ 
CanResults_e CanFlush( CanChannel_e Channel );


/*************************************************/
#ifdef __cplusplus
}
#endif

#endif /* _INNOMATIX_CAN_API_H */
