LCOV - code coverage report
Current view: top level - canbus - MCP2515Controller.cpp (source / functions) Hit Total Coverage
Test: filtered.info Lines: 54 66 81.8 %
Date: 2025-07-25 11:48:17 Functions: 9 11 81.8 %

          Line data    Source code
       1             : /*!
       2             :  * @file MCP2515Controller.cpp
       3             :  * @brief Implementation of the MCP2515Controller 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 MCP2515Controller
      12             :  * class, which controls the MCP2515 CAN controller.
      13             :  *
      14             :  * @note This class is used to control the MCP2515 CAN controller for
      15             :  * communication.
      16             :  *
      17             :  * @warning Ensure that the SPI controller is properly implemented.
      18             :  *
      19             :  * @see MCP2515Controller.hpp for the class definition.
      20             :  *
      21             :  * @copyright Copyright (c) 2025
      22             :  *
      23             :  */
      24             : 
      25             : #include "MCP2515Controller.hpp"
      26             : #include "SPIController.hpp"
      27             : #include "NotificationManager.hpp"
      28             : #include <QDebug>
      29             : #include <QThread>
      30             : #include <cstring>
      31             : #include <stdexcept>
      32             : 
      33             : /*!
      34             :  * @brief Construct a new MCP2515Controller::MCP2515Controller object
      35             :  * @param spiDevice The SPI device to use for communication.
      36             :  * @throw std::runtime_error if the SPI device cannot be opened.
      37             :  * @details This constructor initializes the MCP2515Controller object with the
      38             :  * specified SPI device.
      39             :  */
      40           0 : MCP2515Controller::MCP2515Controller(const std::string &spiDevice)
      41           0 :                 : spiController(new SPIController()), configurator(*spiController),
      42           0 :                         messageProcessor(), ownsSPIController(true) {
      43           0 :         if (!spiController->openDevice(spiDevice)) {
      44           0 :                 throw std::runtime_error("Failed to open SPI device : " + spiDevice);
      45             :         }
      46           0 :         setupHandlers();
      47           0 : }
      48             : 
      49             : /*!
      50             :  * @brief Construct a new MCP2515Controller::MCP2515Controller object
      51             :  * @param spiDevice The SPI device to use for communication.
      52             :  * @param spiController The SPI controller to use for communication.
      53             :  * @throw std::runtime_error if the SPI device cannot be opened.
      54             :  * @details This constructor initializes the MCP2515Controller object with the
      55             :  * specified SPI device and SPI controller.
      56             :  */
      57          10 : MCP2515Controller::MCP2515Controller(const std::string &spiDevice,
      58          10 :                                                                                                                                                  ISPIController &spiController)
      59             :                 : spiController(&spiController), configurator(spiController),
      60          12 :                         messageProcessor(), ownsSPIController(false) {
      61          10 :         if (!spiController.openDevice(spiDevice)) {
      62           1 :                 throw std::runtime_error("Failed to open SPI device : " + spiDevice);
      63             :         }
      64           9 :         setupHandlers();
      65           9 : }
      66             : 
      67             : /*!
      68             :  * @brief Destroy the MCP2515Controller::MCP2515Controller object
      69             :  * @details This destructor closes the SPI device and deletes the SPI controller
      70             :  * if it was created by the MCP2515Controller.
      71             :  */
      72           9 : MCP2515Controller::~MCP2515Controller() {
      73           9 :         spiController->closeDevice();
      74           9 :         if (this->ownsSPIController) {
      75           0 :                 delete this->spiController;
      76             :         }
      77           9 : }
      78             : 
      79             : /*!
      80             :  * @brief Initialize the MCP2515 controller.
      81             :  * @throw std::runtime_error if the MCP2515 cannot be reset.
      82             :  * @returns True if the MCP2515 is successfully initialized
      83             :  * @details This function initializes the MCP2515 controller by resetting the
      84             :  * chip and configuring it.
      85             :  */
      86           1 : bool MCP2515Controller::init() {
      87           1 :         if (!configurator.resetChip()) {
      88           0 :                 throw std::runtime_error("Failed to reset MCP2515");
      89             :         }
      90             : 
      91           1 :         configurator.configureBaudRate();
      92           1 :         configurator.configureTXBuffer();
      93           1 :         configurator.configureRXBuffer();
      94           1 :         configurator.configureFiltersAndMasks();
      95           1 :         configurator.configureInterrupts();
      96           1 :         configurator.setMode(0x00);
      97             : 
      98           1 :         if (!configurator.verifyMode(0x00)) {
      99           0 :                 throw std::runtime_error("Failed to set MCP2515 to normal mode");
     100             :         }
     101             : 
     102           1 :         return true;
     103             : }
     104             : 
     105             : /*!
     106             :  * @brief Start reading CAN messages.
     107             :  * @details This function starts reading CAN messages from the MCP2515.
     108             :  */
     109          12 : void MCP2515Controller::processReading() {
     110          12 :         while (!stopReadingFlag) {
     111             :                 uint16_t frameID;
     112          10 :                 std::vector<uint8_t> data;
     113             :                 // qDebug() << "In loop" << stopReadingFlag;
     114             :                 try {
     115          10 :                         data = configurator.readCANMessage(frameID);
     116           9 :                         if (!data.empty()) {
     117           0 :                                 messageProcessor.processMessage(frameID, data);
     118             :                         }
     119           1 :                 } catch (const std::exception &e) {
     120           1 :                         qDebug() << "Error while processing CAN message:" << e.what();
     121             :                 }
     122             : 
     123          10 :                 if (stopReadingFlag) {
     124           0 :                                 break;
     125             :                 }
     126             : 
     127          10 :                 QThread::msleep(10);
     128             :         }
     129           2 : }
     130             : 
     131             : /*!
     132             :  * @brief Stop reading CAN messages.
     133             :  * @details This function stops reading CAN messages from the MCP2515.
     134             :  */
     135           3 : void MCP2515Controller::stopReading() { stopReadingFlag = true; }
     136             : 
     137             : /*!
     138             :  * @brief Send a CAN message.
     139             :  * @param frameID The frame ID of the message.
     140             :  * @param data The data of the message.
     141             :  * @details This function sends a CAN message with the specified frame ID and
     142             :  * data.
     143             :  */
     144           9 : void MCP2515Controller::setupHandlers() {
     145           9 :         messageProcessor.registerHandler(0x100, [this](const std::vector<uint8_t> &data) {
     146           2 :                 if (data.size() == 1) {
     147           1 :                         float speed = static_cast<float>(data[0]);
     148           1 :                         emit speedUpdated(speed);
     149             :                 }
     150           2 :         });
     151             : 
     152           9 :         messageProcessor.registerHandler(0x300, [this](const std::vector<uint8_t> &data) {
     153           3 :                 if (data.size() == 2) {
     154           3 :                         uint16_t distance = (data[0] << 8) | data[1];
     155             :                         //emit distanceUpdated(distance);
     156           3 :                         qDebug() << "Distance from CAN:" << distance;
     157           3 :                         if (distance > 20) {
     158           2 :                                 if (!brakeWarningActive) {
     159           2 :                                         brakeWarningActive = true;
     160           4 :                                         QString message = QString("Brake!");
     161           2 :                                         NotificationManager::instance()->showPersistentNotification(message, NotificationLevel::Warning);
     162             :                                 }
     163             :                         } else {
     164           1 :                                 if (brakeWarningActive) {
     165           1 :                                         brakeWarningActive = false;
     166           1 :                                         NotificationManager::instance()->clearNotification();
     167             :                                 }
     168             :                         }
     169             :                 }
     170           3 :         });
     171           9 : }
     172             : 
     173             : /*!
     174             :  * @brief Check if the stop reading flag is set.
     175             :  * @returns True if the stop reading flag is set, false otherwise.
     176             :  * @details This function checks if the stop reading flag is set.
     177             :  */
     178           3 : bool MCP2515Controller::isStopReadingFlagSet() const {
     179           3 :         return this->stopReadingFlag;
     180             : }

Generated by: LCOV version 1.14