From e04cf24d034fef396a5fbe7ee62c799be4447df6 Mon Sep 17 00:00:00 2001 From: Michiel van Turnhout Date: Wed, 17 Jul 2019 19:12:07 +0200 Subject: [PATCH] mcp2515 functions from driver --- esphome/components/canbus/canbus.h | 29 +- esphome/components/esp32_can/esp32_can.cpp | 4 + esphome/components/esp32_can/esp32_can.h | 8 +- esphome/components/mcp2515/mcp2515.cpp | 677 ++++++++++++++++++++- esphome/components/mcp2515/mcp2515.h | 117 +++- esphome/components/mcp2515/mcp2515_defs.h | 388 ++++++++++++ 6 files changed, 1204 insertions(+), 19 deletions(-) create mode 100644 esphome/components/mcp2515/mcp2515_defs.h diff --git a/esphome/components/canbus/canbus.h b/esphome/components/canbus/canbus.h index 47176badad..4e520cb316 100644 --- a/esphome/components/canbus/canbus.h +++ b/esphome/components/canbus/canbus.h @@ -31,10 +31,37 @@ class Canbus : public Component { void send(int can_id, uint8_t *data); void register_can_device(CanbusSensor *component){}; void set_sender_id(int sender_id) { this->sender_id_ = sender_id; } - + enum CAN_SPEED { + CAN_5KBPS, + CAN_10KBPS, + CAN_20KBPS, + CAN_31K25BPS, + CAN_33KBPS, + CAN_40KBPS, + CAN_50KBPS, + CAN_80KBPS, + CAN_83K3BPS, + CAN_95KBPS, + CAN_100KBPS, + CAN_125KBPS, + CAN_200KBPS, + CAN_250KBPS, + CAN_500KBPS, + CAN_1000KBPS +}; + enum ERROR : uint8_t { + ERROR_OK = 0, + ERROR_FAIL = 1, + ERROR_ALLTXBUSY = 2, + ERROR_FAILINIT = 3, + ERROR_FAILTX = 4, + ERROR_NOMSG = 5 + }; protected: int sender_id_{0}; virtual bool send_internal_(int can_id, uint8_t *data); + virtual bool setup_internal_(); + virtual ERROR set_bitrate_(const CAN_SPEED canSpeed); }; } // namespace canbus } // namespace esphome \ No newline at end of file diff --git a/esphome/components/esp32_can/esp32_can.cpp b/esphome/components/esp32_can/esp32_can.cpp index 795b8351e9..21457476ff 100644 --- a/esphome/components/esp32_can/esp32_can.cpp +++ b/esphome/components/esp32_can/esp32_can.cpp @@ -8,5 +8,9 @@ static const char *TAG = "esp32_can"; bool ESP32Can::send_internal_(int can_id, uint8_t *data) { return true; }; +bool ESP32Can::setup_internal_ () { return true; }; + +ESP32Can::ERROR ESP32Can::set_bitrate_(const CAN_SPEED canSpeed) { return ERROR_OK; }; + } // namespace esp32_can } // namespace esphome diff --git a/esphome/components/esp32_can/esp32_can.h b/esphome/components/esp32_can/esp32_can.h index 1ab48f0068..a387f7d2ab 100644 --- a/esphome/components/esp32_can/esp32_can.h +++ b/esphome/components/esp32_can/esp32_can.h @@ -1,8 +1,7 @@ #pragma once -#include "esphome/core/component.h" -#include "esphome/core/automation.h" #include "esphome/components/canbus/canbus.h" +#include "esphome/core/component.h" namespace esphome { namespace esp32_can { @@ -10,10 +9,11 @@ namespace esp32_can { class ESP32Can : public canbus::Canbus { public: ESP32Can(){}; - ESP32Can(const std::string &name){}; protected: - bool send_internal_(int can_id, uint8_t *data); + bool send_internal_(int can_id, uint8_t *data) override; + bool setup_internal_() override; + ERROR set_bitrate_(const CAN_SPEED canSpeed) override; }; } // namespace esp32_can } // namespace esphome \ No newline at end of file diff --git a/esphome/components/mcp2515/mcp2515.cpp b/esphome/components/mcp2515/mcp2515.cpp index 66981c407f..acb5ab1882 100644 --- a/esphome/components/mcp2515/mcp2515.cpp +++ b/esphome/components/mcp2515/mcp2515.cpp @@ -8,5 +8,678 @@ static const char *TAG = "mcp2515"; bool MCP2515::send_internal_(int can_id, uint8_t *data) { return true; }; -} // namespace mcp2515 -} // namespace esphome +bool MCP2515::setup_internal_() { + this->reset_(); + return true; +} + +MCP2515::ERROR MCP2515::reset_(void) { + this->enable(); + this->transfer_byte(INSTRUCTION_RESET); + this->disable(); + + delay(10); + + 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); + + 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, + RXBnCTRL_RXM_MASK | RXB0CTRL_BUKT, + RXBnCTRL_RXM_STDEXT | RXB0CTRL_BUKT); + modify_register_(MCP_RXB1CTRL, RXBnCTRL_RXM_MASK, RXBnCTRL_RXM_STDEXT); + + // clear filters and masks + /*RXF filters[] = {RXF0, RXF1, RXF2, RXF3, RXF4, RXF5}; + for (int i=0; i<6; i++) { + ERROR result = set_filter_(filters[i], true, 0); + if (result != ERROR_OK) { + return result; + } + } + + MASK masks[] = {MASK0, MASK1}; + for (int i=0; i<2; i++) { + ERROR result = set_filter_mask_(masks[i], true, 0); + if (result != ERROR_OK) { + return result; + } + }*/ + + return 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; itransfer_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; itransfer_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_(void) +{ + this->enable(); + this->transfer_byte(INSTRUCTION_READ_STATUS); + uint8_t i = this->transfer_byte(0x00); + this->disable(); + + return i; +} + +MCP2515::ERROR MCP2515::set_config_mode_() +{ + return set_mode_(CANCTRL_REQOP_CONFIG); +} + +MCP2515::ERROR MCP2515::set_listen_only_() +{ + return set_mode_(CANCTRL_REQOP_LISTENONLY); +} + +MCP2515::ERROR MCP2515::set_sleep_mode_() +{ + return set_mode_(CANCTRL_REQOP_SLEEP); +} + +MCP2515::ERROR MCP2515::set_loop_back_mode_() +{ + return set_mode_(CANCTRL_REQOP_LOOPBACK); +} + +MCP2515::ERROR MCP2515::set_normal_mode_() +{ + return set_mode_(CANCTRL_REQOP_NORMAL); +} + +MCP2515::ERROR MCP2515::set_mode_(const CANCTRL_REQOP_MODE mode) +{ + modify_register_(MCP_CANCTRL, CANCTRL_REQOP, mode); + + unsigned long endTime = millis() + 10; + bool modeMatch = false; + while (millis() < endTime) { + uint8_t newmode = read_register_(MCP_CANSTAT); + newmode &= CANSTAT_OPMOD; + modeMatch = newmode == mode; + if (modeMatch) { + break; + } + } + return modeMatch ? ERROR_OK : ERROR_FAIL; +} + +MCP2515::ERROR MCP2515::set_clk_out_(const CAN_CLKOUT divisor) +{ + 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 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 ERROR_OK; +} + +void MCP2515::prepare_id_(uint8_t *buffer, const bool ext, const uint32_t id) +{ + uint16_t canid = (uint16_t)(id & 0x0FFFF); + + if (ext) { + 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; + } +} + +MCP2515::ERROR MCP2515::set_filter_mask_(const MASK mask, const bool ext, const uint32_t ulData) +{ + ERROR res = set_config_mode_(); + if (res != ERROR_OK) { + return res; + } + + uint8_t tbufdata[4]; + prepare_id_(tbufdata, ext, ulData); + + REGISTER reg; + switch (mask) { + case MASK0: reg = MCP_RXM0SIDH; break; + case MASK1: reg = MCP_RXM1SIDH; break; + default: + return ERROR_FAIL; + } + + set_registers_(reg, tbufdata, 4); + + return ERROR_OK; +} + +MCP2515::ERROR MCP2515::set_filter_(const RXF num, const bool ext, const uint32_t ulData) +{ + ERROR res = set_config_mode_(); + if (res != 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 ERROR_FAIL; + } + + uint8_t tbufdata[4]; + prepare_id_(tbufdata, ext, ulData); + set_registers_(reg, tbufdata, 4); + + return ERROR_OK; +} + +MCP2515::ERROR MCP2515::send_message_(const TXBn txbn, const struct can_frame *frame) +{ + const struct TXBn_REGS *txbuf = &TXB[txbn]; + + uint8_t data[13]; + + bool ext = (frame->can_id & CAN_EFF_FLAG); + bool rtr = (frame->can_id & CAN_RTR_FLAG); + uint32_t id = (frame->can_id & (ext ? CAN_EFF_MASK : CAN_SFF_MASK)); + + prepare_id_(data, ext, id); + + data[MCP_DLC] = rtr ? (frame->can_dlc | RTR_MASK) : frame->can_dlc; + + memcpy(&data[MCP_DATA], frame->data, frame->can_dlc); + + set_registers_(txbuf->SIDH, data, 5 + frame->can_dlc); + + modify_register_(txbuf->CTRL, TXB_TXREQ, TXB_TXREQ); + + return ERROR_OK; +} + +MCP2515::ERROR MCP2515::send_message_(const struct can_frame *frame) +{ + if (frame->can_dlc > CAN_MAX_DLEN) { + return ERROR_FAILTX; + } + + TXBn txBuffers[N_TXBUFFERS] = {TXB0, TXB1, TXB2}; + + for (int i=0; iCTRL); + if ( (ctrlval & TXB_TXREQ) == 0 ) { + return send_message_(txBuffers[i], frame); + } + } + + return ERROR_FAILTX; +} + +MCP2515::ERROR MCP2515::readMessage(const RXBn rxbn, struct can_frame *frame) +{ + const struct RXBn_REGS *rxb = &RXB[rxbn]; + + uint8_t tbufdata[5]; + + read_registers_(rxb->SIDH, tbufdata, 5); + + uint32_t id = (tbufdata[MCP_SIDH]<<3) + (tbufdata[MCP_SIDL]>>5); + + 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 |= CAN_EFF_FLAG; + } + + uint8_t dlc = (tbufdata[MCP_DLC] & DLC_MASK); + if (dlc > CAN_MAX_DLEN) { + return ERROR_FAIL; + } + + uint8_t ctrl = read_register_(rxb->CTRL); + if (ctrl & RXBnCTRL_RTR) { + id |= CAN_RTR_FLAG; + } + + frame->can_id = id; + frame->can_dlc = dlc; + + read_registers_(rxb->DATA, frame->data, dlc); + + modify_register_(MCP_CANINTF, rxb->CANINTF_RXnIF, 0); + + return ERROR_OK; +} + +MCP2515::ERROR MCP2515::readMessage(struct can_frame *frame) +{ + ERROR rc; + uint8_t stat = get_status_(); + + if ( stat & STAT_RX0IF ) { + rc = readMessage(RXB0, frame); + } else if ( stat & STAT_RX1IF ) { + rc = readMessage(RXB1, frame); + } else { + rc = ERROR_NOMSG; + } + + return rc; +} + +bool MCP2515::check_receive_(void) +{ + uint8_t res = get_status_(); + if ( res & STAT_RXIF_MASK ) { + return true; + } else { + return false; + } +} + +bool MCP2515::check_error_(void) +{ + uint8_t eflg = get_error_flags_(); + + if ( eflg & EFLG_ERRORMASK ) { + return true; + } else { + return false; + } +} + +uint8_t MCP2515::get_error_flags_(void) +{ + return read_register_(MCP_EFLG); +} + +void MCP2515::clearRXnOVRFlags(void) +{ + modify_register_(MCP_EFLG, EFLG_RX0OVR | EFLG_RX1OVR, 0); +} + +uint8_t MCP2515::getInterrupts(void) +{ + return read_register_(MCP_CANINTF); +} + +void MCP2515::clearInterrupts(void) +{ + set_register_(MCP_CANINTF, 0); +} + +uint8_t MCP2515::getInterruptMask(void) +{ + return read_register_(MCP_CANINTE); +} + +void MCP2515::clearTXInterrupts(void) +{ + modify_register_(MCP_CANINTF, (CANINTF_TX0IF | CANINTF_TX1IF | CANINTF_TX2IF), 0); +} + +void MCP2515::clearRXnOVR(void) +{ + uint8_t eflg = get_error_flags_(); + if (eflg != 0) { + clearRXnOVRFlags(); + clearInterrupts(); + //modify_register_(MCP_CANINTF, CANINTF_ERRIF, 0); + } + +} + +void MCP2515::clearMERR() +{ + //modify_register_(MCP_EFLG, EFLG_RX0OVR | EFLG_RX1OVR, 0); + //clearInterrupts(); + modify_register_(MCP_CANINTF, CANINTF_MERRF, 0); +} + +void MCP2515::clearERRIF() +{ + //modify_register_(MCP_EFLG, EFLG_RX0OVR | EFLG_RX1OVR, 0); + //clearInterrupts(); + modify_register_(MCP_CANINTF, CANINTF_ERRIF, 0); +} + + +MCP2515::ERROR MCP2515::set_bitrate_(const CAN_SPEED canSpeed) { + return set_bitrate_(canSpeed, MCP_16MHZ); +} + +MCP2515::ERROR MCP2515::set_bitrate_(const CAN_SPEED canSpeed, CAN_CLOCK canClock) +{ + ERROR error = set_config_mode_(); + if (error != ERROR_OK) { + return error; + } + + uint8_t set, cfg1, cfg2, cfg3; + set = 1; + switch (canClock) + { + case (MCP_8MHZ): + switch (canSpeed) + { + case (CAN_5KBPS): // 5KBPS + cfg1 = MCP_8MHz_5kBPS_CFG1; + cfg2 = MCP_8MHz_5kBPS_CFG2; + cfg3 = MCP_8MHz_5kBPS_CFG3; + break; + case (CAN_10KBPS): // 10KBPS + cfg1 = MCP_8MHz_10kBPS_CFG1; + cfg2 = MCP_8MHz_10kBPS_CFG2; + cfg3 = MCP_8MHz_10kBPS_CFG3; + break; + case (CAN_20KBPS): // 20KBPS + cfg1 = MCP_8MHz_20kBPS_CFG1; + cfg2 = MCP_8MHz_20kBPS_CFG2; + cfg3 = MCP_8MHz_20kBPS_CFG3; + break; + case (CAN_31K25BPS): // 31.25KBPS + cfg1 = MCP_8MHz_31k25BPS_CFG1; + cfg2 = MCP_8MHz_31k25BPS_CFG2; + cfg3 = MCP_8MHz_31k25BPS_CFG3; + break; + case (CAN_33KBPS): // 33.333KBPS + cfg1 = MCP_8MHz_33k3BPS_CFG1; + cfg2 = MCP_8MHz_33k3BPS_CFG2; + cfg3 = MCP_8MHz_33k3BPS_CFG3; + break; + case (CAN_40KBPS): // 40Kbps + cfg1 = MCP_8MHz_40kBPS_CFG1; + cfg2 = MCP_8MHz_40kBPS_CFG2; + cfg3 = MCP_8MHz_40kBPS_CFG3; + break; + case (CAN_50KBPS): // 50Kbps + cfg1 = MCP_8MHz_50kBPS_CFG1; + cfg2 = MCP_8MHz_50kBPS_CFG2; + cfg3 = MCP_8MHz_50kBPS_CFG3; + break; + case (CAN_80KBPS): // 80Kbps + cfg1 = MCP_8MHz_80kBPS_CFG1; + cfg2 = MCP_8MHz_80kBPS_CFG2; + cfg3 = MCP_8MHz_80kBPS_CFG3; + break; + case (CAN_100KBPS): // 100Kbps + cfg1 = MCP_8MHz_100kBPS_CFG1; + cfg2 = MCP_8MHz_100kBPS_CFG2; + cfg3 = MCP_8MHz_100kBPS_CFG3; + break; + case (CAN_125KBPS): // 125Kbps + cfg1 = MCP_8MHz_125kBPS_CFG1; + cfg2 = MCP_8MHz_125kBPS_CFG2; + cfg3 = MCP_8MHz_125kBPS_CFG3; + break; + case (CAN_200KBPS): // 200Kbps + cfg1 = MCP_8MHz_200kBPS_CFG1; + cfg2 = MCP_8MHz_200kBPS_CFG2; + cfg3 = MCP_8MHz_200kBPS_CFG3; + break; + case (CAN_250KBPS): // 250Kbps + cfg1 = MCP_8MHz_250kBPS_CFG1; + cfg2 = MCP_8MHz_250kBPS_CFG2; + cfg3 = MCP_8MHz_250kBPS_CFG3; + break; + case (CAN_500KBPS): // 500Kbps + cfg1 = MCP_8MHz_500kBPS_CFG1; + cfg2 = MCP_8MHz_500kBPS_CFG2; + cfg3 = MCP_8MHz_500kBPS_CFG3; + break; + case (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 (canSpeed) + { + case (CAN_5KBPS): // 5Kbps + cfg1 = MCP_16MHz_5kBPS_CFG1; + cfg2 = MCP_16MHz_5kBPS_CFG2; + cfg3 = MCP_16MHz_5kBPS_CFG3; + break; + case (CAN_10KBPS): // 10Kbps + cfg1 = MCP_16MHz_10kBPS_CFG1; + cfg2 = MCP_16MHz_10kBPS_CFG2; + cfg3 = MCP_16MHz_10kBPS_CFG3; + break; + case (CAN_20KBPS): // 20Kbps + cfg1 = MCP_16MHz_20kBPS_CFG1; + cfg2 = MCP_16MHz_20kBPS_CFG2; + cfg3 = MCP_16MHz_20kBPS_CFG3; + break; + case (CAN_33KBPS): // 33.333Kbps + cfg1 = MCP_16MHz_33k3BPS_CFG1; + cfg2 = MCP_16MHz_33k3BPS_CFG2; + cfg3 = MCP_16MHz_33k3BPS_CFG3; + break; + case (CAN_40KBPS): // 40Kbps + cfg1 = MCP_16MHz_40kBPS_CFG1; + cfg2 = MCP_16MHz_40kBPS_CFG2; + cfg3 = MCP_16MHz_40kBPS_CFG3; + break; + case (CAN_50KBPS): // 50Kbps + cfg2 = MCP_16MHz_50kBPS_CFG2; + cfg3 = MCP_16MHz_50kBPS_CFG3; + break; + case (CAN_80KBPS): // 80Kbps + cfg1 = MCP_16MHz_80kBPS_CFG1; + cfg2 = MCP_16MHz_80kBPS_CFG2; + cfg3 = MCP_16MHz_80kBPS_CFG3; + break; + case (CAN_83K3BPS): // 83.333Kbps + cfg1 = MCP_16MHz_83k3BPS_CFG1; + cfg2 = MCP_16MHz_83k3BPS_CFG2; + cfg3 = MCP_16MHz_83k3BPS_CFG3; + break; + case (CAN_100KBPS): // 100Kbps + cfg1 = MCP_16MHz_100kBPS_CFG1; + cfg2 = MCP_16MHz_100kBPS_CFG2; + cfg3 = MCP_16MHz_100kBPS_CFG3; + break; + case (CAN_125KBPS): // 125Kbps + cfg1 = MCP_16MHz_125kBPS_CFG1; + cfg2 = MCP_16MHz_125kBPS_CFG2; + cfg3 = MCP_16MHz_125kBPS_CFG3; + break; + case (CAN_200KBPS): // 200Kbps + cfg1 = MCP_16MHz_200kBPS_CFG1; + cfg2 = MCP_16MHz_200kBPS_CFG2; + cfg3 = MCP_16MHz_200kBPS_CFG3; + break; + case (CAN_250KBPS): // 250Kbps + cfg1 = MCP_16MHz_250kBPS_CFG1; + cfg2 = MCP_16MHz_250kBPS_CFG2; + cfg3 = MCP_16MHz_250kBPS_CFG3; + break; + case (CAN_500KBPS): // 500Kbps + cfg1 = MCP_16MHz_500kBPS_CFG1; + cfg2 = MCP_16MHz_500kBPS_CFG2; + cfg3 = MCP_16MHz_500kBPS_CFG3; + break; + case (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 (canSpeed) + { + case (CAN_33KBPS): // 33.333Kbps + cfg1 = MCP_20MHz_33k3BPS_CFG1; + cfg2 = MCP_20MHz_33k3BPS_CFG2; + cfg3 = MCP_20MHz_33k3BPS_CFG3; + break; + case (CAN_40KBPS): // 40Kbps + cfg1 = MCP_20MHz_40kBPS_CFG1; + cfg2 = MCP_20MHz_40kBPS_CFG2; + cfg3 = MCP_20MHz_40kBPS_CFG3; + break; + case (CAN_50KBPS): // 50Kbps + cfg1 = MCP_20MHz_50kBPS_CFG1; + cfg2 = MCP_20MHz_50kBPS_CFG2; + cfg3 = MCP_20MHz_50kBPS_CFG3; + break; + case (CAN_80KBPS): // 80Kbps + cfg1 = MCP_20MHz_80kBPS_CFG1; + cfg2 = MCP_20MHz_80kBPS_CFG2; + cfg3 = MCP_20MHz_80kBPS_CFG3; + break; + case (CAN_83K3BPS): // 83.333Kbps + cfg1 = MCP_20MHz_83k3BPS_CFG1; + cfg2 = MCP_20MHz_83k3BPS_CFG2; + cfg3 = MCP_20MHz_83k3BPS_CFG3; + break; + case (CAN_100KBPS): // 100Kbps + cfg1 = MCP_20MHz_100kBPS_CFG1; + cfg2 = MCP_20MHz_100kBPS_CFG2; + cfg3 = MCP_20MHz_100kBPS_CFG3; + break; + case (CAN_125KBPS): // 125Kbps + cfg1 = MCP_20MHz_125kBPS_CFG1; + cfg2 = MCP_20MHz_125kBPS_CFG2; + cfg3 = MCP_20MHz_125kBPS_CFG3; + break; + case (CAN_200KBPS): // 200Kbps + cfg1 = MCP_20MHz_200kBPS_CFG1; + cfg2 = MCP_20MHz_200kBPS_CFG2; + cfg3 = MCP_20MHz_200kBPS_CFG3; + break; + case (CAN_250KBPS): // 250Kbps + cfg1 = MCP_20MHz_250kBPS_CFG1; + cfg2 = MCP_20MHz_250kBPS_CFG2; + cfg3 = MCP_20MHz_250kBPS_CFG3; + break; + case (CAN_500KBPS): // 500Kbps + cfg1 = MCP_20MHz_500kBPS_CFG1; + cfg2 = MCP_20MHz_500kBPS_CFG2; + cfg3 = MCP_20MHz_500kBPS_CFG3; + break; + case (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 ERROR_OK; + } + else { + return ERROR_FAIL; + } +} +} // namespace mcp2515 +} // namespace esphome diff --git a/esphome/components/mcp2515/mcp2515.h b/esphome/components/mcp2515/mcp2515.h index 690abb9c2d..212a5d5cc8 100644 --- a/esphome/components/mcp2515/mcp2515.h +++ b/esphome/components/mcp2515/mcp2515.h @@ -1,24 +1,117 @@ #pragma once -#include "esphome/core/component.h" -#include "esphome/components/spi/spi.h" #include "esphome/components/canbus/canbus.h" +#include "esphome/components/spi/spi.h" +#include "esphome/core/component.h" +#include "mcp2515_defs.h" namespace esphome { namespace mcp2515 { class MCP2515 : public canbus::Canbus, - public spi::SPIDevice { - public: + public spi::SPIDevice { +public: MCP2515(){}; - MCP2515(const std::string &name){}; - + void set_cs_pin(GPIOPin *cs_pin) { cs_pin_ = cs_pin; } - protected: - GPIOPin *cs_pin_; - bool send_internal_(int can_id, uint8_t *data); + static const uint32_t SPI_CLOCK = 10000000; // 10MHz + /* special address description flags for the CAN_ID */ + static const uint32_t CAN_EFF_FLAG = + 0x80000000UL; /* EFF/SFF is set in the MSB */ + static const uint32_t CAN_RTR_FLAG = + 0x40000000UL; /* remote transmission request */ + static const uint32_t CAN_ERR_FLAG = 0x20000000UL; /* error message frame */ + + /* valid bits in CAN ID for frame formats */ + static const uint32_t CAN_SFF_MASK = + 0x000007FFUL; /* standard frame format (SFF) */ + static const uint32_t CAN_EFF_MASK = + 0x1FFFFFFFUL; /* extended frame format (EFF) */ + static const uint32_t CAN_ERR_MASK = + 0x1FFFFFFFUL; /* omit EFF, RTR, ERR flags */ + + static const int N_TXBUFFERS = 3; + static const int N_RXBUFFERS = 2; + +/* + * Controller Area Network Identifier structure + * + * bit 0-28 : CAN identifier (11/29 bit) + * bit 29 : error message frame flag (0 = data frame, 1 = error message) + * bit 30 : remote transmission request flag (1 = rtr frame) + * bit 31 : frame format flag (0 = standard 11 bit, 1 = extended 29 bit) + */ +typedef uint32_t canid_t; + +/* CAN payload length and DLC definitions according to ISO 11898-1 */ +static const uint8_t CAN_MAX_DLC = 8; +static const uint8_t CAN_MAX_DLEN =8; + + +struct can_frame { + canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */ + uint8_t can_dlc; /* frame payload length in byte (0 .. CAN_MAX_DLEN) */ + uint8_t data[CAN_MAX_DLEN] __attribute__((aligned(8))); }; -} // namespace mcp2515 -} // namespace esphome \ No newline at end of file + + + + static const struct TXBn_REGS { + REGISTER CTRL; + REGISTER SIDH; + REGISTER DATA; + } TXB[N_TXBUFFERS]; + + static const struct RXBn_REGS { + REGISTER CTRL; + REGISTER SIDH; + REGISTER DATA; + CANINTF CANINTF_RXnIF; + } RXB[N_RXBUFFERS]; + + +protected: + GPIOPin *cs_pin_; + bool send_internal_(int can_id, uint8_t *data) override; + bool setup_internal_() override; + ERROR set_mode_(const CANCTRL_REQOP_MODE mode); + + uint8_t read_register_(const REGISTER reg); + void read_registers_(const REGISTER reg, uint8_t values[], const uint8_t n); + void set_register_(const REGISTER reg, const uint8_t value); + void set_registers_(const REGISTER reg, uint8_t values[], const uint8_t n); + void modify_register_(const REGISTER reg, const uint8_t mask, const uint8_t data); + + void prepare_id_(uint8_t *buffer, const bool ext, const uint32_t id); + ERROR reset_(void); + ERROR set_config_mode_(); + ERROR set_listen_only_(); + ERROR set_sleep_mode_(); + ERROR set_loop_back_mode_(); + ERROR set_normal_mode_(); + ERROR set_clk_out_(const CAN_CLKOUT divisor); + ERROR set_bitrate_(const CAN_SPEED canSpeed) override; + ERROR set_bitrate_(const CAN_SPEED canSpeed, const CAN_CLOCK canClock); + ERROR set_filter_mask_(const MASK num, const bool ext, const uint32_t ulData); + ERROR set_filter_(const RXF num, const bool ext, const uint32_t ulData); + ERROR send_message_(const TXBn txbn, const struct can_frame *frame); + ERROR send_message_(const struct can_frame *frame); + ERROR readMessage(const RXBn rxbn, struct can_frame *frame); + ERROR readMessage(struct can_frame *frame); + bool check_receive_(void); + bool check_error_(void); + uint8_t get_error_flags_(void); + void clearRXnOVRFlags(void); + uint8_t getInterrupts(void); + uint8_t getInterruptMask(void); + void clearInterrupts(void); + void clearTXInterrupts(void); + uint8_t get_status_(void); + void clearRXnOVR(void); + void clearMERR(); + void clearERRIF(); +}; +} // namespace mcp2515 +} // namespace esphome \ No newline at end of file diff --git a/esphome/components/mcp2515/mcp2515_defs.h b/esphome/components/mcp2515/mcp2515_defs.h new file mode 100644 index 0000000000..c6b0711077 --- /dev/null +++ b/esphome/components/mcp2515/mcp2515_defs.h @@ -0,0 +1,388 @@ +#pragma once + +namespace esphome { +namespace mcp2515 { + +enum CAN_CLOCK { + MCP_20MHZ, + MCP_16MHZ, + MCP_8MHZ +}; + enum MASK { + MASK0, + MASK1 + }; + + enum RXF { + RXF0 = 0, + RXF1 = 1, + RXF2 = 2, + RXF3 = 3, + RXF4 = 4, + RXF5 = 5 + }; + + enum RXBn { + RXB0 = 0, + RXB1 = 1 + }; + + enum TXBn { + TXB0 = 0, + TXB1 = 1, + TXB2 = 2 + }; + + enum CAN_CLKOUT { + CLKOUT_DISABLE = -1, + CLKOUT_DIV1 = 0x0, + CLKOUT_DIV2 = 0x1, + CLKOUT_DIV4 = 0x2, + CLKOUT_DIV8 = 0x3, + }; + + enum /*class*/ CANINTF : uint8_t { + CANINTF_RX0IF = 0x01, + CANINTF_RX1IF = 0x02, + CANINTF_TX0IF = 0x04, + CANINTF_TX1IF = 0x08, + CANINTF_TX2IF = 0x10, + CANINTF_ERRIF = 0x20, + CANINTF_WAKIF = 0x40, + CANINTF_MERRF = 0x80 + }; + + enum /*class*/ EFLG : uint8_t { + EFLG_RX1OVR = (1<<7), + EFLG_RX0OVR = (1<<6), + EFLG_TXBO = (1<<5), + EFLG_TXEP = (1<<4), + EFLG_RXEP = (1<<3), + EFLG_TXWAR = (1<<2), + EFLG_RXWAR = (1<<1), + EFLG_EWARN = (1<<0) + }; + + static const uint8_t CANCTRL_REQOP = 0xE0; + static const uint8_t CANCTRL_ABAT = 0x10; + static const uint8_t CANCTRL_OSM = 0x08; + static const uint8_t CANCTRL_CLKEN = 0x04; + static const uint8_t CANCTRL_CLKPRE = 0x03; + enum /*class*/ CANCTRL_REQOP_MODE : uint8_t { + CANCTRL_REQOP_NORMAL = 0x00, + CANCTRL_REQOP_SLEEP = 0x20, + CANCTRL_REQOP_LOOPBACK = 0x40, + CANCTRL_REQOP_LISTENONLY = 0x60, + CANCTRL_REQOP_CONFIG = 0x80, + CANCTRL_REQOP_POWERUP = 0xE0 + }; + + enum /*class*/ STAT : uint8_t { + STAT_RX0IF = (1<<0), + STAT_RX1IF = (1<<1) + }; + + static const uint8_t STAT_RXIF_MASK = STAT_RX0IF | STAT_RX1IF; + + enum /*class*/ TXBnCTRL : uint8_t { + TXB_ABTF = 0x40, + TXB_MLOA = 0x20, + TXB_TXERR = 0x10, + TXB_TXREQ = 0x08, + TXB_TXIE = 0x04, + TXB_TXP = 0x03 + }; + + static const uint8_t EFLG_ERRORMASK = EFLG_RX1OVR + | EFLG_RX0OVR + | EFLG_TXBO + | EFLG_TXEP + | EFLG_RXEP; + + enum /*class*/ INSTRUCTION : uint8_t { + INSTRUCTION_WRITE = 0x02, + INSTRUCTION_READ = 0x03, + INSTRUCTION_BITMOD = 0x05, + INSTRUCTION_LOAD_TX0 = 0x40, + INSTRUCTION_LOAD_TX1 = 0x42, + INSTRUCTION_LOAD_TX2 = 0x44, + INSTRUCTION_RTS_TX0 = 0x81, + INSTRUCTION_RTS_TX1 = 0x82, + INSTRUCTION_RTS_TX2 = 0x84, + INSTRUCTION_RTS_ALL = 0x87, + INSTRUCTION_READ_RX0 = 0x90, + INSTRUCTION_READ_RX1 = 0x94, + INSTRUCTION_READ_STATUS = 0xA0, + INSTRUCTION_RX_STATUS = 0xB0, + INSTRUCTION_RESET = 0xC0 + }; + + enum /*class*/ REGISTER : uint8_t { + MCP_RXF0SIDH = 0x00, + MCP_RXF0SIDL = 0x01, + MCP_RXF0EID8 = 0x02, + MCP_RXF0EID0 = 0x03, + MCP_RXF1SIDH = 0x04, + MCP_RXF1SIDL = 0x05, + MCP_RXF1EID8 = 0x06, + MCP_RXF1EID0 = 0x07, + MCP_RXF2SIDH = 0x08, + MCP_RXF2SIDL = 0x09, + MCP_RXF2EID8 = 0x0A, + MCP_RXF2EID0 = 0x0B, + MCP_CANSTAT = 0x0E, + MCP_CANCTRL = 0x0F, + MCP_RXF3SIDH = 0x10, + MCP_RXF3SIDL = 0x11, + MCP_RXF3EID8 = 0x12, + MCP_RXF3EID0 = 0x13, + MCP_RXF4SIDH = 0x14, + MCP_RXF4SIDL = 0x15, + MCP_RXF4EID8 = 0x16, + MCP_RXF4EID0 = 0x17, + MCP_RXF5SIDH = 0x18, + MCP_RXF5SIDL = 0x19, + MCP_RXF5EID8 = 0x1A, + MCP_RXF5EID0 = 0x1B, + MCP_TEC = 0x1C, + MCP_REC = 0x1D, + MCP_RXM0SIDH = 0x20, + MCP_RXM0SIDL = 0x21, + MCP_RXM0EID8 = 0x22, + MCP_RXM0EID0 = 0x23, + MCP_RXM1SIDH = 0x24, + MCP_RXM1SIDL = 0x25, + MCP_RXM1EID8 = 0x26, + MCP_RXM1EID0 = 0x27, + MCP_CNF3 = 0x28, + MCP_CNF2 = 0x29, + MCP_CNF1 = 0x2A, + MCP_CANINTE = 0x2B, + MCP_CANINTF = 0x2C, + MCP_EFLG = 0x2D, + MCP_TXB0CTRL = 0x30, + MCP_TXB0SIDH = 0x31, + MCP_TXB0SIDL = 0x32, + MCP_TXB0EID8 = 0x33, + MCP_TXB0EID0 = 0x34, + MCP_TXB0DLC = 0x35, + MCP_TXB0DATA = 0x36, + MCP_TXB1CTRL = 0x40, + MCP_TXB1SIDH = 0x41, + MCP_TXB1SIDL = 0x42, + MCP_TXB1EID8 = 0x43, + MCP_TXB1EID0 = 0x44, + MCP_TXB1DLC = 0x45, + MCP_TXB1DATA = 0x46, + MCP_TXB2CTRL = 0x50, + MCP_TXB2SIDH = 0x51, + MCP_TXB2SIDL = 0x52, + MCP_TXB2EID8 = 0x53, + MCP_TXB2EID0 = 0x54, + MCP_TXB2DLC = 0x55, + MCP_TXB2DATA = 0x56, + MCP_RXB0CTRL = 0x60, + MCP_RXB0SIDH = 0x61, + MCP_RXB0SIDL = 0x62, + MCP_RXB0EID8 = 0x63, + MCP_RXB0EID0 = 0x64, + MCP_RXB0DLC = 0x65, + MCP_RXB0DATA = 0x66, + MCP_RXB1CTRL = 0x70, + MCP_RXB1SIDH = 0x71, + MCP_RXB1SIDL = 0x72, + MCP_RXB1EID8 = 0x73, + MCP_RXB1EID0 = 0x74, + MCP_RXB1DLC = 0x75, + MCP_RXB1DATA = 0x76 + }; + + static const uint8_t CANSTAT_OPMOD = 0xE0; + static const uint8_t CANSTAT_ICOD = 0x0E; + + static const uint8_t CNF3_SOF = 0x80; + + static const uint8_t TXB_EXIDE_MASK = 0x08; + static const uint8_t DLC_MASK = 0x0F; + static const uint8_t RTR_MASK = 0x40; + + static const uint8_t RXBnCTRL_RXM_STD = 0x20; + static const uint8_t RXBnCTRL_RXM_EXT = 0x40; + static const uint8_t RXBnCTRL_RXM_STDEXT = 0x00; + static const uint8_t RXBnCTRL_RXM_MASK = 0x60; + static const uint8_t RXBnCTRL_RTR = 0x08; + static const uint8_t RXB0CTRL_BUKT = 0x04; + + static const uint8_t MCP_SIDH = 0; + static const uint8_t MCP_SIDL = 1; + static const uint8_t MCP_EID8 = 2; + static const uint8_t MCP_EID0 = 3; + static const uint8_t MCP_DLC = 4; + static const uint8_t MCP_DATA = 5; + +/* + * Speed 8M + */ +static const uint8_t MCP_8MHz_1000kBPS_CFG1 =0x00; +static const uint8_t MCP_8MHz_1000kBPS_CFG2 =0x80; +static const uint8_t MCP_8MHz_1000kBPS_CFG3 =0x80; + +static const uint8_t MCP_8MHz_500kBPS_CFG1 =0x00; +static const uint8_t MCP_8MHz_500kBPS_CFG2 =0x90; +static const uint8_t MCP_8MHz_500kBPS_CFG3 =0x82; + +static const uint8_t MCP_8MHz_250kBPS_CFG1 =0x00; +static const uint8_t MCP_8MHz_250kBPS_CFG2 =0xB1; +static const uint8_t MCP_8MHz_250kBPS_CFG3 =0x85; + +static const uint8_t MCP_8MHz_200kBPS_CFG1 =0x00; +static const uint8_t MCP_8MHz_200kBPS_CFG2 =0xB4; +static const uint8_t MCP_8MHz_200kBPS_CFG3 =0x86; + +static const uint8_t MCP_8MHz_125kBPS_CFG1 =0x01; +static const uint8_t MCP_8MHz_125kBPS_CFG2 =0xB1; +static const uint8_t MCP_8MHz_125kBPS_CFG3 =0x85; + +static const uint8_t MCP_8MHz_100kBPS_CFG1 =0x01; +static const uint8_t MCP_8MHz_100kBPS_CFG2 =0xB4; +static const uint8_t MCP_8MHz_100kBPS_CFG3 =0x86; + +static const uint8_t MCP_8MHz_80kBPS_CFG1 =0x01; +static const uint8_t MCP_8MHz_80kBPS_CFG2 =0xBF; +static const uint8_t MCP_8MHz_80kBPS_CFG3 =0x87; + +static const uint8_t MCP_8MHz_50kBPS_CFG1 =0x03; +static const uint8_t MCP_8MHz_50kBPS_CFG2 =0xB4; +static const uint8_t MCP_8MHz_50kBPS_CFG3 =0x86; + +static const uint8_t MCP_8MHz_40kBPS_CFG1 =0x03; +static const uint8_t MCP_8MHz_40kBPS_CFG2 =0xBF; +static const uint8_t MCP_8MHz_40kBPS_CFG3 =0x87; + +static const uint8_t MCP_8MHz_33k3BPS_CFG1 =0x47; +static const uint8_t MCP_8MHz_33k3BPS_CFG2 =0xE2; +static const uint8_t MCP_8MHz_33k3BPS_CFG3 =0x85; + +static const uint8_t MCP_8MHz_31k25BPS_CFG1 =0x07; +static const uint8_t MCP_8MHz_31k25BPS_CFG2 =0xA4; +static const uint8_t MCP_8MHz_31k25BPS_CFG3 =0x84; + +static const uint8_t MCP_8MHz_20kBPS_CFG1 =0x07; +static const uint8_t MCP_8MHz_20kBPS_CFG2 =0xBF; +static const uint8_t MCP_8MHz_20kBPS_CFG3 =0x87; + +static const uint8_t MCP_8MHz_10kBPS_CFG1 =0x0F; +static const uint8_t MCP_8MHz_10kBPS_CFG2 =0xBF; +static const uint8_t MCP_8MHz_10kBPS_CFG3 =0x87; + +static const uint8_t MCP_8MHz_5kBPS_CFG1 =0x1F; +static const uint8_t MCP_8MHz_5kBPS_CFG2 =0xBF; +static const uint8_t MCP_8MHz_5kBPS_CFG3 =0x87; + +/* + * speed 16M + */ +static const uint8_t MCP_16MHz_1000kBPS_CFG1 =0x00; +static const uint8_t MCP_16MHz_1000kBPS_CFG2 =0xD0; +static const uint8_t MCP_16MHz_1000kBPS_CFG3 =0x82; + +static const uint8_t MCP_16MHz_500kBPS_CFG1 =0x00; +static const uint8_t MCP_16MHz_500kBPS_CFG2 =0xF0; +static const uint8_t MCP_16MHz_500kBPS_CFG3 =0x86; + +static const uint8_t MCP_16MHz_250kBPS_CFG1 =0x41; +static const uint8_t MCP_16MHz_250kBPS_CFG2 =0xF1; +static const uint8_t MCP_16MHz_250kBPS_CFG3 =0x85; + +static const uint8_t MCP_16MHz_200kBPS_CFG1 =0x01; +static const uint8_t MCP_16MHz_200kBPS_CFG2 =0xFA; +static const uint8_t MCP_16MHz_200kBPS_CFG3 =0x87; + +static const uint8_t MCP_16MHz_125kBPS_CFG1 =0x03; +static const uint8_t MCP_16MHz_125kBPS_CFG2 =0xF0; +static const uint8_t MCP_16MHz_125kBPS_CFG3 =0x86; + +static const uint8_t MCP_16MHz_100kBPS_CFG1 =0x03; +static const uint8_t MCP_16MHz_100kBPS_CFG2 =0xFA; +static const uint8_t MCP_16MHz_100kBPS_CFG3 =0x87; + +static const uint8_t MCP_16MHz_80kBPS_CFG1 =0x03; +static const uint8_t MCP_16MHz_80kBPS_CFG2 =0xFF; +static const uint8_t MCP_16MHz_80kBPS_CFG3 =0x87; + +static const uint8_t MCP_16MHz_83k3BPS_CFG1 =0x03; +static const uint8_t MCP_16MHz_83k3BPS_CFG2 =0xBE; +static const uint8_t MCP_16MHz_83k3BPS_CFG3 =0x07; + +static const uint8_t MCP_16MHz_50kBPS_CFG1 =0x07; +static const uint8_t MCP_16MHz_50kBPS_CFG2 =0xFA; +static const uint8_t MCP_16MHz_50kBPS_CFG3 =0x87; + +static const uint8_t MCP_16MHz_40kBPS_CFG1 =0x07; +static const uint8_t MCP_16MHz_40kBPS_CFG2 =0xFF; +static const uint8_t MCP_16MHz_40kBPS_CFG3 =0x87; + +static const uint8_t MCP_16MHz_33k3BPS_CFG1 =0x4E; +static const uint8_t MCP_16MHz_33k3BPS_CFG2 =0xF1; +static const uint8_t MCP_16MHz_33k3BPS_CFG3 =0x85; + +static const uint8_t MCP_16MHz_20kBPS_CFG1 =0x0F; +static const uint8_t MCP_16MHz_20kBPS_CFG2 =0xFF; +static const uint8_t MCP_16MHz_20kBPS_CFG3 =0x87; + +static const uint8_t MCP_16MHz_10kBPS_CFG1 =0x1F; +static const uint8_t MCP_16MHz_10kBPS_CFG2 =0xFF; +static const uint8_t MCP_16MHz_10kBPS_CFG3 =0x87; + +static const uint8_t MCP_16MHz_5kBPS_CFG1 =0x3F; +static const uint8_t MCP_16MHz_5kBPS_CFG2 =0xFF; +static const uint8_t MCP_16MHz_5kBPS_CFG3 =0x87; + +/* + * speed 20M + */ +static const uint8_t MCP_20MHz_1000kBPS_CFG1 =0x00; +static const uint8_t MCP_20MHz_1000kBPS_CFG2 =0xD9; +static const uint8_t MCP_20MHz_1000kBPS_CFG3 =0x82; + +static const uint8_t MCP_20MHz_500kBPS_CFG1 =0x00; +static const uint8_t MCP_20MHz_500kBPS_CFG2 =0xFA; +static const uint8_t MCP_20MHz_500kBPS_CFG3 =0x87; + +static const uint8_t MCP_20MHz_250kBPS_CFG1 =0x41; +static const uint8_t MCP_20MHz_250kBPS_CFG2 =0xFB; +static const uint8_t MCP_20MHz_250kBPS_CFG3 =0x86; + +static const uint8_t MCP_20MHz_200kBPS_CFG1 =0x01; +static const uint8_t MCP_20MHz_200kBPS_CFG2 =0xFF; +static const uint8_t MCP_20MHz_200kBPS_CFG3 =0x87; + +static const uint8_t MCP_20MHz_125kBPS_CFG1 =0x03; +static const uint8_t MCP_20MHz_125kBPS_CFG2 =0xFA; +static const uint8_t MCP_20MHz_125kBPS_CFG3 =0x87; + +static const uint8_t MCP_20MHz_100kBPS_CFG1 =0x04; +static const uint8_t MCP_20MHz_100kBPS_CFG2 =0xFA; +static const uint8_t MCP_20MHz_100kBPS_CFG3 =0x87; + +static const uint8_t MCP_20MHz_83k3BPS_CFG1 =0x04; +static const uint8_t MCP_20MHz_83k3BPS_CFG2 =0xFE; +static const uint8_t MCP_20MHz_83k3BPS_CFG3 =0x87; + +static const uint8_t MCP_20MHz_80kBPS_CFG1 =0x04; +static const uint8_t MCP_20MHz_80kBPS_CFG2 =0xFF; +static const uint8_t MCP_20MHz_80kBPS_CFG3 =0x87; + +static const uint8_t MCP_20MHz_50kBPS_CFG1 =0x09; +static const uint8_t MCP_20MHz_50kBPS_CFG2 =0xFA; +static const uint8_t MCP_20MHz_50kBPS_CFG3 =0x87; + +static const uint8_t MCP_20MHz_40kBPS_CFG1 =0x09; +static const uint8_t MCP_20MHz_40kBPS_CFG2 =0xFF; +static const uint8_t MCP_20MHz_40kBPS_CFG3 =0x87; + +static const uint8_t MCP_20MHz_33k3BPS_CFG1 =0x0B; +static const uint8_t MCP_20MHz_33k3BPS_CFG2 =0xFF; +static const uint8_t MCP_20MHz_33k3BPS_CFG3 =0x87; + +}} \ No newline at end of file