mcp2515: Initial implementation; C; C++

The mcp2515 is a CAN bus controller.  It was developed using the Seeed
CAN bus shield.

Signed-off-by: Jon Trulson <jtrulson@ics.com>
This commit is contained in:
Jon Trulson 2016-11-10 11:55:48 -07:00
parent 5eb8af6d70
commit fcb4d9d36d
23 changed files with 4129 additions and 0 deletions

View File

@ -327,6 +327,7 @@ add_example (ecezo)
add_example (mb704x) add_example (mb704x)
add_example (rf22-server) add_example (rf22-server)
add_example (rf22-client) add_example (rf22-client)
add_example (mcp2515)
# These are special cases where you specify example binary, source file and module(s) # These are special cases where you specify example binary, source file and module(s)
include_directories (${PROJECT_SOURCE_DIR}/src) include_directories (${PROJECT_SOURCE_DIR}/src)
@ -369,3 +370,4 @@ if (OPENZWAVE_FOUND)
add_custom_example (tzemt400-example-cxx tzemt400.cxx ozw) add_custom_example (tzemt400-example-cxx tzemt400.cxx ozw)
endif() endif()
add_custom_example (nmea_gps_i2c_example-cxx nmea_gps_i2c.cxx nmea_gps) add_custom_example (nmea_gps_i2c_example-cxx nmea_gps_i2c.cxx nmea_gps)
add_custom_example (mcp2515-txrx-example-cxx mcp2515-txrx.cxx mcp2515)

View File

@ -0,0 +1,125 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <unistd.h>
#include <stdio.h>
#include <iostream>
#include <signal.h>
#include <upm_utilities.h>
#include "mcp2515.hpp"
using namespace std;
bool shouldRun = true;
void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
}
int main(int argc, char **argv)
{
signal(SIGINT, sig_handler);
// by default we just receive packets
bool do_tx = false;
// if an argument is given, we will transmit packets
if (argc > 1)
do_tx = true;
//! [Interesting]
// NOTE: This example assumes that only two devices are connected
// to the CAN bus, and that both devices are running this example;
// one in TX (transmit) mode, and one in RX (receive) mode.
// If this is not the case, then in rx mode you may see other
// packets from other devices, or not, depending on whether the
// speed is correct for the network. In tx mode, errors may be
// generated on the bus, especially if the CAN bus speed does not
// match the rest of the network.
// You should start the receiver example first. The transmitter
// example will fail after about 5 seconds (timeout) of not being
// able to transmit a message.
// Instantiate a MCP2515 on SPI bus 0 using a hw CS pin (-1).
upm::MCP2515 *sensor = new upm::MCP2515(0, 9);
// By default, after initialization, the baud rate is set to
// 50Kbps, and the mode is NORMAL, so we don't need to set any of
// that here.
// our TX payload. If transmitting, the first number will be
// incremented (and rollover) on each transmission.
string myPayload = "01234567";
while (shouldRun)
{
if (do_tx)
{
cout << "Loading a packet of 8 numbers (0-7) into a TX buffer..."
<< endl;
sensor->loadTXBuffer(MCP2515_TX_BUFFER0, 0, false, false,
myPayload);
// now lets try to transmit it
cout << "Transmitting packet..." << endl;
sensor->transmitBuffer(MCP2515_TX_BUFFER0, true);
myPayload[0]++;
cout << "Transmit successful" << endl;
cout << endl;
upm_delay_ms(500);
}
else
{
// RX mode
// Look for a packet waiting for us in RXB0
if (sensor->rxStatusMsgs() == MCP2515_RXMSG_RXB0)
{
cout << "Packet received in RXB0, decoding..." << endl;
// now lets retrieve and print it
sensor->getRXMsg(MCP2515_RX_BUFFER0);
sensor->printMsg();
cout << endl;
}
upm_delay_ms(100);
}
}
cout << "Exiting..." << endl;
delete sensor;
//! [Interesting]
return 0;
}

79
examples/c++/mcp2515.cxx Normal file
View File

@ -0,0 +1,79 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <unistd.h>
#include <stdio.h>
#include <iostream>
#include "mcp2515.hpp"
using namespace std;
int main(int argc, char **argv)
{
//! [Interesting]
// Instantiate a MCP2515 on SPI bus 0 using a hw CS pin (-1).
upm::MCP2515 *sensor = new upm::MCP2515(0, -1);
cout << "Setting loopback mode..." << endl;
// set the mode to loopback mode. In loopback mode, transmitted
// packets are sent directly to an appropriate receive buffer
// without actually going out onto the CAN bus.
sensor->setOpmode(MCP2515_OPMODE_LOOPBACK);
// lets build up a packet and try loading it (8 bytes max).
string myPayload = "01234567";
cout << "Loading a packet of 8 numbers (0-7) into a TX buffer..." << endl;
sensor->loadTXBuffer(MCP2515_TX_BUFFER0, 0, false, false, myPayload);
// now lets try to transmit it
cout << "Transmitting packet..." << endl;
sensor->transmitBuffer(MCP2515_TX_BUFFER0, true);
cout << "Transmit successful" << endl;
// There should now be a packet waiting for us in RXB0
if (sensor->rxStatusMsgs() == MCP2515_RXMSG_RXB0)
{
cout << "Packet received in RXB0, decoding..." << endl;
// now lets retrieve and print it
sensor->getRXMsg(MCP2515_RX_BUFFER0);
sensor->printMsg();
}
else
{
cout << "No packet found, how strange." << endl;
}
cout << "Exiting..." << endl;
delete sensor;
//! [Interesting]
return 0;
}

View File

@ -141,6 +141,7 @@ add_example (ms5803)
add_example (ims) add_example (ims)
add_example (ecezo) add_example (ecezo)
add_example (mb704x) add_example (mb704x)
add_example (mcp2515)
# Custom examples # Custom examples
add_custom_example (nmea_gps_i2c-example-c nmea_gps_i2c.c nmea_gps) add_custom_example (nmea_gps_i2c-example-c nmea_gps_i2c.c nmea_gps)
@ -149,3 +150,4 @@ add_custom_example (lcm1602-parallel-example-c lcm1602-parallel.c lcm1602)
add_custom_example (rpr220-intr-example-c rpr220-intr.c rpr220) add_custom_example (rpr220-intr-example-c rpr220-intr.c rpr220)
add_custom_example (md-stepper-example-c md-stepper.c md) add_custom_example (md-stepper-example-c md-stepper.c md)
add_custom_example (button_intr-example-c button_intr.c button) add_custom_example (button_intr-example-c button_intr.c button)
add_custom_example (mcp2515-txrx-example-c mcp2515-txrx.c mcp2515)

144
examples/c/mcp2515-txrx.c Normal file
View File

@ -0,0 +1,144 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <upm_utilities.h>
#include "mcp2515.h"
bool shouldRun = true;
void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
}
int main(int argc, char **argv)
{
signal(SIGINT, sig_handler);
// by default we just receive packets
bool do_tx = false;
// if an argument is given, we will transmit packets
if (argc > 1)
do_tx = true;
//! [Interesting]
// NOTE: This example assumes that only two devices are connected
// to the CAN bus, and that both devices are running this example;
// one in TX (transmit) mode, and one in RX (receive) mode.
// If this is not the case, then in rx mode you may see other
// packets from other devices, or not, depending on whether the
// speed is correct for the network. In tx mode, errors may be
// generated on the bus, especially if the CAN bus speed does not
// match the rest of the network.
// You should start the receiver example first. The transmitter
// example will fail after about 5 seconds (timeout) of not being
// able to transmit a message.
// Instantiate a MCP2515 on SPI bus 0 using a hw CS pin (-1).
mcp2515_context sensor = mcp2515_init(0, -1);
if (!sensor)
{
printf("mcp2515_init() failed\n");
return 1;
}
// By default, after initialization, the baud rate is set to
// 50Kbps, and the mode is NORMAL, so we don't need to set any of
// that here.
if (!do_tx)
printf("RX mode, waiting for packets...\n");
// our TX payload. If transmitting, the first number will be
// incremented (and rollover) on each transmission.
uint8_t myPayload[8] = {0, 1, 2, 3, 4, 5, 6, 7};
while (shouldRun)
{
if (do_tx)
{
// lets build up a packet and try loading it.
printf("Loading a packet of 8 numbers into a tx buffer...\n");
if (mcp2515_load_tx_buffer(sensor, MCP2515_TX_BUFFER0, 0,
false, false, myPayload, 8))
{
printf("mcp2515_load_tx_buffer() failed\n");
return 1;
}
// now lets try to transmit it
printf("Transmitting packet...\n");
upm_result_t rv = 0;
if ((rv = mcp2515_transmit_buffer(sensor, MCP2515_TX_BUFFER0,
true)))
{
printf("mcp2515_transmit_buffer() failed with code %d\n", rv);
return 1;
}
// increment the first number for each transmission
myPayload[0]++;
printf("Transmit successful\n\n");
upm_delay_ms(500);
}
else
{
// RX mode
// Look for a packet waiting for us in RXB0
if (mcp2515_rx_status_msgs(sensor) == MCP2515_RXMSG_RXB0)
{
printf("Packet received in RXB0, decoding...\n");
// now lets retrieve it
MCP2515_MSG_T msg;
if (mcp2515_get_rx_msg(sensor, MCP2515_RX_BUFFER0, &msg))
{
printf("mcp2515_get_rx_msg() failed\n");
return 1;
}
mcp2515_print_msg(sensor, &msg);
printf("\n");
}
upm_delay_ms(100);
}
}
printf("Exiting...\n");
mcp2515_close(sensor);
//! [Interesting]
return 0;
}

101
examples/c/mcp2515.c Normal file
View File

@ -0,0 +1,101 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <unistd.h>
#include <stdio.h>
#include "mcp2515.h"
int main(int argc, char **argv)
{
//! [Interesting]
// Instantiate a MCP2515 on SPI bus 0 using a hw CS pin (-1).
mcp2515_context sensor = mcp2515_init(0, -1);
if (!sensor)
{
printf("mcp2515_init() failed\n");
return 1;
}
printf("Setting loopback mode...\n");
// set the mode to loopback mode. In loopback mode, transmitted
// packets are sent directly to an appropriate receive buffer
// without actually going out onto the CAN bus.
if (mcp2515_set_opmode(sensor, MCP2515_OPMODE_LOOPBACK))
{
printf("mcp2515_set_opmode(loopback) failed.\n");
return 1;
}
// lets build up a packet and try loading it.
uint8_t myPayload[8] = {0, 1, 2, 3, 4, 5, 6, 7};
printf("Loading a packet of 8 numbers (0-7) into a TX buffer...\n");
if (mcp2515_load_tx_buffer(sensor, MCP2515_TX_BUFFER0, 0, false, false,
myPayload, 8))
{
printf("mcp2515_load_tx_buffer() failed\n");
return 1;
}
// now lets try to transmit it
printf("Transmitting packet...\n");
upm_result_t rv = 0;
if ((rv = mcp2515_transmit_buffer(sensor, MCP2515_TX_BUFFER0, true)))
{
printf("mcp2515_transmit_buffer() failed with code %d\n", rv);
return 1;
}
printf("Transmit successful\n");
// There should now be a packet waiting for us in RXB0
if (mcp2515_rx_status_msgs(sensor) == MCP2515_RXMSG_RXB0)
{
printf("Packet received in RXB0, decoding...\n");
// now lets retrieve it
MCP2515_MSG_T msg;
if (mcp2515_get_rx_msg(sensor, MCP2515_RX_BUFFER0, &msg))
{
printf("mcp2515_get_rx_msg() failed\n");
return 1;
}
mcp2515_print_msg(sensor, &msg);
}
else
{
printf("No packet found, how strange.\n");
}
printf("Exiting...\n");
mcp2515_close(sensor);
//! [Interesting]
return 0;
}

