/* * Author: Jon Trulson * 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 #include "mcp2515.h" namespace upm { /** * @brief MCP2515 Can bus controller * @defgroup mcp2515 libupm-mcp2515 * @ingroup spi gpio */ /** * @library mcp2515 * @sensor mcp2515 * @comname 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 csPin 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 isr 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 }; }