esphome/esphome/components/mcp2515/mcp2515.cpp

613 lines
18 KiB
C++

#include "mcp2515.h"
#include "esphome/core/log.h"
namespace esphome {
namespace mcp2515 {
static const char *TAG = "mcp2515";
const struct MCP2515::TxBnRegs MCP2515::TXB[N_TXBUFFERS] = {{MCP_TXB0CTRL, MCP_TXB0SIDH, MCP_TXB0DATA},
{MCP_TXB1CTRL, MCP_TXB1SIDH, MCP_TXB1DATA},
{MCP_TXB2CTRL, MCP_TXB2SIDH, MCP_TXB2DATA}};
const struct MCP2515::RxBnRegs MCP2515::RXB[N_RXBUFFERS] = {{MCP_RXB0CTRL, MCP_RXB0SIDH, MCP_RXB0DATA, CANINTF_RX0IF},
{MCP_RXB1CTRL, MCP_RXB1SIDH, MCP_RXB1DATA, CANINTF_RX1IF}};
bool MCP2515::setup_internal() {
this->spi_setup();
if (this->reset_() == canbus::ERROR_FAIL)
return false;
this->set_bitrate_(this->bit_rate_, this->mcp_clock_);
this->set_mode_(this->mcp_mode_);
ESP_LOGV(TAG, "setup done");
return true;
}
canbus::Error MCP2515::reset_() {
this->enable();
this->transfer_byte(INSTRUCTION_RESET);
this->disable();
ESP_LOGV(TAG, "reset_()");
delay(10);
ESP_LOGV(TAG, "reset() CLEAR ALL TXB registers");
uint8_t zeros[14];
memset(zeros, 0, sizeof(zeros));
set_registers_(MCP_TXB0CTRL, zeros, 14);
set_registers_(MCP_TXB1CTRL, zeros, 14);
set_registers_(MCP_TXB2CTRL, zeros, 14);
ESP_LOGD(TAG, "reset() CLEARED TXB registers");
set_register_(MCP_RXB0CTRL, 0);
set_register_(MCP_RXB1CTRL, 0);
set_register_(MCP_CANINTE, CANINTF_RX0IF | CANINTF_RX1IF | CANINTF_ERRIF | CANINTF_MERRF);
modify_register_(MCP_RXB0CTRL, RXB_CTRL_RXM_MASK | RXB_0_CTRL_BUKT, RXB_CTRL_RXM_STDEXT | RXB_0_CTRL_BUKT);
modify_register_(MCP_RXB1CTRL, RXB_CTRL_RXM_MASK, RXB_CTRL_RXM_STDEXT);
return canbus::ERROR_OK;
}
uint8_t MCP2515::read_register_(const REGISTER reg) {
this->enable();
this->transfer_byte(INSTRUCTION_READ);
this->transfer_byte(reg);
uint8_t ret = this->transfer_byte(0x00);
this->disable();
return ret;
}
void MCP2515::read_registers_(const REGISTER reg, uint8_t values[], const uint8_t n) {
this->enable();
this->transfer_byte(INSTRUCTION_READ);
this->transfer_byte(reg);
// this->transfer_array(values, n);
// mcp2515 has auto - increment of address - pointer
for (uint8_t i = 0; i < n; i++) {
values[i] = this->transfer_byte(0x00);
}
this->disable();
}
void MCP2515::set_register_(const REGISTER reg, const uint8_t value) {
this->enable();
this->transfer_byte(INSTRUCTION_WRITE);
this->transfer_byte(reg);
this->transfer_byte(value);
this->disable();
}
void MCP2515::set_registers_(const REGISTER reg, uint8_t values[], const uint8_t n) {
this->enable();
this->transfer_byte(INSTRUCTION_WRITE);
this->transfer_byte(reg);
// this->transfer_array(values, n);
for (uint8_t i = 0; i < n; i++) {
this->transfer_byte(values[i]);
}
this->disable();
}
void MCP2515::modify_register_(const REGISTER reg, const uint8_t mask, const uint8_t data) {
this->enable();
this->transfer_byte(INSTRUCTION_BITMOD);
this->transfer_byte(reg);
this->transfer_byte(mask);
this->transfer_byte(data);
this->disable();
}
uint8_t MCP2515::get_status_() {
this->enable();
this->transfer_byte(INSTRUCTION_READ_STATUS);
uint8_t i = this->transfer_byte(0x00);
this->disable();
return i;
}
canbus::Error MCP2515::set_mode_(const CanctrlReqopMode mode) {
modify_register_(MCP_CANCTRL, CANCTRL_REQOP, mode);
unsigned long end_time = millis() + 10;
bool mode_match = false;
while (millis() < end_time) {
uint8_t new_mode = read_register_(MCP_CANSTAT);
new_mode &= CANSTAT_OPMOD;
mode_match = new_mode == mode;
if (mode_match) {
break;
}
}
return mode_match ? canbus::ERROR_OK : canbus::ERROR_FAIL;
}
canbus::Error MCP2515::set_clk_out_(const CanClkOut divisor) {
canbus::Error res;
uint8_t cfg3;
if (divisor == CLKOUT_DISABLE) {
/* Turn off CLKEN */
modify_register_(MCP_CANCTRL, CANCTRL_CLKEN, 0x00);
/* Turn on CLKOUT for SOF */
modify_register_(MCP_CNF3, CNF3_SOF, CNF3_SOF);
return canbus::ERROR_OK;
}
/* Set the prescaler (CLKPRE) */
modify_register_(MCP_CANCTRL, CANCTRL_CLKPRE, divisor);
/* Turn on CLKEN */
modify_register_(MCP_CANCTRL, CANCTRL_CLKEN, CANCTRL_CLKEN);
/* Turn off CLKOUT for SOF */
modify_register_(MCP_CNF3, CNF3_SOF, 0x00);
return canbus::ERROR_OK;
}
void MCP2515::prepare_id_(uint8_t *buffer, const bool extended, const uint32_t id) {
uint16_t canid = (uint16_t)(id & 0x0FFFF);
if (extended) {
buffer[MCP_EID0] = (uint8_t)(canid & 0xFF);
buffer[MCP_EID8] = (uint8_t)(canid >> 8);
canid = (uint16_t)(id >> 16);
buffer[MCP_SIDL] = (uint8_t)(canid & 0x03);
buffer[MCP_SIDL] += (uint8_t)((canid & 0x1C) << 3);
buffer[MCP_SIDL] |= TXB_EXIDE_MASK;
buffer[MCP_SIDH] = (uint8_t)(canid >> 5);
} else {
buffer[MCP_SIDH] = (uint8_t)(canid >> 3);
buffer[MCP_SIDL] = (uint8_t)((canid & 0x07) << 5);
buffer[MCP_EID0] = 0;
buffer[MCP_EID8] = 0;
}
}
canbus::Error MCP2515::set_filter_mask_(const MASK mask, const bool extended, const uint32_t ul_data) {
canbus::Error res = set_mode_(CANCTRL_REQOP_CONFIG);
if (res != canbus::ERROR_OK) {
return res;
}
uint8_t tbufdata[4];
prepare_id_(tbufdata, extended, ul_data);
REGISTER reg;
switch (mask) {
case MASK0:
reg = MCP_RXM0SIDH;
break;
case MASK1:
reg = MCP_RXM1SIDH;
break;
default:
return canbus::ERROR_FAIL;
}
set_registers_(reg, tbufdata, 4);
return canbus::ERROR_OK;
}
canbus::Error MCP2515::set_filter_(const RXF num, const bool extended, const uint32_t ul_data) {
canbus::Error res = set_mode_(CANCTRL_REQOP_CONFIG);
if (res != canbus::ERROR_OK) {
return res;
}
REGISTER reg;
switch (num) {
case RXF0:
reg = MCP_RXF0SIDH;
break;
case RXF1:
reg = MCP_RXF1SIDH;
break;
case RXF2:
reg = MCP_RXF2SIDH;
break;
case RXF3:
reg = MCP_RXF3SIDH;
break;
case RXF4:
reg = MCP_RXF4SIDH;
break;
case RXF5:
reg = MCP_RXF5SIDH;
break;
default:
return canbus::ERROR_FAIL;
}
uint8_t tbufdata[4];
prepare_id_(tbufdata, extended, ul_data);
set_registers_(reg, tbufdata, 4);
return canbus::ERROR_OK;
}
canbus::Error MCP2515::send_message_(TXBn txbn, struct canbus::CanFrame *frame) {
const struct TxBnRegs *txbuf = &TXB[txbn];
uint8_t data[13];
prepare_id_(data, frame->use_extended_id, frame->can_id);
data[MCP_DLC] =
frame->remote_transmission_request ? (frame->can_data_length_code | RTR_MASK) : frame->can_data_length_code;
memcpy(&data[MCP_DATA], frame->data, frame->can_data_length_code);
set_registers_(txbuf->SIDH, data, 5 + frame->can_data_length_code);
modify_register_(txbuf->CTRL, TXB_TXREQ, TXB_TXREQ);
return canbus::ERROR_OK;
}
canbus::Error MCP2515::send_message(struct canbus::CanFrame *frame) {
if (frame->can_data_length_code > canbus::CAN_MAX_DATA_LENGTH) {
return canbus::ERROR_FAILTX;
}
TXBn tx_buffers[N_TXBUFFERS] = {TXB0, TXB1, TXB2};
for (auto &tx_buffer : tx_buffers) {
const struct TxBnRegs *txbuf = &TXB[tx_buffer];
uint8_t ctrlval = read_register_(txbuf->CTRL);
if ((ctrlval & TXB_TXREQ) == 0) {
return send_message_(tx_buffer, frame);
}
}
return canbus::ERROR_FAILTX;
}
canbus::Error MCP2515::read_message_(RXBn rxbn, struct canbus::CanFrame *frame) {
const struct RxBnRegs *rxb = &RXB[rxbn];
uint8_t tbufdata[5];
read_registers_(rxb->SIDH, tbufdata, 5);
uint32_t id = (tbufdata[MCP_SIDH] << 3) + (tbufdata[MCP_SIDL] >> 5);
bool use_extended_id = false;
bool remote_transmission_request = false;
if ((tbufdata[MCP_SIDL] & TXB_EXIDE_MASK) == TXB_EXIDE_MASK) {
id = (id << 2) + (tbufdata[MCP_SIDL] & 0x03);
id = (id << 8) + tbufdata[MCP_EID8];
id = (id << 8) + tbufdata[MCP_EID0];
// id |= canbus::CAN_EFF_FLAG;
use_extended_id = true;
}
uint8_t dlc = (tbufdata[MCP_DLC] & DLC_MASK);
if (dlc > canbus::CAN_MAX_DATA_LENGTH) {
return canbus::ERROR_FAIL;
}
uint8_t ctrl = read_register_(rxb->CTRL);
if (ctrl & RXB_CTRL_RTR) {
// id |= canbus::CAN_RTR_FLAG;
remote_transmission_request = true;
}
frame->can_id = id;
frame->can_data_length_code = dlc;
frame->use_extended_id = use_extended_id;
frame->remote_transmission_request = remote_transmission_request;
read_registers_(rxb->DATA, frame->data, dlc);
modify_register_(MCP_CANINTF, rxb->CANINTF_RXnIF, 0);
return canbus::ERROR_OK;
}
canbus::Error MCP2515::read_message(struct canbus::CanFrame *frame) {
canbus::Error rc;
uint8_t stat = get_status_();
if (stat & STAT_RX0IF) {
rc = read_message_(RXB0, frame);
} else if (stat & STAT_RX1IF) {
rc = read_message_(RXB1, frame);
} else {
rc = canbus::ERROR_NOMSG;
}
return rc;
}
bool MCP2515::check_receive_() {
uint8_t res = get_status_();
return (res & STAT_RXIF_MASK) != 0;
}
bool MCP2515::check_error_() {
uint8_t eflg = get_error_flags_();
return (eflg & EFLG_ERRORMASK) != 0;
}
uint8_t MCP2515::get_error_flags_() { return read_register_(MCP_EFLG); }
void MCP2515::clear_rx_n_ovr_flags_() { modify_register_(MCP_EFLG, EFLG_RX0OVR | EFLG_RX1OVR, 0); }
uint8_t MCP2515::get_int_() { return read_register_(MCP_CANINTF); }
void MCP2515::clear_int_() { set_register_(MCP_CANINTF, 0); }
uint8_t MCP2515::get_int_mask_() { return read_register_(MCP_CANINTE); }
void MCP2515::clear_tx_int_() { modify_register_(MCP_CANINTF, (CANINTF_TX0IF | CANINTF_TX1IF | CANINTF_TX2IF), 0); }
void MCP2515::clear_rx_n_ovr_() {
uint8_t eflg = get_error_flags_();
if (eflg != 0) {
clear_rx_n_ovr_flags_();
clear_int_();
// modify_register_(MCP_CANINTF, CANINTF_ERRIF, 0);
}
}
void MCP2515::clear_merr_() {
// modify_register_(MCP_EFLG, EFLG_RX0OVR | EFLG_RX1OVR, 0);
// clear_int_();
modify_register_(MCP_CANINTF, CANINTF_MERRF, 0);
}
void MCP2515::clear_errif_() {
// modify_register_(MCP_EFLG, EFLG_RX0OVR | EFLG_RX1OVR, 0);
// clear_int_();
modify_register_(MCP_CANINTF, CANINTF_ERRIF, 0);
}
canbus::Error MCP2515::set_bitrate_(canbus::CanSpeed can_speed) { return this->set_bitrate_(can_speed, MCP_16MHZ); }
canbus::Error MCP2515::set_bitrate_(canbus::CanSpeed can_speed, CanClock can_clock) {
canbus::Error error = set_mode_(CANCTRL_REQOP_CONFIG);
if (error != canbus::ERROR_OK) {
return error;
}
uint8_t set, cfg1, cfg2, cfg3;
set = 1;
switch (can_clock) {
case (MCP_8MHZ):
switch (can_speed) {
case (canbus::CAN_5KBPS): // 5KBPS
cfg1 = MCP_8MHZ_5KBPS_CFG1;
cfg2 = MCP_8MHZ_5KBPS_CFG2;
cfg3 = MCP_8MHZ_5KBPS_CFG3;
break;
case (canbus::CAN_10KBPS): // 10KBPS
cfg1 = MCP_8MHZ_10KBPS_CFG1;
cfg2 = MCP_8MHZ_10KBPS_CFG2;
cfg3 = MCP_8MHZ_10KBPS_CFG3;
break;
case (canbus::CAN_20KBPS): // 20KBPS
cfg1 = MCP_8MHZ_20KBPS_CFG1;
cfg2 = MCP_8MHZ_20KBPS_CFG2;
cfg3 = MCP_8MHZ_20KBPS_CFG3;
break;
case (canbus::CAN_31K25BPS): // 31.25KBPS
cfg1 = MCP_8MHZ_31K25BPS_CFG1;
cfg2 = MCP_8MHZ_31K25BPS_CFG2;
cfg3 = MCP_8MHZ_31K25BPS_CFG3;
break;
case (canbus::CAN_33KBPS): // 33.333KBPS
cfg1 = MCP_8MHZ_33K3BPS_CFG1;
cfg2 = MCP_8MHZ_33K3BPS_CFG2;
cfg3 = MCP_8MHZ_33K3BPS_CFG3;
break;
case (canbus::CAN_40KBPS): // 40Kbps
cfg1 = MCP_8MHZ_40KBPS_CFG1;
cfg2 = MCP_8MHZ_40KBPS_CFG2;
cfg3 = MCP_8MHZ_40KBPS_CFG3;
break;
case (canbus::CAN_50KBPS): // 50Kbps
cfg1 = MCP_8MHZ_50KBPS_CFG1;
cfg2 = MCP_8MHZ_50KBPS_CFG2;
cfg3 = MCP_8MHZ_50KBPS_CFG3;
break;
case (canbus::CAN_80KBPS): // 80Kbps
cfg1 = MCP_8MHZ_80KBPS_CFG1;
cfg2 = MCP_8MHZ_80KBPS_CFG2;
cfg3 = MCP_8MHZ_80KBPS_CFG3;
break;
case (canbus::CAN_100KBPS): // 100Kbps
cfg1 = MCP_8MHZ_100KBPS_CFG1;
cfg2 = MCP_8MHZ_100KBPS_CFG2;
cfg3 = MCP_8MHZ_100KBPS_CFG3;
break;
case (canbus::CAN_125KBPS): // 125Kbps
cfg1 = MCP_8MHZ_125KBPS_CFG1;
cfg2 = MCP_8MHZ_125KBPS_CFG2;
cfg3 = MCP_8MHZ_125KBPS_CFG3;
break;
case (canbus::CAN_200KBPS): // 200Kbps
cfg1 = MCP_8MHZ_200KBPS_CFG1;
cfg2 = MCP_8MHZ_200KBPS_CFG2;
cfg3 = MCP_8MHZ_200KBPS_CFG3;
break;
case (canbus::CAN_250KBPS): // 250Kbps
cfg1 = MCP_8MHZ_250KBPS_CFG1;
cfg2 = MCP_8MHZ_250KBPS_CFG2;
cfg3 = MCP_8MHZ_250KBPS_CFG3;
break;
case (canbus::CAN_500KBPS): // 500Kbps
cfg1 = MCP_8MHZ_500KBPS_CFG1;
cfg2 = MCP_8MHZ_500KBPS_CFG2;
cfg3 = MCP_8MHZ_500KBPS_CFG3;
break;
case (canbus::CAN_1000KBPS): // 1Mbps
cfg1 = MCP_8MHZ_1000KBPS_CFG1;
cfg2 = MCP_8MHZ_1000KBPS_CFG2;
cfg3 = MCP_8MHZ_1000KBPS_CFG3;
break;
default:
set = 0;
break;
}
break;
case (MCP_16MHZ):
switch (can_speed) {
case (canbus::CAN_5KBPS): // 5Kbps
cfg1 = MCP_16MHZ_5KBPS_CFG1;
cfg2 = MCP_16MHZ_5KBPS_CFG2;
cfg3 = MCP_16MHZ_5KBPS_CFG3;
break;
case (canbus::CAN_10KBPS): // 10Kbps
cfg1 = MCP_16MHZ_10KBPS_CFG1;
cfg2 = MCP_16MHZ_10KBPS_CFG2;
cfg3 = MCP_16MHZ_10KBPS_CFG3;
break;
case (canbus::CAN_20KBPS): // 20Kbps
cfg1 = MCP_16MHZ_20KBPS_CFG1;
cfg2 = MCP_16MHZ_20KBPS_CFG2;
cfg3 = MCP_16MHZ_20KBPS_CFG3;
break;
case (canbus::CAN_33KBPS): // 33.333Kbps
cfg1 = MCP_16MHZ_33K3BPS_CFG1;
cfg2 = MCP_16MHZ_33K3BPS_CFG2;
cfg3 = MCP_16MHZ_33K3BPS_CFG3;
break;
case (canbus::CAN_40KBPS): // 40Kbps
cfg1 = MCP_16MHZ_40KBPS_CFG1;
cfg2 = MCP_16MHZ_40KBPS_CFG2;
cfg3 = MCP_16MHZ_40KBPS_CFG3;
break;
case (canbus::CAN_50KBPS): // 50Kbps
cfg2 = MCP_16MHZ_50KBPS_CFG2;
cfg3 = MCP_16MHZ_50KBPS_CFG3;
break;
case (canbus::CAN_80KBPS): // 80Kbps
cfg1 = MCP_16MHZ_80KBPS_CFG1;
cfg2 = MCP_16MHZ_80KBPS_CFG2;
cfg3 = MCP_16MHZ_80KBPS_CFG3;
break;
case (canbus::CAN_83K3BPS): // 83.333Kbps
cfg1 = MCP_16MHZ_83K3BPS_CFG1;
cfg2 = MCP_16MHZ_83K3BPS_CFG2;
cfg3 = MCP_16MHZ_83K3BPS_CFG3;
break;
case (canbus::CAN_100KBPS): // 100Kbps
cfg1 = MCP_16MHZ_100KBPS_CFG1;
cfg2 = MCP_16MHZ_100KBPS_CFG2;
cfg3 = MCP_16MHZ_100KBPS_CFG3;
break;
case (canbus::CAN_125KBPS): // 125Kbps
cfg1 = MCP_16MHZ_125KBPS_CFG1;
cfg2 = MCP_16MHZ_125KBPS_CFG2;
cfg3 = MCP_16MHZ_125KBPS_CFG3;
break;
case (canbus::CAN_200KBPS): // 200Kbps
cfg1 = MCP_16MHZ_200KBPS_CFG1;
cfg2 = MCP_16MHZ_200KBPS_CFG2;
cfg3 = MCP_16MHZ_200KBPS_CFG3;
break;
case (canbus::CAN_250KBPS): // 250Kbps
cfg1 = MCP_16MHZ_250KBPS_CFG1;
cfg2 = MCP_16MHZ_250KBPS_CFG2;
cfg3 = MCP_16MHZ_250KBPS_CFG3;
break;
case (canbus::CAN_500KBPS): // 500Kbps
cfg1 = MCP_16MHZ_500KBPS_CFG1;
cfg2 = MCP_16MHZ_500KBPS_CFG2;
cfg3 = MCP_16MHZ_500KBPS_CFG3;
break;
case (canbus::CAN_1000KBPS): // 1Mbps
cfg1 = MCP_16MHZ_1000KBPS_CFG1;
cfg2 = MCP_16MHZ_1000KBPS_CFG2;
cfg3 = MCP_16MHZ_1000KBPS_CFG3;
break;
default:
set = 0;
break;
}
break;
case (MCP_20MHZ):
switch (can_speed) {
case (canbus::CAN_33KBPS): // 33.333Kbps
cfg1 = MCP_20MHZ_33K3BPS_CFG1;
cfg2 = MCP_20MHZ_33K3BPS_CFG2;
cfg3 = MCP_20MHZ_33K3BPS_CFG3;
break;
case (canbus::CAN_40KBPS): // 40Kbps
cfg1 = MCP_20MHZ_40KBPS_CFG1;
cfg2 = MCP_20MHZ_40KBPS_CFG2;
cfg3 = MCP_20MHZ_40KBPS_CFG3;
break;
case (canbus::CAN_50KBPS): // 50Kbps
cfg1 = MCP_20MHZ_50KBPS_CFG1;
cfg2 = MCP_20MHZ_50KBPS_CFG2;
cfg3 = MCP_20MHZ_50KBPS_CFG3;
break;
case (canbus::CAN_80KBPS): // 80Kbps
cfg1 = MCP_20MHZ_80KBPS_CFG1;
cfg2 = MCP_20MHZ_80KBPS_CFG2;
cfg3 = MCP_20MHZ_80KBPS_CFG3;
break;
case (canbus::CAN_83K3BPS): // 83.333Kbps
cfg1 = MCP_20MHZ_83K3BPS_CFG1;
cfg2 = MCP_20MHZ_83K3BPS_CFG2;
cfg3 = MCP_20MHZ_83K3BPS_CFG3;
break;
case (canbus::CAN_100KBPS): // 100Kbps
cfg1 = MCP_20MHZ_100KBPS_CFG1;
cfg2 = MCP_20MHZ_100KBPS_CFG2;
cfg3 = MCP_20MHZ_100KBPS_CFG3;
break;
case (canbus::CAN_125KBPS): // 125Kbps
cfg1 = MCP_20MHZ_125KBPS_CFG1;
cfg2 = MCP_20MHZ_125KBPS_CFG2;
cfg3 = MCP_20MHZ_125KBPS_CFG3;
break;
case (canbus::CAN_200KBPS): // 200Kbps
cfg1 = MCP_20MHZ_200KBPS_CFG1;
cfg2 = MCP_20MHZ_200KBPS_CFG2;
cfg3 = MCP_20MHZ_200KBPS_CFG3;
break;
case (canbus::CAN_250KBPS): // 250Kbps
cfg1 = MCP_20MHZ_250KBPS_CFG1;
cfg2 = MCP_20MHZ_250KBPS_CFG2;
cfg3 = MCP_20MHZ_250KBPS_CFG3;
break;
case (canbus::CAN_500KBPS): // 500Kbps
cfg1 = MCP_20MHZ_500KBPS_CFG1;
cfg2 = MCP_20MHZ_500KBPS_CFG2;
cfg3 = MCP_20MHZ_500KBPS_CFG3;
break;
case (canbus::CAN_1000KBPS): // 1Mbps
cfg1 = MCP_20MHZ_1000KBPS_CFG1;
cfg2 = MCP_20MHZ_1000KBPS_CFG2;
cfg3 = MCP_20MHZ_1000KBPS_CFG3;
break;
default:
set = 0;
break;
}
break;
default:
set = 0;
break;
}
if (set) {
set_register_(MCP_CNF1, cfg1);
set_register_(MCP_CNF2, cfg2);
set_register_(MCP_CNF3, cfg3);
return canbus::ERROR_OK;
} else {
return canbus::ERROR_FAIL;
}
}
} // namespace mcp2515
} // namespace esphome