View File

@ -160,6 +160,7 @@ add_example(MS5803_Example ms5803)
add_example(ECEZO_Example ecezo) add_example(ECEZO_Example ecezo)
add_example(IMS_Example ims) add_example(IMS_Example ims)
add_example(MB704X_Example mb704x) add_example(MB704X_Example mb704x)
add_example(MCP2515_Example mcp2515)
add_example_with_path(Jhd1313m1_lcdSample lcd i2clcd) add_example_with_path(Jhd1313m1_lcdSample lcd i2clcd)
add_example_with_path(Jhd1313m1Sample lcd i2clcd) add_example_with_path(Jhd1313m1Sample lcd i2clcd)
@ -181,3 +182,4 @@ if (OPENZWAVE_FOUND)
add_example_with_path(TZEMT400_Example ozw ozw) add_example_with_path(TZEMT400_Example ozw ozw)
endif() endif()
add_example_with_path(NMEAGPS_I2C_Example nmea_gps nmea_gps) add_example_with_path(NMEAGPS_I2C_Example nmea_gps nmea_gps)
add_example_with_path(MCP2515_TXRX_Example mcp2515 mcp2515)

View File

@ -0,0 +1,73 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import upm_mcp2515.MCP2515;
public class MCP2515_Example
{
public static void main(String[] args) throws InterruptedException
{
// ! [Interesting]
// Instantiate a MCP2515 on SPI bus 0 using a hw CS pin (-1).
MCP2515 sensor = new MCP2515(0, -1);
// set the mode to loopback mode. In loopback mode, transmitted
// packets are sent directly to an appropriate receive buffer
// without actually going out onto the CAN bus.
sensor.setOpmode(upm_mcp2515.MCP2515_OPMODE_T.MCP2515_OPMODE_LOOPBACK);
// lets build up a packet and try loading it (8 bytes max).
String myPayload = "01234567";
System.out.println("Loading a packet of 8 numbers (0-7) into a TX buffer...");
sensor.loadTXBuffer(upm_mcp2515.MCP2515_TX_BUFFER_T.MCP2515_TX_BUFFER0,
0, false, false, myPayload);
// now lets try to transmit it
System.out.println("Transmitting packet...");
sensor.transmitBuffer(upm_mcp2515.MCP2515_TX_BUFFER_T.MCP2515_TX_BUFFER0,
true);
System.out.println("Transmit successful");
// There should now be a packet waiting for us in RXB0
if (sensor.rxStatusMsgs() == upm_mcp2515.MCP2515_RXMSG_T.MCP2515_RXMSG_RXB0)
{
System.out.println("Packet received in RXB0, decoding...");
// now lets retrieve and print it
sensor.getRXMsg(upm_mcp2515.MCP2515_RX_BUFFER_T.MCP2515_RX_BUFFER0);
sensor.printMsg();
}
else
{
System.out.println("No packet found, how strange.");
}
System.out.println("Exiting...");
// ! [Interesting]
}
}

View File

@ -0,0 +1,94 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import upm_mcp2515.MCP2515;
public class MCP2515_TXRX_Example
{
public static void main(String[] args) throws InterruptedException
{
// ! [Interesting]
// by default we just receive packets
Boolean do_tx = false;
if (args.length > 0)
do_tx = true;
// Instantiate a MCP2515 on SPI bus 0 using a hw CS pin (-1).
MCP2515 sensor = new MCP2515(0, -1);
// NOTE: This example assumes that only two devices are connected
// to the CAN bus, and that both devices are running this example;
// one in TX (transmit) mode, and one in RX (receive) mode.
// If this is not the case, then in rx mode you may see other
// packets from other devices, or not, depending on whether the
// speed is correct for the network. In tx mode, errors may be
// generated on the bus, especially if the CAN bus speed does not
// match the rest of the network.
// You should start the receiver example first. The transmitter
// example will fail after about 5 seconds (timeout) of not being
// able to transmit a message.
while (true)
{
if (do_tx)
{
// lets build up a packet and try loading it (8 bytes max).
String myPayload = "01234567";
System.out.println("Loading a packet of 8 numbers (0-7) into a TX buffer...");
sensor.loadTXBuffer(upm_mcp2515.MCP2515_TX_BUFFER_T.MCP2515_TX_BUFFER0,
0, false, false, myPayload);
// now lets try to transmit it
System.out.println("Transmitting packet...");
sensor.transmitBuffer(upm_mcp2515.MCP2515_TX_BUFFER_T.MCP2515_TX_BUFFER0,
true);
System.out.println("Transmit successful");
System.out.println();
Thread.sleep(500);
}
else
{
// There should now be a packet waiting for us in RXB0
if (sensor.rxStatusMsgs() == upm_mcp2515.MCP2515_RXMSG_T.MCP2515_RXMSG_RXB0)
{
System.out.println("Packet received in RXB0, decoding...");
// now lets retrieve and print it
sensor.getRXMsg(upm_mcp2515.MCP2515_RX_BUFFER_T.MCP2515_RX_BUFFER0);
sensor.printMsg();
System.out.println();
}
Thread.sleep(100);
}
}
// ! [Interesting]
}
}

View File

@ -0,0 +1,94 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
var sensorObj = require('jsupm_mcp2515');
// Instantiate a MCP2515 on SPI bus 0 using a hw CS pin (-1).
var sensor = new sensorObj.MCP2515(0, -1);
// NOTE: This example assumes that only two devices are connected
// to the CAN bus, and that both devices are running this example;
// one in TX (transmit) mode, and one in RX (receive) mode.
// If this is not the case, then in rx mode you may see other
// packets from other devices, or not, depending on whether the
// speed is correct for the network. In tx mode, errors may be
// generated on the bus, especially if the CAN bus speed does not
// match the rest of the network.
// You should start the receiver example first. The transmitter
// example will fail after about 5 seconds (timeout) of not being
// able to transmit a message.
function transmit(sensor)
{
// lets build up a packet and try loading it (8 bytes max).
var myPayload = "01234567";
console.log("Loading a packet of 8 numbers (0-7) into a TX buffer...");
sensor.loadTXBuffer(sensorObj.MCP2515_TX_BUFFER0,
0, false, false, myPayload);
// now lets try to transmit it
console.log("Transmitting packet...");
sensor.transmitBuffer(sensorObj.MCP2515_TX_BUFFER0, true);
console.log("Transmit successful");
console.log();
}
function receive(sensor)
{
// There should now be a packet waiting for us in RXB0
if (sensor.rxStatusMsgs() == sensorObj.MCP2515_RXMSG_RXB0)
{
console.log("Packet received in RXB0, decoding...");
// now lets retrieve and print it
sensor.getRXMsg(sensorObj.MCP2515_RX_BUFFER0);
sensor.printMsg();
console.log();
}
}
// by default we just receive packets
if (process.argv.length > 2)
{
// transmit mode
interval = setInterval(function() { transmit(sensor); }, 500);
}
else
{
// receive mode
interval = setInterval(function() { receive(sensor); }, 100);
}
process.on('SIGINT', function()
{
sensor = null;
sensorObj.cleanUp();
sensorObj = null;
console.log("Exiting...");
process.exit(0);
});

View File

@ -0,0 +1,66 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
var sensorObj = require('jsupm_mcp2515');
// Instantiate a MCP2515 on SPI bus 0 using a hw CS pin (-1).
var sensor = new sensorObj.MCP2515(0, -1);
// set the mode to loopback mode. In loopback mode, transmitted
// packets are sent directly to an appropriate receive buffer
// without actually going out onto the CAN bus.
sensor.setOpmode(sensorObj.MCP2515_OPMODE_LOOPBACK);
// lets build up a packet and try loading it (8 bytes max).
var myPayload = "01234567";
console.log("Loading a packet of 8 numbers (0-7) into a TX buffer...");
sensor.loadTXBuffer(sensorObj.MCP2515_TX_BUFFER0, 0, false, false, myPayload);
// now lets try to transmit it
console.log("Transmitting packet...");
sensor.transmitBuffer(sensorObj.MCP2515_TX_BUFFER0, true);
console.log("Transmit successful");
// There should now be a packet waiting for us in RXB0
if (sensor.rxStatusMsgs() == sensorObj.MCP2515_RXMSG_RXB0)
{
console.log("Packet received in RXB0, decoding...");
// now lets retrieve and print it
sensor.getRXMsg(sensorObj.MCP2515_RX_BUFFER0);
sensor.printMsg();
}
else
{
console.log("No packet found, how strange.");
}
console.log("Exiting...");
sensor = null;
sensorObj.cleanUp();
sensorObj = null;
process.exit(0);

99
examples/python/mcp2515-txrx.py Executable file
View File

@ -0,0 +1,99 @@
#!/usr/bin/python
# Author: Jon Trulson <jtrulson@ics.com>
# Copyright (c) 2016 Intel Corporation.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
from __future__ import print_function
import time, sys, signal, atexit
from upm import pyupm_mcp2515 as MCP2515
def main():
# Instantiate a MCP2515 on SPI bus 0 using a hw CS pin (-1).
sensor = MCP2515.MCP2515(0, -1)
## Exit handlers ##
# This function stops python from printing a stacktrace when you
# hit control-C
def SIGINTHandler(signum, frame):
raise SystemExit
# This function lets you run code on exit, including functions from sensor
def exitHandler():
print("Exiting")
sys.exit(0)
# Register exit handlers
atexit.register(exitHandler)
signal.signal(signal.SIGINT, SIGINTHandler)
# by default we just receive packets
do_tx = False;
if (len(sys.argv) > 1):
do_tx = True
# NOTE: This example assumes that only two devices are connected
# to the CAN bus, and that both devices are running this example;
# one in TX (transmit) mode, and one in RX (receive) mode.
# If this is not the case, then in rx mode you may see other
# packets from other devices, or not, depending on whether the
# speed is correct for the network. In tx mode, errors may be
# generated on the bus, especially if the CAN bus speed does not
# match the rest of the network.
# You should start the receiver example first. The transmitter
# example will fail after about 5 seconds (timeout) of not being
# able to transmit a message.
# By default, after initialization, the baud rate is set to
# 50Kbps, and the mode is NORMAL, so we don't need to set any of
# that here.
while (True):
if (do_tx):
print("Loading a packet of 8 numbers (0-7) into a TX buffer...")
myPayload = "01234567";
sensor.loadTXBuffer(MCP2515.MCP2515_TX_BUFFER0, 0, False,
False, myPayload);
# now lets try to transmit it
print("Transmitting packet...")
sensor.transmitBuffer(MCP2515.MCP2515_TX_BUFFER0, True)
print("Transmit successful")
print()
time.sleep(.5)
else:
# RX mode
# Look for a packet waiting for us in RXB0
if (sensor.rxStatusMsgs() == MCP2515.MCP2515_RXMSG_RXB0):
print("Packet received in RXB0, decoding...")
# now lets retrieve and print it
sensor.getRXMsg(MCP2515.MCP2515_RX_BUFFER0)
sensor.printMsg();
print()
print("Exiting...")
if __name__ == '__main__':
main()

79
examples/python/mcp2515.py Executable file
View File

