Line data Source code
1 : /*! 2 : * @file MCP2515Configurator.cpp 3 : * @brief Implementation of the MCP2515Configurator class. 4 : * @version 0.1 5 : * @date 2025-01-31 6 : * @author Félix LE BIHAN (@Fle-bihh) 7 : * @author Tiago Pereira (@t-pereira06) 8 : * @author Ricardo Melo (@reomelo) 9 : * @author Michel Batista (@MicchelFAB) 10 : * 11 : * @details This file contains the implementation of the MCP2515Configurator 12 : * class, which configures the MCP2515 CAN controller. 13 : * 14 : * @note This class is used to configure the MCP2515 CAN controller for 15 : * communication. 16 : * 17 : * @warning Ensure that the SPI controller is properly implemented. 18 : * 19 : * @see MCP2515Configurator.hpp for the class definition. 20 : * 21 : * @copyright Copyright (c) 2025 22 : * 23 : */ 24 : 25 : #include "MCP2515Configurator.hpp" 26 : #include <chrono> 27 : #include <thread> 28 : 29 : /*! 30 : * @brief Construct a new MCP2515Configurator::MCP2515Configurator object 31 : * @param spiController The SPI controller to use for communication. 32 : * @details This constructor initializes the MCP2515Configurator object with the 33 : * specified SPI controller. 34 : */ 35 33 : MCP2515Configurator::MCP2515Configurator(ISPIController &spiController) 36 33 : : spiController(spiController) {} 37 : 38 : /*! 39 : * @brief clean up the resources used by the MCP2515Configurator. 40 : * @returns The chip in configuration mode. 41 : * @details This function cleans up the resources used putting the MCP2515 to 42 : * default configuration. 43 : */ 44 3 : bool MCP2515Configurator::resetChip() { 45 3 : sendCommand(RESET_CMD); 46 3 : std::this_thread::sleep_for(std::chrono::milliseconds(10)); 47 3 : uint8_t status = readRegister(CANSTAT); 48 3 : return (status & 0xE0) == 0x80; // Verify configuration mode 49 : } 50 : 51 : /*! 52 : * @brief Configure the baud rate for the MCP2515. 53 : * @details This function sets the baud rate for the MCP2515. 54 : */ 55 2 : void MCP2515Configurator::configureBaudRate() { 56 2 : writeRegister(CNF1, 0x00); // Set BRP (Baud Rate Prescaler) 57 2 : writeRegister(CNF2, 0x90); // Set Propagation and Phase Segment 1 58 2 : writeRegister(CNF3, 0x02); // Set Phase Segment 2 59 2 : } 60 : 61 : /*! 62 : * @brief Configure the TX buffer for the MCP2515. 63 : * @details This function configures the TX buffer for the MCP2515. 64 : */ 65 2 : void MCP2515Configurator::configureTXBuffer() { 66 2 : writeRegister(TXB0CTRL, 0x00); // Clear TX buffer control register 67 2 : } 68 : 69 : /*! 70 : * @brief Configure the RX buffer for the MCP2515. 71 : * @details This function configures the RX buffer for the MCP2515. 72 : */ 73 2 : void MCP2515Configurator::configureRXBuffer() { 74 2 : writeRegister(RXB0CTRL, 75 : 0x60); // Enable rollover and set RX mode to receive all 76 2 : } 77 : 78 : /*! 79 : * @brief Configure the filters and masks for the MCP2515. 80 : * @details This function configures the filters and masks for the MCP2515. 81 : */ 82 2 : void MCP2515Configurator::configureFiltersAndMasks() { 83 2 : writeRegister(0x00, 0xFF); // Set filter 0 84 2 : writeRegister(0x01, 0xFF); // Set mask 0 85 2 : } 86 : 87 : /*! 88 : * @brief Configure the interrupts for the MCP2515. 89 : * @details This function configures the interrupts for the MCP2515. 90 : */ 91 2 : void MCP2515Configurator::configureInterrupts() { 92 2 : writeRegister(CANINTE, 0x01); // Enable receive interrupt 93 2 : } 94 : 95 : /*! 96 : * @brief Set the mode for the MCP2515. 97 : * @param mode The mode to set. 98 : * @details This function sets the mode for the MCP2515. 99 : */ 100 2 : void MCP2515Configurator::setMode(uint8_t mode) { 101 2 : writeRegister(CANCTRL, mode); 102 2 : } 103 : 104 : /*! 105 : * @brief Verify the mode of the MCP2515. 106 : * @param expectedMode The expected mode. 107 : * @returns True if the mode is as expected, false otherwise. 108 : * @details This function verifies the mode of the MCP2515. 109 : */ 110 3 : bool MCP2515Configurator::verifyMode(uint8_t expectedMode) { 111 3 : uint8_t mode = readRegister(CANSTAT) & 0xE0; 112 3 : return mode == expectedMode; 113 : } 114 : 115 : /*! 116 : * @brief Write a value to a register. 117 : * @param address The address of the register. 118 : * @param value The value to write. 119 : * @details This function writes a value to a register. 120 : */ 121 29 : void MCP2515Configurator::writeRegister(uint8_t address, uint8_t value) { 122 29 : spiController.writeByte(address, value); 123 29 : } 124 : 125 : /*! 126 : * @brief Read a value from a register. 127 : * @param address The address of the register. 128 : * @returns The value read from the register. 129 : * @details This function reads a value from a register. 130 : */ 131 29 : uint8_t MCP2515Configurator::readRegister(uint8_t address) { 132 29 : return spiController.readByte(address); 133 : } 134 : 135 : /*! 136 : * @brief Send a command to the MCP2515. 137 : * @param command The command to send. 138 : * @returns The response from the MCP2515. 139 : * @details This function sends a command to the MCP2515 140 : */ 141 3 : void MCP2515Configurator::sendCommand(uint8_t command) { 142 3 : uint8_t tx[] = {command}; 143 3 : spiController.spiTransfer(tx, nullptr, sizeof(tx)); 144 3 : } 145 : 146 : /*! 147 : * @brief Read a CAN message from the MCP2515. 148 : * @param frameID The frame ID of the message. 149 : * @returns The data of the message. 150 : * @details This function reads a CAN message from the MCP2515. 151 : */ 152 12 : std::vector<uint8_t> MCP2515Configurator::readCANMessage(uint16_t &frameID) { 153 12 : std::vector<uint8_t> CAN_RX_Buf; 154 : 155 12 : if (readRegister(CANINTF) & 0x01) { // Check if data is available 156 2 : uint8_t sidh = readRegister(RXB0SIDH); 157 2 : uint8_t sidl = readRegister(RXB0SIDL); 158 2 : frameID = (sidh << 3) | (sidl >> 5); 159 : 160 2 : uint8_t len = readRegister(0x65); // Length of the data 161 5 : for (uint8_t i = 0; i < len; ++i) { 162 3 : CAN_RX_Buf.push_back(readRegister(0x66 + i)); 163 : } 164 : 165 2 : writeRegister(CANINTF, 0x00); // Clear interrupt flag 166 : } 167 : 168 11 : return CAN_RX_Buf; 169 : } 170 : 171 : /*! 172 : * @brief Send a CAN message to the MCP2515. 173 : * @param frameID The frame ID of the message. 174 : * @param CAN_TX_Buf The data of the message. 175 : * @param length1 The length of the data. 176 : * @details This function sends a CAN message to the MCP2515. 177 : */ 178 1 : void MCP2515Configurator::sendCANMessage(uint16_t frameID, uint8_t *CAN_TX_Buf, 179 : uint8_t length1) { 180 1 : uint8_t tempdata = readRegister(CAN_RD_STATUS); 181 1 : writeRegister(TXB0SIDH, (frameID >> 3) & 0xFF); 182 1 : writeRegister(TXB0SIDL, (frameID & 0x07) << 5); 183 : 184 1 : writeRegister(TXB0EID8, 0); 185 1 : writeRegister(TXB0EID0, 0); 186 1 : writeRegister(TXB0DLC, length1); 187 4 : for (uint8_t j = 0; j < length1; ++j) { 188 3 : writeRegister(TXB0D0 + j, CAN_TX_Buf[j]); 189 : } 190 : 191 1 : if (tempdata & 0x04) { // TXREQ 192 1 : std::this_thread::sleep_for( 193 1 : std::chrono::milliseconds(10)); // sleep for 0.01 seconds 194 1 : writeRegister(TXB0CTRL, 0); // clean flag 195 : while (true) { 196 1 : if ((readRegister(CAN_RD_STATUS) & 0x04) != 1) { 197 1 : break; 198 : } 199 : } 200 : } 201 1 : uint8_t rtsCommand = CAN_RTS_TXB0; 202 1 : spiController.spiTransfer(&rtsCommand, nullptr, 1); 203 1 : }