eeprom adding

Fork of SEEED_CAN by Sophie Dexter

Files at this revision

API Documentation at this revision

Comitter:
Just4pLeisure
Date:
Tue Nov 05 22:37:35 2013 +0000
Child:
1:ad71faa09868
Commit message:
Beta release of a CAN-BUS library for Seeed Studios' CAN BUS Shield

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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/seeed_can.cpp	Tue Nov 05 22:37:35 2013 +0000
@@ -0,0 +1,113 @@
+/* mbed FRDM-KL25Z Library for Seeed Studios CAN-BUS Shield
+ * Copyright (c) 2013 Sophie Dexter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "seeed_can.h"
+
+/** Seeed Studios CAN-BUS Shield Constructor - initialise FRDM-KL25Z's SPI0 for the MCP2515
+ */
+SEEED_CAN::SEEED_CAN(PinName ncs, PinName irq, PinName mosi, PinName miso, PinName clk, int spiBitrate, int canBitrate) :
+    _spi(mosi, miso, clk),
+    _can(_spi, ncs, irq)
+{
+    // Make sure CS is high
+    _can.ncs = 1;
+    // Set up the spi interface
+    _can.spi.format(8, 3);
+    _can.spi.frequency(spiBitrate);
+    mcpInit(&_can, canBitrate);                                             
+}
+
+/** Set CAN-BUS frequency (Bit Rate)
+*/
+int SEEED_CAN::frequency(int setBitRate)
+{
+//    return mcpSetBitRate(&_can, (uint32_t) setBitRate);
+    return mcpInit(&_can, (uint32_t) setBitRate);
+}
+
+/** Read a CAN bus message from the MCP2515 (if there is one)
+ */
+int SEEED_CAN::read(SEEED_CANMessage &msg)
+{
+    return mcpCanRead(&_can, &msg);
+}
+
+/**  Write a CAN bus message to the MCP2515 (if there is a free message buffer)
+ */
+int SEEED_CAN::write(SEEED_CANMessage msg)
+{
+    return mcpCanWrite(&_can, msg);
+}
+
+/** Returns number of message reception (read) errors to detect read overflow errors.
+ */
+unsigned char SEEED_CAN::rderror(void)
+{
+    return mcpReceptionErrorCount(&_can);
+}
+
+/** Returns number of message transmission (write) errors to detect write overflow errors.
+ */
+unsigned char SEEED_CAN::tderror(void)
+{
+    return mcpTransmissionErrorCount(&_can);
+}
+
+/** Check if any type of error has been detected
+ */
+int SEEED_CAN::errors(void)
+{
+    return (mcpRead(&_can, MCP_EFLG) & MCP_EFLG_ERRORMASK) ? 1 : 0;
+}
+
+/** Puts or removes the Seeed Studios CAN-BUS shield into or from silent monitoring mode
+ */
+void SEEED_CAN::monitor(bool silent)
+{
+    mcpMonitor(&_can, silent);
+}
+
+/** Puts or removes the Seeed Studios CAN-BUS shield into the specified mode
+ */
+int SEEED_CAN::mode(Mode mode)
+{
+    return mcpMode(&_can, (CANMode)mode);
+}
+
+/** Configure one of the Accpetance Masks (0 or 1)
+ */
+int SEEED_CAN::Mask(int maskNum, int canId, CANFormat format) {
+    return mcpInitMask(&_can, maskNum, canId, format);
+}
+
+/** Configure one of the Acceptance Filters (0 through 5)
+ */
+int SEEED_CAN::Filter(int filterNum, int canId, CANFormat format) {
+    return mcpInitFilter(&_can, filterNum, canId, format);
+}
+
+/** Attach a function to call whenever a CAN frame received interrupt is generated.
+ */
+void SEEED_CAN::attach(void (*fptr)(void), IrqType type)
+{
+    _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);
+    }*/
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/seeed_can.h	Tue Nov 05 22:37:35 2013 +0000
@@ -0,0 +1,223 @@
+/* seeed_can.h
+ * Copyright (c) 2013 Sophie Dexter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _SEEED_CAN_H_
+#define _SEEED_CAN_H_
+
+#include "seeed_can_api.h"
+
+// if print debug information
+#define DEBUG
+
+/** CANMessage class
+ */
+class SEEED_CANMessage : public CAN_Message
+{
+
+public:
+    /** Creates empty CAN message.
+     */
+    SEEED_CANMessage() {
+        id     = 0;
+        memset(data, 0, 8);
+        len    = 8;
+        type   = CANData;
+        format = CANStandard;
+    }
+
+    /** Creates CAN message with specific content.
+     */
+    SEEED_CANMessage(int _id, const char *_data, char _len = 8, CANType _type = CANData, CANFormat _format = CANStandard) {
+        id     = _id;
+        memcpy(data, _data, _len);
+        len    = _len & 0xF;
+        type   = _type;
+        format = _format;
+    }
+
+    /** Creates CAN remote message.
+     */
+    SEEED_CANMessage(int _id, CANFormat _format = CANStandard) {
+        id     = _id;
+        memset(data, 0, 8);
+        len    = 0;
+        type   = CANRemote;
+        format = _format;
+    }
+};
+
+
+/** A can bus client, used for communicating with Seeed Studios' CAN-BUS Arduino Shield.
+ */
+class SEEED_CAN
+{
+    /** can operator functions
+     */
+public:
+    /** 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.
+     *
+     * @param ncs Active low chip select (This function accepts mbed (PTD0/5) and Seeed Studios' (CS/IO9) pin names. The default value would be PTD0 or CS but if you change the link on the Seeed Studios CAN-BUS shield you should use a volue of PTD5 or IO9 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 canBitrate CAN Bus Clock frequency (default: 100 kHz).
+     */
+    SEEED_CAN(PinName ncs, PinName irq=SEEED_CAN_IRQ, PinName mosi=SEEED_CAN_MOSI, PinName miso=SEEED_CAN_MISO, PinName clk=SEEED_CAN_CLK, int spiBitrate=1000000, int canBitrate=100000);
+//    virtual ~SEEED_CAN(); // !!! Need a de-constructor for the interrrupt pin !!!
+
+    /** Set the frequency of the CAN interface
+     *
+     *  @param hz The bus frequency in Hertz
+     *
+     *  @returns
+     *    1 if successful,
+     *    0 otherwise
+     */
+    int frequency(int setBitRate);
+
+    /** Write a CANMessage to the bus.
+     *
+     *  @param msg The CANMessage to write.
+     *
+     *  @returns
+     *    0 if write failed,
+     *    1 if write was successful
+     */
+    int write(SEEED_CANMessage msg);
+
+    /** Read a CANMessage from the bus.
+     *
+     *  @param msg A CANMessage to read to.
+     *
+     *  @returns
+     *    0 if no message arrived,
+     *    1 if message arrived
+     */
+    int read(SEEED_CANMessage &msg);
+
+    /** Configure one of the Accpetance Masks (0 or 1)
+     *
+     *  @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).
+     *
+     *  @returns
+     *    0 if the Acceptance Mask could not be set
+     *    1 if Acceptance Mask was set
+     */
+    int Mask(int maskNum, int canId, CANFormat format = CANStandard);
+
+    /** Configure one of the Acceptance Filters (0 through 5)
+     *
+     *  @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).
+     *
+     *  @returns
+     *    0 if the Acceptance Filter could not be set
+     *    1 if Acceptance Filter was set
+     */
+    int Filter(int filterNum, int canId, CANFormat format = CANStandard);
+
+    /** Returns number of message reception (read) errors to detect read overflow errors.
+     */
+    unsigned char rderror(void);
+
+    /** Returns number of message transmission (write) errors to detect write overflow errors.
+     */
+    unsigned char tderror(void);
+
+    /** Check if any type of error
+     *
+     *  @returns
+     *    0 if no errors
+     *    1 if any type of error has been detected
+     */
+    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);
+
+    enum Mode {
+        Normal = 0,
+        Sleep,
+        Loopback,
+        Monitor,
+        Config,
+        Reset
+    };
+
+    /** Change CAN operation to the specified mode
+     *
+     *  @param mode The new operation mode (SEED_CAN::Normal, SEED_CAN::Sleep, SEED_CAN::Loopback, SEED_CAN::Monitor, SEEED_CAN::Reset)
+     *
+     *  @returns
+     *    0 if mode change failed or unsupported,
+     *    1 if mode change was successful
+     */
+    int mode(Mode mode);
+
+    enum IrqType {
+        RxIrq = 0,
+        TxIrq,
+        EwIrq,
+        DoIrq,
+        WuIrq,
+        EpIrq,
+        AlIrq,
+        BeIrq,
+        IdIrq
+    };
+
+    /** 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)
+     */
+    void attach(void (*fptr)(void), IrqType type=RxIrq);
+
+    /** 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)
+     */
+    template<typename T>
+    void attach(T* tptr, void (T::*mptr)(void), IrqType type=RxIrq) {
+        _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);
+        }*/
+    }
+
+protected:
+    SPI     _spi;
+    can_t   _can;
+
+};
+
+#endif      // SEEED_CAN_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/seeed_can_api.cpp	Tue Nov 05 22:37:35 2013 +0000
@@ -0,0 +1,400 @@
+/* seeed_can_api.cpp
+ * Copyright (c) 2013 Sophie Dexter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "seeed_can_api.h"
+
+/** Initialise the MCP2515 and set the bit rate
+ */
+uint8_t mcpInit(can_t *obj, const uint32_t bitRate)
+{
+    union {                                                             // Access CANMsg as:
+        CANMsg x;                                                       // the organised struct
+        uint8_t y[];                                                    // or contiguous memory array
+    };
+    uint8_t maskFilt[8] = { MCP_RXM0SIDH, MCP_RXM1SIDH, MCP_RXF0SIDH, MCP_RXF1SIDH, MCP_RXF2SIDH, MCP_RXF3SIDH, MCP_RXF4SIDH, MCP_RXF5SIDH };
+    uint8_t canBufCtrl[5] = { MCP_TXB0CTRL, MCP_TXB1CTRL, MCP_TXB2CTRL, MCP_RXB0CTRL, MCP_RXB1CTRL };
+    uint8_t canBuffer[3] = { MCP_TXB0CTRL+1, MCP_TXB1CTRL+1, MCP_TXB2CTRL+1 };
+
+#ifdef DEBUG
+    printf("Reseting MCP2515\r\n");
+#endif
+    mcpReset(obj);
+    for (uint32_t i = 0; i < 8; i++) {                                  // Clear all CAN id masks and filters
+        mcpWriteId(obj, maskFilt[i], NULL, NULL);
+    }
+    for (uint32_t i = 0; i < 5; i++) {                                  // Clear all CAN buffer control registers
+        mcpWrite(obj, canBufCtrl[i], NULL);
+    }
+    for (uint32_t i = 0; i < sizeof(x); i++) y[i] = NULL;               // Initialise empty CAN message buffer
+    for (uint32_t i = 0; i < 3; i++) {                                  // Clear all CAN TX buffers
+        mcpWriteMultiple(obj, canBuffer[i], y, sizeof(x) );             // using empty CAN message (as an array)
+    }
+    mcpWrite(obj, MCP_CANINTE, MCP_RX0IF | MCP_RX1IF);                  // RX buffers can generate a interrupt
+#if (DEBUG_RXANY==1)
+    // enable both receive-buffers to receive any message and enable rollover
+    mcpBitModify(obj, MCP_RXB0CTRL, MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK, MCP_RXB_RX_ANY | MCP_RXB_BUKT_MASK);
+    mcpBitModify(obj, MCP_RXB1CTRL, MCP_RXB_RX_MASK, MCP_RXB_RX_ANY);
+#else
+    // enable both receive-buffers to receive messages with std. and ext. identifiers and enable rollover
+    mcpBitModify(obj, MCP_RXB0CTRL, MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK, MCP_RXB_RX_STDEXT | MCP_RXB_BUKT_MASK );
+    mcpBitModify(obj, MCP_RXB1CTRL, MCP_RXB_RX_MASK, MCP_RXB_RX_STDEXT);
+#endif
+#ifdef DEBUG
+    printf("Setting bit rate\r\n");
+#endif
+    return (mcpSetBitRate(obj, bitRate)) ? 1 : 0;                       // set baudrate and return
+}
+
+/**  set MCP2515 operation mode
+ *
+ * Configuration, Normal, Sleep, Listen-only or Loopback
+ */
+uint8_t mcpSetMode(can_t *obj, const uint8_t newmode)
+{
+    mcpBitModify(obj, MCP_CANCTRL, MODE_MASK, newmode);
+    for (uint32_t i = 0; i<10; i++) {
+        if ((mcpRead(obj, MCP_CANSTAT) & MODE_MASK) == newmode) {
+#ifdef DEBUG
+            printf("Successfully entered mode: %02x time: %dms\r\n", newmode, i);
+            printf("CANCTRL:%02x CANSTAT:%02x TXB0:%02x TXB1:%02x TXB2:%02x\r\n", mcpRead(obj, MCP_CANCTRL),  mcpRead(obj, MCP_CANSTAT), mcpRead(obj, MCP_TXB0CTRL), mcpRead(obj, MCP_TXB1CTRL), mcpRead(obj, MCP_TXB2CTRL));
+#endif
+            return 1;
+        }
+        wait_ms(1);
+    }
+#ifdef DEBUG
+    printf("Failed to enter mode: %02x\r\n", newmode);
+    printf("CANCTRL:%02x CANSTAT:%02x TXB0:%02x TXB1:%02x TXB2:%02x\r\n", mcpRead(obj, MCP_CANCTRL),  mcpRead(obj, MCP_CANSTAT), mcpRead(obj, MCP_TXB0CTRL), mcpRead(obj, MCP_TXB1CTRL), mcpRead(obj, MCP_TXB2CTRL));
+#endif
+    return 0;
+}
+
+/** set the CAN bus bitrate
+ *
+ * Calculate suitable BTR register values.
+ * The Bit Rate Pre-scaler (BRP) can be in the range of 1-64.
+ * According to CANopen, Bit Time can be be between 25 and 8 Time Quanta (TQU).
+ * Bit Time = SyncSeg(1 TQU) + PropSeg(1-8 TQU) + PhaseSeg1(1-8 TQU) + PhaseSeg2(2-8 TQU).
+ * SyncSeg is always 1TQU, PhaseSeg2 must be at least 2TQU to be longer than the processing time.
+ * Opinions vary on when to take a sample but a point roughly 2/3 of Bit Time seems OK.
+ * Synchronisation Jump width can be 1-4 TQU, a value of 1 seems to be normal.
+ *
+ * All register values are -1, e.g. PropSeg can range from 1-8 TQU, so values are 0-7 (0-63 for BRP).
+ *
+ * This table has the sampling points as close to 2/3 (66.7%) as possible.
+ * The first value is PropSeg, 2nd PhaseSeg1.
+ * PhaseSeg2 will be the same as PhaseSeg1 when btlmode bit is initialised to 0.
+ */
+static const uint8_t timing_pts[18][2] = {
+    {0x0, 0x2},    // 8,  62.5%
+    {0x1, 0x2},    // 9,  66.7%
+    {0x2, 0x2},    // 10, 70.0%
+    {0x1, 0x3},    // 11, 63.6%
+    {0x2, 0x3},    // 12, 66.7%
+    {0x3, 0x3},    // 13, 69.2%
+    {0x2, 0x4},    // 14, 64.3%
+    {0x3, 0x4},    // 15, 66.7%
+    {0x4, 0x4},    // 16, 68.75%
+    {0x3, 0x5},    // 17, 64.7%
+    {0x4, 0x5},    // 18, 66.7%
+    {0x5, 0x5},    // 19, 63.2%
+    {0x4, 0x6},    // 20, 65.0%
+    {0x5, 0x6},    // 21, 66.7%
+    {0x6, 0x6},    // 22, 68.2%
+    {0x5, 0x7},    // 23, 65.2
+    {0x6, 0x7},    // 24, 66.7%
+    {0x7, 0x7},    // 25, 68.0%
+};
+
+uint8_t mcpSetBitRate(can_t *obj, const uint32_t bitRate)
+{
+    union {                                                             // Access CANtiming as:
+        CANtiming x;                                                    // the organised struct
+        uint8_t y[];                                                    // or contiguous memory array
+    };
+    uint32_t bestBRP = 0;
+    uint32_t bestTQU = 0;
+    uint32_t bestCanRate = 0;
+    uint32_t minBRP = (MCP_CLOCK_FREQ / (2 * MCP_MAX_TIME_QUANTA * bitRate));
+    uint32_t maxBRP = (MCP_CLOCK_FREQ / (2 * MCP_MIN_TIME_QUANTA * bitRate));
+    
+    #ifdef DEBUG
+        printf("Setting configuration mode\r\n");
+    #endif
+        if(!mcpSetMode(obj, MODE_CONFIG)) {                                      // Go into configuration mode
+            return 0;
+        }
+    
+    for (uint32_t i = 0; i < sizeof(x); i++) y[i] = NULL;               // Initialise CANtiming (btlmode, sjw and sam all = 0)
+    if ((bitRate < CAN_MIN_RATE) || (bitRate > CAN_MAX_RATE)) {
+#ifdef DEBUG
+        printf("FAILED!! The requested Bit Rate is too high or too low: %d\r\n", bitRate);
+#endif
+        return 0;                                                       // Cannot set the requested bit rate!
+    }
+    minBRP = (minBRP == 0) ? MCP_MIN_PRESCALER : minBRP;
+    maxBRP = (maxBRP > MCP_MAX_PRESCALER) ? MCP_MAX_PRESCALER : maxBRP;
+    for (uint32_t BRP = minBRP; BRP < (maxBRP + 1); BRP++) {
+        uint32_t timeQuanta = (MCP_CLOCK_FREQ / (2 * BRP * bitRate));
+        if ((timeQuanta >= MCP_MIN_TIME_QUANTA) && (timeQuanta <= MCP_MAX_TIME_QUANTA)) {
+            for (uint32_t TQU = timeQuanta; TQU <= MCP_MAX_TIME_QUANTA; TQU++) {
+                uint32_t thisCanRate = MCP_CLOCK_FREQ / (2 * BRP * TQU);
+                if ( abs((int)bitRate - (int)thisCanRate) < abs((int)bitRate - (int)bestCanRate)) {
+                    bestCanRate = thisCanRate;
+                    bestBRP= BRP;
+                    bestTQU= TQU;
+                }
+            }
+        }
+    }
+    x.brp = (bestBRP - 1);
+    x.prseg = (timing_pts[bestTQU - 8][0]);
+    x.phseg1 = (timing_pts[bestTQU - 8][1]);
+    mcpWriteMultiple(obj,  MCP_CNF3, y, sizeof(x) );                    // Copy CANtiming to the MCP2515 (as an array)
+#ifdef DEBUG
+    printf("minBRP %d maxBRP %d\r\n", minBRP, maxBRP);
+    printf("Bitrate: %d\tactualBitRate: %d\t Error: %1.2f percent.\r\n", bitRate, bestCanRate, (100-(100*(float)bitRate/(float)bestCanRate)));
+    printf("TimeQuanta: %d\tbitRatePrescaler: %d\tSamplePoint: %2.2f percent\r\n", bestTQU, bestBRP, 100*(float)(3 + x.prseg + x.phseg1)/(float)bestTQU ) ;
+    printf("Syncseg: 1\tPropSeg: %d\tPhaseSeg1: %d\tPhaseSeg2: %d\r\n", (x.prseg+1), (x.phseg1+1), (x.phseg1+1));
+    printf("Setting normal mode\r\n");
+#endif
+    return (mcpSetMode(obj, MODE_NORMAL)) ? 1 : 0;                      // desired bit rate set enter normal mode and return
+}
+
+/** 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 )
+{
+    union {                                                             // Access CANid as:
+        CANid x;                                                        // the organised struct
+        uint8_t y[];                                                    // or contiguous memory array
+    };
+
+    for (uint32_t i = 0; i < sizeof(x); i++) y[i] = NULL;               // Initialise CANid structure
+    x.ide = ext;                                                        // Extended Identifier Flag
+    if (x.ide == CANExtended) {
+        x.sid10_3  = (uint8_t) (id >> 21);                              // SID10..3
+        x.sid2_0   = (uint8_t) (id >> 18) & 0x07;                       // SID2..0
+        x.eid17_16 = (uint8_t) (id >> 16) & 0x03;                       // EID17..16
+        x.eid15_8  = (uint8_t) (id >> 8);                               // EID15..8
+        x.eid7_0   = (uint8_t) id;                                      // EID7..0
+    } else {
+        x.sid10_3  = (uint8_t) (id >> 3);                               // SID10..3
+        x.sid2_0   = (uint8_t) (id & 0x07);                             // SID2..0
+    }
+#ifdef DEBUG
+    printf("sizeof CanIdStruct: %d bytes\r\n", sizeof(x));
+    printf("sid10_3: %x\r\n", x.sid10_3);
+    printf("eid17_16: %x\r\n", x.eid17_16);
+    printf("ide: %x\r\n", x.ide);
+    printf("srtr: %x\r\n", x.srtr);
+    printf("sid2_0: %x\r\n", x.sid2_0);
+    printf("eid15_8: %x\r\n", x.eid15_8);
+    printf("eid7_0: %x\r\n", x.eid7_0);
+#endif
+    mcpWriteMultiple(obj,  mcp_addr, y, sizeof(x) );                     // Copy CANid to the MCP2515 (as an array)
+}
+
+/**  write a CAN message to the MCP2515
+ */
+uint8_t mcpCanWrite(can_t *obj, CAN_Message msg)
+{
+    union {                                                             // Access CANMsg as:
+        CANMsg x;                                                       // the organised struct
+        uint8_t y[];                                                    // or contiguous memory array
+    };
+    uint8_t bufferCommand[] = {MCP_WRITE_TX0, MCP_WRITE_TX1, MCP_WRITE_TX2};
+    uint8_t rtsCommand[] = {MCP_RTS_TX0, MCP_RTS_TX1, MCP_RTS_TX2};
+    uint8_t status = mcpStatus(obj);
+    uint32_t num = 0;
+// Check if there is a free message buffer
+    if (!(status & MCP_STAT_TX0REQ)) {                                  // TX Message Buffer 0 free?
+        num = 0;
+    } else if (!(status & MCP_STAT_TX1REQ)) {                           // TX Message Buffer 1 free?
+        num = 1;
+    } else if (!(status & MCP_STAT_TX2REQ)) {                           // TX Message Buffer 2 free?
+        num = 2;
+    } else {
+        return 0;                                                       // No free transmit buffers in the MCP2515 CAN controller chip
+    }
+// populate CANMsg structure
+    for (uint32_t i = 0; i < sizeof(x); i++) y[i] = NULL;               // Initialise CANMsg structure
+    x.id.ide = msg.format;                                              // Extended Identifier Flag
+    if (x.id.ide == CANExtended) {
+        x.id.sid10_3  = (uint8_t) (msg.id >> 21);                       // SID10..3
+        x.id.sid2_0   = (uint8_t) (msg.id >> 18) & 0x07;                // SID2..0
+        x.id.eid17_16 = (uint8_t) (msg.id >> 16) & 0x03;                // EID17..16
+        x.id.eid15_8  = (uint8_t) (msg.id >> 8);                        // EID15..8
+        x.id.eid7_0   = (uint8_t) msg.id;                               // EID7..0
+    } else {
+        x.id.sid10_3  = (uint8_t) (msg.id >> 3);                        // SID10..3
+        x.id.sid2_0   = (uint8_t) (msg.id & 0x07);                      // SID2..0
+    }
+    x.dlc = msg.len & 0x0f;                                             // Number of bytes in can message
+    x.ertr = msg.type;                                                  // Data or remote message
+    memcpy(x.data,msg.data,x.dlc);                                      // Get the Data bytes
+// write CANmsg to the specified TX buffer 'num'
+    mcpWriteBuffer(obj, bufferCommand[num], y, sizeof(x));              // Write the message ,CANMsg, to the MCP2515's Tx buffer 'num' (as an array)
+    mcpBufferRTS(obj, rtsCommand[num]);
+    return 1;                                                           // Indicate that message has been transmitted
+}
+
+/** read a CAN message from the MCP2515
+ */
+uint8_t mcpCanRead(can_t *obj, CAN_Message *msg)
+{
+    union {                                                             // Access CANMsg as:
+        CANMsg x;                                                       // the organised struct
+        uint8_t y[];                                                    // or contiguous memory array
+    };
+    uint8_t bufferCommand[] = {MCP_READ_RX0, MCP_READ_RX1};
+    uint8_t status = mcpReceiveStatus(obj);
+    bool num = 0;
+// Check if there is a message the buffers
+    if (status & MCP_RXSTAT_RXB0) {                                     // Msg in Buffer 0?
+        num = 0;
+    } else if (status & MCP_RXSTAT_RXB1) {                              // Msg in Buffer 1?
+        num = 1;
+    } else {
+        return 0;                                                       // No messages waiting
+    }
+    mcpReadBuffer(obj, bufferCommand[0], y, sizeof(x));                 // Read the message into CANMsg (as an array)
+    mcpBitModify(obj, MCP_CANINTF, (!num ? MCP_RX0IF : MCP_RX1IF), 0);  // Free the message buffer
+#ifdef DEBUG
+    printf("sizeof CanMsgStruct: %d bytes\r\n", sizeof(x));
+    printf("sizeof CanMsgArray: %d bytes\r\n", sizeof(y));
+    printf("sid10_3: %x\r\n", x.id.sid10_3);
+    printf("eid17_16: %x\r\n", x.id.eid17_16);
+    printf("ide: %x\r\n", x.id.ide);
+    printf("srtr: %x\r\n", x.id.srtr);
+    printf("sid2_0: %x\r\n", x.id.sid2_0);
+    printf("eid15_8: %x\r\n", x.id.eid15_8);
+    printf("eid7_0: %x\r\n", x.id.eid7_0);
+    printf("dlc: %x\r\n", x.dlc);
+    printf("ertr: %x\r\n", x.ertr);
+    printf("data: ");
+    for (char i=0; i<8; i++)
+        printf("%02x,", x.data[i]);
+    printf("\r\n");
+#endif
+    msg->format = (status & MCP_RXSTAT_IDE) ? CANExtended : CANStandard;// Extended CAN id Flag
+    if (msg->format == CANExtended) {                                   // Assemble the Extended CAN id
+        msg->id = (x.id.sid10_3 << 21)  |
+                  (x.id.sid2_0 << 18)   |
+                  (x.id.eid17_16 << 16) |
+                  (x.id.eid15_8 << 8)   |
+                  (x.id.eid7_0);
+    } else {                                                            // Assemble the Standard CAN id
+        msg->id = (x.id.sid10_3 << 3)   |
+                  (x.id.sid2_0);
+    }
+    msg->len    = x.dlc;                                                // Number of bytes in CAN message
+    msg->type = (status & MCP_RXSTAT_RTR) ? CANRemote : CANData;        // Determine if a Remote or Data message type
+    memcpy(msg->data,x.data,x.dlc);                                     // Get the Data bytes
+    return 1;                                                           // Indicate that message has been retrieved
+}
+
+/** initialise an Acceptance Mask
+ */
+uint8_t mcpInitMask(can_t *obj, uint8_t num, uint32_t ulData, bool ext)
+{
+    uint8_t mask[2] = { MCP_RXM0SIDH, MCP_RXM1SIDH };
+
+    if (num > 1) {
+#ifdef DEBUG
+        printf("Trying to set an invalid Mask number: %d\r\n", num);
+#endif
+        return 0;
+    }
+#ifdef DEBUG
+    printf("Begin to set Mask!!\r\n");
+#endif
+    if(!mcpSetMode(obj, MODE_CONFIG)) {
+        return 0;
+    }
+    mcpWriteId(obj, mask[num], ext, ulData);
+    if(!mcpSetMode(obj, MODE_NORMAL)) {
+        return 0;
+    }
+#ifdef DEBUG
+    printf("Successfully set Mask number: %d\r\n", num);
+#endif
+    return 1;
+}
+
+/** initialise an Acceptance Filter
+ */
+uint8_t mcpInitFilter(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 };
+
+    if (num > 5) {
+#ifdef DEBUG
+        printf("Trying to set an invalid Filter number: %d\r\n", num);
+#endif
+        return 0;
+    }
+#ifdef DEBUG
+    printf("Begin to set Filter!!\r\n");
+#endif
+    if(!mcpSetMode(obj, MODE_CONFIG)) {
+        return 0;
+    }
+    mcpWriteId(obj, filter[num], ext, ulData);
+    if(!mcpSetMode(obj, MODE_NORMAL)) {
+        return 0;
+    }
+#ifdef DEBUG
+    printf("Successfully set Filter: %d\r\n", num);
+#endif
+    return 1;
+}
+
+/*  Number of message reception errors
+ */
+uint8_t mcpReceptionErrorCount(can_t *obj)
+{
+    return (mcpRead(obj, MCP_REC));
+}
+
+/*  Number of message transmission errors
+ */
+uint8_t mcpTransmissionErrorCount(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)
+{
+    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 which[] = { MODE_NORMAL, MODE_SLEEP, MODE_LOOPBACK, MODE_LISTENONLY, MODE_CONFIG, MODE_CONFIG};
+
+    if (mode == _RESET) {
+        mcpReset(obj);
+    }
+    if (mcpSetMode(obj, which[mode])) {
+        return 1;
+    }
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/seeed_can_api.h	Tue Nov 05 22:37:35 2013 +0000
@@ -0,0 +1,137 @@
+/* seeed_can_api.h
+ * Copyright (c) 2013 Sophie Dexter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _SEEED_CAN_API_H_
+#define _SEEED_CAN_API_H_
+
+#include "seeed_can_spi.h"
+
+// print debug information...
+//#define DEBUG
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** CAN driver typedefs
+ */
+
+// The 'MCP_xyz' structs mimic MCP register organisations
+// A union of the struct and a simple array can be used to:
+//  Process and manipulate the struct in an ordered way
+//  Copy the struct to/from the MCP2512 as an array
+
+/// Type definition to hold an MCP2515 CAN id structure
+    struct MCP_CANtiming {
+        uint8_t phseg2    : 3;      // PS2 length bits 2..0 (PHSEG2 + 1) Tq (minimum valid setting is 2 Tq)
+        uint8_t reserved1 : 3;      // Unused bits (read as '0')
+        uint8_t wakfil    : 1;      // Wake-up filter enable bit (1 = enabled, 0 = disabled)
+        uint8_t sof       : 1;      // Start of frame bit (1 = CLKOUT pin is SOF, 0 = CLKOUT is clock)
+        uint8_t prseg     : 3;      // Propagation Segment length bits 2..0 (PRSEG + 1) Tq (minimum valid setting is 1 Tq)
+        uint8_t phseg1    : 3;      // PS2 length bits 2..0 (PRSEG + 1) Tq (minimum valid setting is 1 Tq)
+        uint8_t sam       : 1;      // Sample Point Configuration bit (1 = Bus line is sampled 3 times, 0 = sampled once)
+        uint8_t btlmode   : 1;      // PS2 Bit Time Length (1 = determined by phseg2, 0 = greater of PS1 an IPT (2 Tq))
+        uint8_t brp       : 6;      // Baud Rate Prescaler bits 5..0 (Tq = 2 x (BRP + 1) / Fosc)
+        uint8_t sjw       : 2;      // Synchronisation Jump Width Length bits 1..0 ((SJW + 1) Tq)
+    };
+    typedef struct MCP_CANtiming CANtiming;
+
+/// Type definition to hold an MCP2515 CAN id structure
+    struct MCP_CANid {
+        uint8_t sid10_3   : 8;      // Bits 10..3 of a standard identifier
+        uint8_t eid17_16  : 2;      // Bits 17..16 of an extended identifier
+        uint8_t reserved1 : 1;      // Unused bit in RXBbSIDL
+        uint8_t ide       : 1;      // Extended Identifier Flag
+        // CANformat 'type'
+        uint8_t srtr      : 1;      // Standard Frame Remote Transmit Request Bit (valid when IDE = 0)
+        // CANtype 'type'
+        // Unimplimented  in TXBnSIDL, filters and acceptance masks
+        uint8_t sid2_0    : 3;      // Bits 2..0 of a standard identifier
+        uint8_t eid15_8   : 8;      // Bits 15..8 of an extended identifier
+        uint8_t eid7_0    : 8;      // Bits 7..0 of an extended identifier
+    };
+    typedef struct MCP_CANid CANid;
+
+/// Type definition to hold an MCP2515 CAN message structure
+    struct MCP_CANMsg {
+        CANid id;
+        uint8_t dlc       : 4;      // Bits 3..0: DLC - Data Length Counter
+        uint8_t reserved1 : 2;      // unused bits in RXBnDLC
+        uint8_t ertr      : 1;      // Extended Frame Remote Transmit Request Bit (valid when IDE = 1)
+        // CANtype 'type'
+        uint8_t reserved2 : 1;      // unused bit in RXBnDLC
+        uint8_t data[8];            // CAN Message Data Bytes 0-7
+    };
+    typedef struct MCP_CANMsg CANMsg;
+
+    enum CANFormat {
+        CANStandard = 0,
+        CANExtended = 1
+    };
+    typedef enum CANFormat CANFormat;
+
+    enum CANType {
+        CANData   = 0,
+        CANRemote = 1
+    };
+    typedef enum CANType CANType;
+
+    struct CAN_Message {
+        unsigned int   id;          // 11 or 29 bit identifier
+        unsigned char  data[8];     // Data field
+        unsigned char  len;         // Length of data field in bytes
+        CANFormat      format;      // 0 - STANDARD, 1- EXTENDED IDENTIFIER
+        CANType        type;        // 0 - DATA FRAME, 1 - REMOTE FRAME
+    };
+    typedef struct CAN_Message CAN_Message;
+    
+    enum MCP_Mode {
+        _NORMAL,
+        _SLEEP,
+        _LOOPBACK,
+        _MONITOR,
+        _CONFIG,
+        _RESET,
+    };
+    typedef MCP_Mode CANMode;
+
+/** 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
+    
+    void mcpWriteId(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 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 mcpReceptionErrorCount(can_t *obj);                         // number of message reception errors
+    uint8_t mcpTransmissionErrorCount(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
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif    // SEEED_CAN_API_H
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/seeed_can_defs.h	Tue Nov 05 22:37:35 2013 +0000
@@ -0,0 +1,258 @@
+/* seeed_can_defs.h
+ * Copyright (c) 2013 Sophie Dexter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef SEEED_CAN_DEFS_H
+#define SEEED_CAN_DEFS_H
+
+#include "mbed.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    /** FRDM-KL25Z port pins used by Seeed Studios CAN-BUS Shield
+     */
+#define SEEED_CAN_MOSI      PTD2
+#define SEEED_CAN_MISO      PTD3
+#define SEEED_CAN_CLK       PTD1
+#define SEEED_CAN_CS        PTD0
+#define SEEED_CAN_IO9       PTD5
+#define SEEED_CAN_IRQ       PTD4
+    /** Define MCP2515 register addresses
+     */
+#define MCP_RXF0SIDH        0x00
+#define MCP_RXF0SIDL        0x01
+#define MCP_RXF0EID8        0x02
+#define MCP_RXF0EID0        0x03
+#define MCP_RXF1SIDH        0x04
+#define MCP_RXF1SIDL        0x05
+#define MCP_RXF1EID8        0x06
+#define MCP_RXF1EID0        0x07
+#define MCP_RXF2SIDH        0x08
+#define MCP_RXF2SIDL        0x09
+#define MCP_RXF2EID8        0x0A
+#define MCP_RXF2EID0        0x0B
+#define MCP_CANSTAT         0x0E
+#define MCP_CANCTRL         0x0F
+#define MCP_RXF3SIDH        0x10
+#define MCP_RXF3SIDL        0x11
+#define MCP_RXF3EID8        0x12
+#define MCP_RXF3EID0        0x13
+#define MCP_RXF4SIDH        0x14
+#define MCP_RXF4SIDL        0x15
+#define MCP_RXF4EID8        0x16
+#define MCP_RXF4EID0        0x17
+#define MCP_RXF5SIDH        0x18
+#define MCP_RXF5SIDL        0x19
+#define MCP_RXF5EID8        0x1A
+#define MCP_RXF5EID0        0x1B
+#define MCP_TEC             0x1C
+#define MCP_REC             0x1D
+#define MCP_RXM0SIDH        0x20
+#define MCP_RXM0SIDL        0x21
+#define MCP_RXM0EID8        0x22
+#define MCP_RXM0EID0        0x23
+#define MCP_RXM1SIDH        0x24
+#define MCP_RXM1SIDL        0x25
+#define MCP_RXM1EID8        0x26
+#define MCP_RXM1EID0        0x27
+#define MCP_CNF3            0x28
+#define MCP_CNF2            0x29
+#define MCP_CNF1            0x2A
+#define MCP_CANINTE         0x2B
+#define MCP_CANINTF         0x2C
+#define MCP_EFLG            0x2D
+#define MCP_TXB0CTRL        0x30
+#define MCP_TXB1CTRL        0x40
+#define MCP_TXB2CTRL        0x50
+#define MCP_RXB0CTRL        0x60
+#define MCP_RXB0SIDH        0x61
+#define MCP_RXB1CTRL        0x70
+#define MCP_RXB1SIDH        0x71
+    /** Define MCP2515 SPI Instructions
+     */
+#define MCP_WRITE           0x02
+
+#define MCP_READ            0x03
+
+#define MCP_BITMOD          0x05
+
+#define MCP_WRITE_TX0       0x40
+#define MCP_WRITE_TX1       0x42
+#define MCP_WRITE_TX2       0x44
+
+#define MCP_RTS_TX0         0x81
+#define MCP_RTS_TX1         0x82
+#define MCP_RTS_TX2         0x84
+#define MCP_RTS_ALL         0x87
+
+#define MCP_READ_RX0        0x90
+#define MCP_READ_RX1        0x94
+
+#define MCP_READ_STATUS     0xA0
+
+#define MCP_RX_STATUS       0xB0
+
+#define MCP_RESET           0xC0
+
+//#define TIMEOUTVALUE        50
+//#define MCP_SIDH            0
+//#define MCP_SIDL            1
+//#define MCP_EID8            2
+//#define MCP_EID0            3
+
+#define MCP_TXB_EXIDE_M     0x08                                        /* In TXBnSIDL                  */
+#define MCP_DLC_MASK        0x0F                                        /* 4 LSBits                     */
+#define MCP_RTR_MASK        0x40                                        /* (1<<6) Bit 6                 */
+
+#define MCP_RXB_RX_ANY      0x60
+#define MCP_RXB_RX_EXT      0x40
+#define MCP_RXB_RX_STD      0x20
+#define MCP_RXB_RX_STDEXT   0x00
+#define MCP_RXB_RX_MASK     0x60
+#define MCP_RXB_BUKT_MASK   (1<<2)
+    /** Bits in the TXBnCTRL registers.
+     */
+#define MCP_TXB_TXBUFE_M    0x80
+#define MCP_TXB_ABTF_M      0x40
+#define MCP_TXB_MLOA_M      0x20
+#define MCP_TXB_TXERR_M     0x10
+#define MCP_TXB_TXREQ_M     0x08
+#define MCP_TXB_TXIE_M      0x04
+#define MCP_TXB_TXP10_M     0x03
+
+#define MCP_TXB_RTR_M       0x40                                        /* In TXBnDLC                   */
+#define MCP_RXB_IDE_M       0x08                                        /* In RXBnSIDL                  */
+#define MCP_RXB_RTR_M       0x40                                        /* In RXBnDLC                   */
+
+    /** STATUS Command Values
+     */
+#define MCP_STAT_RXIF_MASK  (0x03)
+#define MCP_STAT_RX0IF      (1<<0)
+#define MCP_STAT_RX1IF      (1<<1)
+#define MCP_STAT_TX0REQ     (1<<2)
+#define MCP_STAT_TX0IF      (1<<3)
+#define MCP_STAT_TX1REQ     (1<<4)
+#define MCP_STAT_TX1IF      (1<<5)
+#define MCP_STAT_TX2REQ     (1<<6)
+#define MCP_STAT_TX2IF      (1<<7)
+
+    /** RX STATUS Command Values
+     */
+#define MCP_RXSTAT_RXF_MASK (7<<0)
+#define MCP_RXSTAT_RXF0     (0<<0)
+#define MCP_RXSTAT_RXF1     (1<<0)
+#define MCP_RXSTAT_RXF2     (2<<0)
+#define MCP_RXSTAT_RXF3     (3<<0)
+#define MCP_RXSTAT_RXF4     (4<<0)
+#define MCP_RXSTAT_RXF5     (5<<0)
+#define MCP_RXSTAT_RXROF0   (6<<0)                                      // RXF0 rollover to RXB1
+#define MCP_RXSTAT_RXROF1   (7<<0)                                      // RXF1 rollover to RXB1
+#define MCP_RXSTAT_RTR      (1<<3)
+#define MCP_RXSTAT_IDE      (1<<4)
+#define MCP_RXSTAT_RXB_MASK (3<<6)
+#define MCP_RXSTAT_NONE     (0<<6)
+#define MCP_RXSTAT_RXB0     (1<<6)
+#define MCP_RXSTAT_RXB1     (2<<6)
+#define MCP_RXSTAT_BOTH     (3<<6)
+
+    /** EFLG Register Values
+     */
+#define MCP_EFLG_ERRORMASK  (0xF8)                                      /* 5 MS-Bits                    */
+#define MCP_EFLG_EWARN      (1<<0)
+#define MCP_EFLG_RXWAR      (1<<1)
+#define MCP_EFLG_TXWAR      (1<<2)
+#define MCP_EFLG_RXEP       (1<<3)
+#define MCP_EFLG_TXEP       (1<<4)
+#define MCP_EFLG_TXBO       (1<<5)
+#define MCP_EFLG_RX0OVR     (1<<6)
+#define MCP_EFLG_RX1OVR     (1<<7)
+
+    /** CANCTRL Register Values
+     */
+#define CLKOUT_PS1          (0<<0)
+#define CLKOUT_PS2          (1<<0)
+#define CLKOUT_PS4          (2<<0)
+#define CLKOUT_PS8          (3<<0)
+#define CLKOUT_ENABLE       (1<<2)
+#define CLKOUT_DISABLE      (0<<2)
+#define MODE_ONESHOT        (1<<3)
+#define ABORT_TX            (1<<4)
+#define MODE_NORMAL         (0<<5)
+#define MODE_SLEEP          (1<<5)
+#define MODE_LOOPBACK       (2<<5)
+#define MODE_LISTENONLY     (3<<5)
+#define MODE_CONFIG         (4<<5)
+#define MODE_POWERUP        (7<<5)
+#define MODE_MASK           (7<<5)
+
+    /** 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 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
+#define MCP_MIN_TIME_QUANTA     8
+#define MCP_MAX_PRESCALER       64
+#define MCP_MIN_PRESCALER       1
+    /** CNF1 Register Values
+     */
+#define SJW1                (0<<6)
+#define SJW2                (1<<6)
+#define SJW3                (2<<6)
+#define SJW4                (3<<6)
+    /** CNF2 Register Values
+     */
+#define BTLMODE             (1<<7)
+#define SAMPLE_1X           (0<<4)
+#define SAMPLE_3X           (1<<4)
+    /** CNF3 Register Values
+     */
+#define WAKFIL_ENABLE       (1<<4)
+#define WAKFIL_DISABLE      (0<<4)
+#define SOF_ENABLE          (1<<7)
+#define SOF_DISABLE         (0<<7)
+    /** CANINTF Register Bits
+     */
+#define MCP_RX0IF           (1<<0)
+#define MCP_RX1IF           (1<<1)
+#define MCP_TX0IF           (1<<2)
+#define MCP_TX1IF           (1<<3)
+#define MCP_TX2IF           (1<<4)
+#define MCP_ERRIF           (1<<5)
+#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)
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif    // SEEED_CAN_DEFS_H
+/*********************************************************************************************************
+  END FILE
+*********************************************************************************************************/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/seeed_can_spi.cpp	Tue Nov 05 22:37:35 2013 +0000
@@ -0,0 +1,149 @@
+/* seeed_can_spi.cpp
+ * Copyright (c) 2013 Sophie Dexter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#include "seeed_can_spi.h"
+
+/** reset the MCP2515
+ */
+void mcpReset(can_t *obj)
+{
+    obj->ncs = 0;
+    obj->spi.write(MCP_RESET);
+    obj->ncs = 1;
+    wait_ms(10);
+}
+
+/** read from a single MCP2515 register
+ */
+uint8_t mcpRead(can_t *obj, const uint8_t address)
+{
+    uint8_t result;
+
+    obj->ncs = 0;
+    obj->spi.write(MCP_READ);
+    obj->spi.write(address);
+    result = obj->spi.write(0x00);
+    obj->ncs = 1;
+    return result;
+}
+
+/** 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)
+{
+    obj->ncs = 0;
+    obj->spi.write(MCP_READ);
+    obj->spi.write(address);
+    for (uint32_t i=0; i<n; i++) {
+        values[i] = obj->spi.write(0x00);
+    }
+    obj->ncs = 1;
+}
+
+/** 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)
+{
+    obj->ncs = 0;
+    obj->spi.write(command);
+    for (uint32_t i=0; i<n; i++) {
+        values[i] = obj->spi.write(0x00);
+    }
+    obj->ncs = 1;
+}
+
+/**  write to a single MCP2515 register
+ */
+void mcpWrite(can_t *obj, const uint8_t address, const uint8_t value)
+{
+    obj->ncs = 0;
+    obj->spi.write(MCP_WRITE);
+    obj->spi.write(address);
+    obj->spi.write(value);
+    obj->ncs = 1;
+}
+
+/** 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)
+{
+    obj->ncs = 0;
+    obj->spi.write(MCP_WRITE);
+    obj->spi.write(address);
+    for (uint32_t i=0; i<n; i++) {
+        obj->spi.write(values[i]);
+    }
+    obj->ncs = 1;
+}
+
+/** 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)
+{
+    obj->ncs = 0;
+    obj->spi.write(command);
+    for (uint32_t i=0; i<n; i++) {
+        obj->spi.write(values[i]);
+    }
+    obj->ncs = 1;
+}
+
+/** initiate transmission of the specified MCP2515 transmit buffer
+ */
+void mcpBufferRTS(can_t *obj, const uint8_t command)
+{
+    obj->ncs = 0;
+    obj->spi.write(command);
+    obj->ncs = 1;
+}
+
+/**  read mcp2515's status register
+ */
+uint8_t mcpStatus(can_t *obj)
+{
+    uint8_t status;
+
+    obj->ncs = 0;
+    obj->spi.write(MCP_READ_STATUS);
+    status = obj->spi.write(0x00);
+    obj->ncs = 1;
+    return status;
+}
+
+/**  read mcp2515's receive status register
+ */
+uint8_t mcpReceiveStatus(can_t *obj)
+{
+    uint8_t status;
+
+    obj->ncs = 0;
+    obj->spi.write(MCP_RX_STATUS);
+    status = obj->spi.write(0x00);
+    obj->ncs = 1;
+    return status;
+}
+
+/** 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)
+{
+    obj->ncs = 0;
+    obj->spi.write(MCP_BITMOD);
+    obj->spi.write(address);
+    obj->spi.write(mask);
+    obj->spi.write(data);
+    obj->ncs = 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/seeed_can_spi.h	Tue Nov 05 22:37:35 2013 +0000
@@ -0,0 +1,76 @@
+/* seeed_can_spi.h
+ * Copyright (c) 2013 Sophie Dexter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _SEEED_CAN_SPI_H_
+#define _SEEED_CAN_SPI_H_
+
+#include "seeed_can_defs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    /** CAN driver typedefs
+     */
+    struct Seeed_MCP_CAN_Shield {
+        SPI             spi;
+        DigitalOut      ncs;
+        InterruptIn     irq;
+        Seeed_MCP_CAN_Shield(SPI _spi_, DigitalOut _ncs_, InterruptIn _irq_) :
+            spi(_spi_),
+            ncs(_ncs_),
+            irq(_irq_)
+        {}
+    };
+    typedef struct Seeed_MCP_CAN_Shield can_t;
+
+    /** mcp2515 spi instructions
+     */
+    void mcpReset(can_t *obj);                                          // reset the MCP2515 CAN controller chip
+
+    uint8_t mcpRead(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
+                         const uint8_t address,
+                         uint8_t values[],
+                         const uint8_t n);
+    void mcpReadBuffer(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
+                  const uint8_t address,
+                  const uint8_t value);
+    void mcpWriteMultiple(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
+                        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
+                      const uint8_t address,
+                      const uint8_t mask,
+                      const uint8_t data);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif    // SEEED_CAN_SPI_H
\ No newline at end of file