@ -0,0 +1,79 @@
#!/usr/bin/python
# Author: Jon Trulson <jtrulson@ics.com>
# Copyright (c) 2016 Intel Corporation.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
from __future__ import print_function
import time, sys, signal, atexit
from upm import pyupm_mcp2515 as MCP2515
def main():
# Instantiate a MCP2515 on SPI bus 0 using a hw CS pin (-1).
sensor = MCP2515.MCP2515(0, -1)
## Exit handlers ##
# This function stops python from printing a stacktrace when you
# hit control-C
def SIGINTHandler(signum, frame):
raise SystemExit
# This function lets you run code on exit, including functions from sensor
def exitHandler():
print("Exiting")
sys.exit(0)
# Register exit handlers
atexit.register(exitHandler)
signal.signal(signal.SIGINT, SIGINTHandler)
print("Setting loopback mode...")
# set the mode to loopback mode. In loopback mode, transmitted
# packets are sent directly to an appropriate receive buffer
# without actually going out onto the CAN bus.
sensor.setOpmode(MCP2515.MCP2515_OPMODE_LOOPBACK);
# lets build up a packet and try loading it (8 bytes max).
myPayload = "01234567";
print("Loading a packet of 8 numbers (0-7) into a TX buffer...")
sensor.loadTXBuffer(MCP2515.MCP2515_TX_BUFFER0, 0, False, False, myPayload);
# now lets try to transmit it
print("Transmitting packet...")
sensor.transmitBuffer(MCP2515.MCP2515_TX_BUFFER0, True);
print("Transmit successful")
# There should now be a packet waiting for us in RXB0
if (sensor.rxStatusMsgs() == MCP2515.MCP2515_RXMSG_RXB0):
print("Packet received in RXB0, decoding...")
# now lets retrieve and print it
sensor.getRXMsg(MCP2515.MCP2515_RX_BUFFER0);
sensor.printMsg();
else:
print("No packet found, how strange.")
print("Exiting...")
if __name__ == '__main__':
main()

View File

@ -0,0 +1,8 @@
upm_mixed_module_init (NAME mcp2515
DESCRIPTION "CAN bus controller"
C_HDR mcp2515.h mcp2515_regs.h
C_SRC mcp2515.c
CPP_HDR mcp2515.hpp
CPP_SRC mcp2515.cxx
CPP_WRAPS_C
REQUIRES mraa)

View File

@ -0,0 +1,25 @@
%module javaupm_mcp2515
%include "../upm.i"
%include "typemaps.i"
%include "arrays_java.i"
%include "../java_buffer.i"
%include "std_string.i"
%include "../carrays_uint8_t.i"
%include "mcp2515_regs.h"
%include "mcp2515.hpp"
%{
#include "mcp2515.hpp"
%}
%pragma(java) jniclasscode=%{
static {
try {
System.loadLibrary("javaupm_mcp2515");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. \n" + e);
System.exit(1);
}
}
%}

View File

@ -0,0 +1,13 @@
%module jsupm_mcp2515
%include "../upm.i"
%include "cpointer.i"
%include "std_string.i"
%include "../carrays_uint8_t.i"
%pointer_functions(float, floatp);
%include "mcp2515_regs.h"
%include "mcp2515.hpp"
%{
#include "mcp2515.hpp"
%}

51
src/mcp2515/license.txt Normal file
View File

