/**
 * \file RDM1516X.C
 * 
 * \author Axel Wolf, SCI Cupertino
 * \author Dr. Jens Barrenscheen, HL MC PD, Munich
 * \author Hubert Piontek, University of Ulm
 *
 * Routine for reading data from the last 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:	"RDM1516X.C"                                     *
 * Compiler used:	BSO/Tasking C166                                 *
 * Task:		Source File for procedure rd_mo15_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                  *
 *********************************************************************/

#include <REG167.H>         /* register definitions C167             */
#include <CANR_16X.H>       /* CAN control register definitions      */

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

/**
 * Use this function to read received data (and the message id) from the last message object (#15).
 *
 * \param *mo15_db_ptr Pointer to a buffer where the received data will be put.
 * \param *mo15_id_ptr Pointer to a long where the message id of the newly received message will be put.
 * \param *mo15_dlc_ptr Pointer to a character where the length of the received message will be put.
 *
 * \warning *mo15_db_ptr must point to an array large enough to hold all received data. Always make this
 *          large enough for the largest possible amount of payload, being 8 bytes.
 */
void rd_mo15_16x(unsigned char *mo15_db_ptr,
	unsigned long *mo15_id_ptr, unsigned char *mo15_dlc_ptr)
{

	unsigned char i;
	unsigned int dummy_int1, dummy_int2;
	unsigned char *dummy_dbptr;
	unsigned int *dummy_idptr;

	/* read actual data length code from momentarily accessed buffer: */
	*mo15_dlc_ptr=dlc_16x[15]=(*msgconf_ptr_16x[15]>>4);

	/* read actual identifier from momentarily accessed buffer */
	/* and convert it into a usable long: */
	dummy_idptr=id_ptr_16x[15];
	if (xtd_bit_16x[15]) {		/* calculate XTD ID: */
		dummy_int1=*dummy_idptr++;
	   	dummy_int2=*dummy_idptr;
	   	dummy_int1=(dummy_int1<<8)+(dummy_int1>>8);
	   	dummy_int2=(dummy_int2<<8)+(dummy_int2>>8);
	   	*mo15_id_ptr=((((unsigned long)(dummy_int1))<<16) + dummy_int2)>>3;
	} else {				/* calculate STD ID: */
	   	dummy_int1=*dummy_idptr;
	   	*mo15_id_ptr=(unsigned long) (((dummy_int1<<8)+(dummy_int1>>8))>>5);
	}

	/* get actual data bytes from momentarily accessed buffer: */
	dummy_dbptr=db0_ptr_16x[15];
	for (i=0;i<dlc_16x[15];i++) 
		*mo15_db_ptr++ = *dummy_dbptr++;

	/* clr NEWDAT,INTPND & RMTPND to release mom. acc. buffer: */
	*msgctrl_ptr_16x[15]=0xedfd;
}