189 lines
6.6 KiB
C++

/**
* @file can.cpp
*
* @brief Implementation file for CAN-related functions in the ChainLube application.
*
* This file contains the implementation of functions related to CAN (Controller Area Network)
* communication within the ChainLube application. It includes the initialization of the CAN module,
* setup of masks and filters, and processing of CAN messages. Additionally, a debug message function
* is included if CAN debugging is enabled.
*
* @author Your Name
* @date Date
*/
#include "can.h"
MCP_CAN CAN0(GPIO_CS_CAN);
#ifdef CAN_DEBUG_MESSAGE
#define MAX_DEBUG_RETRIES 100
void sendCANDebugMessage();
#endif
/**
* @brief Initializes the CAN module, sets masks, and filters based on the configured CAN source.
*
* This function initializes the CAN module, sets masks and filters based on the configured CAN source
* in the application settings, and sets the CAN module in normal mode for communication.
*/
void Init_CAN()
{
if (CAN0.begin(MCP_STDEXT, CAN_500KBPS, MCP_16MHZ) != CAN_OK)
MaintainDTC(DTC_CAN_TRANSCEIVER_FAILED, true);
CAN0.init_Mask(0, 0, 0x07FF0000); // Init first mask...
CAN0.init_Mask(1, 0, 0x07FF0000); // Init second mask...
switch (LubeConfig.CANSource)
{
case KTM_890_ADV_R_2021:
CAN0.init_Filt(0, 0, 0x012D0000); // Init first filter...
break;
case KTM_1290_SD_R_2023:
CAN0.init_Filt(0, 0, 0x012D0000); // Init first filter...
break;
default:
break;
}
CAN0.setMode(MCP_NORMAL);
}
/**
* @brief Processes CAN messages and sends a CAN debug message periodically.
*
* This function processes CAN messages and sends a CAN debug message periodically based on a time interval.
*/
void CAN_Process()
{
static uint32_t previousMillis = 0;
if (millis() - previousMillis >= 100)
{
sendCANDebugMessage();
previousMillis = millis();
}
}
/**
* @brief Processes CAN messages to determine the wheel speed based on the configured CAN source.
*
* This function reads incoming CAN messages and extracts the rear wheel speed information.
* The wheel speed is then converted to millimeters per second based on the configured CAN source.
* The function also monitors the CAN signal for potential issues and triggers diagnostic trouble codes (DTCs).
*
* @return The calculated distance traveled in millimeters since the last call.
*/
uint32_t Process_CAN_WheelSpeed()
{
#define FACTOR_RWP_KMH_890ADV 18 // Divider to convert Raw Data to km/h
#define FACTOR_RWP_KMH_1290SD 18 // Divider to convert Raw Data to km/h
can_frame canMsg;
static uint32_t lastRecTimestamp = 0;
uint16_t RearWheelSpeed_raw;
uint32_t milimeters_to_add = 0;
uint32_t RWP_millimeter_per_second = 0;
if (CAN0.readMsgBuf(&canMsg.can_id, &canMsg.can_dlc, canMsg.data) == CAN_OK)
{
switch (LubeConfig.CANSource)
{
case KTM_890_ADV_R_2021:
// raw / FACTOR_RWP_KMH_890ADV -> km/h * 100000 -> cm/h / 3600 -> cm/s
// raw * 500 -> cm/s
RearWheelSpeed_raw = (uint16_t)canMsg.data[5] << 8 | canMsg.data[6];
RWP_millimeter_per_second = (((uint32_t)RearWheelSpeed_raw * 1000000) / FACTOR_RWP_KMH_890ADV) / 3600;
break;
case KTM_1290_SD_R_2023:
// raw / FACTOR_RWP_KMH_1290SD -> km/h * 100000 -> cm/h / 3600 -> cm/s
// raw * 500 -> cm/s
RearWheelSpeed_raw = (uint16_t)canMsg.data[5] << 8 | canMsg.data[6];
RWP_millimeter_per_second = (((uint32_t)RearWheelSpeed_raw * 1000000) / FACTOR_RWP_KMH_1290SD) / 3600;
break;
default:
break;
}
uint32_t timesincelast = millis() - lastRecTimestamp;
lastRecTimestamp = millis();
milimeters_to_add = (RWP_millimeter_per_second * timesincelast) / 1000;
}
if (lastRecTimestamp > 1000)
{
MaintainDTC(DTC_NO_CAN_SIGNAL, (millis() > lastRecTimestamp + 10000 ? true : false));
}
return milimeters_to_add;
}
#ifdef CAN_DEBUG_MESSAGE
/**
* @brief Sends periodic CAN debug messages for monitoring and diagnostics.
*
* This function sends periodic CAN debug messages containing various system information for monitoring and diagnostics.
* The information includes system status, timestamps, tank percentage, DTC flags, and other relevant data.
* The debug messages are sent with a configurable multiplexer to broadcast different types of information in each cycle.
*/
void sendCANDebugMessage()
{
#define MAX_DEBUG_MULTIPLEXER 6
static uint16_t DebugSendFailTimeout = 0;
static uint8_t debugMultiplexer = 0;
byte data[8] = {debugMultiplexer, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
uint32_t millisValue = millis();
switch (debugMultiplexer)
{
case 0:
memcpy(&data[1], &millisValue, sizeof(millisValue));
memcpy(&data[5], &globals.purgePulses, sizeof(globals.purgePulses));
break;
case 1:
data[1] = (uint8_t)globals.systemStatus;
data[2] = (uint8_t)globals.resumeStatus;
data[3] = (uint8_t)globals.requestEEAction;
data[4] = globals.TankPercentage;
data[5] = (0x01 & globals.hasDTC) | ((0x01 & globals.measurementActive) << 1);
break;
case 2:
memcpy(&data[1], &globals.eePersistanceAdress, sizeof(globals.eePersistanceAdress));
memcpy(&data[3], &PersistenceData.tankRemain_microL, sizeof(PersistenceData.tankRemain_microL));
break;
case 3:
memcpy(&data[1], &PersistenceData.writeCycleCounter, sizeof(PersistenceData.writeCycleCounter));
memcpy(&data[3], &PersistenceData.TravelDistance_highRes_mm, sizeof(PersistenceData.TravelDistance_highRes_mm));
break;
case 4:
memcpy(&data[1], &PersistenceData.odometer_mm, sizeof(PersistenceData.odometer_mm));
break;
case 5:
memcpy(&data[1], &PersistenceData.odometer, sizeof(PersistenceData.odometer));
break;
case 6:
memcpy(&data[1], &PersistenceData.checksum, sizeof(PersistenceData.checksum));
break;
default:
break;
}
debugMultiplexer++;
debugMultiplexer = debugMultiplexer > MAX_DEBUG_MULTIPLEXER ? 0 : debugMultiplexer;
if (DebugSendFailTimeout < MAX_DEBUG_RETRIES)
{
byte sndStat = CAN0.sendMsgBuf(0x7FF, 0, 8, data);
if (sndStat != CAN_OK)
{
Debug_pushMessage("failed sending CAN-DbgMsg: %d, %d\n", sndStat, DebugSendFailTimeout);
DebugSendFailTimeout++;
}
}
else if (DebugSendFailTimeout == MAX_DEBUG_RETRIES)
{
Debug_pushMessage("disable CAN-DbgMsg due to timeout");
DebugSendFailTimeout++;
}
}
#endif