@ -0,0 +1,51 @@
The table of CNF1-3 valuses used to set the CAN bus baudrate were
taken from the Seeed studio code at:
https://github.com/Seeed-Studio/CAN_BUS_Shield/
/*
mcp_can.cpp
2012 Copyright (c) Seeed Technology Inc. All right reserved.
Author:Loovee
2014-1-16
Contributor:
Cory J. Fowler
Latonita
Woodward1
Mehtajaghvi
BykeBlast
TheRo0T
Tsipizic
ralfEdmund
Nathancheek
BlueAndi
Adlerweb
Btetz
Hurvajs
xboxpro1
The MIT License (MIT)
Copyright (c) 2013 Seeed Technology Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

1112
src/mcp2515/mcp2515.c Normal file

File diff suppressed because it is too large Load Diff

253
src/mcp2515/mcp2515.cxx Normal file
View File

@ -0,0 +1,253 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <unistd.h>
#include <iostream>
#include <stdexcept>
#include <string>
#include "mcp2515.hpp"
using namespace upm;
using namespace std;
MCP2515::MCP2515(int bus, int csPin) :
m_mcp2515(mcp2515_init(bus, csPin))
{
if (!m_mcp2515)
throw std::runtime_error(string(__FUNCTION__)
+ ": mcp2515_init() failed");
}
MCP2515::~MCP2515()
{
mcp2515_close(m_mcp2515);
}
void MCP2515::reset()
{
if (mcp2515_reset(m_mcp2515))
throw std::runtime_error(string(__FUNCTION__)
+ ": mcp2515_reset() failed");
}
void MCP2515::setOpmode(MCP2515_OPMODE_T opmode)
{
if (mcp2515_set_opmode(m_mcp2515, opmode))
throw std::runtime_error(string(__FUNCTION__)
+ ": mcp2515_set_opmode() failed");
}
void MCP2515::setSpeed(MCP2515_SPEED_T speed)
{
if (mcp2515_set_speed(m_mcp2515, speed))
throw std::runtime_error(string(__FUNCTION__)
+ ": mcp2515_set_speed() failed");
}
void MCP2515::loadTXBuffer(MCP2515_TX_BUFFER_T bufnum, int id, bool ext,
bool rtr, std::string payload)
{
if (mcp2515_load_tx_buffer(m_mcp2515, bufnum, id, ext, rtr,
(uint8_t *)payload.data(), payload.size()))
throw std::runtime_error(string(__FUNCTION__)
+ ": mcp2515_load_tx_buffer() failed");
}
void MCP2515::transmitBuffer(MCP2515_TX_BUFFER_T bufnum, bool wait)
{
if (mcp2515_transmit_buffer(m_mcp2515, bufnum, wait))
throw std::runtime_error(string(__FUNCTION__)
+ ": mcp2515_transmit_buffer() failed");
}
bool MCP2515::isTXBufferFree(MCP2515_TX_BUFFER_T bufnum)
{
return mcp2515_tx_buffer_is_free(m_mcp2515, bufnum);
}
MCP2515_TX_BUFFER_T MCP2515::findFreeTXBuffer()
{
return mcp2515_find_free_tx_buffer(m_mcp2515);
}
void MCP2515::setTXBufferPriority(MCP2515_TX_BUFFER_T bufnum,
MCP2515_TXP_T priority)
{
if (mcp2515_set_tx_buffer_priority(m_mcp2515, bufnum, priority))
throw std::runtime_error(string(__FUNCTION__)
+ ": mcp2515_set_tx_buffer_priority() failed");
}
void MCP2515::abortTX(MCP2515_TX_BUFFER_T bufnum)
{
if (mcp2515_abort_tx(m_mcp2515, bufnum))
throw std::runtime_error(string(__FUNCTION__)
+ ": mcp2515_abort_tx() failed");
}
void MCP2515::setRXBufferMode(MCP2515_RX_BUFFER_T bufnum, MCP2515_RXMODE_T rxm)
{
if (mcp2515_set_rx_buffer_mode(m_mcp2515, bufnum, rxm))
throw std::runtime_error(string(__FUNCTION__)
+ ": mcp2515_set_rx_buffer_mode() failed");
}
MCP2515_RXMSG_T MCP2515::rxStatusMsgs()
{
return mcp2515_rx_status_msgs(m_mcp2515);
}
MCP2515_MSGTYPE_T MCP2515::rxStatusMsgType()
{
return mcp2515_rx_status_msg_type(m_mcp2515);
}
MCP2515_FILTERMATCH_T MCP2515::rxStatusFiltermatch()
{
return mcp2515_rx_status_filtermatch(m_mcp2515);
}
upm_result_t MCP2515::getRXMsg(MCP2515_RX_BUFFER_T bufnum)
{
return mcp2515_get_rx_msg(m_mcp2515, bufnum, &m_message);
}
void MCP2515::printMsg()
{
mcp2515_print_msg(m_mcp2515, &m_message);
}
void MCP2515::installISR(int pin, void (*isr)(void *), void *arg)
{
if (mcp2515_install_isr(m_mcp2515, pin, isr, arg))
throw std::runtime_error(string(__FUNCTION__)
+ ": mcp2515_install_isr() failed");
}
void MCP2515::uninstallISR()
{
mcp2515_uninstall_isr(m_mcp2515);
}
void MCP2515::setIntrEnables(uint8_t enables)
{
if (mcp2515_set_intr_enables(m_mcp2515, enables))
throw std::runtime_error(string(__FUNCTION__)
+ ": mcp2515_set_intr_enables() failed");
}
uint8_t MCP2515::getIntrFlags()
{
uint8_t flags = 0;
if (mcp2515_get_intr_flags(m_mcp2515, &flags))
throw std::runtime_error(string(__FUNCTION__)
+ ": mcp2515_get_intr_flags() failed");
return flags;
}
void MCP2515::setIntrFlags(uint8_t flags)
{
if (mcp2515_set_intr_flags(m_mcp2515, flags))
throw std::runtime_error(string(__FUNCTION__)
+ ": mcp2515_set_intr_flags() failed");
}
void MCP2515::clearIntrFlags(uint8_t flags)
{
if (mcp2515_clear_intr_flags(m_mcp2515, flags))
throw std::runtime_error(string(__FUNCTION__)
+ ": mcp2515_clear_intr_flags() failed");
}
uint8_t MCP2515::getErrorFlags()
{
uint8_t flags = 0;
if (mcp2515_get_error_flags(m_mcp2515, &flags))
throw std::runtime_error(string(__FUNCTION__)
+ ": mcp2515_get_error_flags() failed");
return flags;
}
void MCP2515::clearErrorFlags(uint8_t flags)
{
if (mcp2515_clear_error_flags(m_mcp2515, flags))
throw std::runtime_error(string(__FUNCTION__)
+ ": mcp2515_clear_error_flags() failed");
}
void MCP2515::setFilter(MCP2515_RX_FILTER_T filter, bool ext, int id)
{
if (mcp2515_set_filter(m_mcp2515, filter, ext, id))
throw std::runtime_error(string(__FUNCTION__)
+ ": mcp2515_set_filter() failed");
}
void MCP2515::setMask(MCP2515_RX_MASK_T mask, bool ext, int id)
{
if (mcp2515_set_mask(m_mcp2515, mask, ext, id))
throw std::runtime_error(string(__FUNCTION__)
+ ": mcp2515_set_mask() failed");
}
string MCP2515::busRead(uint8_t cmd, std::string args, int datalen)
{
uint8_t data[datalen];
if (mcp2515_bus_read(m_mcp2515, cmd, (uint8_t *)args.data(), args.size(),
data, datalen))
throw std::runtime_error(string(__FUNCTION__)
+ ": mcp2515_bus_read() failed");
return string((char *)data, datalen);
}
void MCP2515::busWrite(uint8_t cmd, std::string data)
{
if (mcp2515_bus_write(m_mcp2515, cmd, (uint8_t *)data.data(), data.size()))
throw std::runtime_error(string(__FUNCTION__)
+ ": mcp2515_bus_write() failed");
}
void MCP2515::writeReg(uint8_t reg, uint8_t value)
{
if (mcp2515_write_reg(m_mcp2515, reg, value))
throw std::runtime_error(string(__FUNCTION__)
+ ": mcp2515_write_reg() failed");
}
void MCP2515::writeRegs(uint8_t reg, std::string buffer)
{
if (mcp2515_write_regs(m_mcp2515, reg, (uint8_t *)buffer.data(),
buffer.size()))
throw std::runtime_error(string(__FUNCTION__)
+ ": mcp2515_write_regs() failed");
}
void MCP2515::bitModify(uint8_t addr, uint8_t mask, uint8_t value)
{
if (mcp2515_bit_modify(m_mcp2515, addr, mask, value))
throw std::runtime_error(string(__FUNCTION__)
+ ": mcp2515_bit_modify() failed");
}

525
src/mcp2515/mcp2515.h Normal file
View File

@ -0,0 +1,525 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <upm.h>
#include <mraa/i2c.h>
#include <mraa/spi.h>
#include <mraa/gpio.h>
#include <mcp2515_regs.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file mcp2515
* @library mcp2515
* @brief C API for the MCP2515 CAN bus controller
*
* @include mcp2515.c
* @include mcp2515_regs.c
*/
/**
* Device context
*/
typedef struct _mcp2515_context {
mraa_spi_context spi;
// CS pin, if we are using one
mraa_gpio_context gpio;
// interrupt, if enabled
mraa_gpio_context intr;
} *mcp2515_context;
/**
* MCP2515 initializer
*
* @param bus spi bus to use
* @param cs_pin The GPIO pin to use for Chip Select (CS). Pass
* pass -1 if your CS is handled automatically by your SPI
* implementation (Edison).
* @return an initialized device context on success, NULL on error.
*/
mcp2515_context mcp2515_init(int bus, int cs_pin);
/**
* MCP2515 close
*
* @param dev Device context.
*/
void mcp2515_close(mcp2515_context dev);
/**
* Reset the device.
*
* @param dev Device context.
* @return UPM result.
*/
upm_result_t mcp2515_reset(const mcp2515_context dev);
/**
* Set the operating mode of the device. After initialization
* (mcp2515_init()), the device mode will be set to NORMAL. Note
* that some operations require the device to be placed into CONFIG
* mode. This function will wait until the selected mode has been
* entered.
*
* @param dev Device context.
* @param opmode One of the MCP2515_OPMODE_T values.
* @return UPM result.
*/
upm_result_t mcp2515_set_opmode(const mcp2515_context dev,
MCP2515_OPMODE_T opmode);
/**
* Set the baud rate of the CAN bus. All devices on a given CAN
* bus must be operating at the correct speed. The device must be
* switched into CONFIG mode bofore this function will have any
* effect. On initialization (mcp2515_init()), the default CAN
* bus speed will be set to 50Kbps.
*
* @param dev Device context.
* @param speed One of the MCP2515_SPEED_T values.
* @return UPM result.
*/
upm_result_t mcp2515_set_speed(const mcp2515_context dev,
MCP2515_SPEED_T speed);
/**
* Load a transmit buffer with the id, payload, and other
* information. This function does not actually transmit the
* buffer. There are 3 TX buffers available. The buffer must be
* free (ie: not awaiting transmit) before it can be loaded. Once
* a TX buffer has been successfully loaded, it can be transmitted
* with the mcp2515_transmit_buffer() function.
*
* @param dev Device context.
* @param bufnum The buffer to load. One of the
* MCP2515_TX_BUFFER_T values.
* @param id The integer representation of the CAN bus ID.
* @param ext True if the ID is an extended identifier, false otherwise.
* @param rtr True if this is a Remote Transfer Request, false otherwise.
* @param payload A pointer to an array of bytes that make up the
* payload to send.
* @param len The length of the payload. The length is limited to
* 8.
* @return UPM result.
*/
upm_result_t mcp2515_load_tx_buffer(const mcp2515_context dev,
MCP2515_TX_BUFFER_T bufnum,
int id, bool ext, bool rtr,
uint8_t *payload, int len);
/**
* Transmit a buffer already loaded by mcp2515_load_tx_buffer().
*
* @param dev Device context.
* @param bufnum The buffer to transmit. One of the
* MCP2515_TX_BUFFER_T values.
* @param wait True if the function should wait until transmission
* is complete before returning, false otherwise.
* @return UPM result.
*/
upm_result_t mcp2515_transmit_buffer(const mcp2515_context dev,
MCP2515_TX_BUFFER_T bufnum,
bool wait);
/**
* Determine whether a TX buffer is available for use or not. A TX
* buffer is unavailable if a transmit request is pending on it,
* but transmission has not yet completed.
*
* @param dev Device context.
* @param bufnum The buffer to check. One of the
* MCP2515_TX_BUFFER_T values.
* @return True if the buffer is availabe, false otherwise.
*/
bool mcp2515_tx_buffer_is_free(const mcp2515_context dev,
MCP2515_TX_BUFFER_T bufnum);
/**
* Find a free TX buffer and return it.
*
* @param dev Device context.
* @return One of the MCP2515_TX_BUFFER_T values. If no buffers
* are available, MCP2515_TX_NO_BUFFERS will be returned.
*/
MCP2515_TX_BUFFER_T mcp2515_find_free_tx_buffer(const mcp2515_context dev);
/**
* Set the transmit priority of a TX buffer. Higher priority
* buffers are always transmitted before lower priority buffers.
* This function can be called on a buffer at any time prior to
* actual transmission.
*
* @param dev Device context.
* @param bufnum The buffer to set priority for. One of the
* MCP2515_TX_BUFFER_T values.
* @param priority The priority to set for the buffer. One of the
* MCP2515_TXP_T values.
* @return UPM result.
*/
upm_result_t mcp2515_set_tx_buffer_priority(const mcp2515_context dev,
MCP2515_TX_BUFFER_T bufnum,
MCP2515_TXP_T priority);
/**
* Abort a transmission that has been queued, but not yet
* completed. This will also free up the TX buffer for future
* use. Note, if you abort a transmission, but transmission has
* already started, this call will have no effect, and the buffer
* will complete transmission.
*
* @param dev Device context.
* @param bufnum The buffer to abort. One of the
* MCP2515_TX_BUFFER_T values.
* @return UPM result.
*/
upm_result_t mcp2515_abort_tx(const mcp2515_context dev,
MCP2515_TX_BUFFER_T bufnum);
/**
* Set the mode for an RX buffer. The mode specifies, at a high
* level, what packets should be captured from the bus and placed
* into an RX buffer. See the datasheet for details, but the
* default, MCP2515_RXMODE_ANY_FILTER, should be sufficient in
* most cases. It is also possible to use this to restrict the
* types of CAN ids accepted (extended only, standard only) as
* well as a debug ANY_NOFILTER mode.
*
* @param dev Device context.
* @param bufnum The buffer to set the mode for. One of the
* MCP2515_RX_BUFFER_T values.
* @param rxm The mode to set. One of the MCP2515_RXMODE_T values.
* @return UPM result.
*/
upm_result_t mcp2515_set_rx_buffer_mode(const mcp2515_context dev,
MCP2515_RX_BUFFER_T bufnum,
MCP2515_RXMODE_T rxm);
/**
* Return a bitmask indicating which of the 2 RX buffers have
* packets waiting in them. This can be 0 (no packets), 1(RXB0),
* 2(RXB1), or 3 (RXB0 and RXB1). This information is retrieved
* using the MCP2515_CMD_RX_STATUS command.
*
* @param dev Device context.
* @return A bitmask indicating which RX buffers (if any) have
* packets in them. One of the MCP2515_RXMSG_T values.
*/
MCP2515_RXMSG_T mcp2515_rx_status_msgs(const mcp2515_context dev);
/**
* Return the message type present in one of the RX buffers. RXB0
* has the highest priority, so if both RX buffers are full, this
* function will only return data for the packet in RXB0. This
* information is retrieved using the MCP2515_CMD_RX_STATUS
* command.
*
* @param dev Device context.
* @return One of the MCP2515_MSGTYPE_T values.
*/
MCP2515_MSGTYPE_T mcp2515_rx_status_msg_type(const mcp2515_context dev);
/**
* Return the filter that matched an RX buffer. RXB0 has the
* highest priority, so if both RX buffers are full, this function
* will only return data for the packet in RXB0. This information
* is retrieved using the MCP2515_CMD_RX_STATUS command.
*
* @param dev Device context.
* @return One of the MCP2515_FILTERMATCH_T values.
*/
MCP2515_FILTERMATCH_T mcp2515_rx_status_filtermatch(const mcp2515_context dev);
/**
* This function retrieves a message from the specified RX buffer.
* The message (MCP2515_MSG_T) contains all of the data in the
* packet, including id, rtr, ext, payload and payload length. In
* addition, after retrieving the message, the RX buffer is freed
* to receive further data from the CAN bus.
*
* @param dev Device context.
* @param bufnum The buffer to retrieve. One of the
* MCP2515_RX_BUFFER_T values.
* @param msg A pointer to a MCP2515_MSG_T, which will be filled
* with the decoded contents of the RX buffer.
* @return UPM result.
*/
upm_result_t mcp2515_get_rx_msg(const mcp2515_context dev,
MCP2515_RX_BUFFER_T bufnum,
MCP2515_MSG_T *msg);
/**
* This is a utility function that accepts a MCP2515_MSG_T and
* prints out it's decoded contents. This is of primary
* importance for debugging, and to simplify the examples
* somewhat.
*
* The output will look similar to:
*
* id 00000000 ext 0 rtr 0 filt 0 len 8
* payload: 0xc8 0x01 0x02 0x03 0x04 0x05 0x06 0x07
*
* @param dev Device context.
* @param msg A pointer to a MCP2515_MSG_T containing the data to
* be printed out.
*/
void mcp2515_print_msg(const mcp2515_context dev, MCP2515_MSG_T *msg);
/**
* Installs an interrupt service routine (ISR) to be called when
* an interrupt occurs.
*
* @param dev Device context.
* @param pin GPIO pin to use as the interrupt pin.
* @param fptr Pointer to a function to be called on interrupt.
* @param arg Pointer to an object to be supplied as an
* argument to the ISR.
* @return UPM result.
*/
upm_result_t mcp2515_install_isr(const mcp2515_context dev, int pin,
void (*isr)(void *), void *arg);
/**
* Uninstalls the previously installed ISR
*
* @param dev Device context.
*/
void mcp2515_uninstall_isr(const mcp2515_context dev);
/**
* Set the interrupt enables register.
*
* @param dev Device context.
* @param enables A bitmask of interrupts to enable from
* MCP2515_CANINT_BITS_T.
* @return UPM result.
*/
upm_result_t mcp2515_set_intr_enables(const mcp2515_context dev,
uint8_t enables);
/**
* Retrieve the interrupt flags register.
*
* @param dev Device context.
* @param flags A pointer to a bitmask that will be filled with
* values from MCP2515_CANINT_BITS_T, indicating which interrupt
* flags are set.
* @return UPM result.
*/
upm_result_t mcp2515_get_intr_flags(const mcp2515_context dev,
uint8_t *flags);
/**
* This function allows you to set specific interrupt flags. If
* the corresponding interrupt enable is set, an interrupt will be
* generated.
*
* @param dev Device context.
* @param flags A bitmask of interrupt flags to set, from
* MCP2515_CANINT_BITS_T values.
* @return UPM result.
*/
upm_result_t mcp2515_set_intr_flags(const mcp2515_context dev,
uint8_t flags);
/**
* This function allows you to clear specific interrupt flags.
* See the datasheet. Some flags cannot be cleared until the
* underlying cause has been corrected.
*
* @param dev Device context.
* @param flags A bitmask of interrupt flags to clear, from
* MCP2515_CANINT_BITS_T values.
* @return UPM result.
*/
upm_result_t mcp2515_clear_intr_flags(const mcp2515_context dev,
uint8_t flags);
/**
* Retrieve the error flags register
*
* @param dev Device context.
* @param flags A pointer to a uint8_t that will hold the flags
* with values from MCP2515_EFLG_BITS_T.
* @return UPM result.
*/
upm_result_t mcp2515_get_error_flags(const mcp2515_context dev,
uint8_t *flags);
/**
* Clear error flags. Note, some flags cannot be cleared
* until the underlying issues is resolved.
*
* @param dev Device context.
* @param flags A bitmask of values from MCP2515_EFLG_BITS_T
* specifying the flags to clear.
* @return UPM result.
*/
upm_result_t mcp2515_clear_error_flags(const mcp2515_context dev,
uint8_t flags);
/**
* This function allows you to set one of the 6 RX filters
* available. Filters 0 and 1 are for RXB0 only, while filters
* 2-5 are for RXB1. See the datasheet for details on how these
* filters (along with the masks) are used to select candidate CAN
* bus data for retrieval from the CAN bus.
*
* These can only be set when the device is in CONFIG mode.
*
* @param dev Device context.
* @param filter One of the 6 MCP2515_RX_FILTER_T values.
* @param ext True if the id is extended, false for standard.
* @param id Integer representation of a CAN bus ID.
* @return UPM result.
*/
upm_result_t mcp2515_set_filter(const mcp2515_context dev,
MCP2515_RX_FILTER_T filter, bool ext,
int id);
/**
* This function allows you to set one of the 2 RX masks. Mask 0
* is for RXB0, mask 1 is for RXB1. The masks specify which bits
* in the filters are used for matching CAN bus data. See the
* datasheet for details on how these masks (along with the
* filters) are used to select candidate CAN bus data for retrieval
* from the CAN bus.
*
* These can only be set when the device is in CONFIG mode.
*
* @param dev Device context.
* @param mask One of the 2 MCP2515_RX_MASK_T values.
* @param ext True if the id is extended, false for standard.
* @param id Integer representation of a CAN bus ID.
* @return UPM result.
*/
upm_result_t mcp2515_set_mask(const mcp2515_context dev,
MCP2515_RX_MASK_T mask, bool ext, int id);
/**
* Perform a bus read. This function is exposed here for those
* users wishing to perform their own low level accesses. This is
* a low level function, and should not be used unless you know
* what you are doing.
*
* @param dev Device context.
* @param cmd The command to send.
* @param args An array of arguments, or NULL.
* @param arglen The number of args, or 0.
* @param data A pointer to a buffer in which data will be read into.
* @param len The number of bytes to read.
* @return UPM result.
*/
upm_result_t mcp2515_bus_read(const mcp2515_context dev, uint8_t cmd,
uint8_t *args, unsigned int arglen,
uint8_t *data, uint8_t len);
/**
* Perform a bus write. This function is exposed here for those
* users wishing to perform their own low level accesses. This is
* a low level function, and should not be used unless you know
* what you are doing.
*
* @param dev Device context
* @param cmd The command to send.
* @param data A pointer to a buffer containing data to write.
* @param len The number of bytes to write.
* @return UPM Status
*/
upm_result_t mcp2515_bus_write(const mcp2515_context dev, uint8_t cmd,
uint8_t *data, uint8_t len);
/**
* Write to a specific register. This function is exposed here
* for those users wishing to perform their own low level
* accesses. This is a low level function, and should not be used
* unless you know what you are doing.
*
* @param dev Device context
* @param reg The register to write to.
* @param value The byte to write.
* @return UPM Status
*/
upm_result_t mcp2515_write_reg(const mcp2515_context dev, uint8_t reg,
uint8_t value);
/**
* Write to multiple consecutive registers. This function is
* exposed here for those users wishing to perform their own low
* level accesses. This is a low level function, and should not
* be used unless you know what you are doing.
*
* @param dev Device context
* @param reg The register to start writing to.
* @param buffer A pointer to an array of bytes to write.
* @param len The number of bytes to write.
* @return UPM Status
*/
upm_result_t mcp2515_write_regs(const mcp2515_context dev, uint8_t reg,
uint8_t *buffer, int len);
/**
* Read a register. This function is exposed here for those users
* wishing to perform their own low level accesses. This is a low
* level function, and should not be used unless you know what you
* are doing.
*
* @param dev Device context
* @param reg The register to read.
* @param buffer A pointer to a a byte where the value will be placed.
* @return UPM Status
*/
upm_result_t mcp2515_read_reg(const mcp2515_context dev, uint8_t reg,
uint8_t *value);
/**
* Perform a bit modify operation on a register. Only certain
* registers support this method of access - check the datasheet.
* This function is exposed here for those users wishing to
* perform their own low level accesses. This is a low level
* function, and should not be used unless you know what you are
* doing.
*
* @param dev Device context
* @param addr The address of the register to access.
* @param mask A bitmask used to mask off value bits.
* @param value The value to write (bits masked by mask).
* @return UPM Status
*/
upm_result_t mcp2515_bit_modify(const mcp2515_context dev, uint8_t addr,
uint8_t mask, uint8_t value);
#ifdef __cplusplus
}
#endif

