/**
 * \file DEFMO16X.C
 * 
 * \author Axel Wolf, SCI Cupertino
 * \author Dr. Jens Barrenscheen, HL MC PD, Munich
 * \author Hubert Piontek, University of Ulm
 *
 * Routine for defining a message object.
 *
 * Most of this is based von the Infineon/Siemens Application Note AP2922.
 * Some additions made at University of Ulm, February 2003.
 *
 * This CAN driver is mainly meant to be used by the publisher/subscriber
 * library developed at the University of Ulm, 1999-2003.
 */

/*********************************************************************
 * Program name:	"DEFMO16X.C"                                     *
 * Compiler used:	BSO/Tasking C166                                 *
 * Task:		Source File for procedure def_mo_16x                 *
 *			belonging to Siemens ApNote AP2922                       *
 *			"'C' CAN Driver Routines for the C166 family"            *
 *                                                                   * 
 * Last modifications:	April 28nd 1997                              *
 * Version:		1.0                                                  *
 * Authors:		Axel Wolf,  SCI Cupertino                            *
 *			Dr. Jens Barrenscheen, HL MC PD, Munich                  *
 *********************************************************************/

extern unsigned int  *id_ptr_16x[16];		///< pointer to message id's (UAReg)
extern unsigned char *db0_ptr_16x[16];		///< pointer to 'databyte 0's
extern unsigned int  *msgctrl_ptr_16x[16];	///< pointer to message control registers
extern unsigned char *msgconf_ptr_16x[16];	///< pointer to message configuration registers
extern unsigned char dir_bit_16x[16];		///< DIR bits MO 1...15
extern unsigned char xtd_bit_16x[16];		///< XTD bits MO 1...15
extern unsigned char dlc_16x[16];			///< data byte lengths MO 1...15

/**
 * If the message object is not to be used anymore, you can disable it using this
 * function.
 *
 * \param nr Number of the message object to disable.
 */
void undef_mo_16x( unsigned char nr )
{
	   *msgctrl_ptr_16x[nr]=0x5555;
}

/**
 * Use this function to define a message object, i.e. to configure it as extended frame or standard, assign
 * a transmission id, set the data length, enable or disable interrupts on transmit/receive, and of course, 
 * whether it's going to be sent or received.
 *
 * \param nr   Number of the message object to configure.
 * \param xtd  Flag whether to use extended frames (USE_XTID) or to use standard frames (USE_STID).
 * \param id   Identifier of the message.
 * \param dir  Flag for the direction of the message. Use DIR_XMIT for transmission objects and DIR_RECV for receiving objects
 * \param dlc  Length of the message. Only important for transmission objects.
 * \param txie Flag for enabling/disabling transmit interrupts (TX_INT/NO_TX_INT)
 * \param rxie Flag for enabling/disabling receive interrupts (RX_INT/NO_RX_INT)
 */
void def_mo_16x(unsigned char nr, unsigned char xtd, unsigned long id,
	unsigned char dir, unsigned char dlc, unsigned char txie,
	unsigned char rxie) 
{
	unsigned int dummy_int;
	unsigned int *dummy_idptr;

	if ((nr<16) && (nr)) {
		dummy_idptr=id_ptr_16x[nr] + 1;	/* set dummy ptr to LAR */

		if (xtd) { /* load Arbitration Registers with XTD ID: */
			/* load Upper Arb. Reg.: */
			id=id<<3;
			dummy_int=(unsigned int) (id>>16);
			*id_ptr_16x[nr]=(dummy_int<<8)+(dummy_int>>8); 

			/* load Lower Arb. Reg. */
			dummy_int=(unsigned int) id;
			*dummy_idptr=(dummy_int<<8)+(dummy_int>>8);
	   	} else {	/* load Arbitration Registers with STD ID: */
			/* load Upper Arb. Reg.: */
			dummy_int=(unsigned int) id;
			dummy_int=dummy_int<<5;
			*id_ptr_16x[nr]=(dummy_int<<8)+(dummy_int>>8);

			/* load Lower Arb. Reg.: */
			*dummy_idptr=0x0800;
	   	}

	   	/* prepare Message Control Register: */
	   	if (txie==1) 
			(txie=0x20); 
		else 
			(txie=0x10);
	   	if (rxie==1) 
			(rxie=0x08); 
		else 
			(rxie=0x04);
	   	if (dir==1) 
			dummy_int = (0x5981 | txie | rxie); /* CPUUPD set */
	   	else 
			dummy_int = (0x5581 | txie | rxie);	/* MSGLST reset */
	   	*msgctrl_ptr_16x[nr]=dummy_int;	/* load Mess. Contr. Reg. */

	   	/* prepare Message Configuration Register: */
	   	if (dlc>8) 
			dlc=8;
	   	dlc_16x[nr]=dlc;
	   	dir_bit_16x[nr]=dir;
	   	xtd_bit_16x[nr]=xtd;
	   	*msgconf_ptr_16x[nr] = (dlc<<4) + (dir<<3) + (xtd<<2);
	}
}

/* 
The function def_mo_16x defines a message object for the CAN 167 module
with a standard or extended identifier.
The function parameters are :
- Parameter nr defines the number of the message object (1..15)
- Parameter xtd defines if it is a 11-bit id (xtd=0) or 29-bit id (xtd=1)
- Parameter id defines the 11/29-Bit identifier of the message object
- Parameter dir (direction) defines if the message object is a receive object
  (dir=0) or a transmit object (dir=1)
- Parameter dlc (data length code) defines the data length
  of the message object (0 data bytes ... 8 data bytes)
- Parameter txie enables transmit interrupts of this MO
- Parameter rxie enables receive interrupts of this MO

Other Message control register loading ( t r a n s m i t  object):

         5                9               ?             ? 
    01       01       10      01      10    user   user     01
  RMTPND    TXRQ    CPUUPD  NEWDAT  MSGVAL  TXIE   RXIE   INTPND
   15 14    13 12    11 10    9 8    7 6     5 4    3 2    1 0

Other Message control register loading ( r e c e i v e  object):

         5                5               ?             ? 
    01       01       01      01      10    user   user     01
  RMTPND    TXRQ    MSGLST  NEWDAT  MSGVAL  TXIE   RXIE   INTPND
   15 14    13 12    11 10    9 8    7 6     5 4    3 2    1 0
*/
}