diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..eb7750c --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "cmake.configureOnOpen": false +} \ No newline at end of file diff --git a/CanHacker.cpp b/CanHacker.cpp index 734764a..a146c3d 100644 --- a/CanHacker.cpp +++ b/CanHacker.cpp @@ -34,113 +34,90 @@ static inline void _put_id(char *buf, int end_offset, canid_t id) #define put_sff_id(buf, id) _put_id(buf, 2, id) #define put_eff_id(buf, id) _put_id(buf, 7, id) -CanHacker::CanHacker(Stream *stream, Stream *debugStream, uint8_t cs) { +CanHacker::CanHacker(Stream *stream, Stream *debugStream, uint8_t cs, const uint32_t spi_clock) { _stream = stream; _debugStream = debugStream; writeDebugStream(F("Initialization\n")); - _cs = cs; - mcp2515 = new MCP2515(_cs); - mcp2515->reset(); - mcp2515->setConfigMode(); + if(spi_clock == 0) { + can_instance = new MCP_CAN(cs); + } else { + can_instance = new MCP_CAN(cs, spi_clock); + } + + can_instance->begin(); + +} + +CanHacker::CanHacker(Stream *stream, Stream *debugStream, BASE_CAN *can) { + _stream = stream; + _debugStream = debugStream; + + writeDebugStream(F("Initialization\n")); + + can_instance = can; + + can_instance->begin(); } CanHacker::~CanHacker() { - delete mcp2515; + delete can_instance; } Stream *CanHacker::getInterfaceStream() { return _stream; } -void CanHacker::setClock(CAN_CLOCK clock){ - canClock = clock; +BASE_CAN *CanHacker::get_can_instance(){ + return can_instance; +} + +void CanHacker::setClock(BASE_CAN::CAN_CLOCK clock){ + can_instance->setClock(clock); } CanHacker::ERROR CanHacker::connectCan() { - MCP2515::ERROR error = mcp2515->setBitrate(bitrate, canClock); - if (error != MCP2515::ERROR_OK) { + can_instance->connectCan(); + + ERROR error = (ERROR)can_instance->getError(); + + if(error == ERROR_BITRATE){ writeDebugStream(F("setBitrate error:\n")); writeDebugStream((int)error); writeDebugStream("\n"); - return ERROR_MCP2515_INIT_BITRATE; + return ERROR_BITRATE; } - - if (_loopback) { - error = mcp2515->setLoopbackMode(); - } else if (_listenOnly) { - error = mcp2515->setListenOnlyMode(); - } else { - error = mcp2515->setNormalMode(); + else if (error == ERROR_SET_MODE) { + writeDebugStream(F("error setting mode: ")); + writeDebugStream((int)error); + writeDebugStream("\n"); + return ERROR_SET_MODE; } - - if (error != MCP2515::ERROR_OK) { - return ERROR_MCP2515_INIT_SET_MODE; + else if(error != ERROR_OK){ + writeDebugStream(F("error: ")); + writeDebugStream((int)error); + writeDebugStream("\n"); + return ERROR_INVALID_COMMAND; } - _isConnected = true; return ERROR_OK; } CanHacker::ERROR CanHacker::disconnectCan() { - _isConnected = false; - mcp2515->setConfigMode(); - return ERROR_OK; + return (ERROR)can_instance->disconnectCan(); } bool CanHacker::isConnected() { - return _isConnected; -} - -CanHacker::ERROR CanHacker::writeCan(const struct can_frame *frame) { - if (mcp2515->sendMessage(frame) != MCP2515::ERROR_OK) { - return ERROR_MCP2515_SEND; - } - - return ERROR_OK; + return can_instance->isConnected(); } -CanHacker::ERROR CanHacker::pollReceiveCan() { - if (!isConnected()) { +CanHacker::ERROR CanHacker::writeCan(const can_message &frame) { + if (can_instance->write(frame)) { return ERROR_OK; } - while (mcp2515->checkReceive()) { - struct can_frame frame; - if (mcp2515->readMessage(&frame) != MCP2515::ERROR_OK) { - return ERROR_MCP2515_READ; - } - - ERROR error = receiveCanFrame(&frame); - if (error != ERROR_OK) { - return error; - } - } - - return ERROR_OK; -} - -CanHacker::ERROR CanHacker::receiveCan(const MCP2515::RXBn rxBuffer) { - if (!isConnected()) { - return ERROR_OK; - } - - struct can_frame frame; - MCP2515::ERROR result = mcp2515->readMessage(rxBuffer, &frame); - if (result == MCP2515::ERROR_NOMSG) { - return ERROR_OK; - } - - if (result != MCP2515::ERROR_OK) { - return ERROR_MCP2515_READ; - } - - return receiveCanFrame(&frame); -} - -MCP2515 *CanHacker::getMcp2515() { - return mcp2515; + return ERROR_SEND; } uint16_t CanHacker::getTimestamp() { @@ -164,31 +141,31 @@ CanHacker::ERROR CanHacker::receiveSetBitrateCommand(const char *buffer, const i switch(buffer[1]) { case '0': writeDebugStream(F("Set bitrate 10KBPS\n")); - bitrate = CAN_10KBPS; + can_instance->setBaudRate(BASE_CAN::CAN_10KBPS); break; case '1': writeDebugStream(F("Set bitrate 20KBPS\n")); - bitrate = CAN_20KBPS; + can_instance->setBaudRate(BASE_CAN::CAN_20KBPS); break; case '2': writeDebugStream(F("Set bitrate 50KBPS\n")); - bitrate = CAN_50KBPS; + can_instance->setBaudRate(BASE_CAN::CAN_50KBPS); break; case '3': writeDebugStream(F("Set bitrate 100KBPS\n")); - bitrate = CAN_100KBPS; + can_instance->setBaudRate(BASE_CAN::CAN_100KBPS); break; case '4': writeDebugStream(F("Set bitrate 125KBPS\n")); - bitrate = CAN_125KBPS; + can_instance->setBaudRate(BASE_CAN::CAN_125KBPS); break; case '5': writeDebugStream(F("Set bitrate 250KBPS\n")); - bitrate = CAN_250KBPS; + can_instance->setBaudRate(BASE_CAN::CAN_250KBPS); break; case '6': writeDebugStream(F("Set bitrate 500KBPS\n")); - bitrate = CAN_500KBPS; + can_instance->setBaudRate(BASE_CAN::CAN_500KBPS); break; case '7': writeDebugStream(F("Bitrate 7 is not supported\n")); @@ -199,7 +176,7 @@ CanHacker::ERROR CanHacker::receiveSetBitrateCommand(const char *buffer, const i break; case '8': writeDebugStream(F("Set bitrate 1000KBPS\n")); - bitrate = CAN_1000KBPS; + can_instance->setBaudRate(BASE_CAN::CAN_1000KBPS); break; default: writeDebugStream(F("Unexpected bitrate\n")); @@ -213,97 +190,6 @@ CanHacker::ERROR CanHacker::receiveSetBitrateCommand(const char *buffer, const i return writeStream(CR); } -CanHacker::ERROR CanHacker::processInterrupt() { - if (!isConnected()) { - return ERROR_OK; - writeDebugStream(F("Process interrupt while not connected\n")); - return ERROR_NOT_CONNECTED; - } - - uint8_t irq = mcp2515->getInterrupts(); - - if (irq & MCP2515::CANINTF_ERRIF) { - // reset RXnOVR errors - mcp2515->clearRXnOVR(); - } - - if (irq & MCP2515::CANINTF_RX0IF) { - ERROR error = receiveCan(MCP2515::RXB0); - if (error != ERROR_OK) { - return error; - } - } - - if (irq & MCP2515::CANINTF_RX1IF) { - ERROR error = receiveCan(MCP2515::RXB1); - if (error != ERROR_OK) { - return error; - } - } - - /*if (irq & (MCP2515::CANINTF_TX0IF | MCP2515::CANINTF_TX1IF | MCP2515::CANINTF_TX2IF)) { - _debugStream->print("MCP_TXxIF\r\n"); - //stopAndBlink(1); - }*/ - - - - if (irq & MCP2515::CANINTF_WAKIF) { - _debugStream->print(F("MCP_WAKIF\r\n")); - mcp2515->clearInterrupts(); - } - - if (irq & MCP2515::CANINTF_ERRIF) { - _debugStream->print(F("ERRIF\r\n")); - - //return ERROR_MCP2515_MERRF; - mcp2515->clearMERR(); - } - - if (irq & MCP2515::CANINTF_MERRF) { - _debugStream->print(F("MERRF\r\n")); - - //return ERROR_MCP2515_MERRF; - mcp2515->clearInterrupts(); - } - - return ERROR_OK; -} - -CanHacker::ERROR CanHacker::setFilter(const uint32_t filter) { - if (isConnected()) { - writeDebugStream(F("Filter cannot be set while connected\n")); - return ERROR_CONNECTED; - } - - MCP2515::RXF filters[] = {MCP2515::RXF0, MCP2515::RXF1, MCP2515::RXF2, MCP2515::RXF3, MCP2515::RXF4, MCP2515::RXF5}; - for (int i=0; i<6; i++) { - MCP2515::ERROR result = mcp2515->setFilter(filters[i], false, filter); - if (result != MCP2515::ERROR_OK) { - return ERROR_MCP2515_FILTER; - } - } - - return ERROR_OK; -} - -CanHacker::ERROR CanHacker::setFilterMask(const uint32_t mask) { - if (isConnected()) { - writeDebugStream(F("Filter mask cannot be set while connected\n")); - return ERROR_CONNECTED; - } - - MCP2515::MASK masks[] = {MCP2515::MASK0, MCP2515::MASK1}; - for (int i=0; i<2; i++) { - MCP2515::ERROR result = mcp2515->setFilterMask(masks[i], false, mask); - if (result != MCP2515::ERROR_OK) { - return ERROR_MCP2515_FILTER; - } - } - - return ERROR_OK; -} - CanHacker::ERROR CanHacker::writeStream(const char character) { char str[2]; str[0] = character; @@ -434,16 +320,21 @@ CanHacker::ERROR CanHacker::receiveCommand(const char *buffer, const int length) } } -CanHacker::ERROR CanHacker::receiveCanFrame(const struct can_frame *frame) { +CanHacker::ERROR CanHacker::receiveCanFrame(const can_message *frame) { char out[35]; - ERROR error = createTransmit(frame, out, 35); + + ERROR error = createTransmit(frame, out, sizeof(out)); if (error != ERROR_OK) { return error; } - return writeStream(out); + error = writeStream(out); + if (error != ERROR_OK) { + return error; + } + return ERROR_OK; } -CanHacker::ERROR CanHacker::parseTransmit(const char *buffer, int length, struct can_frame *frame) { +CanHacker::ERROR CanHacker::parseTransmit(const char *buffer, int length, can_message *frame) { if (length < MIN_MESSAGE_LENGTH) { writeDebugStream(F("Transmit message lenght < minimum\n")); writeDebugStream((const uint8_t*)buffer, length); @@ -517,7 +408,7 @@ CanHacker::ERROR CanHacker::parseTransmit(const char *buffer, int length, struct return ERROR_OK; } -CanHacker::ERROR CanHacker::createTransmit(const struct can_frame *frame, char *buffer, const int length) { +CanHacker::ERROR CanHacker::createTransmit(const can_message *frame, char *buffer, const int length) { int offset; int len = frame->can_dlc; @@ -563,7 +454,14 @@ CanHacker::ERROR CanHacker::createTransmit(const struct can_frame *frame, char * return ERROR_OK; } -CanHacker::ERROR CanHacker::sendFrame(const struct can_frame *frame) { +bool CanHacker::readFrame(can_message &frame){ + if(can_instance->read(frame)){ + return true; + } + return false; +} + +CanHacker::ERROR CanHacker::sendFrame(const can_message &frame) { return writeCan(frame); } @@ -577,14 +475,14 @@ CanHacker::ERROR CanHacker::receiveTransmitCommand(const char *buffer, const int return ERROR_LISTEN_ONLY; } - struct can_frame frame; + can_message frame; ERROR error = parseTransmit(buffer, length, &frame); if (error != ERROR_OK) { return error; } - error = writeCan(&frame); - if (error != ERROR_OK) { - return error; + bool sent = can_instance->write(frame); + if (!sent) { + return ERROR_SEND; } return writeStream(CR); @@ -672,6 +570,7 @@ CanHacker::ERROR CanHacker::receiveListenOnlyCommand(const char *buffer, const i return ERROR_CONNECTED; } _listenOnly = true; + can_instance->setListenOnly(true); return writeStream(CR); } @@ -699,13 +598,13 @@ CanHacker::ERROR CanHacker::receiveSetAcrCommand(const char *buffer, const int l } } - error = setFilter(id); - if (error != ERROR_OK) { - return error; + if(!can_instance->setFilter(id)){ + writeDebugStream(F("Filter cannot be set.\n")); + return ERROR_NOT_CONNECTED; } if (beenConnected) { - error = connectCan(); + error = (ERROR)isConnected(); if (error != ERROR_OK) { return error; } @@ -738,7 +637,7 @@ CanHacker::ERROR CanHacker::receiveSetAmrCommand(const char *buffer, const int l } } - error = setFilterMask(id); + error = (ERROR)can_instance->setFilterMask(id); if (error != ERROR_OK) { return error; } @@ -759,7 +658,7 @@ CanHacker::ERROR CanHacker::enableLoopback() { return ERROR_CONNECTED; } - _loopback = true; + can_instance->enableLoopBack(true); return ERROR_OK; } @@ -770,7 +669,7 @@ CanHacker::ERROR CanHacker::disableLoopback() { return ERROR_CONNECTED; } - _loopback = false; + can_instance->enableLoopBack(false); return ERROR_OK; } diff --git a/CanHacker.h b/CanHacker.h index 1e79947..7d75655 100644 --- a/CanHacker.h +++ b/CanHacker.h @@ -8,7 +8,9 @@ #define CANHACKER_H_ #include -#include +#include +#include +#include #define CAN_MIN_DLEN 1 #define HEX_PER_BYTE 2 @@ -24,6 +26,8 @@ class CanHacker { public: + typedef BASE_CAN::can_frame can_message; + enum ERROR { ERROR_OK, ERROR_CONNECTED, @@ -34,30 +38,30 @@ class CanHacker { ERROR_BUFFER_OVERFLOW, ERROR_SERIAL_TX_OVERRUN, ERROR_LISTEN_ONLY, - ERROR_MCP2515_INIT, - ERROR_MCP2515_INIT_CONFIG, - ERROR_MCP2515_INIT_BITRATE, - ERROR_MCP2515_INIT_SET_MODE, - ERROR_MCP2515_SEND, - ERROR_MCP2515_READ, - ERROR_MCP2515_FILTER, - ERROR_MCP2515_ERRIF, - ERROR_MCP2515_MERRF + ERROR_INIT, + ERROR_CONFIG, + ERROR_BITRATE, + ERROR_SET_MODE, + ERROR_SEND, + ERROR_READ, + ERROR_FILTER, + ERROR_ERRIF, + ERROR_MERRF, + ERROR_WAKIF }; - CanHacker(Stream *stream, Stream *debugStream, uint8_t cs); + CanHacker(Stream *stream, Stream *debugStream, uint8_t cs, const uint32_t spi_clock = 0); + CanHacker(Stream *stream, Stream *debugStream, BASE_CAN *can); ~CanHacker(); - void setClock(const CAN_CLOCK clock); + void setClock(const BASE_CAN::CAN_CLOCK clock); ERROR receiveCommand(const char *buffer, const int length); - ERROR receiveCanFrame(const struct can_frame *frame); - ERROR sendFrame(const struct can_frame *); + ERROR receiveCanFrame(const can_message *frame); + ERROR sendFrame(const can_message &frame); + bool readFrame(can_message &frame); ERROR enableLoopback(); ERROR disableLoopback(); - ERROR pollReceiveCan(); - ERROR receiveCan(const MCP2515::RXBn rxBuffer); - MCP2515 *getMcp2515(); - ERROR processInterrupt(); Stream *getInterfaceStream(); + BASE_CAN *get_can_instance(); private: @@ -65,16 +69,14 @@ class CanHacker { static const char BEL = 7; static const uint16_t TIMESTAMP_LIMIT = 0xEA60; - CAN_CLOCK canClock = MCP_16MHZ; bool _timestampEnabled = false; bool _listenOnly = false; - bool _loopback = false; - uint8_t _cs; - MCP2515 *mcp2515; - CAN_SPEED bitrate; - bool _isConnected = false; + + BASE_CAN *can_instance = nullptr; + Stream *_stream; Stream *_debugStream; + uint8_t scratch = 0; enum /*class*/ COMMAND : char { COMMAND_SET_BITRATE = 'S', // set CAN bit rate @@ -99,17 +101,15 @@ class CanHacker { COMMAND_LISTEN_ONLY = 'L' // switch to listen only mode }; - ERROR parseTransmit(const char *buffer, int length, struct can_frame *frame); - ERROR createTransmit(const struct can_frame *frame, char *buffer, const int length); + ERROR parseTransmit(const char *buffer, int length, can_message *frame); + ERROR createTransmit(const can_message *frame, char *buffer, const int length); uint16_t getTimestamp(); - ERROR setFilter(const uint32_t filter); - ERROR setFilterMask(const uint32_t mask); ERROR connectCan(); ERROR disconnectCan(); bool isConnected(); - ERROR writeCan(const struct can_frame *); + ERROR writeCan(const can_message &); ERROR writeStream(const char character); ERROR writeStream(const char *buffer); ERROR writeDebugStream(const char character); diff --git a/CanHacker_updated_structure.png b/CanHacker_updated_structure.png new file mode 100644 index 0000000..d3c3d86 Binary files /dev/null and b/CanHacker_updated_structure.png differ diff --git a/README.md b/README.md index 08d0149..9893ff3 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,19 @@ # CanHacker (lawicel) CAN adapter on Arduino + MCP2515 + +## enVgo Library Structure and Flow +![](./CanHacker_updated_structure.png) + + +## enVgo Driver Configuration + +To configure if MCP2515 or STM32 driver should be used, uncomment/comment the respective lines in `can_driver_config.h` + + Use that [Library](https://github.com/autowp/arduino-mcp2515) to communicate with MCP2515 +--- + ## Features Implement communication with CAN bus via MCP2515 by CanHacker (lawicel) protocol.