522
src/mcp2515/mcp2515.hpp Normal file
View File

@ -0,0 +1,522 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <string>
#include "mcp2515.h"
namespace upm {
/**
* @brief MCP2515 Can bus controller
* @defgroup mcp2515 libupm-mcp2515
* @ingroup spi gpio
*/
/**
* @library mcp2515
* @sensor mcp2515
* @comname MCP2515 CAN bus controller
* @man seeed
* @con spi gpio
* @web https://www.seeedstudio.com/CANBUS-Shield-p-2256.html
*
* @brief API for the MCP2515 CAN bus controller
*
* The MCP2515 is a stand-alone CAN controller developed to
* simplify applications that require interfacing with a CAN bus.
*
* This driver was developed using the Grove CAN bus shield
* version 1.2.
*
* An example using the loopback mode.
* @snippet mcp2515.cxx Interesting
* A simple transmit and receive example.
* @snippet mcp2515-txrx.cxx Interesting
*/
class MCP2515 {
public:
/**
* MCP2515 constructor.
*
* @param bus spi bus to use
* @param cs_pin The GPIO pin to use for Chip Select (CS). Pass
* pass -1 if your CS is handled automatically by your SPI
* implementation (Edison).
*/
MCP2515(int bus, int csPin);
/**
* MCP2515 Destructor
*/
~MCP2515();
/**
* Reset the device.
*
*/
void reset();
/**
* Set the operating mode of the device. After initialization,
* the device mode will be set to NORMAL. Note that some
* operations require the device to be placed into CONFIG mode.
* This function will wait until the selected mode has been
* entered.
*
* @param opmode One of the MCP2515_OPMODE_T values.
*/
void setOpmode(MCP2515_OPMODE_T opmode);
/**
* Set the baud rate of the CAN bus. All devices on a given
* CAN bus must be operating at the correct speed. The device
* must be switched into CONFIG mode bofore this function will
* have any effect. On initialization, the default CAN bus
* speed will be set to 50Kbps.
*
* @param speed One of the MCP2515_SPEED_T values.
*/
void setSpeed(MCP2515_SPEED_T speed);
/**
* Load a transmit buffer with the id, payload, and other
* information. This function does not actually transmit the
* buffer. There are 3 TX buffers available. The buffer must be
* free (ie: not awaiting transmit) before it can be loaded. Once
* a TX buffer has been successfully loaded, it can be transmitted
* with the TransmitBuffer() method.
*
* @param bufnum The buffer to load. One of the
* MCP2515_TX_BUFFER_T values.
* @param id The integer representation of the CAN bus ID.
* @param ext True if the ID is an extended identifier, false otherwise.
* @param rtr True if this is a Remote Transfer Request, false
* otherwise.
* @param payload A string containing the payload bytes.
* Maximum length is 8.
*/
void loadTXBuffer(MCP2515_TX_BUFFER_T bufnum,
int id, bool ext, bool rtr,
std::string payload);
/**
* Transmit a buffer already loaded by loadTXBuffer().
*
* @param bufnum The buffer to transmit. One of the
* MCP2515_TX_BUFFER_T values.
* @param wait True if the function should wait until transmission
* is complete before returning, false otherwise.
*/
void transmitBuffer(MCP2515_TX_BUFFER_T bufnum, bool wait);
/**
* Determine whether a TX buffer is available for use or not. A TX
* buffer is unavailable if a transmit request is pending on it,
* but transmission has not yet completed.
*
* @param bufnum The buffer to check. One of the
* MCP2515_TX_BUFFER_T values.
* @return True if the buffer is availabe, false otherwise.
*/
bool isTXBufferFree(MCP2515_TX_BUFFER_T bufnum);
/**
* Find a free TX buffer and return it.
*
* @return One of the MCP2515_TX_BUFFER_T values. If no buffers
* are available, MCP2515_TX_NO_BUFFERS will be returned.
*/
MCP2515_TX_BUFFER_T findFreeTXBuffer();
/**
* Set the transmit priority of a TX buffer. Higher priority
* buffers are always transmitted before lower priority buffers.
* This function can be called on a buffer at any time prior to
* actual transmission.
*
* @param bufnum The buffer to set priority for. One of the
* MCP2515_TX_BUFFER_T values.
* @param priority The priority to set for the buffer. One of the
* MCP2515_TXP_T values.
*/
void setTXBufferPriority(MCP2515_TX_BUFFER_T bufnum,
MCP2515_TXP_T priority);
/**
* Abort a transmission that has been queued, but not yet
* completed. This will also free up the TX buffer for future
* use. Note, if you abort a transmission, but transmission has
* already started, this call will have no effect, and the buffer
* will complete transmission.
*
* @param bufnum The buffer to abort. One of the
* MCP2515_TX_BUFFER_T values.
*/
void abortTX(MCP2515_TX_BUFFER_T bufnum);
/**
* Set the mode for an RX buffer. The mode specifies, at a high
* level, what packets should be captured from the bus and placed
* into an RX buffer. See the datasheet for details, but the
* default, MCP2515_RXMODE_ANY_FILTER, should be sufficient in
* most cases. It is also possible to use this to restrict the
* types of CAN ids accepted (extended only, standard only) as
* well as a debug ANY_NOFILTER mode.
*
* @param bufnum The buffer to set the mode for. One of the
* MCP2515_RX_BUFFER_T values.
* @param rxm The mode to set. One of the MCP2515_RXMODE_T values.
*/
void setRXBufferMode(MCP2515_RX_BUFFER_T bufnum,
MCP2515_RXMODE_T rxm);
/**
* Return a bitmask indicating which of the 2 RX buffers have
* packets waiting in them. This can be 0 (no packets), 1(RXB0),
* 2(RXB1), or 3 (RXB0 and RXB1). This information is retrieved
* using the MCP2515_CMD_RX_STATUS command.
*
* @return A bitmask indicating which RX buffers (if any) have
* packets in them. One of the MCP2515_RXMSG_T values.
*/
MCP2515_RXMSG_T rxStatusMsgs();
/**
* Return the message type present in one of the RX buffers. RXB0
* has the highest priority, so if both RX buffers are full, this
* function will only return data for the packet in RXB0. This
* information is retrieved using the MCP2515_CMD_RX_STATUS
* command.
*
* @return One of the MCP2515_MSGTYPE_T values.
*/
MCP2515_MSGTYPE_T rxStatusMsgType();
/**
* Return the filter that matched an RX buffer. RXB0 has the
* highest priority, so if both RX buffers are full, this function
* will only return data for the packet in RXB0. This information
* is retrieved using the MCP2515_CMD_RX_STATUS command.
*
* @return One of the MCP2515_FILTERMATCH_T values.
*/
MCP2515_FILTERMATCH_T rxStatusFiltermatch();
/**
* This function retrieves a message from the specified RX
* buffer. The message (MCP2515_MSG_T) contains all of the
* data in the packet, including id, rtr, ext, payload and
* payload length. In addition, after retrieving the message,
* the RX buffer is freed to receive further data from the CAN
* bus. The message is stored within the class.
*
* @param bufnum The buffer to retrieve. One of the
* MCP2515_RX_BUFFER_T values.
*/
upm_result_t getRXMsg(MCP2515_RX_BUFFER_T bufnum);
/**
* This is a utility function prints the current (last
* received) messages decoded contents. This is of
* primary importance for debugging, and to simplify the
* examples somewhat.
*
* The output will look similar to:
*
* id 00000000 ext 0 rtr 0 filt 0 len 8
* payload: 0xc8 0x01 0x02 0x03 0x04 0x05 0x06 0x07
*
*/
void printMsg();
/**
* This method returns the id of a received message. It will
* only be valid after a successful completion of rxGetMsg().
*
* @return ID of the last received message.
*/
int msgGetID()
{
return m_message.id;
}
/**
* This method returns the RTR flag of a received message. It will
* only be valid after a successful completion of rxGetMsg().
*
* @return True if the message has the RTR flag set, false otherwise.
*/
bool msgGetRTR()
{
return m_message.rtr;
}
/**
* This method returns the EXT (extended ID) flag of a
* received message. It will only be valid after a successful
* completion of rxGetMsg().
*
* @return True if the message has an extended ID, false otherwise.
*/
bool msgGetEXT()
{
return m_message.ext;
}
/**
* This method returns the filter number that caused the
* message to be stored in the RX buffer. It will only be
* valid after a successful completion of rxGetMsg().
*
* @return The filter number that was matched.
*/
int msgGetFilterNum()
{
return m_message.filter_num;
}
/**
* This method returns the length of the payload of the RX
* buffer. It will only be valid after a successful
* completion of rxGetMsg().
*
* @return Length of the payload in bytes, max 8.
*/
int msgGetPayloadLen()
{
return m_message.len;
}
/**
* This method returns the contents of the payload in the last
* received message. It will only be valid after a successful
* completion of rxGetMsg().
*
* @return String containing the payload.
*/
std::string msgGetPayload()
{
return std::string((char *)m_message.pkt.data, m_message.len);
}
#if defined(SWIGJAVA) || defined(JAVACALLBACK)
void installISR(int pin, jobject runnable)
{
installISR(pin, mraa_java_isr_callback, runnable);
}
#else
/**
* Installs an interrupt service routine (ISR) to be called when
* an interrupt occurs.
*
* @param pin GPIO pin to use as the interrupt pin.
* @param fptr Pointer to a function to be called on interrupt.
* @param arg Pointer to an object to be supplied as an
* argument to the ISR.
*/
void installISR(int pin, void (*isr)(void *), void *arg);
#endif
/**
* Uninstalls the previously installed ISR
*
* @param dev Device context.
*/
void uninstallISR();
/**
* Set the interrupt enables register.
*
* @param enables A bitmask of interrupts to enable from
* MCP2515_CANINT_BITS_T.
*/
void setIntrEnables(uint8_t enables);
/**
* Retrieve the interrupt flags register.
*
* @return A bitmask that will be filled with values from
* MCP2515_CANINT_BITS_T, indicating which interrupt flags are
* set.
*/
uint8_t getIntrFlags();
/**
* This function allows you to set specific interrupt flags. If
* the corresponding interrupt enable is set, an interrupt will be
* generated.
*
* @param flags A bitmask of interrupt flags to set, from
* MCP2515_CANINT_BITS_T values.
*/
void setIntrFlags(uint8_t flags);
/**
* This function allows you to clear specific interrupt flags.
* See the datasheet. Some flags cannot be cleared until the
* underlying cause has been corrected.
*
* @param flags A bitmask of interrupt flags to clear, from
* MCP2515_CANINT_BITS_T values.
*/
void clearIntrFlags(uint8_t flags);
/**
* Retrieve the error flags register
*
* @return A bitmask that will be filled with values from
* MCP2515_EFLG_BITS_T, indicating which error flags are set.
*/
uint8_t getErrorFlags();
/**
* Clear error flags. Note, some flags cannot be cleared
* until the underlying issues is resolved.
*
* @return A bitmask of values from MCP2515_EFLG_BITS_T,
* indicating which error flags to clear.
*/
void clearErrorFlags(uint8_t flags);
/**
* This function allows you to set one of the 6 RX filters
* available. Filters 0 and 1 are for RXB0 only, while filters
* 2-5 are for RXB1. See the datasheet for details on how these
* filters (along with the masks) are used to select candidate CAN
* bus data for retrieval from the CAN bus.
*
* These can only be set when the device is in CONFIG mode.
*
* @param filter One of the 6 MCP2515_RX_FILTER_T values.
* @param ext True if the id is extended, false for standard.
* @param id Integer representation of a CAN bus ID.
*/
void setFilter(MCP2515_RX_FILTER_T filter, bool ext, int id);
/**
* This function allows you to set one of the 2 RX masks. Mask 0
* is for RXB0, mask 1 is for RXB1. The masks specify which bits
* in the filters are used for matching CAN bus data. See the
* datasheet for details on how these masks (along with the
* filters) are used to select candidate CAN bus data for retrieval
* from the CAN bus.
*
* These can only be set when the device is in CONFIG mode.
*
* @param mask One of the 2 MCP2515_RX_MASK_T values.
* @param ext True if the id is extended, false for standard.
* @param id Integer representation of a CAN bus ID.
*/
void setMask(MCP2515_RX_MASK_T mask, bool ext, int id);
protected:
mcp2515_context m_mcp2515;
// We operate only on this message (for received messages) to
// simplify SWIG accesses.
MCP2515_MSG_T m_message;
/**
* Perform a bus read. This function is exposed here for those
* users wishing to perform their own low level accesses. This is
* a low level function, and should not be used unless you know
* what you are doing.
*
* @param cmd The command to send.
* @param args String containing arguments, or empty for no arguments.
* @param datalen The length of the data to read.
* @return A string containing the data.
*/
std::string busRead(uint8_t cmd, std::string args, int datalen);
/**
* Perform a bus write. This function is exposed here for those
* users wishing to perform their own low level accesses. This is
* a low level function, and should not be used unless you know
* what you are doing.
*
* @param cmd The command to send.
* @param data A string containing the data to write.
* @param len The number of bytes to write.
*/
void busWrite(uint8_t cmd, std::string data);
/**
* Write to a specific register. This function is exposed here
* for those users wishing to perform their own low level
* accesses. This is a low level function, and should not be used
* unless you know what you are doing.
*
* @param reg The register to write to.
* @param value The byte to write.
*/
void writeReg(uint8_t reg, uint8_t value);
/**
* Write to multiple consecutive registers. This function is
* exposed here for those users wishing to perform their own low
* level accesses. This is a low level function, and should not
* be used unless you know what you are doing.
*
* @param reg The register to start writing to.
* @param buffer A string containing data to write.
*/
void writeRegs(uint8_t reg, std::string buffer);
/**
* Read a register. This function is exposed here for those users
* wishing to perform their own low level accesses. This is a low
* level function, and should not be used unless you know what you
* are doing.
*
* @param reg The register to read.
* @return The register contents.
*/
uint8_t readReg(uint8_t reg);
/**
* Perform a bit modify operation on a register. Only certain
* registers support this method of access - check the datasheet.
* This function is exposed here for those users wishing to
* perform their own low level accesses. This is a low level
* function, and should not be used unless you know what you are
* doing.
*
* @param addr The address of the register to access.
* @param mask A bitmask used to mask off value bits.
* @param value The value to write (bits masked by mask).
*/
void bitModify(uint8_t addr, uint8_t mask, uint8_t value);
private:
#if defined(SWIGJAVA) || defined(JAVACALLBACK)
void installISR(int pin, void (*isr)(void *), void *arg);
#endif
};
}

