36 #define TIMEOUTVALUE 50
42 #define MCP_TXB_EXIDE_M 0x08 // In TXBnSIDL
43 #define MCP_DLC_MASK NIBBLE_0
44 #define MCP_RTR_MASK BIT_6
46 #define MCP_RXB_RX_ANY 0x60
47 #define MCP_RXB_RX_EXT 0x40
48 #define MCP_RXB_RX_STD 0x20
49 #define MCP_RXB_RX_STDEXT 0x00
50 #define MCP_RXB_RX_MASK 0x60
51 #define MCP_RXB_BUKT_MASK BIT_2
56 #define MCP_TXB_TXBUFE_M 0x80
57 #define MCP_TXB_ABTF_M 0x40
58 #define MCP_TXB_MLOA_M 0x20
59 #define MCP_TXB_TXERR_M 0x10
60 #define MCP_TXB_TXREQ_M 0x08
61 #define MCP_TXB_TXIE_M 0x04
62 #define MCP_TXB_TXP10_M 0x03
64 #define MCP_TXB_RTR_M 0x40 // In TXBnDLC
65 #define MCP_RXB_IDE_M 0x08 // In RXBnSIDL
66 #define MCP_RXB_RTR_M 0x40 // In RXBnDLC
68 #define MCP_EFLG_RX1OVR BIT_7
69 #define MCP_EFLG_RX0OVR BIT_6
70 #define MCP_EFLG_TXBO BIT_5
71 #define MCP_EFLG_TXEP BIT_4
72 #define MCP_EFLG_RXEP BIT_3
73 #define MCP_EFLG_TXWAR BIT_2
74 #define MCP_EFLG_RXWAR BIT_1
75 #define MCP_EFLG_EWARN BIT_0
76 #define MCP_EFLG_ERRORMASK (0xF8) // 5 MS-Bits
79 #define MCP_TX_INT 0x1C // Enable all transmit interrup ts
80 #define MCP_TX01_INT 0x0C // Enable TXB0 and TXB1 interru pts
81 #define MCP_RX_INT 0x03 // Enable receive interrupts
82 #define MCP_NO_INT 0x00 // Disable all interrupts
84 #define MCP_TX01_MASK 0x14
85 #define MCP_TX_MASK 0x54
87 #define MCP_N_TXBUFFERS (3)
91 #define CANSENDTIMEOUT (200) // milliseconds
96 #define CANAUTOPROCESS (1)
98 #define CANAUTOOFF (0)
100 #define CAN_STDID (0)
101 #define CAN_EXTID (1)
103 #define CANDEFAULTIDENT (0x55CC)
104 #define CANDEFAULTIDENTEXT (CAN_EXTID)
194 enum class BufferNumber {
199 enum class FilterNumber {
212 LISTENONLY = BIT_6 | BIT_5,
214 POWERUP = BIT_7 | BIT_6 | BIT_5
222 GET_TX_BUFFER_TIMEOUT,
223 SEND_MESSAGE_TIMEOUT,
228 static const Mode DEFAULT_MODE = Mode::NORMAL;
230 static const uint8_t MODE_MASK = BIT_7 | BIT_6 | BIT_5;
235 #define ABORT_TX 0x10
236 #define MODE_ONESHOT 0x08
237 #define CLKOUT_ENABLE 0x04
238 #define CLKOUT_DISABLE 0x00
239 #define CLKOUT_PS1 0x00
240 #define CLKOUT_PS2 0x01
241 #define CLKOUT_PS4 0x02
242 #define CLKOUT_PS8 0x03
244 enum class BaudRate {
264 static const uint8_t SJW1 = NULL_BIT;
265 static const uint8_t SJW2 = BIT_6;
266 static const uint8_t SJW3 = BIT_7;
267 static const uint8_t SJW4 = BIT_7 | BIT_6;
274 static const uint8_t SAMPLE_1X = NULL_BIT;
275 static const uint8_t SAMPLE_3X = BIT_6;
276 static const uint8_t BTLMODE = BIT_7;
283 static const uint8_t SOF_ENABLE = 0x80;
284 static const uint8_t SOF_DISABLE = 0x00;
285 static const uint8_t WAKFIL_ENABLE = 0x40;
286 static const uint8_t WAKFIL_DISABLE = 0x00;
288 static const uint8_t CNF1_16MHz_1000kBPS = SJW1;
289 static const uint8_t CNF2_16MHz_1000kBPS = 0xD0;
290 static const uint8_t CNF3_16MHz_1000kBPS = 0x82;
292 static const uint8_t CNF1_16MHz_500kBPS = SJW1;
293 static const uint8_t CNF2_16MHz_500kBPS = 0xF0;
294 static const uint8_t CNF3_16MHz_500kBPS = 0x86;
296 static const uint8_t CNF1_16MHz_250kBPS = SJW2 | 1;
297 static const uint8_t CNF2_16MHz_250kBPS = 0xF1;
298 static const uint8_t CNF3_16MHz_250kBPS = 0x85;
300 static const uint8_t CNF1_16MHz_200kBPS = SJW1 | 1;
301 static const uint8_t CNF2_16MHz_200kBPS = 0xFA;
302 static const uint8_t CNF3_16MHz_200kBPS = 0x87;
304 static const uint8_t CNF1_16MHz_125kBPS = SJW1 | 3;
305 static const uint8_t CNF2_16MHz_125kBPS = 0xF0;
306 static const uint8_t CNF3_16MHz_125kBPS = 0x86;
308 static const uint8_t CNF1_16MHz_100kBPS = SJW1 | 3;
309 static const uint8_t CNF2_16MHz_100kBPS = 0xFA;
310 static const uint8_t CNF3_16MHz_100kBPS = 0x87;
312 static const uint8_t CNF1_16MHz_80kBPS = SJW1 | 3;
313 static const uint8_t CNF2_16MHz_80kBPS = 0xFF;
314 static const uint8_t CNF3_16MHz_80kBPS = 0x87;
316 static const uint8_t CNF1_16MHz_50kBPS = SJW1 | 7;
317 static const uint8_t CNF2_16MHz_50kBPS = 0xFA;
318 static const uint8_t CNF3_16MHz_50kBPS = 0x87;
320 static const uint8_t CNF1_16MHz_40kBPS = SJW1 | 7;
321 static const uint8_t CNF2_16MHz_40kBPS = 0xFF;
322 static const uint8_t CNF3_16MHz_40kBPS = 0x87;
324 static const uint8_t CNF1_16MHz_31k25BPS = SJW1 | 15;
325 static const uint8_t CNF2_16MHz_31k25BPS = 0xF1;
326 static const uint8_t CNF3_16MHz_31k25BPS = 0x85;
328 static const uint8_t CNF1_16MHz_20kBPS = SJW1 | 15;
329 static const uint8_t CNF2_16MHz_20kBPS = 0xFF;
330 static const uint8_t CNF3_16MHz_20kBPS = 0x87;
332 static const uint8_t CNF1_16MHz_10kBPS = SJW1 | 31;
333 static const uint8_t CNF2_16MHz_10kBPS = 0xFF;
334 static const uint8_t CNF3_16MHz_10kBPS = 0x87;
336 static const uint8_t CNF1_16MHz_5kBPS = SJW1 | 63;
337 static const uint8_t CNF2_16MHz_5kBPS = 0xFF;
338 static const uint8_t CNF3_16MHz_5kBPS = 0x87;
347 : m_spi(&
SPI::get_instance()),
348 m_cs(cs,
Pin::Dir::OUT) {
354 m_cs(cs,
Pin::Dir::OUT) {
367 PropWare::ErrorCode
start (
const BaudRate baudRate,
const Mode mode = DEFAULT_MODE) {
368 PropWare::ErrorCode err;
372 check_errors(this->set_control_mode(Mode::CONFIG));
374 this->set_baud(baudRate);
375 this->initialize_buffers();
377 this->set_register(CANINTE, RX0IF | RX1IF);
379 #if (DEBUG_RXANY == 1)
381 this->modifyRegister(RXB0CTRL,
382 MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK,
383 MCP_RXB_RX_ANY | MCP_RXB_BUKT_MASK);
384 this->modifyRegister(RXB1CTRL, MCP_RXB_RX_MASK, MCP_RXB_RX_ANY);
387 this->modify_register(RXB0CTRL,
388 MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK,
389 MCP_RXB_RX_STDEXT | MCP_RXB_BUKT_MASK);
390 this->modify_register(RXB1CTRL, MCP_RXB_RX_MASK, MCP_RXB_RX_STDEXT);
395 check_errors(this->set_control_mode(this->m_mode));
400 PropWare::ErrorCode set_mask (
const BufferNumber bufferNumber,
const uint32_t
id,
401 const bool extendedID =
false)
const {
402 PropWare::ErrorCode err;
404 check_errors(this->set_control_mode(Mode::CONFIG));
406 if (BufferNumber::BUFFER_0 == bufferNumber)
407 this->write_id(RXM0SIDH,
id, extendedID);
409 this->write_id(RXM1SIDH,
id, extendedID);
411 return this->set_control_mode(this->m_mode);
414 PropWare::ErrorCode set_filter (
const FilterNumber num,
415 const uint32_t
id,
const bool extendedID =
false)
const {
416 PropWare::ErrorCode err;
417 check_errors(this->set_control_mode(Mode::CONFIG));
420 case FilterNumber::FILTER_0:
421 this->write_id(RXF0SIDH,
id, extendedID);
423 case FilterNumber::FILTER_1:
424 this->write_id(RXF1SIDH,
id, extendedID);
426 case FilterNumber::FILTER_2:
427 this->write_id(RXF2SIDH,
id, extendedID);
429 case FilterNumber::FILTER_3:
430 this->write_id(RXF3SIDH,
id, extendedID);
432 case FilterNumber::FILTER_4:
433 this->write_id(RXF4SIDH,
id, extendedID);
435 case FilterNumber::FILTER_5:
436 this->write_id(RXF5SIDH,
id, extendedID);
440 return this->set_control_mode(this->m_mode);
451 PropWare::ErrorCode
send_message (
const uint32_t
id,
const uint8_t len,
const uint8_t buf[],
452 const bool extendedID =
false) {
453 this->set_message(
id, len, buf, extendedID);
468 PropWare::ErrorCode err;
470 *len = this->m_dataLength;
471 memcpy(buf, this->m_messageBuffer, this->m_dataLength);
484 PropWare::ErrorCode
read_message (
const BufferNumber bufferNumber, uint8_t *len, uint8_t *buf) {
485 PropWare::ErrorCode err;
487 *len = this->m_dataLength;
488 memcpy(buf, this->m_messageBuffer, this->m_dataLength);
498 return static_cast<bool>(this->read_status() & (RX0IF | RX1IF));
509 return static_cast<bool>(this->read_status() & (RX0IF +
static_cast<unsigned int>(bufferNumber)));
512 PropWare::ErrorCode check_error ()
const {
513 const uint8_t eflg = this->read_register(EFLG);
515 if (eflg & MCP_EFLG_ERRORMASK)
516 return CONTROL_ERROR;
521 uint32_t get_id ()
const {
526 void reset ()
const {
528 this->m_spi->
shift_out(8, SPIInstructionSet::RESET);
533 uint8_t read_register (
const uint8_t address)
const {
537 this->m_spi->
shift_out(8, SPIInstructionSet::READ);
539 ret = (uint8_t) this->m_spi->
shift_in(8);
545 void read_registers (
const uint8_t address, uint8_t *values,
const uint8_t n) {
546 const uint32_t tmp = SPIInstructionSet::READ << 8;
547 const uint32_t combinedBits = tmp | address;
549 this->m_spi->
shift_out(16, combinedBits);
555 void set_register (
const uint8_t address,
const uint8_t value)
const {
556 const uint32_t tmp = SPIInstructionSet::WRITE << 16;
557 const uint32_t combinedBits = tmp | (address << 8) | value;
559 this->m_spi->
shift_out(24, combinedBits);
563 void set_registers (
const uint8_t address,
const uint8_t values[],
const uint8_t n)
const {
564 const uint32_t tmp = SPIInstructionSet::WRITE << 8;
565 const uint32_t combinedBits = tmp | address;
567 this->m_spi->
shift_out(16, combinedBits);
572 void initialize_buffers ()
const {
573 uint8_t i, a1, a2, a3;
575 uint32_t ulMask = 0x00, ulFilt = 0x00;
578 this->write_id(RXM0SIDH, ulMask,
true);
579 this->write_id(RXM1SIDH, ulMask,
true);
582 this->write_id(RXF0SIDH, ulFilt,
true);
583 this->write_id(RXF1SIDH, ulFilt,
false);
584 this->write_id(RXF2SIDH, ulFilt,
true);
585 this->write_id(RXF3SIDH, ulFilt,
false);
586 this->write_id(RXF4SIDH, ulFilt,
true);
587 this->write_id(RXF5SIDH, ulFilt,
false);
595 for (i = 0; i < 14; i++) {
596 this->set_register(a1, 0);
597 this->set_register(a2, 0);
598 this->set_register(a3, 0);
603 this->set_register(RXB0CTRL, 0);
604 this->set_register(RXB1CTRL, 0);
607 void modify_register (
const uint8_t address,
const uint8_t mask,
const uint8_t data)
const {
609 this->m_spi->
shift_out(8, SPIInstructionSet::BITMOD);
616 uint8_t read_status ()
const {
618 this->m_spi->
shift_out(8, SPIInstructionSet::READ_STATUS);
619 const uint8_t i = this->m_spi->
shift_in(8);
624 PropWare::ErrorCode set_control_mode (
const Mode mode)
const {
625 this->modify_register(CANCTRL, MODE_MASK, mode);
627 const Mode actualMode =
static_cast<Mode
>(this->read_register(CANCTRL) & MODE_MASK);
628 if (actualMode == mode)
631 return MODE_SET_FAILURE;
634 void set_baud (
const BaudRate baudRate)
const {
639 case BaudRate::BAUD_5KBPS:
640 cnf1 = CNF1_16MHz_5kBPS;
641 cnf2 = CNF2_16MHz_5kBPS;
642 cnf3 = CNF3_16MHz_5kBPS;
644 case BaudRate::BAUD_10KBPS:
645 cnf1 = CNF1_16MHz_10kBPS;
646 cnf2 = CNF2_16MHz_10kBPS;
647 cnf3 = CNF3_16MHz_10kBPS;
649 case BaudRate::BAUD_20KBPS:
650 cnf1 = CNF1_16MHz_20kBPS;
651 cnf2 = CNF2_16MHz_20kBPS;
652 cnf3 = CNF3_16MHz_20kBPS;
654 case BaudRate::BAUD_31K25BPS:
655 cnf1 = CNF1_16MHz_31k25BPS;
656 cnf2 = CNF2_16MHz_31k25BPS;
657 cnf3 = CNF3_16MHz_31k25BPS;
659 case BaudRate::BAUD_40KBPS:
660 cnf1 = CNF1_16MHz_40kBPS;
661 cnf2 = CNF2_16MHz_40kBPS;
662 cnf3 = CNF3_16MHz_40kBPS;
664 case BaudRate::BAUD_50KBPS:
665 cnf1 = CNF1_16MHz_50kBPS;
666 cnf2 = CNF2_16MHz_50kBPS;
667 cnf3 = CNF3_16MHz_50kBPS;
669 case BaudRate::BAUD_80KBPS:
670 cnf1 = CNF1_16MHz_80kBPS;
671 cnf2 = CNF2_16MHz_80kBPS;
672 cnf3 = CNF3_16MHz_80kBPS;
674 case BaudRate::BAUD_100KBPS:
675 cnf1 = CNF1_16MHz_100kBPS;
676 cnf2 = CNF2_16MHz_100kBPS;
677 cnf3 = CNF3_16MHz_100kBPS;
679 case BaudRate::BAUD_125KBPS:
680 cnf1 = CNF1_16MHz_125kBPS;
681 cnf2 = CNF2_16MHz_125kBPS;
682 cnf3 = CNF3_16MHz_125kBPS;
684 case BaudRate::BAUD_200KBPS:
685 cnf1 = CNF1_16MHz_200kBPS;
686 cnf2 = CNF2_16MHz_200kBPS;
687 cnf3 = CNF3_16MHz_200kBPS;
689 case BaudRate::BAUD_250KBPS:
690 cnf1 = CNF1_16MHz_250kBPS;
691 cnf2 = CNF2_16MHz_250kBPS;
692 cnf3 = CNF3_16MHz_250kBPS;
694 case BaudRate::BAUD_500KBPS:
695 cnf1 = CNF1_16MHz_500kBPS;
696 cnf2 = CNF2_16MHz_500kBPS;
697 cnf3 = CNF3_16MHz_500kBPS;
699 case BaudRate::BAUD_1000KBPS:
700 cnf1 = CNF1_16MHz_1000kBPS;
701 cnf2 = CNF2_16MHz_1000kBPS;
702 cnf3 = CNF3_16MHz_1000kBPS;
706 this->set_register(CNF1, cnf1);
707 this->set_register(CNF2, cnf2);
708 this->set_register(CNF3, cnf3);
711 void write_id (
const uint8_t address,
const uint32_t
id,
const bool extendedID)
const {
713 const uint16_t canIDLow =
static_cast<uint16_t
>(
id & WORD_0);
716 const uint16_t canIDHigh =
static_cast<uint16_t
>(
id >> 16);
718 buffer[MCP_EID0] =
static_cast<uint8_t
>(canIDLow & BYTE_0);
719 buffer[MCP_EID8] =
static_cast<uint8_t
>(canIDLow >> 8);
721 buffer[MCP_SIDL] =
static_cast<uint8_t
>(canIDHigh & 0x03);
722 buffer[MCP_SIDL] +=
static_cast<uint8_t
>((canIDHigh & 0x1C) << 3);
723 buffer[MCP_SIDL] |= MCP_TXB_EXIDE_M;
724 buffer[MCP_SIDH] =
static_cast<uint8_t
>(canIDHigh >> 5);
726 buffer[MCP_SIDH] =
static_cast<uint8_t
>(canIDLow >> 3);
727 buffer[MCP_SIDL] =
static_cast<uint8_t
>(canIDLow << 5);
729 buffer[MCP_EID0] = 0;
730 buffer[MCP_EID8] = 0;
732 this->set_registers(address, buffer, 4);
735 void read_id (
const uint8_t address, uint32_t *
id,
bool *extendedID) {
738 this->read_registers(address, buffer, 4);
740 *
id = (buffer[MCP_SIDH] << 3) + (buffer[MCP_SIDL] >> 5);
741 if ((buffer[MCP_SIDL] & MCP_TXB_EXIDE_M) == MCP_TXB_EXIDE_M) {
743 *
id = (*
id << 2) + (buffer[MCP_SIDL] & 0x03);
744 *
id = (*
id << 8) + buffer[MCP_EID8];
745 *
id = (*
id << 8) + buffer[MCP_EID0];
751 void write_can_message (
const uint8_t bufferSIDHAddress) {
753 mcp_addr = bufferSIDHAddress;
754 this->set_registers(mcp_addr + 5, this->m_messageBuffer, this->m_dataLength);
755 if (this->m_rtr == 1)
756 this->m_dataLength |= MCP_RTR_MASK;
758 this->set_register((mcp_addr + 4), this->m_dataLength);
759 this->write_id(mcp_addr, this->m_id, this->m_extendedID);
763 void read_can_message (
const uint8_t bufferSIDHAddress) {
764 this->read_id(bufferSIDHAddress, &this->m_id, &this->m_extendedID);
766 const uint8_t ctrl = this->read_register(bufferSIDHAddress - 1);
767 this->m_dataLength = this->read_register(bufferSIDHAddress + 4);
774 this->m_dataLength &= MCP_DLC_MASK;
775 read_registers(bufferSIDHAddress + 5, &(this->m_messageBuffer[0]), this->m_dataLength);
778 void start_transmit (
const uint8_t address) {
779 this->modify_register(address - 1, MCP_TXB_TXREQ_M, MCP_TXB_TXREQ_M);
782 PropWare::ErrorCode get_next_free_tx_buffer (uint8_t *txbuf_n)
const {
783 const uint8_t controlRegisters[] = {TXB0CTRL, TXB1CTRL, TXB2CTRL};
787 const uint8_t controlValue = read_register(controlRegisters[i]);
788 if ((controlValue & MCP_TXB_TXREQ_M) == 0) {
790 *txbuf_n =
static_cast<uint8_t
>(controlRegisters[i] + 1);
797 uint8_t set_message (
const uint32_t
id,
const uint8_t length,
const uint8_t data[],
const bool extendedID) {
798 this->m_extendedID = extendedID;
800 this->m_dataLength = length;
803 return MESSAGE_TOO_LONG;
805 memcpy(this->m_messageBuffer, data, length);
810 void clear_message () {
812 this->m_dataLength = 0;
813 this->m_extendedID = 0;
815 memset(this->m_messageBuffer, 0, this->m_dataLength);
819 const uint8_t
stat = this->read_status();
821 if (Utility::bit_read(
stat, (Bit) RX0IF)) {
822 this->read_can_message((RXB0SIDH));
823 this->modify_register(CANINTF, RX0IF, 0);
825 }
else if (Utility::bit_read(
stat, (Bit) RX1IF)) {
826 this->read_can_message((RXB1SIDH));
827 this->modify_register(CANINTF, RX1IF, 0);
833 PropWare::ErrorCode
read_message (
const BufferNumber bufferNumber) {
834 const uint8_t
stat = this->read_status();
836 const Bit interruptFlag = (Bit) (RX0IF +
static_cast<uint8_t
>(bufferNumber));
837 uint8_t bufferAddress = RXB0SIDH;
838 if (BufferNumber::BUFFER_1 == bufferNumber)
839 bufferAddress += 0x10;
841 if (Utility::bit_read(
stat, interruptFlag)) {
842 this->read_can_message(bufferAddress);
843 this->modify_register(CANINTF, interruptFlag, 0);
850 PropWare::ErrorCode err;
852 uint16_t retryCount = 0;
856 err = this->get_next_free_tx_buffer(&txbuf_n);
858 }
while (err == ALLTXBUSY && (TIMEOUTVALUE > retryCount));
860 if (TIMEOUTVALUE == retryCount)
861 return GET_TX_BUFFER_TIMEOUT;
864 this->write_can_message(txbuf_n);
865 this->start_transmit(txbuf_n);
872 messageSent = this->read_register(txbuf_n) & BIT_3;
873 }
while (messageSent && (TIMEOUTVALUE > retryCount));
875 if (retryCount == TIMEOUTVALUE)
876 return SEND_MESSAGE_TIMEOUT;
895 uint8_t m_dataLength;