This library for Seeed Studio's CAN-BUS Shield has a similar API to mbed's LPC1768 CAN library making it easy to add CAN functionality to mbed systems that support Arduino type 'Shields. This Beta release of my CAN-BUS Library is largely working but lacks interrupt 'attach' functions.

Dependents:   Seeed_CAN_Hello_World ws-canrecv-1 CAN_SPI_modulo

Fork of SEEED_CAN by Sophie Dexter

Files at this revision

API Documentation at this revision

Comitter:
Just4pLeisure
Date:
Tue Nov 12 20:54:16 2013 +0000
Parent:
1:ad71faa09868
Commit message:
Updated 12-11-2013 - attach functions are now usable. Changes to allow the the library to be used with more mbeds (e.g. LPC1768). I have also added new functions/methods which give more information about errors and interrupts.

Changed in this revision

seeed_can.cpp Show annotated file Show diff for this revision Revisions of this file
seeed_can.h Show annotated file Show diff for this revision Revisions of this file
seeed_can_api.cpp Show annotated file Show diff for this revision Revisions of this file
seeed_can_api.h Show annotated file Show diff for this revision Revisions of this file
seeed_can_defs.h Show annotated file Show diff for this revision Revisions of this file
seeed_can_spi.cpp Show annotated file Show diff for this revision Revisions of this file
seeed_can_spi.h Show annotated file Show diff for this revision Revisions of this file
--- a/seeed_can.cpp	Wed Nov 06 20:16:11 2013 +0000
+++ b/seeed_can.cpp	Tue Nov 12 20:54:16 2013 +0000
@@ -20,21 +20,37 @@
  */
 SEEED_CAN::SEEED_CAN(PinName ncs, PinName irq, PinName mosi, PinName miso, PinName clk, int spiBitrate) :
     _spi(mosi, miso, clk),
-    _can(_spi, ncs, irq)
+    _can(_spi, ncs, irq),
+    _irqpin(irq)
 {
     // Make sure CS is high
     _can.ncs = 1;
     // Set up the spi interface
     _can.spi.format(8, 3);
     _can.spi.frequency(spiBitrate);
-    _can.irq.fall(this, &SEEED_CAN::call_irq);
+//    _can.irq.fall(this, &SEEED_CAN::call_irq);
+    _irqpin.fall(this, &SEEED_CAN::call_irq);
 }
 
 /** Open initialises the Seeed Studios CAN-BUS Shield.
  */
-int SEEED_CAN::open(int canBitrate)
+int SEEED_CAN::open(int canBitrate, Mode mode)
+{
+    return mcpInit(&_can, (uint32_t) canBitrate, (CANMode)mode);
+}
+
+/** Puts or removes the Seeed Studios CAN-BUS shield into or from silent monitoring mode
+ */
+void SEEED_CAN::monitor(bool silent)
 {
-    return mcpInit(&_can, (uint32_t) canBitrate);
+    mcpMonitor(&_can, silent);
+}
+
+/** Change the Seeed Studios CAN-BUS shield CAN operation mode
+ */
+int SEEED_CAN::mode(Mode mode)
+{
+    return mcpMode(&_can, (CANMode)mode);
 }
 
 /** Set the CAN bus frequency (Bit Rate)
@@ -42,7 +58,7 @@
 int SEEED_CAN::frequency(int canBitRate)
 {
 //    return mcpSetBitRate(&_can, (uint32_t) canBitRate);
-    return mcpInit(&_can, (uint32_t) canBitRate);
+    return mcpInit(&_can, (uint32_t) canBitRate, (CANMode)Normal);
 }
 
 /** Read a CAN bus message from the MCP2515 (if one has been received)
@@ -89,36 +105,49 @@
 
 /** Check if any type of error has been detected on the CAN bus
  */
-int SEEED_CAN::errors(void)
+int SEEED_CAN::errors(ErrorType type)
 {
-    return (mcpRead(&_can, MCP_EFLG) & MCP_EFLG_ERRORMASK) ? 1 : 0;
+    return mcpErrorType(&_can, (CANFlags)type);
 }
 
-/** Puts or removes the Seeed Studios CAN-BUS shield into or from silent monitoring mode
+/** Returns the contents of the MCP2515's Error Flag register
  */
-void SEEED_CAN::monitor(bool silent)
-{
-    mcpMonitor(&_can, silent);
-}
-
-/** Change the Seeed Studios CAN-BUS shield CAN operation mode
- */
-int SEEED_CAN::mode(Mode mode)
-{
-    return mcpMode(&_can, (CANMode)mode);
-}
+ unsigned char SEEED_CAN::errorFlags(void)
+ {
+    return mcpErrorFlags(&_can);
+ }
 
 /** Attach a function to call whenever a CAN frame received interrupt is generated.
  */
-void SEEED_CAN::attach(void (*fptr)(void), IrqType type)
+void SEEED_CAN::attach(void (*fptr)(void), IrqType event)
+{
+    if (fptr) {
+        _callback_irq.attach(fptr);
+        mcpSetInterrupts(&_can, (CANIrqs)event);
+//        _irq[(CanIrqType)type].attach(fptr);
+//        can_irq_set(&_can, (CanIrqType)type, 1);
+    } else {
+        mcpSetInterrupts(&_can, (CANIrqs)SEEED_CAN::None);
+//        can_irq_set(&_can, (CanIrqType)type, 0);
+    }
+}
+
+
+void SEEED_CAN::call_irq(void)
 {
-    _callback_irq.attach(fptr);
-    mcpWrite(&_can, MCP_CANINTE, MCP_RX0IF | MCP_RX1IF);                // RX buffers can generate a interrupt
-//    _can.irq.fall(fptr);
-    /*    if (fptr) {
-            _irq[(CanIrqType)type].attach(fptr);
-            can_irq_set(&_can, (CanIrqType)type, 1);
-        } else {
-            can_irq_set(&_can, (CanIrqType)type, 0);
-        }*/
+    _callback_irq.call();
 }