641
src/mcp2515/mcp2515_regs.h Normal file
View File

@ -0,0 +1,641 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
// maximum number of bytes we can send/receive
#define MCP2515_MAX_PAYLOAD_DATA (8)
// This includes SIDH, SIDL, EID8, EID0, DLC, and 8 payload bytes.
// This represents the non-control components of the RX and TX
// buffers.
#define MCP2515_MAX_PKT_DATA (13)
// Now we break them out for clarity. These are offsets into a
// transmitted or received packet.
#define MCP2515_PKT_SIDH (0)
#define MCP2515_PKT_SIDL (1)
#define MCP2515_PKT_EID8 (2)
#define MCP2515_PKT_EID0 (3)
#define MCP2515_PKT_DLC (4)
#define MCP2515_PKT_D0 (5)
#define MCP2515_PKT_D1 (6)
#define MCP2515_PKT_D2 (7)
#define MCP2515_PKT_D3 (8)
#define MCP2515_PKT_D4 (9)
#define MCP2515_PKT_D5 (10)
#define MCP2515_PKT_D6 (11)
#define MCP2515_PKT_D7 (12)
// The number of bytes that make up an ID (SIDH, SIDL, EID8, EID0)
#define MCP2515_MAX_ID_BYTES (4)
// 4 byte SIDH, SIDL, SID8, SID0 id. This is used only for
// converting back and forth from an integer and 4-byte device
// representation of a standard or extended ID.
typedef union {
uint8_t data[MCP2515_MAX_ID_BYTES];
struct {
uint8_t SIDH;
uint8_t SIDL;
uint8_t EID8;
uint8_t EID0;
};
} MCP2515_ID_T;
// 13 byte packet starting at SIDH. This is used to represent
// packets for transmission and reception.
typedef union {
uint8_t data[MCP2515_MAX_PKT_DATA];
struct {
uint8_t SIDH; // Id data
uint8_t SIDL;
uint8_t EID8;
uint8_t EID0;
uint8_t DLC; // DLC (data length)
uint8_t D0; // start of 8 byte (max) payload
uint8_t D1;
uint8_t D2;
uint8_t D3;
uint8_t D4;
uint8_t D5;
uint8_t D6;
uint8_t D7;
};
} MCP2515_PKT_T;
// A received message. This includes the packet, and some decoded
// data (rtr, ext, id, etc.
typedef struct {
int id;
bool rtr;
bool ext;
int filter_num;
int len;
MCP2515_PKT_T pkt;
} MCP2515_MSG_T;
// Registers
typedef enum {
// 5 RX filters, each composed of SIDH, SIDL, EID8, EID0. We
// only specify the leading (SIDH) address here.
// first two filters are associated with rxb0
MCP2515_REG_FILTER0 = 0x00,
MCP2515_REG_FILTER1 = 0x04,
// remaining 4 filters are associated with rxb1
MCP2515_REG_FILTER2 = 0x08,
MCP2515_REG_FILTER3 = 0x10,
MCP2515_REG_FILTER4 = 0x14,
MCP2515_REG_FILTER5 = 0x18,
// 2 RX filter mask registers, like above, we only specify the
// SIDH address
// associated with rxb0
MCP2515_REG_MASK0 = 0x20,
// associated with rxb1
MCP2515_REG_MASK1 = 0x24,
MCP2515_REG_BFPCTL = 0x0c,
MCP2515_REG_TXRTSCTRL = 0x0d, // tx ready-to-send
// CANSTAT and CANCTRL are aliased in several locations to
// make it easier to get maximum data using burst reads. In
// reality, they are the same register, but we list them all
// anyway for completeness.
// CANSTAT and aliases
MCP2515_REG_CANSTAT = 0x0e,
MCP2515_REG_CANSTAT_0 = 0x0e, // same as CANSTAT
MCP2515_REG_CANSTAT_1 = 0x1e, // rest of the aliases
MCP2515_REG_CANSTAT_2 = 0x2e,
MCP2515_REG_CANSTAT_3 = 0x3e,
MCP2515_REG_CANSTAT_4 = 0x4e,
MCP2515_REG_CANSTAT_5 = 0x5e,
MCP2515_REG_CANSTAT_6 = 0x6e,
MCP2515_REG_CANSTAT_7 = 0x7e,
// CANCTRL and aliases
MCP2515_REG_CANCTRL = 0x0f,
MCP2515_REG_CANCTRL_0 = 0x0f, // same as CANCTRL
MCP2515_REG_CANCTRL_1 = 0x1f, // rest of the aliases
MCP2515_REG_CANCTRL_2 = 0x2f,
MCP2515_REG_CANCTRL_3 = 0x3f,
MCP2515_REG_CANCTRL_4 = 0x4f,
MCP2515_REG_CANCTRL_5 = 0x5f,
MCP2515_REG_CANCTRL_6 = 0x6f,
MCP2515_REG_CANCTRL_7 = 0x7f,
MCP2515_REG_TEC = 0x1c, // tx error count
MCP2515_REG_REC = 0x1d, // rx error count
MCP2515_REG_CNF3 = 0x28, // configuration bytes
MCP2515_REG_CNF2 = 0x29,
MCP2515_REG_CNF1 = 0x2a,
MCP2515_REG_CANINTE = 0x2b, // intr enables
MCP2515_REG_CANINTF = 0x2c, // intr flags
MCP2515_REG_EFLG = 0x2a, // error flags
// Start of the buffer reg ranges for tx and rx buffers.
// There are 3 transmit buffers and 2 rx buffers. You can
// read and write 16 bytes (0x0f) starting at these locations
// to set and/get buffer control bits, message ids, msg
// content, and CANSTAT and CANCTRL regs in one bus transaction.
// See the datasheet page 61
MCP2515_REG_TXB0CTRL = 0x30, // tx buffer 0 ctrl
MCP2515_REG_TXB1CTRL = 0x40, // tx buffer 1 ctrl
MCP2515_REG_TXB2CTRL = 0x50, // tx buffer 2 ctrl
MCP2515_REG_RXB0CTRL = 0x60, // rx buffer 0 ctrl
MCP2515_REG_RXB1CTRL = 0x70 // rx buffer 1 ctrl
} MCP2515_REG_T;
// MCP2515_REG_CANCTRL bits
typedef enum {
MCP2515_CANCTRL_CLKPRE0 = 0x01,
MCP2515_CANCTRL_CLKPRE1 = 0x02,
_MCP2515_CANCTRL_CLKPRE_MASK = 3,
_MCP2515_CANCTRL_CLKPRE_SHIFT = 0,
MCP2515_CANCTRL_CLKEN = 0x04, //enable CLKOUT pin
MCP2515_CANCTRL_OSM = 0x08, // one shot mode
MCP2515_CANCTRL_ABAT = 0x10, // abort all pending tx
MCP2515_CANCTRL_REQOP0 = 0x20, // request new operating mode
MCP2515_CANCTRL_REQOP1 = 0x40,
MCP2515_CANCTRL_REQOP2 = 0x80,
_MCP2515_CANCTRL_REQOP_MASK = 7,
_MCP2515_CANCTRL_REQOP_SHIFT = 5,
} MCP2515_CANCTRL_BITS_T;
// MCP2515_CLKPRE values
typedef enum {
MCP2515_CLKPRE_DIV1 = 0, // sysclk/1
MCP2515_CLKPRE_DIV2 = 1, // sysclk/2
MCP2515_CLKPRE_DIV4 = 2, // sysclk/4
MCP2515_CLKPRE_DIV8 = 3 // sysclk/8
} MCP2515_CLKPRE_T;
// MCP2515_OPMODE values. These are the same for the CANCTRL_REQOP and
// CANSTAT_OPMODE bitfields.
typedef enum {
MCP2515_OPMODE_NORMAL = 0,
MCP2515_OPMODE_SLEEP = 1,
MCP2515_OPMODE_LOOPBACK = 2,
MCP2515_OPMODE_LISTENONLY = 3,
MCP2515_OPMODE_CONFIG = 4
} MCP2515_OPMODE_T;
// MCP2515_REG_CANSTAT bits
typedef enum {
// 0x01 reserved
MCP2515_CANSTAT_ICOD0 = 0x02, // intr flag code
MCP2515_CANSTAT_ICOD1 = 0x04,
MCP2515_CANSTAT_ICOD2 = 0x08,
_MCP2515_CANSTAT_ICOD_MASK = 7,
_MCP2515_CANSTAT_ICOD_SHIFT = 1,
// 0x10 reserved
MCP2515_CANSTAT_OPMODE0 = 0x20, // request new operating mode
MCP2515_CANSTAT_OPMODE1 = 0x40,
MCP2515_CANSTAT_OPMODE2 = 0x80,
_MCP2515_CANSTAT_OPMODE_MASK = 7,
_MCP2515_CANSTAT_OPMODE_SHIFT = 5,
} MCP2515_CANSTAT_BITS_T;
// MCP2515_REG_BFPCTL bits, Buffer Pin Control
typedef enum {
MCP2515_BFPCTL_B0BFM = 0x01, // opmode bit
MCP2515_BFPCTL_B1BFM = 0x02,
MCP2515_BFPCTL_B0BFE = 0x04, // func enable bit
MCP2515_BFPCTL_B1BFE = 0x08,
MCP2515_BFPCTL_B0BFS = 0x10, // pin state (output mode only)
MCP2515_BFPCTL_B1BFS = 0x20,
// 0x40-0x080 reserved
} MCP2515_BFPCTL_BITS_T;
// MCP2515_REG_TXRTSCTRL bits, TX RTS pin control
typedef enum {
MCP2515_TXRTSCTRL_B0RTSM = 0x01, // pin mode
MCP2515_TXRTSCTRL_B1RTSM = 0x02,
MCP2515_TXRTSCTRL_B2RTSM = 0x04,
MCP2515_TXRTSCTRL_B0RTS = 0x08, // pin state when in
// input mode
MCP2515_TXRTSCTRL_B1RTS = 0x10,
MCP2515_TXRTSCTRL_B2RTS = 0x20,
// 0x40-0x80 reserved
} MCP2515_TXRTSCTRL_BITS_T;
// MCP2515_REG_EFLG bits, Error flags
typedef enum {
MCP2515_EFLG_EWARN = 0x01, // error warning (TEC/REC > 96)
MCP2515_EFLG_RXWAR = 0x02, // rx warning (REC > 96)
MCP2515_EFLG_TXWAR = 0x04, // tx warning (REC > 96)
MCP2515_EFLG_RXEP = 0x08, // rx error-passive
MCP2515_EFLG_TXEP = 0x10, // tx error-passive
MCP2515_EFLG_TXBO = 0x20, // tx bus off
MCP2515_EFLG_RX0OVR = 0x40, // rx buf 0 overflow
MCP2515_EFLG_RX1OVR = 0x80, // rx buf 1 overflow
} MCP2515_EFLG_BITS_T;
// MCP2515_REG_CANINTE and MCP2515_REG_CANINTF bits, interrupt
// enables and flags. We use the same enum here as the two regs
// have the same bits.
typedef enum {
MCP2515_CANINT_RX0I = 0x01, // rx buf 0 full
MCP2515_CANINT_RX1I = 0x02, // rx buf 1 full
MCP2515_CANINT_TX0I = 0x04, // tx buf 1 empty
MCP2515_CANINT_TX1I = 0x08, // tx buf 2 empty
MCP2515_CANINT_TX2I = 0x10, // tx buf 3 empty
MCP2515_CANINT_ERRI = 0x20, // error intr
MCP2515_CANINT_WAKI = 0x40, // wakeup intr
MCP2515_CANINT_MERR = 0x80 // msg error
} MCP2515_CANINT_BITS_T;
// MCP2515_REG_TXBCTRL, TX control for tx buffers 0 (0x30), 1
// (0x40), and 2 (0x50)
typedef enum {
MCP2515_TXBCTRL_TXP0 = 0x01, // message priority
MCP2515_TXBCTRL_TXP1 = 0x02,
_MCP2515_TXBCTRL_TXP_MASK = 3,
_MCP2515_TXBCTRL_TXP_SHIFT = 0,
// 0x04 reserved
MCP2515_TXBCTRL_TXREQ = 0x08, // tx request
MCP2515_TXBCTRL_TXERR = 0x10, // tx error detected
MCP2515_TXBCTRL_MLOA = 0x20, // msg lost arbitration
MCP2515_TXBCTRL_ABTF = 0x40 // msg aborted flag
// 0x80 reserved
} MCP2515_TXBCTRL_BITS_T;
// MCP2515_TXBCTRL_TXP priority values
typedef enum {
MCP2515_TXP_LOWEST = 0,
MCP2515_TXP_LOW = 1,
MCP2515_TXP_HIGH = 2,
MCP2515_TXP_HIGHEST = 3
} MCP2515_TXP_T;
// MCP2515_TXBDLC bits, (addresses 0x35, 0x45, 0x55)
typedef enum {
MCP2515_TXBDLC_DLC0 = 0x01, // data length code
MCP2515_TXBDLC_DLC1 = 0x02, // max is 8 bytes
MCP2515_TXBDLC_DLC2 = 0x04,
MCP2515_TXBDLC_DLC3 = 0x08,
_MCP2515_TXBDLC_MASK = 15,
_MCP2515_TXBDLC_SHIFT = 0,
// 0x10-0x20 reserved
MCP2515_TXBDLC_RTR = 0x40, // remote
// transmission
// request bit
// 0x80 reserved
} MCP2515_TXBDLC_BITS_T;
// MCP2515_REG_RXB0CTRL, RX control for rx buffer 0 (0x60)
typedef enum {
MCP2515_RXB0CTRL_FILHIT = 0x01, // which filter was hit
MCP2515_RXB0CTRL_BUKT1 = 0x02, // readonly version of BUKT
MCP2515_RXB0CTRL_BUKT = 0x04, // rollover enable (to rx1)
MCP2515_RXB0CTRL_RXRTR = 0x08, // RTR request
// 0x10 reserved
MCP2515_RXB0CTRL_RXMODE0 = 0x20, // rx buf mode bits
MCP2515_RXB0CTRL_RXMODE1 = 0x40,
_MCP2515_RXB0CTRL_RXMODE_MASK = 3,
_MCP2515_RXB0CTRL_RXMODE_SHIFT = 5
// 0x80 reserved
} MCP2515_RXB0CTRL_BITS_T;
// These values determine whether the filters are used and what
// kinds of messages to accept. They are the same for both rx
// buffers.
typedef enum {
MCP2515_RXMODE_ANY_FILTER = 0, // std/ext based on filter
MCP2515_RXMODE_STANDARD_FILTER = 1, // standard only, filter
MCP2515_RXMODE_EXTENDED_FILTER = 2, // extended only, filter
MCP2515_RXMODE_ANY_NOFILTER = 3 // any, no filter
} MCP2515_RXMODE_T;
// MCP2515_REG_RXB1CTRL, RX control for rx buffer 1 (0x70)
typedef enum {
MCP2515_RXB1CTRL_FILHIT0 = 0x01, // which filter was hit
MCP2515_RXB1CTRL_FILHIT1 = 0x02, // for a rollover, this can
MCP2515_RXB1CTRL_FILHIT2 = 0x04, // be filter 0 or 1 too.
_MCP2515_RXB1CTRL_FILHIT_MASK = 7,
_MCP2515_RXB1CTRL_FILHIT_SHIFT = 0,
MCP2515_RXB1CTRL_RXRTR = 0x08, // RTR request
// 0x10 reserved
MCP2515_RXB1CTRL_RXMODE0 = 0x20, // rx buf mode bits
MCP2515_RXB1CTRL_RXMODE1 = 0x40,
_MCP2515_RXB1CTRL_RXMODE_MASK = 3,
_MCP2515_RXB1CTRL_RXMODE_SHIFT = 5
// 0x80 reserved
} MCP2515_RXB1CTRL_BITS_T;
// MCP2515_RXB1CTRL_FILHIT values for rx buffer 1
typedef enum {
MCP2515_FILHIT_F0 = 0, // filter 0 hit (only if bukt)
MCP2515_FILHIT_F1 = 1, // filter 1 hit (only if bukt)
MCP2515_FILHIT_F2 = 2, // filter 2 hit
MCP2515_FILHIT_F3 = 3,
MCP2515_FILHIT_F4 = 4,
MCP2515_FILHIT_F5 = 5
} MCP2515_FILHIT_T;
// Valid CANBUS speeds. These are precomputed and represented in
// a table in mcp2515.c. It is a requirement that the enum values
// below correspond to the indexes in the speed table. Keep them
// in sync! Add any new values to the end of this enum, and to
// the corresponding table in mcp2515.c.
//
// These values are valid only for 16Mhz clocks.
typedef enum {
MCP2515_SPEED_5KBPS = 0,
MCP2515_SPEED_10KBPS = 1,
MCP2515_SPEED_20KBPS = 2,
MCP2515_SPEED_25KBPS = 3,
MCP2515_SPEED_31_25KBPS = 4, // 31.25kbps
MCP2515_SPEED_33KBPS = 5,
MCP2515_SPEED_40KBPS = 6,
MCP2515_SPEED_50KBPS = 7,
MCP2515_SPEED_80KBPS = 8,
MCP2515_SPEED_83KBPS = 9,
MCP2515_SPEED_95KBPS = 10,
MCP2515_SPEED_100KBPS = 11,
MCP2515_SPEED_125KBPS = 12,
MCP2515_SPEED_200KBPS = 13,
MCP2515_SPEED_250KBPS = 14,
MCP2515_SPEED_500KBPS = 15,
MCP2515_SPEED_666KBPS = 16,
MCP2515_SPEED_1000KBPS = 17
} MCP2515_SPEED_T;
// MCP2515_RXBDLC bits, (addresses 0x65, 0x75)
typedef enum {
MCP2515_RXBDLC_DLC0 = 0x01, // data length code
MCP2515_RXBDLC_DLC1 = 0x02, // max is 8 bytes
MCP2515_RXBDLC_DLC2 = 0x04,
MCP2515_RXBDLC_DLC3 = 0x08,
_MCP2515_RXBDLC_MASK = 15,
_MCP2515_RXBDLC_SHIFT = 0,
// 0x10-0x20 reserved
MCP2515_RXBDLC_RTR = 0x40, // remote
// transmission
// request bit, if
// extended id
// 0x80 reserved
} MCP2515_RXBDLC_BITS_T;
// SPI commands - these are commands sent to the device to start
// certain operations. The datasheet specifies that after CS is
// active, the first byte must be the command byte. It is not
// possible to send multiple commands in a single transaction
// (a CS On/CS Off sequence).
typedef enum {
MCP2515_CMD_RESET = 0xc0,
MCP2515_CMD_READ = 0x03,
// These commands allows the specification of a read buffer.
// The real command is 0x90. The lower nibble is 0mn0,
// where m and n specify the 4 locations to start reading
// from. In this list, we will enumerate all of them.
//
// n m cmd real hex addr
// ------------------------------
// 0 0 RXB0SIDH 0x61
// 0 1 RXB0D0 0x66
// 1 0 RXB1SIDH 0x71
// 1 1 RXB1D0 0x76
MCP2515_CMD_READ_RXBUF_RXB0SIDH = 0x90,
MCP2515_CMD_READ_RXBUF_RXB0D0 = 0x92,
MCP2515_CMD_READ_RXBUF_RXB1SIDH = 0x94,
MCP2515_CMD_READ_RXBUF_RXB1D0 = 0x96,
MCP2515_CMD_WRITE = 0x02,
// This command allows speedier loading of tx buffer contents.
// The lower nibble is 0b0abc, where abc specifies 6 location
// addresses to start writing to. This works similarly to the
// READ_RXBUF_* commands.
//
// a b c cmd real hex addr
// ----------------------------------
// 0 0 0 TXB0SIDH 0x31
// 0 0 1 TXB0D0 0x36
// 0 1 0 TXB1SIDH 0x41
// 0 1 1 TXB1D0 0x46
// 1 0 0 TXB2SIDH 0x51
// 1 0 1 TXB2D0 0x56
MCP2515_CMD_LOAD_TXBUF_TXB0SIDH = 0x40,
MCP2515_CMD_LOAD_TXBUF_TXB0D0 = 0x41,
MCP2515_CMD_LOAD_TXBUF_TXB1SIDH = 0x42,
MCP2515_CMD_LOAD_TXBUF_TXB1D0 = 0x43,
MCP2515_CMD_LOAD_TXBUF_TXB2SIDH = 0x44,
MCP2515_CMD_LOAD_TXBUF_TXB2D0 = 0x45,
// Request to Send. This is a quick way to request the
// sending of tx buffers without having to do a
// read/modify/write register sequence. The lower 3 bits
// indicate which buffer(s) to setup for transmission.
//
// 0x8n Where n is 0b0xxx. bit 0 is for txb 0, bit 1 for txb 1
// and bit 2 for txb 2.
MCP2515_CMD_RTS = 0x80,
MCP2515_CMD_RTS_BUFFER0 = 0x81,
MCP2515_CMD_RTS_BUFFER1 = 0x82,
MCP2515_CMD_RTS_BUFFER2 = 0x84,
// return status bits for rx and tx. See MCP2515_RDSTATUS_BITS_T.
MCP2515_CMD_READ_STATUS = 0xa0,
// returns information on which filters have been matched.
// See MCP2515_RXSTATUS_BITS_T.
MCP2515_CMD_RX_STATUS = 0xb0,
// This command allows for certain registers to have certain
// bit(s) modified w/o going through a read/modify/write cycle
// of the whole register. See the datasheet - only certain
// registers can be used with this command.
//
// The format for this command is: cmd, addr, mask, value
MCP2515_CMD_BIT_MODIFY = 0x05
} MCP2515_CMD_T;
// This bitfield is the contents of the byte returned from a
// CMD_READ_STATUS command.
typedef enum {
MCP2515_RDSTATUS_RX0IF = 0x01, // rx buf 0 full IF
MCP2515_RDSTATUS_RX1IF = 0x02, // rx buf 1 full IF
MCP2515_RDSTATUS_TXB0REQ = 0x04, // TX buf 0 req bit
MCP2515_RDSTATUS_TXB0IF = 0x08, // TX buf 0 empty IF
MCP2515_RDSTATUS_TXB1REQ = 0x10, // TX buf 1 req bit
MCP2515_RDSTATUS_TXB1IF = 0x20, // TX buf 1 empty IF
MCP2515_RDSTATUS_TXB2REQ = 0x40, // TX buf 2 req bit
MCP2515_RDSTATUS_TXB2IF = 0x80 // TX buf 2 empty IF
} MCP2515_RDSTATUS_BITS_T;
// This bitfield is the contents of the byte returned from a
// CMD_READ_RX_STATUS command.
typedef enum {
MCP2515_RXSTATUS_FILTERMATCH0 = 0x01,
MCP2515_RXSTATUS_FILTERMATCH1 = 0x02,
MCP2515_RXSTATUS_FILTERMATCH2 = 0x04,
_MCP2515_RXSTATUS_FILTERMATCH_MASK = 7,
_MCP2515_RXSTATUS_FILTERMATCH_SHIFT = 0,
MCP2515_RXSTATUS_MSGTYPE0 = 0x08,
MCP2515_RXSTATUS_MSGTYPE1 = 0x10,
_MCP2515_RXSTATUS_MSGTYPE_MASK = 3,
_MCP2515_RXSTATUS_MSGTYPE_SHIFT = 3,
// 0x20 is not mentioned in the DS
MCP2515_RXSTATUS_RXMSG0 = 0x40,
MCP2515_RXSTATUS_RXMSG1 = 0x80,
_MCP2515_RXSTATUS_RXMSG_MASK = 3,
_MCP2515_RXSTATUS_RXMSG_SHIFT = 6
} MCP2515_RXSTATUS_BITS_T;
// MCP2515_RXSTATUS_FILTERMATCH values
typedef enum {
MCP2515_FILTERMATCH_RXF0 = 0,
MCP2515_FILTERMATCH_RXF1 = 1,
MCP2515_FILTERMATCH_RXF2 = 2,
MCP2515_FILTERMATCH_RXF3 = 3,
MCP2515_FILTERMATCH_RXF4 = 4,
MCP2515_FILTERMATCH_RXF5 = 5,
MCP2515_FILTERMATCH_RXF0_ROLLOVER = 6,
MCP2515_FILTERMATCH_RXF1_ROLLOVER = 7
} MCP2515_FILTERMATCH_T;
// MCP2515_RXSTATUS_MSGTYPE values
typedef enum {
MCP2515_MSGTYPE_STD = 0, // standard
MCP2515_MSGTYPE_STDRF = 1, // standard remote frame
MCP2515_MSGTYPE_EXT = 2, // extended
MCP2515_MSGTYPE_EXTRF = 3 // extended remote frame
} MCP2515_MSGTYPE_T;
// MCP2515_RXSTATUS_RXMSG values
typedef enum {
MCP2515_RXMSG_NONE = 0, // no msg
MCP2515_RXMSG_RXB0 = 1, // msg in rxb0
MCP2515_RXMSG_RXB1 = 2, // msg in rxb1
MCP2515_RXMSG_BOTH = 3 // msg in both
} MCP2515_RXMSG_T;
// we spell out the SIDL registers as they contain the EXIDE bit.
// The others (SIDL, EID0 and EID8 just contain their respective
// ID bits.
typedef enum {
MCP2515_SIDL_EID16 = 0x01,
MCP2515_SIDL_EID17 = 0x02,
// 0x04 reserved
MCP2515_SIDL_EXIDE = 0x08,
// 0x10 reserved
MCP2515_SIDL_SID0 = 0x20,
MCP2515_SIDL_SID1 = 0x40,
MCP2515_SIDL_SID2 = 0x80
} MCP2515_SIDL_T;
// An enum to specify one of the 3 TX buffers
typedef enum {
MCP2515_TX_BUFFER0 = 0,
MCP2515_TX_BUFFER1 = 1,
MCP2515_TX_BUFFER2 = 2,
// special value indicating no buffers
MCP2515_TX_NO_BUFFERS = 255
} MCP2515_TX_BUFFER_T;
// An enum to specify one of the 2 rx buffers
typedef enum {
MCP2515_RX_BUFFER0 = 0,
MCP2515_RX_BUFFER1 = 1
} MCP2515_RX_BUFFER_T;
// An enum to specify one of the 6 rx filters
typedef enum {
MCP2515_RX_FILTER0 = 0,
MCP2515_RX_FILTER1 = 1,
MCP2515_RX_FILTER2 = 2,
MCP2515_RX_FILTER3 = 3,
MCP2515_RX_FILTER4 = 4,
MCP2515_RX_FILTER5 = 5
} MCP2515_RX_FILTER_T;
// An enum to specify one of the 2 rx masks
typedef enum {
MCP2515_RX_MASK0 = 0,
MCP2515_RX_MASK1 = 1
} MCP2515_RX_MASK_T;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,19 @@
// Include doxygen-generated documentation
%include "pyupm_doxy2swig.i"
%module pyupm_mcp2515
%include "../upm.i"
%include "cpointer.i"
%include "std_string.i"
%include "../carrays_uint8_t.i"
%include "stdint.i"
%feature("autodoc", "3");
%pointer_functions(float, floatp);
%include "mcp2515_regs.h"
%include "mcp2515.hpp"
%{
#include "mcp2515.hpp"
%}