#ifndef __canr_16x_h
#define __canr_16x_h
/**
* \file CANR_16X.H
*
* \author Axel Wolf, SCI Cupertino
* \author Dr. Jens Barrenscheen, HL MC PD, Munich
* \author Hubert Piontek, University of Ulm
*
* CAN Driver include file for the C166 family. $Id: CANR_16X.H,v 1.1 2003/07/15 11:38:59 hp Exp $
* This file contains the definitions for the CAN driver for the C166 family.
* 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.
*/
/**
* \mainpage CAN Driver library for the C166 family
*
* \section Introduction
*
* This library provides a more convienient API to the CAN controller
* of the C166 family of microcontrollers than the <i>Special Function Registers</i>
* (SFRs) themselves. The library is based on the Siemens/Infineon Application Note AP2922.
* It was extended and modified in a few ways to further enhance convienience and fully
* support the publisher/subscriber library developed at the University of Ulm.
*
* \section API
*
* The API consists of a total of 13 functions, and one typedef'd struct:
* -# init_can_16x()
* -# def_mo_16x()
* -# undef_mo_16x()
* -# ld_modata_16x()
* -# send_mo_16x()
* -# rd_modata_16x()
* -# rd_mo15_16x()
* -# check_mo_16x()
* -# check_mo15_16x()
* -# check_busoff_16x()
* -# set_global_mask()
* -# can_write()
* -# can_read()
* -# ::canmsg
*
* \section Usage
*
* \subsection Enabling the CAN module
*
* To use the CAN controller on the C166, together with this library, you must make sure
* that access to the on-chip CAN and XRAM is enabled with your compiler.
* Also check any startup-code that is involved, so that it enables the CAN module and don't
* forget to set the XPEN bit in the SYSCON register,
* as this also controls the CAN controller for newer versions of the C167CR (steppings ES-GA,
* GA, GA-T, GA-T 6, ES-JA and later; see also Infineon Errata Sheet for the C167CR, Release 1.2,
* June 18, 2001) and may not be documented in your version of the C167 manual.
*
* For a quick-start with the KEIL Compiler suite, make sure that in the "Options for Target XXX"
* dialog, you have the following settings:
*
* - Tab Target: set the Memory Model to HLarge, and check the Use On-Chip CAN+XRAM checkbox.
* If using a Phytec MM167 module, enter for External Memory locations #1 type ROM, start
* address 0x00000, size 0x40000, and for #2 type RAM, start address 0x40000, size 0x40000.
* - Tab Output: select Create Library and set the output filename to canlib.lib if you want
* to (re)create the library.
*
* If you want to use the (pre-compiled) CAN library with the KEIL suite, select "Add files to Group",
* and look for the library file (default is canlib.lib). Then look for CANR_16X.H and add that one
* too; it contains all the prototypes of the CAN library.
*
* In your application project, make sure, that you set the Target Options as described above. They must match
* for all libraries used, and the application project itself. For the application, you also
* must edit the assembly startup file, for me, it's called START167.A66, and was just magically there
* on the PC. If you need it, contact me.
* In that file, you need to change the following definitions:
* - _XPEN EQU 1 to enable the CAN module
* - $SET (BUSCON1 = 1)
* - \%DEFINE (ADDRESS1) (040000H)
* - \%DEFINE (RANGE1) (256K)
* - $SET (BUSCON4 = 1)
* - \%DEFINE (ADDRESS4) (100000H)
* - \%DEFINE (RANGE4) (4K)
*
* \subsection Initializing the CAN module
*
* To initialize the CAN module, call the init_can_16x() function. It will reset the CAN
* module, and configure it to your needs.
*
* Before sending or receiving any message through one of the 15 so-called <i>message objects</i>
* of the C166 CAN module, these message objects must be "defined" (configured). Use def_mo_16x()
* for that.
*
* Before sending a CAN message with payload, you need to load the payload into the corresponding
* message object. This can be done using ld_modata_16x().
*
* Sending the message is finally triggered by calling send_mo_16x().
*
* For reception of CAN messages, you can check a message object by calling check_mo_16x() (for message objects 1 through 14) or
* check_mo15_16x() (for message object 15). If the return value of these messages is "true", then
* a new message arrived and can be read using read_modata_16x() and rd_mo15_16x(), respectively.
*
* The function check_busoff_16x() can be used for some basic error checking and recovery in case
* of a <i>busoff</i> state.
*
* After initialization, the <i>global mask</i> for message objects 1 through 14 is set in a way
* that for a successful reception of a message, all identifier bits of the message must match the
* repective identifier bits of the message object. Message object 15, on the other hand, is
* configured to be able receive all messages, regardless of their identifier, unless they already
* could be matched to a properly configured message object 1..14. To change this behaviour for
* the message objects 1..14, use set_global_mask().
*
* If you are done using a configured message object and don't want to be bothered by it anymore,
* use undef_mo_16x() to disable it.
*
* Finally, can_write() and can_read() give you some nice wrappers for some of the above functions.
* As one of their parameters, they take a pointer to a ::canmsg structure, holding a complete
* can message. can_write() always uses message object 1 to send CAN messages. can_read() can be
* used on any of the message objects 2..14. These functions are mainly meant to be used by
* the publisher/subscriber library, but can save some typing in other cases, too ;).
*
* \subsection Hints
*
* Do not access the CAN controller by any other means than this library. Better yet, do not use
* this library directly, but use the publisher/subscriber library. It's even more convienient to
* use, and you don't need to bother with a lot of low-level things.
*
* This library doesn't support the interrupt generation feature of the CAN controller for now.
* If you enable interrupts, you need to write your own interrupt service routines.
*
*/
#include "../sys/time.h"
/* ----------------------------------------- header: ----------------*/
/*********************************************************************
* Program name: "CANR_16X.H" *
* Task: Include file *
* belonging to Siemens ApNote AP2922 *
* "'C' CAN Driver Routines for the C166 family" *
* *
* Last modifications: Feb 24th 2003 *
* Version: 1.1 *
* Authors: Axel Wolf, SCI Cupertino *
* Dr. Jens Barrenscheen, HL MC PD, Munich *
* Hubert Piontek, Uni Ulm *
*********************************************************************/
/**
* \defgroup canregs CAN registers
*
* \brief definitions of CAN module control registers
*
* The C166 CAN module has 9 SFRs dedicated to it. They are
* used to control it, set the baudrate, set message masks, and other things.
*/
/*@{*/
/// The Command register
#define CR *(unsigned char*) 0xef00
/// The Status register
#define SR *(unsigned char*) 0xef01
/// The Interrupt register
#define IR *(unsigned char*) 0xef02
/// The baudrate register
#define BTR *(unsigned int *) 0xef04
/// The global short mask (11 Bit IDs)
#define GMS *(unsigned int *) 0xef06
/// The upper half of the global long mask (29 Bit IDs)
#define UGML *(unsigned int *) 0xef08
/// The lower half of the global long mask (29 Bit IDs)
#define LGML *(unsigned int *) 0xef0a
/// The upper half of the long mask for the last message
#define UMLM *(unsigned int *) 0xef0c
/// The lower half of the long mask for the last message
#define LMLM *(unsigned int *) 0xef0e
/*@}*/
/// The interrupt vector of the CAN module
#define CAN_INTERRUPT 0x40
/**
* \defgroup msgconsts Constants for defining Message Objects
*
* \brief these defines can be used to make the definition of message objects more readable
*/
/*@{*/
/// Use the extended frame format with 29 bit identifiers
#define USE_XTID 1
/// Use the standard frame format with 11 bit identifiers
#define USE_STID 0
/// Make the message object a transmit object
#define DIR_XMIT 1
/// Make the message object a receive object
#define DIR_RECV 0
/// Disable transmit interrupts
#define NO_TX_INT 0
/// Disable receive interrupts
#define NO_RX_INT 0
/// Enable transmit interrupts
#define TX_INT 1
/// Enable receive interrupts
#define RX_INT 1
/*@}*/
/**
* \defgroup canapi CAN controller API functions
*/
/*@{*/
/**
* \brief Initialize the CAN module
*/
void init_can_16x(unsigned int baud_rate, unsigned char eie,
unsigned char sie, unsigned char ie);
/**
* \brief Send a message object
*/
void send_mo_16x(unsigned char nr);
/**
* \brief Read data from a message object
*/
void rd_modata_16x(unsigned char nr, unsigned char *downl_data_ptr, unsigned long *mo_id_ptr, unsigned char *mo_dlc_ptr);
/**
* \brief Read data from the last message object
*/
void rd_mo15_16x(unsigned char *mo15_db_ptr,
unsigned long *mo15_id_ptr, unsigned char *mo15_dlc_ptr);
/**
* \brief Load data into a message object
*/
void ld_modata_16x(unsigned char nr, unsigned char *upl_data_ptr);
/**
* \brief Define a message object
*/
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);
/**
* \brief Clear a message object
*/
void undef_mo_16x( unsigned char nr );
/**
* \brief Check a message object for freshly received data
*/
unsigned char check_mo_16x(unsigned char nr);
/**
* \brief Check the last message object for new data
*/
unsigned char check_mo15_16x(void);
/**
* \brief Checks for a busoff state of the controller
*/
unsigned char check_busoff_16x(void);
/**
* \brief Sets the global reception mask.
*/
void set_global_mask( unsigned long mask );
/**
* \brief Structure for a can message
*
* This is mainly used by the publisher/subscriber library to transmit and receive
* messages.
*/
typedef struct {
unsigned long id; ///< message identifier
int rtr; ///< remote transmission request flag
int len; ///< data length (0..8)
unsigned char d[8]; ///< the data
time_t timestamp; ///< time when it was sent or received
} canmsg;
/**
* \brief Send a can message
*/
void can_write(canmsg *cm);
/**
* \brief Try reading a can message
*/
int can_read(int nr, canmsg *cm);
/*@}*/
#endif