#ifndef _CAN_H_
#define _CAN_H_

#include "compiler.h"

//#define CAN_RCVQUEUESIZE  16        /* Plaetze im RCV-Queue + 1 */
//#define CAN_XMTQUEUESIZE  8         /* Plaetze im XMT-Queue + 1 */

/**** Fehlerzustaende ****/
#define CAN_ERR_OK        0x00
#define CAN_ERR_ACTIVE    0x01  /* Sendepuffer im Controller ist voll */
#define CAN_ERR_OVERRUN   0x02  /* CAN-Controller wurde zu spaet gelesen */
#define CAN_ERR_WARNING   0x04  /* Busfehler: ein Errorcounter erreichte Limit 96 */
#define CAN_ERR_PASSIVE   0x08  /* Busfehler: ein Errorcounter erreichte Limit 128 */
#define CAN_ERR_BUSOFF    0x10  /* Busfehler: CAN_Controller ging 'Bus-Off' , 255 */
#define CAN_ERR_QRCVEMPTY 0x20  /* RcvQueue ist leergelesen */
#define CAN_ERR_QOVERRUN  0x40  /* RcvQueue wurde zu spaet gelesen */
#define CAN_ERR_QXMTFULL  0x80  /* Sendequeue ist voll */
#define CAN_ANY_ERROR	(CAN_ERR_ACTIVE|CAN_ERR_WARNING|CAN_ERR_PASSIVE|CAN_ERR_BUSOFF)
#define CAN_ErrorDummyID  0xFFFFFFFF /*ms ID fuer Messages, die keine empfangenen
									      Message, sondern Fehler transportieren */

#define CAN_BAUD_2M     0x1400u
#define CAN_BAUD_1M     0x1C00u
#define CAN_BAUD_500K   0x1C01u
#define CAN_BAUD_250K   0x1C03u
#define CAN_BAUD_125K   0x3A07u  
#define CAN_BAUD_100K   0x4D07u  
#define CAN_BAUD_50K    0x4D0fu  
#define CAN_BAUD_20K    0x4D27u 
#define CAN_BAUD_10K    0x7FFFu  
#define CAN_BAUD_83K3	0x1417u
#define CAN_BAUD_47K6	0x1429u
#define CAN_BAUD_95K2	0x1414u
#define CAN_BAUD_33K3	0x581Du
#define CAN_BAUD_800K   0x4d80u		// 75% SP, SJW=3

/* Defines for CANI_qentrytyp.FORMAT */ 
#define CAN_EXT			0x02     // for Extended CAN-ID
#define CAN_RTR			0x01	 //	for RTR

extern const unsigned int nBaudrate[13];
		
                                   
/* CAN-IRQ XP0 an/ausschalten */
#define CAN_IRQ_DISABLE    ICR00 = 7 //__DI()	
#define CAN_IRQ_ENABLE     ICR00 = 6 //__EI() 

#define CAN_SETBUSON	CSR_HALT=0;
#define CAN_SETBUSOFF	CSR_HALT=1;


/*** Eine im Queue gepufferte CAN-Message */
typedef struct {
        long int ID ;		// Identifier of CAN-Message, 0x000...0x7FF for Standard Identifier, 0x0000000-0x1FFFFFFF for Extended Identifier
        //u16_t   	 LEN_ERR ;	// Length of CAN-Message 0..8
        u8_t 	LEN;
        u8_t 	ERROR;
        u8_t    DATA[8] ;	// Data-Array
        u8_t    FORMAT;	// Bit 0: 0=DataFrame / 1=RTR-Frame
							// Bit 1: 0=11bit ID / 1=29 bit ID
        u8_t  	 INDEX;		
        //u8_t    reserve;
				
        } CANI_qentrytyp ;

/*** Zeiger auf eine im BUFSPACE liegenden Queue-Eintrag */
typedef  CANI_qentrytyp* CANI_qentryptr ;

// <TITLE  CAN_Init()>
// Description:
// Initializes the CAN-Bus with a given Baudrate
// Parameter:
// Baudrate: common Baudrates are defined in the header file
// Result:
// none
// Example:
// void main()
//
//{
// CANI_qentrytyp rcv_queue[8];
//
// CANI_qentrytyp xmt_queue[8]; 
//
// CAN_SetXMTQueue(xmt_queue, 8);
//
// CAN_SetRCVQueue(rcv_queue, 8);
//
// CAN_Init(CAN_BAUD_500k);
//
// CAN_RegisterMsg(0);
//
// CAN_BUFF_ID=0x100;
//
// CAN_BUFF_LEN=4;
//
// CAN_BUFF_DATA[0]=0x12;
//
// CAN_BUFF_DATA[1]=0x34;
//
// CAN_BUFF_DATA[2]=0x45;
//
// CAN_BUFF_DATA[3]=0x67;
//
// CAN_BUFF_FORMAT=0;
//
// CAN_Online();
//
// CAN_Write();	// Send a CAN-Message
//
// while(1)
//
// {
//
// if(CAN_Read()==CAN_ERR_OK)	// Wait for a CAN-Message with any ID
//
// {
//  
// CAN_BUFF_ID++;
//
// CAN_Write();	// echo Message 
//
// }
// ;
//