+
+/** Check if the specified interrupt event has occurred
+ */
+int SEEED_CAN::interrupts(IrqType type)
+{
+    return mcpInterruptType(&_can, (CANIrqs)type);
+}
+
+/** Returns the contents of the MCP2515's Interrupt Flag register
+ */
+ unsigned char SEEED_CAN::interruptFlags(void)
+ {
+    return mcpInterruptFlags(&_can);
+ }
--- a/seeed_can.h	Wed Nov 06 20:16:11 2013 +0000
+++ b/seeed_can.h	Tue Nov 12 20:54:16 2013 +0000
@@ -66,35 +66,78 @@
 public:
     /** Seeed Studios CAN-BUS Shield Constructor - Create a SEEED_CAN interface connected to the specified pins.
      *
-     * The Seeed Studio CAN-BUS shield is an Arduino compatible shield and connects to the FRDM-KL25Z SPI0 interface using pins PTD2 (mosi) PTD3 (miso) PTD1 (clk). The Active low chip select normally connects to the FRDM-KL25Z's PTD0 pin, but there is an option on the Seeed Studio CAN-BUS shield to connect to the PTD5 pin. The CAN-BUS shield uses the FRDM-KL25Z's PTD4 pin for its (active low) interrupt capability. The defaults allow you to plug the Seeed Studios' CAN-BUS Shield into a FRDM-KL25Z mbed and it to work without specifying any parameters.
+     *  The Seeed Studio CAN-BUS shield is an Arduino compatible shield and connects to the FRDM-KL25Z SPI0 interface using pins PTD2 (mosi) PTD3 (miso) PTD1 (clk). The Active low chip select normally connects to the FRDM-KL25Z's PTD0 pin, but there is an option on the Seeed Studio CAN-BUS shield to connect to the PTD5 pin. The CAN-BUS shield uses the FRDM-KL25Z's PTD4 pin for its (active low) interrupt capability. The defaults allow you to plug the Seeed Studios' CAN-BUS Shield into a FRDM-KL25Z mbed and it to work without specifying any parameters.
      *
-     * @param ncs Active low chip select (default SEEED_CAN_CS is FRDM-KL25Z PTD0 pin but if you change the link on the Seeed Studios CAN-BUS shield you should use a value of SEEED_CAN_IO9 or PTD5 instead).
-     * @param irq Active low interrupt pin (default SEEED_CAN_IRQ is FRDM-KL25Z PTD4 pin).
-     * @param mosi SPI Master Out, Slave In pin  (default SEEED_CAN_MOSI is FRDM-KL25Z PTD2 pin).
-     * @param miso SPI Master In, Slave Out pin  (default SEEED_CAN_MISO is FRDM-KL25Z PTD3 pin).
-     * @param clk SPI Clock pin (default SEEED_CAN_MISO is FRDM-KL25Z PTD1 pin).
-     * @param spiBitrate SPI Clock frequency (default: 1 MHz).
+     *  @param ncs Active low chip select, @b default: @p SEEED_CAN_CS is FRDM-KL25Z PTD0 pin (p9 on LPC1768).
+     *  @n If you change the link on the Seeed Studios CAN-BUS shield you should use a value of SEEED_CAN_IO9 or PTD5 instead.
+     *  @param irq Active low interrupt pin, @b default: @p SEEED_CAN_IRQ is FRDM-KL25Z PTD4 pin (p10 on LPC1768).
+     *  @param mosi SPI Master Out, Slave In pin, @b default: @p SEEED_CAN_MOSI is FRDM-KL25Z PTD2 pin (p11 on LPC1768).
+     *  @param miso SPI Master In, Slave Out pin, @b default: :p SEEED_CAN_MISO is FRDM-KL25Z PTD3 pin (p12 on LPC1768).
+     *  @param clk SPI Clock pin, @b default: @p SEEED_CAN_MISO is FRDM-KL25Z PTD1 pin (p13 on LPC1768).
+     *  @param spiBitrate SPI Clock frequency, @b default: @p 1000000 (1 MHz).
      */
+#if defined MKL25Z4_H_                                                  // defined in MKL25Z4.h
     SEEED_CAN(PinName ncs=SEEED_CAN_CS, PinName irq=SEEED_CAN_IRQ, PinName mosi=SEEED_CAN_MOSI, PinName miso=SEEED_CAN_MISO, PinName clk=SEEED_CAN_CLK, int spiBitrate=1000000);
+#elif defined __LPC17xx_H__                                             // defined in LPC17xx.h
+    SEEED_CAN(PinName ncs=p9, PinName irq=p10, PinName mosi=p11, PinName miso=p12, PinName clk=p13, int spiBitrate=1000000);
+#else                                                                   // No default constructor for other...
+    SEEED_CAN(PinName ncs, PinName irq, PinName mosi, PinName miso, PinName clk, int spiBitrate=1000000);
+#endif
 //    virtual ~SEEED_CAN(); // !!! Need a de-constructor for the interrrupt pin !!!
 
+    enum Mode {
+        Normal = 0,
+        Sleep,
+        Loopback,
+        Monitor,
+        Config,
+        Reset
+    };
+
     /** Open initialises the Seeed Studios CAN-BUS Shield.
      *
-     * @param canBitrate CAN Bus Clock frequency (default: 100 kHz).
+     *  @param canBitrate CAN Bus Clock frequency, @b default: @p 100000 (100 kHz).
+     *  @param mode The initial operation mode, @b default: @p Normal.
+     *  @n @p SEEED_CAN::Normal - Normal mode is the standard operating mode,
+     *  @n @p SEEED_CAN::Monitor - This mode can be used for bus monitor applications.
+     *  @n @p SEEED_CAN::Sleep - This mode can be used to minimize the current consumption,
+     *  @n @p SEEED_CAN::Loopback - This mode can be used in system development and testing.
+     *  @n @p SEEED_CAN::Config - Open with this mode to prevent unwanted messages being received while you configure Filters.
      *
      *  @returns
-     *    1 if successful,
-     *    0 otherwise
+     *     1 if successful,
+     *  @n 0 otherwise
+     */
+    int open(int canBitrate=100000, Mode mode = Normal);
+
+    /** Puts or removes the Seeed Studios CAN-BUS shield into or from silent monitoring mode.
+     *
+     *  @param silent boolean indicating whether to go into silent mode or not.
      */
-    int open(int canBitrate=100000);
+    void monitor(bool silent);
+
+    /** Change the Seeed Studios CAN-BUS shield CAN operation mode.
+     *
+     *  @param mode The new operation mode
+     *  @n @p SEEED_CAN::Normal - Normal mode is the standard operating mode,
+     *  @n @p SEEED_CAN::Monitor - This mode can be used for bus monitor applications.
+     *  @n @p SEEED_CAN::Sleep - This mode can be used to minimize the current consumption,
+     *  @n @p SEEED_CAN::Loopback - This mode can be used in system development and testing.
+     *  @n @p SEEED_CAN::Reset - Reset the MCP2515 device and stay in Configuration mode.
+     *
+     *  @returns
+     *     1 if mode change was successful
+     *  @n 0 if mode change failed or unsupported,
+     */
+    int mode(Mode mode);
 
     /** Set the CAN bus frequency (Bit Rate)
      *
      *  @param hz The bus frequency in Hertz
      *
      *  @returns
-     *    1 if successful,
-     *    0 otherwise
+     *     1 if successful,
+     *  @n 0 otherwise
      */
     int frequency(int canBitRate);
 
