rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
can_rx.cpp
Go to the documentation of this file.
1/**
2 * @file can_rx.cpp
3 *
4 * CAN reception handling. This file handles multiplexing incoming CAN frames as appropriate
5 * to the subsystems that consume them.
6 *
7 * @date Mar 19, 2020
8 * @author Matthew Kennedy, (c) 2020
9 */
10
11#include "pch.h"
12
13#if EFI_CAN_SUPPORT
14
15#include "rusefi_lua.h"
16#include "can_bench_test.h"
17#include "bench_test.h"
18#include "can_common.h"
19
20#include "can_rx.h"
21#include "obd2.h"
22#include "can_sensor.h"
23#include "can_vss.h"
24#include "rusefi_wideband.h"
25#include "board_overrides.h"
26/**
27 * this build-in CAN sniffer is very basic but that's our CAN sniffer
28 */
29static void printPacket(const size_t busIndex, const CANRxFrame &rx) {
30 // only print info if we're in can debug mode
31
32 int id = CAN_ID(rx);
33
34 if (CAN_ISX(rx)) {
35 // print extended IDs in hex only
36 efiPrintf("CAN%d RX: ID %07x DLC %d: %02x %02x %02x %02x %02x %02x %02x %02x",
37 busIndex + 1,
38 id,
39 rx.DLC,
40 rx.data8[0], rx.data8[1], rx.data8[2], rx.data8[3],
41 rx.data8[4], rx.data8[5], rx.data8[6], rx.data8[7]);
42 } else {
43 // internet people use both hex and decimal to discuss packed IDs, for usability it's better to print both right here
44 efiPrintf("CAN%d RX: ID %03x(%d) DLC %d: %02x %02x %02x %02x %02x %02x %02x %02x",
45 busIndex + 1,
46 id, id, // once in hex, once in dec
47 rx.DLC,
48 rx.data8[0], rx.data8[1], rx.data8[2], rx.data8[3],
49 rx.data8[4], rx.data8[5], rx.data8[6], rx.data8[7]);
50 }
51}
52
53struct CanListenerTailSentinel : public CanListener {
54 CanListenerTailSentinel()
55 : CanListener(0)
56 {
57 }
58
59 bool acceptFrame(const size_t, const CANRxFrame&) const override {
60 return false;
61 }
62
63 void decodeFrame(const CANRxFrame&, efitick_t) override {
64 // nothing to do
65 }
66};
67
68static CanListenerTailSentinel tailSentinel;
70
71void serviceCanSubscribers(const size_t busIndex, const CANRxFrame &frame, efitick_t nowNt) {
73 size_t iterationValidationCounter = 0;
74
75 while (current) {
76 current = current->processFrame(busIndex, frame, nowNt);
77 if (iterationValidationCounter++ > 239) {
78 criticalError("forever loop canListeners_head");
79 return;
80 }
81 }
82}
83
85 // If the listener already has a next, it's already registered
86 if (!listener.hasNext()) {
89 }
90}
91
96
97/*
98 * TODO:
99 * - convert to CanListener
100 * - move to hw_layer/sensors/yaw_rate_sensor.cpp | accelerometer.cpp ?
101 */
102
103#define VAG_YAW_RATE_G_LAT 0x130
104#define VAG_YAW_ACCEL_G_LONG 0x131
105
106/* Bosch Acceleration Sensor MM5.10 quantizations */
107#define MM5_10_RATE_QUANT 0.005
108#define MM5_10_ACC_QUANT 0.0001274
109
110/* Bosch Acceleration Sensor MM5.10 CAN IDs */
111#define MM5_10_YAW_Y 0x174
112#define MM5_10_ROLL_X 0x178
113#define MM5_10_Z 0x17C
114
115/* Mercedes pn: A 006 542 26 18 CAN IDs */
116#define MM5_10_MB_YAW_Y_CANID 0x150
117#define MM5_10_MB_ROLL_X_CANID 0x151
118
119uint32_t getFourBytesLsb(const CANRxFrame& frame, int offset) {
120 return (frame.data8[offset + 3] << 24) +
121 (frame.data8[offset + 2] << 16) +
122 (frame.data8[offset + 1] << 8) +
123 frame.data8[offset];
124}
125
126uint16_t getTwoBytesLsb(const CANRxFrame& frame, int offset) {
127 return (frame.data8[offset + 1] << 8) + frame.data8[offset];
128}
129
130uint16_t getTwoBytesMsb(const CANRxFrame& frame, int offset) {
131 return (frame.data8[offset] << 8) + frame.data8[offset + 1];
132}
133
134static int16_t getShiftedLSB_intel(const CANRxFrame& frame, int offset) {
135 return getTwoBytesLsb(frame, offset) - 0x8000;
136}
137
139 float yaw = getShiftedLSB_intel(frame, 0);
140 float accY = getShiftedLSB_intel(frame, 4);
141
142 efiPrintf("CAN_rx MM5_10_YAW_Y %f %f", yaw, accY);
143 engine->sensors.accelerometer.yawRate = yaw * MM5_10_RATE_QUANT;
144 engine->sensors.accelerometer.lat = accY * MM5_10_ACC_QUANT;
145}
146
148 float accX = getShiftedLSB_intel(frame, 4);
149 efiPrintf("CAN_rx MM5_10_ROLL_X %f", accX);
150
151 engine->sensors.accelerometer.lon = accX * MM5_10_ACC_QUANT;
152}
153
154static void processCanRxImu_BoschM5_10_Z(const CANRxFrame& frame) {
155 float accZ = getShiftedLSB_intel(frame, 4);
156 efiPrintf("CAN_rx MM5_10_Z %f", accZ);
157 engine->sensors.accelerometer.vert = accZ * MM5_10_ACC_QUANT;
158}
159
160static void processCanRxImu(const CANRxFrame& frame) {
161/*
162 if (CAN_SID(frame) == 0x130) {
163 float a = getShiftedLSB_intel(frame, 0);
164 float b = getShiftedLSB_intel(frame, 4);
165 efiPrintf("CAN_rx 130 %f %f", a, b);
166 }
167
168 if (engineConfiguration->imuType == IMU_VAG) {
169 if (CAN_SID(frame) == VAG_YAW_RATE_G_LAT) {
170 efiPrintf("CAN_rx VAG_YAW_RATE_G_LAT");
171 } else if (CAN_SID(frame) == VAG_YAW_ACCEL_G_LONG) {
172 efiPrintf("CAN_rx VAG_YAW_ACCEL_G_LONG");
173 }
174 }
175 */
176
177 if (engineConfiguration->imuType == IMU_MM5_10) {
178 if (CAN_SID(frame) == MM5_10_YAW_Y) {
180 } else if (CAN_SID(frame) == MM5_10_ROLL_X) {
182 } else if (CAN_SID(frame) == MM5_10_Z) {
184 }
185 } else if (engineConfiguration->imuType == IMU_TYPE_MB_A0065422618) {
186 if (CAN_SID(frame) == MM5_10_MB_YAW_Y_CANID) {
188 } else if (CAN_SID(frame) == MM5_10_MB_ROLL_X_CANID) {
190 }
191 }
192}
193
194extern bool verboseRxCan;
195
196void boardProcessCanRxMessage(const size_t, const CANRxFrame &, efitick_t) {
197 // this is here to indicate that migration is required
198 // todo: remove in 2026
199}
200
201std::optional<board_can_rx_type> custom_board_can_rx;
202
203void processCanRxMessage(const size_t busIndex, const CANRxFrame &frame, efitick_t nowNt) {
204 if ((engineConfiguration->verboseCan && busIndex == 0) || verboseRxCan) {
205 printPacket(busIndex, frame);
206 } else if (engineConfiguration->verboseCan2 && busIndex == 1) {
207 printPacket(busIndex, frame);
208 }
209
210 if (custom_board_can_rx.has_value()) {
211 custom_board_can_rx.value()(busIndex, frame, nowNt);
212 }
213
214 // see AemXSeriesWideband as an example of CanSensorBase/CanListener
215 serviceCanSubscribers(busIndex, frame, nowNt);
216
217 // todo: convert to CanListener or not?
218 //Vss is configurable, should we handle it here:
219 processCanRxVss(frame, nowNt);
220
222 // todo: convert to CanListener or not?
223 processCanRxImu(frame);
224 }
225
226/*
227static Timer dashAliveTimer;
228
229 if (CAN_EID(frame) == (int)bench_test_packet_ids_e::DASH_ALIVE) {
230 // todo: add an indicator that dash is connected?
231 dashAliveTimer.reset();
232 }
233*/
234
237
238 processLuaCan(busIndex, frame);
239
240 {
241 obdOnCanPacketRx(frame, busIndex);
242 }
243
244#if EFI_ENGINE_CONTROL
245 if (CAN_EID(frame) == GDI4_BASE_ADDRESS && frame.data8[7] == GDI4_MAGIC) {
246// efiPrintf("CAN GDI4 says hi");
248 }
249#endif // EFI_ENGINE_CONTROL
250
251 handleWidebandCan(busIndex, frame);
252#if EFI_USE_OPENBLT
253#include "openblt/efi_blt_ids.h"
254 if ((CAN_SID(frame) == BOOT_COM_CAN_RX_MSG_ID) && (frame.DLC == 2)) {
255 /* TODO: gracefull shutdown? */
256 if (((busIndex == 0) && (engineConfiguration->canOpenBLT)) ||
257 ((busIndex == 1) && (engineConfiguration->can2OpenBLT))) {
259 }
260 }
261#endif
262}
263
264#endif // EFI_CAN_SUPPORT
void jump_to_openblt()
void processCanEcuControl(const CANRxFrame &frame)
Utility methods related to bench testing.
void processCanQcBenchTest(const CANRxFrame &frame)
std::optional< board_can_rx_type > custom_board_can_rx
Definition can_rx.cpp:201
uint16_t getTwoBytesLsb(const CANRxFrame &frame, int offset)
Definition can_rx.cpp:126
void registerCanListener(CanListener &listener)
Definition can_rx.cpp:84
uint32_t getFourBytesLsb(const CANRxFrame &frame, int offset)
Definition can_rx.cpp:119
static void processCanRxImu(const CANRxFrame &frame)
Definition can_rx.cpp:160
static CanListenerTailSentinel tailSentinel
Definition can_rx.cpp:68
static void processCanRxImu_BoschM5_10_RollX(const CANRxFrame &frame)
Definition can_rx.cpp:147
static void processCanRxImu_BoschM5_10_YawY(const CANRxFrame &frame)
Definition can_rx.cpp:138
static int16_t getShiftedLSB_intel(const CANRxFrame &frame, int offset)
Definition can_rx.cpp:134
void processCanRxMessage(const size_t busIndex, const CANRxFrame &frame, efitick_t nowNt)
Definition can_rx.cpp:203
static void printPacket(const size_t busIndex, const CANRxFrame &rx)
Definition can_rx.cpp:29
bool verboseRxCan
Definition settings.cpp:364
uint16_t getTwoBytesMsb(const CANRxFrame &frame, int offset)
Definition can_rx.cpp:130
void registerCanSensor(CanSensorBase &sensor)
Definition can_rx.cpp:92
static void processCanRxImu_BoschM5_10_Z(const CANRxFrame &frame)
Definition can_rx.cpp:154
void boardProcessCanRxMessage(const size_t, const CANRxFrame &, efitick_t)
Definition can_rx.cpp:196
CanListener * canListeners_head
Definition can_rx.cpp:69
void serviceCanSubscribers(const size_t busIndex, const CANRxFrame &frame, efitick_t nowNt)
Definition can_rx.cpp:71
void processCanRxVss(const CANRxFrame &frame, efitick_t nowNt)
Definition can_vss.cpp:177
CanListener * processFrame(const size_t busIndex, const CANRxFrame &frame, efitick_t nowNt)
virtual void decodeFrame(const CANRxFrame &frame, efitick_t nowNt)=0
bool hasNext() const
virtual bool acceptFrame(const size_t busIndex, const CANRxFrame &frame) const
void setNext(CanListener *next)
SensorsState sensors
Definition engine.h:353
Timer externalGdiCanBusComms
bool Register()
Definition sensor.cpp:131
LimpManager * getLimpManager()
Definition engine.cpp:596
static EngineAccessor engine
Definition engine.h:413
static constexpr engine_configuration_s * engineConfiguration
static Lps25Sensor sensor(device)
void processLuaCan(const size_t busIndex, const CANRxFrame &frame)
void obdOnCanPacketRx(const CANRxFrame &rx, size_t busIndex)
Definition obd2.cpp:210
void handleWidebandCan(const size_t busIndex, const CANRxFrame &frame)
static CanTsListener listener
uint8_t data8[8]
Frame data.
Definition can_mocks.h:55
uint8_t DLC
Data length.
Definition can_mocks.h:42
Accelerometer accelerometer
uint16_t offset
Definition tunerstudio.h:0