void CAN_Init(u16_t baudrate);


// <TITLE  CAN_Read>
// Description:
// Reads a received CAN-Message from the internal Receive-Queue.
// Parameter:
//  none
// Result:
// CAN_ERR_OK: Global Variables CAN_BUFF_ID, CAN_BUFF_LEN and CAN_BUFF_DATA[8] contain the received message
//
// CAN_ERR_QRCVEMPTY : no message 
u8_t CAN_Read(void);

// <TITLE  CAN_Write>
// Description:
// Writes a CAN-Message from the global Variables CAN_BUFF_ID, CAN_BUFF_LEN, CAN_BUFF_DATA[8], CAN_BUFF_FORMAT into Transmit-Queue
// Parameter:
//  none
// Result:
// CAN_ERR_OK, CAN_ERR_QXMTFULL 
int CAN_Write(void);

// <TITLE  CAN_RegisterMsg()>
// Description:
// Sets the Acceptance filter for the given Identifier
// Parameter:
//  CAN-ID
// Result:
// none
void CAN_RegisterMsg(u16_t id);

void SendStatus(void);


extern unsigned long CAN_BUFF_ID ;
extern u8_t CAN_BUFF_LEN ;
extern u8_t CAN_BUFF_DATA[8] ;
extern u8_t CAN_BUFF_FORMAT;
extern u8_t CAN_BUFF_INDEX;
extern u8_t CAN_BUFF_ERROR;
extern unsigned long int CAN_SendDirect;
extern unsigned long int CAN_SendIRQ;
extern unsigned long int CAN_Rcv;
extern unsigned long int CAN_RcvOverrun;
extern unsigned long int CAN_RcvQueueOverrun;
extern unsigned long int CAN_XmtQueueOverrun;
extern unsigned long int send_irq;
extern unsigned long int rec_irq;

extern int (*CAN_RxCallback)(CANI_qentryptr);
extern void(*CAN_TxCallback)(u8_t);


__interrupt void CAN_Receive();
__interrupt void CAN_Transmit();

// <TITLE  CANRxISRCallBack()>
// Description:
// The Function is called from CAN Receive Interrupt function for each received CAN-Message 
// to allow a faster response time for a received message. The definition of this function is 
// part of the User Application. If this function returns 0 the CAN-Message is put into the standard receive queue and can be read with CAN_Read().
// Parameter:
//  CAN-ID
// Result:
// 0: put Message into CAN Receive Queue
//
// 1: do not put Message into CAN Receive Queue

//int CANRxISRCallBack (CANI_qentrytyp* p);

// <TITLE  CANTxISRCallBack()>
// Description:
// The Function is called from CAN Transmit Complete Interrupt. 
// The Parameter idx contains the value of CAN_BUFF_INDEX of the last transmitted CAN-Message.

//void CANTxISRCallBack (u8_t idx);


// <TITLE  EnableExtendedID()>
// Description:
// Enables reception of CAN-Messages with extended Identifier. Per default reception of extended Identifier is disabled (0).
// Parameter:
//  number: number of reception slots that can receive extended identifiers.
//
// 0: only standard identifiers
//
// ...
//
// 7: only extended identifiers
// Result:
// none
void EnableExtendedID(int n);

// <TITLE  CAN_Status>
// Description:
// Returns Status of CAN-Controller
// Result:
// CAN_ERR_OK, CAN_ERR_BUSLIGHT, CAN_ERR_BUSHEAVY, CAN_ERR_BUSOFF
u8_t CAN_Status(void);

// <TITLE CAN_Offline>
// Description:
// Sets CAN-Controller offline. No Messages are received or transmitted anymore.
// Result:
// none
void CAN_Offline(void);

// <TITLE CAN_Online>
// Description:
// Sets CAN-Controller online. CAN-Controller can transmit and receive Messages.
// Result:
// none
void CAN_Online(void);

// <TITLE CAN_TxQueueReset>
// Description:
// Clears the CAN Transmit Queue.
void CAN_TxQueueReset(void) ;

// <TITLE CAN_RxQueueReset>
// Description:
// Clears the CAN Receive Queue.
void CAN_RxQueueReset(void) ;

// <TITLE CAN_SetXMTQueue>
// Description:
// Defines the CAN-Transmit-Queue. Queue is allocatec by the Application.
// Queue must have 2,4,8,16,32... entries
// Result: 
// 0=OK,1=Error
int CAN_SetXMTQueue(CANI_qentrytyp*, int entries);

// <TITLE CAN_SetRCVQueue>
// Description:
// Defines the CAN-Receive-Queue. Queue is allocatec by the Application
// Queue must have 2,4,8,16,32... entries
// Result:
// 0=OK, 1=Error
int CAN_SetRCVQueue(CANI_qentrytyp*, int entries);


// <TITLE CAN_SetListenOnly>
// Description:
// Sets the Listen Only Mode of the CAN-Controller
// mode=1:
// Transmit line of CAN-Controller is disabled.
// mode=0:
// normal Operation
void CAN_SetListenOnly(u8_t mode);

void CAN_TransmitFunc(void);
void CAN_ReceiveFunc(void);
#endif