@@ -103,8 +146,8 @@
      *  @param msg A CANMessage to read to.
      *
      *  @returns
-     *    1 if any messages have arrived
-     *    0 if no message arrived,
+     *     1 if any messages have arrived
+     *  @n 0 if no message arrived,
      */
     int read(SEEED_CANMessage &msg);
 
@@ -113,8 +156,8 @@
      *  @param msg The CANMessage to write.
      *
      *  @returns
-     *    1 if write was successful
-     *    0 if write failed,
+     *     1 if write was successful
+     *  @n 0 if write failed,
      */
     int write(SEEED_CANMessage msg);
 
@@ -122,11 +165,11 @@
      *
      *  @param maskNum The number of the Acceptance Mask to configure (Acceptance Mask 0 is associated with Filters 0 and 1, Acceptance Mask 1 is associated with Filters 2 through 5).
      *  @param canId CAN Id Mask bits (Acceptance Filters are only compared against bits that are set to '1' in an Acceptance Mask (e.g. mask 0x07F0 and filter 0x03F0 would allow through messages with CAN Id's 0x03F0 through 0x03FF because the 4 LSBs of the CAN Id are not filtered).
-     *  @param format Describes if the Acceptance Mask is for a standard (CANStandard) or extended (CANExtended) CAN message frame format (default: CANStandard).
+     *  @param format Describes if the Acceptance Mask is for a standard (CANStandard) or extended (CANExtended) CAN message frame format, @b default: @p CANStandard.
      *
      *  @returns
-     *    1 if Acceptance Mask was set
-     *    0 if the Acceptance Mask could not be set
+     *     1 if Acceptance Mask was set
+     *  @n 0 if the Acceptance Mask could not be set
      */
     int mask(int maskNum, int canId, CANFormat format = CANStandard);
 
@@ -134,11 +177,11 @@
      *
      *  @param filterNum The number of the Acceptance Filter to configure (Acceptance Filters 0 and 1 are associated with Mask 0, Acceptance Filters 2 through 5 are associated with Mask 1).
      *  @param canId CAN Id Filter bits (Acceptance Filters are only compared against bits that are set to '1' in an Acceptance Mask (e.g. mask 0x07F0 and filter 0x03F0 would allow through messages with CAN Id's 0x03F0 through 0x03FF because the 4 LSBs of the CAN Id are not filtered).
-     *  @param format Describes if the Acceptance Filter is for a standard (CANStandard) or extended (CANExtended) CAN message frame format (default: CANStandard).
+     *  @param format Describes if the Acceptance Filter is for a standard (CANStandard) or extended (CANExtended) CAN message frame format, @b default: @p CANStandard.
      *
      *  @returns
-     *    1 if Acceptance Filter was set
-     *    0 if the Acceptance Filter could not be set
+     *     1 if Acceptance Filter was set
+     *  @n 0 if the Acceptance Filter could not be set
      */
     int filter(int filterNum, int canId, CANFormat format = CANStandard);
 
@@ -156,82 +199,164 @@
      */
     unsigned char tderror(void);
 
+    enum ErrorType {
+        AnyError = 0,
+        Errors,
+        Warnings,
+        Rx1Ovr,
+        Rx0Ovr,
+        TxBOff,
+        TxPasv,
+        RxPasv,
+        TxWarn,
+        RxWarn,
+        EWarn
+    };
+
     /** Check if any type of error has been detected on the CAN bus
      *
+     *  @param error Specify which type of error to report on, @b default: @p AnyError.
+     *  @n @p SEEED_CAN::AnyError - Any one or more of the following errors and warnings:
+     *  @n @p SEEED_CAN::Errors - Any one or more of the 5 errors:
+     *  @n @p SEEED_CAN::Rx1Ovr - Receive Buffer 1 Overflow Flag bit,
+     *  @n @p SEEED_CAN::Rx0Ovr - Receive Buffer 0 Overflow Flag bit,
+     *  @n @p SEEED_CAN::TxBOff - Bus-Off Error Flag bit,
+     *  @n @p SEEED_CAN::TxPasv - Transmit Error-Passive Flag bit,
+     *  @n @p SEEED_CAN::RxPasv - Receive Error-Passive Flag bit,
+     *  @n @p SEEED_CAN::Warnings - Any one or more of the 3 warnings:
+     *  @n @p SEEED_CAN::TxWarn - Transmit Error Warning Flag bit,
+     *  @n @p SEEED_CAN::RxWarn - Receive Error Warning Flag bit,
+     *  @n @p SEEED_CAN::EWarn - Error Warning Flag bit.
+     *
      *  @returns
-     *    1 if any type of error has been detected
-     *    0 if no errors
+     *     1 if specified type of error has been detected
+     *  @n 0 if no errors
      */
-    int errors(void);
-
-    /** Puts or removes the Seeed Studios CAN-BUS shield into or from silent monitoring mode
-     *
-     *  @param silent boolean indicating whether to go into silent mode or not
-     */
-    void monitor(bool silent);
+    int errors(ErrorType type = AnyError);
 
-    enum Mode {
-        Normal = 0,
-        Sleep,
-        Loopback,
-        Monitor,
-        Config,
-        Reset
-    };
-
-    /** Change the Seeed Studios CAN-BUS shield CAN operation mode
-     *
-     *  @param mode The new operation mode (SEED_CAN::Normal, SEED_CAN::Sleep, SEED_CAN::Loopback, SEED_CAN::Monitor, SEEED_CAN::Reset)
+    /** Returns the contents of the MCP2515's Error Flag register
      *
      *  @returns
-     *    1 if mode change was successful
-     *    0 if mode change failed or unsupported,
+     *     @b Bit_7 - RX1OVR: Receive Buffer 1 Overflow Flag bit - Set when a valid message is received for RXB1 and CANINTF.RX1IF = 1 - Must be reset by MCU,
+     *  @n @b Bit_6 - RX0OVR: Receive Buffer 1 Overflow Flag bit - Set when a valid message is received for RXB0 and CANINTF.RX0IF = 1 - Must be reset by MCU,
+     *  @n @b Bit_5 - TXBO: Bus-Off Error Flag bit - Bit set when TEC reaches 255 - Reset after a successful bus recovery sequence,
+     *  @n @b Bit_4 - TXEP: Transmit Error-Passive Flag bit - Set when TEC is >= 128 - Reset when TEC is less than 128,
+     *  @n @b Bit_3 - RXEP: Receive Error-Passive Flag bit - Set when REC is >= 128 - Reset when REC is less than 128,
+     *  @n @b Bit_2 - TXWAR: Transmit Error Warning Flag bit - Set when TEC is >= 96 - Reset when TEC is less than 96,
+     *  @n @b Bit_1 - RXWAR: Receive Error Warning Flag bit - Set when REC is >= 96 - Reset when REC is less than 96,
+     *  @n @b Bit_0 - EWARN: Error Warning Flag bit - Set when TEC or REC is >= 96 (TXWAR or RXWAR = 1) - Reset when both REC and TEC are < 96.
      */
-    int mode(Mode mode);
+    unsigned char errorFlags(void);
 
     enum IrqType {
-        RxIrq = 0,
-        TxIrq,
-        EwIrq,
-        DoIrq,
-        WuIrq,
-        EpIrq,
-        AlIrq,
-        BeIrq,
-        IdIrq
+        None = 0,
+        AnyIrq,
+        RxAny,
+        TxAny,
+        Rx0Fill,
+        Rx1Full,
+        Tx0Free,
+        Tx1Free,
+        Tx2Free,
+        Error,
+        Wake,
+        MsgError,
     };
 
     /** Attach a function to call whenever a CAN frame received interrupt is generated.
      *
-     *  @param fptr A pointer to a void function, or 0 to set as none
-     *  @param event Which CAN interrupt to attach the member function to (CAN::RxIrq for message received, CAN::TxIrq for transmitted or aborted, CAN::EwIrq for error warning, CAN::DoIrq for data overrun, CAN::WuIrq for wake-up, CAN::EpIrq for error passive, CAN::AlIrq for arbitration lost, CAN::BeIrq for bus error)
+     *  @param fptr A pointer to a void function, or 0 to set as none.
+     *  @param event Which CAN interrupt to attach the member function to, @b default: @p RxAny
+     *  @n @p SEEED_CAN::None - Disable all interrupt sources,
+     *  @n @p SEEED_CAN::AnyIrq - Enable all interrupt sources,
+     *  @n @p SEEED_CAN::RxAny - Any full RX buffer can generate an interrupt,
+     *  @n @p SEEED_CAN::TxAny - Any empty TX buffer can generate an interrupt,
+     *  @n @p SEEED_CAN::Rx0Full - Receive buffer 1 full,
+     *  @n @p SEEED_CAN::Rx1Full - Receive buffer 1 full,
+     *  @n @p SEEED_CAN::Tx0Free - Transmit buffer 2 empty,
+     *  @n @p SEEED_CAN::Tx1Free - Transmit buffer 2 empty,
+     *  @n @p SEEED_CAN::Tx2Free - Transmit buffer 2 empty,
+     *  @n @p SEEED_CAN::Error - Error (multiple sources in EFLG register),
+     *  @n @p SEEED_CAN::Wake - Wakeup,
+     *  @n @p SEEED_CAN::MsgError - Message Error,
      */
-    void attach(void (*fptr)(void), IrqType type=RxIrq);
+    void attach(void (*fptr)(void), IrqType event=RxAny);
 
     /** Attach a member function to call whenever a CAN frame received interrupt is generated.
      *
-     *  @param tptr pointer to the object to call the member function on
-     *  @param mptr pointer to the member function to be called
-     *  @param event Which CAN interrupt to attach the member function to (CAN::RxIrq for message received, TxIrq for transmitted or aborted, EwIrq for error warning, DoIrq for data overrun, WuIrq for wake-up, EpIrq for error passive, AlIrq for arbitration lost, BeIrq for bus error)
+     *  @param tptr pointer to the object to call the member function on.
+     *  @param mptr pointer to the member function to be called.
+     *  @param event Which CAN interrupt to attach the member function to, @b default: @p RxAny
+     *  @n @p SEEED_CAN::None - Disable all interrupt sources,
+     *  @n @p SEEED_CAN::AnyIrq - Enable all interrupt sources,
+     *  @n @p SEEED_CAN::RxAny - Any full RX buffer can generate an interrupt,
+     *  @n @p SEEED_CAN::TxAny - Any empty TX buffer can generate an interrupt,
+     *  @n @p SEEED_CAN::Rx0Full - Receive buffer 1 full,
+     *  @n @p SEEED_CAN::Rx1Full - Receive buffer 1 full,
+     *  @n @p SEEED_CAN::Tx0Free - Transmit buffer 2 empty,
+     *  @n @p SEEED_CAN::Tx1Free - Transmit buffer 2 empty,
+     *  @n @p SEEED_CAN::Tx2Free - Transmit buffer 2 empty,
+     *  @n @p SEEED_CAN::Error - Error (multiple sources in EFLG register),
+     *  @n @p SEEED_CAN::Wake - Wakeup,
+     *  @n @p SEEED_CAN::MsgError - Message Error,
      */
     template<typename T>
-    void attach(T* tptr, void (T::*mptr)(void), IrqType type=RxIrq) {
+    void attach(T* tptr, void (T::*mptr)(void), IrqType event=RxAny) {
         _callback_irq.attach(tptr, mptr);
-        mcpWrite(obj, MCP_CANINTE, MCP_RX0IF | MCP_RX1IF);                  // RX buffers can generate a interrupt
-//        _can.irq.fall(tptr, mptr);
-        /*        if((mptr != NULL) && (tptr != NULL)) {
-                    _irq[type].attach(tptr, mptr);
-                    can_irq_set(&_can, (CanIrqType)type, 1);
-                } else {
-                    can_irq_set(&_can, (CanIrqType)type, 0);
-                }*/
+        mcpSetInterrupts(&_can, (CANIrqs)event);
+        if((mptr != NULL) && (tptr != NULL)) {
+            _callback_irq.attach(tptr, mptr);
+            mcpSetInterrupts(&_can, (CANIrqs)event);
+//            _irq[type].attach(tptr, mptr);
+//            can_irq_set(&_can, (CanIrqType)type, 1);
+        } else {
+            mcpSetInterrupts(&_can, (CANIrqs)SEEED_CAN::None);
+//            can_irq_set(&_can, (CanIrqType)type, 0);
+        }
     }
 
-    void call_irq(void) { _callback_irq.call(); }
+    void call_irq(void);
     
+    /** Check if the specified interrupt event has occurred
+     *
+     *  @param event Which CAN interrupt to attach the member function to
+     *  @n @p SEEED_CAN::RxAny - At least 1 RX buffer is full,
+     *  @n @p SEEED_CAN::TxAny - At least 1 TX buffer is empty,
+     *  @n @p SEEED_CAN::Rx0Full - Receive buffer 1 full,
+     *  @n @p SEEED_CAN::Rx1Full - Receive buffer 1 full,
+     *  @n @p SEEED_CAN::Tx0Free - Transmit buffer 2 empty,
+     *  @n @p SEEED_CAN::Tx1Free - Transmit buffer 2 empty,
+     *  @n @p SEEED_CAN::Tx2Free - Transmit buffer 2 empty,
+     *  @n @p SEEED_CAN::Error - Error (multiple sources in EFLG register),
+     *  @n @p SEEED_CAN::Wake - Wakeup,
+     *  @n @p SEEED_CAN::MsgError - Message Error,
+     *
+     *  @returns
+     *     1 if specified interrupt event has occurred
+     *  @n 0 if no errors
+     */
+    int interrupts(IrqType type);
+
+    /** Returns the contents of the MCP2515's Interrupt Flag register
+     *
+     *  @returns
+     *     @b Bit_7 - MERRF: Message Error Interrupt Flag,
+     *  @n @b Bit_6 - WAKIF: Wake-up Interrupt Flag,
+     *  @n @b Bit_5 - ERRIF: Error Interrupt Flag (multiple sources in EFLG register, see errorFlags)
+     *  @n @b Bit_4 - TX2IF: Transmit Buffer 2 Empty Interrupt Flag
+     *  @n @b Bit_3 - TX1IF: Transmit Buffer 1 Empty Interrupt Flag
+     *  @n @b Bit_2 - TX0IF: Transmit Buffer 0 Empty Interrupt Flag
+     *  @n @b Bit_1 - RX1IF: Receive Buffer 1 Full Interrupt Flag
+     *  @n @b Bit_0 - RX0IF: Receive Buffer 0 Full Interrupt Flag
+     *  @n Bits are set (1) when interrupt pending, clear (0) when no interrupt pending.
+     *  @n Bits must be cleared by MCU to reset interrupt condition.
+     */
+    unsigned char interruptFlags(void);
+
 protected:
     SPI             _spi;
-    can_t           _can;
+    mcp_can_t       _can;
+    InterruptIn     _irqpin;
     FunctionPointer _callback_irq;
 
 };
--- a/seeed_can_api.cpp	Wed Nov 06 20:16:11 2013 +0000
+++ b/seeed_can_api.cpp	Tue Nov 12 20:54:16 2013 +0000
@@ -18,7 +18,7 @@
 
 /** Initialise the MCP2515 and set the bit rate
  */
-uint8_t mcpInit(can_t *obj, const uint32_t bitRate)
+uint8_t mcpInit(mcp_can_t *obj, const uint32_t bitRate, const CANMode mode)
 {
     union {                                                             // Access CANMsg as:
         CANMsg x;                                                       // the organised struct
@@ -51,14 +51,15 @@
     if (!mcpSetBitRate(obj, bitRate)) {                                 // set baudrate
         return 0;
     }
-    return mcpSetMode(obj, MODE_NORMAL) ? 1 : 0;                        // set Normal mode and return
+//    return mcpSetMode(obj, MODE_NORMAL) ? 1 : 0;                        // set Normal mode and return
+    return mcpSetMode(obj, mode) ? 1 : 0;                        // set Normal mode and return
 }
 
 /**  set MCP2515 operation mode
  *
  * Configuration, Normal, Sleep, Listen-only or Loopback
  */
-uint8_t mcpSetMode(can_t *obj, const uint8_t newmode)
+uint8_t mcpSetMode(mcp_can_t *obj, const uint8_t newmode)
 {
     mcpBitModify(obj, MCP_CANCTRL, MODE_MASK, newmode);
     for (uint32_t i = 0; i<10; i++) {
@@ -115,7 +116,7 @@
     {0x7, 0x7},    // 25, 68.0%
 };
 
-uint8_t mcpSetBitRate(can_t *obj, const uint32_t bitRate)
+uint8_t mcpSetBitRate(mcp_can_t *obj, const uint32_t bitRate)
 {
     union {                                                             // Access CANtiming as:
         CANtiming x;                                                    // the organised struct
@@ -173,7 +174,7 @@
 
 /** write a CAN id to a mask, filter or transmit buffer
  */
-void mcpWriteId(can_t *obj, const uint8_t mcp_addr, const uint8_t ext, const uint32_t id )
+void mcpWriteId(mcp_can_t *obj, const uint8_t mcp_addr, const uint8_t ext, const uint32_t id )
 {
     union {                                                             // Access CANid as:
         CANid x;                                                        // the organised struct
@@ -207,7 +208,7 @@
 
 /**  write a CAN message to the MCP2515
  */
-uint8_t mcpCanWrite(can_t *obj, CAN_Message msg)
+uint8_t mcpCanWrite(mcp_can_t *obj, CAN_Message msg)
 {
     union {                                                             // Access CANMsg as:
         CANMsg x;                                                       // the organised struct
@@ -251,7 +252,7 @@
 
 /** read a CAN message from the MCP2515
  */
-uint8_t mcpCanRead(can_t *obj, CAN_Message *msg)
+uint8_t mcpCanRead(mcp_can_t *obj, CAN_Message *msg)
 {
     union {                                                             // Access CANMsg as:
         CANMsg x;                                                       // the organised struct
@@ -306,7 +307,7 @@
 
 /** initialise an Acceptance Mask
  */
-uint8_t mcpInitMask(can_t *obj, uint8_t num, uint32_t ulData, bool ext)
+uint8_t mcpInitMask(mcp_can_t *obj, uint8_t num, uint32_t ulData, bool ext)
 {
     uint8_t mask[2] = { MCP_RXM0SIDH, MCP_RXM1SIDH };
 
@@ -335,7 +336,7 @@
 
 /** initialise an Acceptance Filter
  */
-uint8_t mcpInitFilter(can_t *obj, uint8_t num, uint32_t ulData, bool ext)
+uint8_t mcpInitFilter(mcp_can_t *obj, uint8_t num, uint32_t ulData, bool ext)
 {
     uint8_t filter[6] = { MCP_RXF0SIDH, MCP_RXF1SIDH, MCP_RXF2SIDH, MCP_RXF3SIDH, MCP_RXF4SIDH, MCP_RXF5SIDH };
 
@@ -362,34 +363,67 @@
     return 1;
 }
 
+/*  Report on the specified errors and warnings
+ */
+uint8_t mcpErrorType(mcp_can_t *obj, const CANFlags type)
+{
+    uint8_t which[] = { MCP_EFLG_ALLMASK,
+                        MCP_EFLG_ERRORMASK,
+                        MCP_EFLG_WARNMASK,
+                        MCP_EFLG_RX1OVR,
+                        MCP_EFLG_RX0OVR,
+                        MCP_EFLG_TXBO,
+                        MCP_EFLG_TXEP,
+                        MCP_EFLG_RXEP,
+                        MCP_EFLG_TXWAR,
+                        MCP_EFLG_RXWAR,
+                        MCP_EFLG_EWARN
+                      };
+
+    return (mcpRead(obj, MCP_EFLG) & which[type]) ? 1 : 0;
+}
+
+/*  Return contents of the error and warning flags register
+ */
+uint8_t mcpErrorFlags(mcp_can_t *obj)
+{
+    return (mcpRead(obj, MCP_EFLG));
+}
+
 /*  Number of message reception errors
  */
-uint8_t mcpReceptionErrorCount(can_t *obj)
+uint8_t mcpReceptionErrorCount(mcp_can_t *obj)
 {
     return (mcpRead(obj, MCP_REC));
 }
 
 /*  Number of message transmission errors
  */
-uint8_t mcpTransmissionErrorCount(can_t *obj)
+uint8_t mcpTransmissionErrorCount(mcp_can_t *obj)
 {
     return (mcpRead(obj, MCP_TEC));
 }
 
 /* Select between monitor (silent = 1) and normal (silent = 0) modes
  */
-void mcpMonitor(can_t *obj, const bool silent)
+void mcpMonitor(mcp_can_t *obj, const bool silent)
 {
     silent ? mcpSetMode(obj, MODE_LISTENONLY) : mcpSetMode(obj, MODE_NORMAL);
 }
 
 /* Change CAN operation to the specified mode
  */
-uint8_t mcpMode(can_t *obj, const CANMode mode)
+uint8_t mcpMode(mcp_can_t *obj, const CANMode mode)
 {
-    uint8_t which[] = { MODE_NORMAL, MODE_SLEEP, MODE_LOOPBACK, MODE_LISTENONLY, MODE_CONFIG, MODE_CONFIG};
+    uint8_t which[] = { MODE_NORMAL,
+                        MODE_SLEEP,
+                        MODE_LOOPBACK,
+                        MODE_LISTENONLY,
+                        MODE_CONFIG,
+                        MODE_CONFIG
+                      };
 
-    if (mode == _RESET) {
+    if (mode == _M_RESET) {
         mcpReset(obj);
     }
     if (mcpSetMode(obj, which[mode])) {
@@ -397,3 +431,52 @@
     }
     return 0;
 }
+
+/*  Configure interrupt sources
+ */
+void mcpSetInterrupts(mcp_can_t *obj, const CANIrqs irqSet)
+{
+    uint8_t which[] = { MCP_NO_INTS,
+                        MCP_ALL_INTS,
+                        MCP_RX_INTS,
+                        MCP_TX_INTS,
+                        MCP_RX0IF,
+                        MCP_RX1IF,
+                        MCP_TX0IF,
+                        MCP_TX1IF,
+                        MCP_TX2IF,
+                        MCP_ERRIF,
+                        MCP_WAKIF,
+                        MCP_MERRF
+                      };
+
+    mcpWrite(obj, MCP_CANINTE, which[irqSet]);
+}
+
+/*  Report on the specified interrupt causes
+ */
+uint8_t mcpInterruptType(mcp_can_t *obj, const CANIrqs irqFlag)
+{
+    uint8_t which[] = { MCP_NO_INTS,
+                        MCP_ALL_INTS,
+                        MCP_RX_INTS,
+                        MCP_TX_INTS,
+                        MCP_RX0IF,
+                        MCP_RX1IF,
+                        MCP_TX0IF,
+                        MCP_TX1IF,
+                        MCP_TX2IF,
+                        MCP_ERRIF,
+                        MCP_WAKIF,
+                        MCP_MERRF
+                      };
+
+    return (mcpRead(obj, MCP_EFLG) & which[irqFlag]) ? 1 : 0;
+}
+
+/*  Return contents of the interrupt flags register
+ */
+uint8_t mcpInterruptFlags(mcp_can_t *obj)
+{
+    return (mcpRead(obj, MCP_EFLG));
+}
--- a/seeed_can_api.h	Wed Nov 06 20:16:11 2013 +0000
+++ b/seeed_can_api.h	Tue Nov 12 20:54:16 2013 +0000
@@ -76,6 +76,7 @@
     };
     typedef struct MCP_CANMsg CANMsg;
 
+#ifndef MBED_CAN_HELPER_H                                               // These are already defined for some mbed family members
     enum CANFormat {
         CANStandard = 0,
         CANExtended = 1
@@ -96,39 +97,85 @@
         CANType        type;        // 0 - DATA FRAME, 1 - REMOTE FRAME
     };
     typedef struct CAN_Message CAN_Message;
+#endif
     
     enum MCP_Mode {
-        _NORMAL,
-        _SLEEP,
-        _LOOPBACK,
-        _MONITOR,
-        _CONFIG,
-        _RESET,
+        _M_NORMAL,
+        _M_SLEEP,
+        _M_LOOPBACK,
+        _M_MONITOR,
+        _M_CONFIG,
+        _M_RESET,
     };
     typedef MCP_Mode CANMode;
 
+    enum MCP_Error_Flags {
+        _E_ALL,
+        _E_ERRORS,
+        _E_WARNINGS,
+        _E_RX1OVR,
+        _E_RX0OVR,
+        _E_TXBO,
+        _E_TXEP,
+        _E_RXEP,
+        _E_TXWAR,
+        _E_RXWAR,
+        _E_EWARN
+    };
+    typedef MCP_Error_Flags CANFlags;
+
+    enum MCP_Interrupt_Flags {
+        _I_NONE,
+        _I_ANY,
+        _I_RX,
+        _I_TX,
+        _I_RX0,
+        _I_RX1,
+        _I_TX0,
+        _I_TX1,
+        _I_TX2,
+        _I_ERROR,
+        _I_WAKE,
+        _I_M_ERR
+    };
+    typedef MCP_Interrupt_Flags CANIrqs;
+
 /** CAN driver functions
  */
-    uint8_t mcpInit(can_t *obj, const uint32_t bitRate);                // Initialise the MCP2515 and set the bit rate
-    uint8_t mcpSetMode(can_t *obj, const uint8_t newmode);              // set the MCP2515's operation mode
-    uint8_t mcpSetBitRate(can_t *obj, const uint32_t bitRate);          // set bitrate
+    uint8_t mcpInit(mcp_can_t *obj,                                     // Initialise the MCP2515 and set the bit rate
+                    const uint32_t bitRate,
+                    const CANMode mode);
+    uint8_t mcpSetMode(mcp_can_t *obj, const uint8_t newmode);          // set the MCP2515's operation mode
+    uint8_t mcpSetBitRate(mcp_can_t *obj, const uint32_t bitRate);      // set bitrate
     
-    void mcpWriteId(can_t *obj,                                         // write a CAN id
+    void mcpWriteId(mcp_can_t *obj,                                     // write a CAN id
                     const uint8_t mcp_addr,
                     const uint8_t ext,
                     const uint32_t id );
-    uint8_t mcpCanRead(can_t *obj, CAN_Message *msg);                   // read a CAN message
-    uint8_t mcpCanWrite(can_t *obj, CAN_Message msg);                   // write a CAN message
+    uint8_t mcpCanRead(mcp_can_t *obj, CAN_Message *msg);               // read a CAN message
+    uint8_t mcpCanWrite(mcp_can_t *obj, CAN_Message msg);               // write a CAN message
     
-    uint8_t mcpInitMask(can_t *obj, uint8_t num, uint32_t ulData, bool ext);  // initialise an Acceptance Mask
-    uint8_t mcpInitFilter(can_t *obj, uint8_t num, uint32_t ulData, bool ext);  // initialise an Acceptance Filter
+    uint8_t mcpInitMask(mcp_can_t *obj,                                 // initialise an Acceptance Mask
+                        uint8_t num,
+                        uint32_t ulData,
+                        bool ext);
+    uint8_t mcpInitFilter(mcp_can_t *obj,                               // initialise an Acceptance Filter
+                          uint8_t num,
+                          uint32_t ulData,
+                          bool ext);
 
-    uint8_t mcpReceptionErrorCount(can_t *obj);                         // number of message reception errors
-    uint8_t mcpTransmissionErrorCount(can_t *obj);                      // number of message transmission errors
+    uint8_t mcpErrorType(mcp_can_t *obj, const CANFlags type);          // Report on the specified errors and warnings
+    uint8_t mcpErrorFlags(mcp_can_t *obj);                              // Return contents of the error and warning flags register
+    uint8_t mcpReceptionErrorCount(mcp_can_t *obj);                     // number of message reception errors
+    uint8_t mcpTransmissionErrorCount(mcp_can_t *obj);                  // number of message transmission errors
 
-    void mcpMonitor(can_t *obj, const bool silent);                     // Select between monitor (silent = 1) and normal (silent = 0) modes
-    uint8_t mcpMode(can_t *obj, const CANMode mode);                    // Change CAN operation to the specified mode
+    void mcpMonitor(mcp_can_t *obj, const bool silent);                 // Select between monitor (silent = 1) and normal (silent = 0) modes
+    uint8_t mcpMode(mcp_can_t *obj, const CANMode mode);                // Change CAN operation to the specified mode
 
+    void mcpSetInterrupts(mcp_can_t *obj, const CANIrqs irqSet);        // Configure interrupt sources
+    uint8_t mcpInterruptType(mcp_can_t *obj, const CANIrqs irqFlag);    // Report on the specified interrupt causes
+    uint8_t mcpInterruptFlags(mcp_can_t *obj);                          // Return contents of the interrupt flags register
+    
 #ifdef __cplusplus
 };
 #endif
--- a/seeed_can_defs.h	Wed Nov 06 20:16:11 2013 +0000
+++ b/seeed_can_defs.h	Tue Nov 12 20:54:16 2013 +0000
@@ -170,7 +170,9 @@
 
     /** EFLG Register Values
      */
-#define MCP_EFLG_ERRORMASK  (0xF8)                                      /* 5 MS-Bits                    */
+#define MCP_EFLG_ALLMASK    (0xFF)                                      // All Bits
+#define MCP_EFLG_ERRORMASK  (0xF8)                                      // 5 MS-Bits
+#define MCP_EFLG_WARNMASK   (0x07)                                      // 3 LS-Bits
 #define MCP_EFLG_EWARN      (1<<0)
 #define MCP_EFLG_RXWAR      (1<<1)
 #define MCP_EFLG_TXWAR      (1<<2)
@@ -200,8 +202,8 @@
 
     /** Bit Rate timing
      */
-#define MCP_CLOCK_FREQ          16000000    // 16 MHz Crystal frequency
-#define CAN_SYNCSEG             1           // CAN-BUS Sync segment is always 1 Time Quantum
+#define MCP_CLOCK_FREQ          16000000                                // 16 MHz Crystal frequency
+#define CAN_SYNCSEG             1                                       // CAN-BUS Sync segment is always 1 Time Quantum
 #define CAN_MAX_RATE            MCP_CLOCK_FREQ/(2 * MCP_MIN_TIME_QUANTA)
 #define CAN_MIN_RATE            MCP_CLOCK_FREQ/(2 * MCP_MAX_PRESCALER * MCP_MAX_TIME_QUANTA)
 #define MCP_MAX_TIME_QUANTA     25
@@ -227,6 +229,10 @@
 #define SOF_DISABLE         (0<<7)
     /** CANINTF Register Bits
      */
+#define MCP_NO_INTS         (0x00)                                      // Disable all interrupts
+#define MCP_ALL_INTS        (0xFF)                                      // All Bits
+#define MCP_RX_INTS         (MCP_RX1IF | MCP_RX0IF)                     // Enable all receive interrupts
+#define MCP_TX_INTS         (MCP_TX2IF | MCP_TX1IF | MCP_TX0IF)         // Enable all transmit interrupts
 #define MCP_RX0IF           (1<<0)
 #define MCP_RX1IF           (1<<1)
 #define MCP_TX0IF           (1<<2)
@@ -236,15 +242,6 @@
 #define MCP_WAKIF           (1<<6)
 #define MCP_MERRF           (1<<7)
 
-#define MCP_TX_INT          0x1C                                        // Enable all transmit interrupts
-#define MCP_TX01_INT        0x0C                                        // Enable TXB0 and TXB1 interrupts
-#define MCP_RX_INT          0x03                                        // Enable receive interrupts
-#define MCP_NO_INT          0x00                                        // Disable all interrupts
-
-#define MCP_TX01_MASK       0x14
-#define MCP_TX_MASK         0x54
-
-
 //#define MCP_RXBUF_0         (MCP_RXB0SIDH)
 //#define MCP_RXBUF_1         (MCP_RXB1SIDH)
 
--- a/seeed_can_spi.cpp	Wed Nov 06 20:16:11 2013 +0000
+++ b/seeed_can_spi.cpp	Tue Nov 12 20:54:16 2013 +0000
@@ -18,7 +18,7 @@
 
 /** reset the MCP2515
  */
-void mcpReset(can_t *obj)
+void mcpReset(mcp_can_t *obj)
 {
     obj->ncs = 0;
     obj->spi.write(MCP_RESET);
@@ -28,7 +28,7 @@
 
 /** read from a single MCP2515 register
  */
-uint8_t mcpRead(can_t *obj, const uint8_t address)
+uint8_t mcpRead(mcp_can_t *obj, const uint8_t address)
 {
     uint8_t result;
 
@@ -42,7 +42,7 @@
 
 /** read multiple MCP2515 registers sequentially into an array (relies on address auto-increment)
  */
-void mcpReadMultiple(can_t *obj, const uint8_t address, uint8_t values[], const uint8_t n)
+void mcpReadMultiple(mcp_can_t *obj, const uint8_t address, uint8_t values[], const uint8_t n)
 {
     obj->ncs = 0;
     obj->spi.write(MCP_READ);
@@ -55,7 +55,7 @@
 
 /** read the specified MCP2515 receive buffer into an array (needs one fewer SPI transfer than mcpReadMultiple)
  */
-void mcpReadBuffer(can_t *obj, const uint8_t command, uint8_t values[], const uint8_t n)
+void mcpReadBuffer(mcp_can_t *obj, const uint8_t command, uint8_t values[], const uint8_t n)
 {
     obj->ncs = 0;
     obj->spi.write(command);
@@ -67,7 +67,7 @@
 
 /**  write to a single MCP2515 register
  */
-void mcpWrite(can_t *obj, const uint8_t address, const uint8_t value)
+void mcpWrite(mcp_can_t *obj, const uint8_t address, const uint8_t value)
 {
     obj->ncs = 0;
     obj->spi.write(MCP_WRITE);
@@ -78,7 +78,7 @@
 
 /** write to multiple MCP2515 registers consecutively from an array
  */
-void mcpWriteMultiple(can_t *obj, const uint8_t address, const uint8_t values[], const uint8_t n)
+void mcpWriteMultiple(mcp_can_t *obj, const uint8_t address, const uint8_t values[], const uint8_t n)
 {
     obj->ncs = 0;
     obj->spi.write(MCP_WRITE);
@@ -91,7 +91,7 @@
 
 /** write to the specified MCP2515 transmit buffer from an array (needs one fewer SPI transfer than mcpWriteMultiple)
  */
-void mcpWriteBuffer(can_t *obj, const uint8_t command, uint8_t values[], const uint8_t n)
+void mcpWriteBuffer(mcp_can_t *obj, const uint8_t command, uint8_t values[], const uint8_t n)
 {
     obj->ncs = 0;
     obj->spi.write(command);
@@ -103,7 +103,7 @@
 
 /** initiate transmission of the specified MCP2515 transmit buffer
  */
-void mcpBufferRTS(can_t *obj, const uint8_t command)
+void mcpBufferRTS(mcp_can_t *obj, const uint8_t command)
 {
     obj->ncs = 0;
     obj->spi.write(command);
@@ -112,7 +112,7 @@
 
 /**  read mcp2515's status register
  */
-uint8_t mcpStatus(can_t *obj)
+uint8_t mcpStatus(mcp_can_t *obj)
 {
     uint8_t status;
 
@@ -125,7 +125,7 @@
 
 /**  read mcp2515's receive status register
  */
-uint8_t mcpReceiveStatus(can_t *obj)
+uint8_t mcpReceiveStatus(mcp_can_t *obj)
 {
     uint8_t status;
 
@@ -138,7 +138,7 @@
 
 /** modify bits of a register specified by a mask
  */
-void mcpBitModify(can_t *obj, const uint8_t address, const uint8_t mask, const uint8_t data)
+void mcpBitModify(mcp_can_t *obj, const uint8_t address, const uint8_t mask, const uint8_t data)
 {
     obj->ncs = 0;
     obj->spi.write(MCP_BITMOD);
--- a/seeed_can_spi.h	Wed Nov 06 20:16:11 2013 +0000
+++ b/seeed_can_spi.h	Tue Nov 12 20:54:16 2013 +0000
@@ -35,37 +35,37 @@
             irq(_irq_)
         {}
     };
-    typedef struct Seeed_MCP_CAN_Shield can_t;
+    typedef struct Seeed_MCP_CAN_Shield mcp_can_t;
 
     /** mcp2515 spi instructions
      */
-    void mcpReset(can_t *obj);                                          // reset the MCP2515 CAN controller chip
+    void mcpReset(mcp_can_t *obj);                                      // reset the MCP2515 CAN controller chip
 
-    uint8_t mcpRead(can_t *obj,                                         // read from a single MCP2512 register
+    uint8_t mcpRead(mcp_can_t *obj,                                     // read from a single MCP2512 register
                     const uint8_t address);
-    void mcpReadMultiple(can_t *obj,                                    // read multiple, sequential, registers into an array
+    void mcpReadMultiple(mcp_can_t *obj,                                // read multiple, sequential, registers into an array
                          const uint8_t address,
                          uint8_t values[],
                          const uint8_t n);
-    void mcpReadBuffer(can_t *obj,                                      // read the specified receive buffer into an array
+    void mcpReadBuffer(mcp_can_t *obj,                                  // read the specified receive buffer into an array
                        const uint8_t command,
                        uint8_t values[],
                        const uint8_t n);
-    void mcpWrite(can_t *obj,                                           // write to a single MCP2512 register
+    void mcpWrite(mcp_can_t *obj,                                       // write to a single MCP2512 register
                   const uint8_t address,
                   const uint8_t value);
-    void mcpWriteMultiple(can_t *obj,                                   // write an array into consecutive MCP2515 registers
+    void mcpWriteMultiple(mcp_can_t *obj,                               // write an array into consecutive MCP2515 registers
                           const uint8_t address,
                           const uint8_t values[],
                           const uint8_t n);
-    void mcpWriteBuffer(can_t *obj,                                     // write an array into the specified transmit buffer
+    void mcpWriteBuffer(mcp_can_t *obj,                                 // write an array into the specified transmit buffer
                         const uint8_t command,
                         uint8_t values[],
                         const uint8_t n);
-    void mcpBufferRTS(can_t *obj, const uint8_t command);               // initiate transmission of the specified MCP2515 transmit buffer
-    uint8_t mcpStatus(can_t *obj);                                      // read the MCP2515's status register
-    uint8_t mcpReceiveStatus(can_t *obj);                               // read mcp2515's receive status register
-    void mcpBitModify(can_t *obj,                                       // modify bits of a register specified by a mask
+    void mcpBufferRTS(mcp_can_t *obj, const uint8_t command);           // initiate transmission of the specified MCP2515 transmit buffer
+    uint8_t mcpStatus(mcp_can_t *obj);                                  // read the MCP2515's status register
+    uint8_t mcpReceiveStatus(mcp_can_t *obj);                           // read mcp2515's receive status register
+    void mcpBitModify(mcp_can_t *obj,                                   // modify bits of a register specified by a mask
                       const uint8_t address,
                       const uint8_t mask,
                       const uint8_t data);