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 */
29void printCANRxFrame(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
84// TODO: rework to use utlist.h helpers
85
87 // Do this under lock?
88
89 // If the listener already has a next, it's already registered
90 if (!listener.getNext()) {
91 listener.setNext(canListeners_head);
92 canListeners_head = &listener;
93 }
94}
95
97 // Do this under lock?
98
99 // listener is at head of list...
100 if (canListeners_head == &listener) {
101 canListeners_head = listener.getNext();
102 } else {
104
105 while (current->getNext() && (current->getNext() != &listener)) {
106 current = current->getNext();
107 }
108 if (current->getNext()) {
109 current->setNext(listener.getNext());
110 }
111 }
112
113 listener.setNext(nullptr);
114}
115
120
121/*
122 * TODO:
123 * - convert to CanListener
124 * - move to hw_layer/sensors/yaw_rate_sensor.cpp | accelerometer.cpp ?
125 */
126
127#define VAG_YAW_RATE_G_LAT 0x130
128#define VAG_YAW_ACCEL_G_LONG 0x131
129
130/* Bosch Acceleration Sensor MM5.10 quantizations */
131#define MM5_10_RATE_QUANT 0.005
132#define MM5_10_ACC_QUANT 0.0001274
133
134/* Bosch Acceleration Sensor MM5.10 CAN IDs */
135#define MM5_10_YAW_Y 0x174
136#define MM5_10_ROLL_X 0x178
137#define MM5_10_Z 0x17C
138
139/* Mercedes pn: A 006 542 26 18 CAN IDs */
140#define MM5_10_MB_YAW_Y_CANID 0x150
141#define MM5_10_MB_ROLL_X_CANID 0x151
142
143uint32_t getFourBytesLsb(const CANRxFrame& frame, int offset) {
144 return (frame.data8[offset + 3] << 24) +
145 (frame.data8[offset + 2] << 16) +
146 (frame.data8[offset + 1] << 8) +
147 frame.data8[offset];
148}
149
150uint16_t getTwoBytesLsb(const CANRxFrame& frame, int offset) {
151 return (frame.data8[offset + 1] << 8) + frame.data8[offset];
152}
153
154uint16_t getTwoBytesMsb(const CANRxFrame& frame, int offset) {
155 return (frame.data8[offset] << 8) + frame.data8[offset + 1];
156}
157
158static int16_t getShiftedLSB_intel(const CANRxFrame& frame, int offset) {
159 return getTwoBytesLsb(frame, offset) - 0x8000;
160}
161
163 float yaw = getShiftedLSB_intel(frame, 0);
164 float accY = getShiftedLSB_intel(frame, 4);
165
166 efiPrintf("CAN_rx MM5_10_YAW_Y %f %f", yaw, accY);
167 engine->sensors.accelerometer.yawRate = yaw * MM5_10_RATE_QUANT;
168 engine->sensors.accelerometer.lat = accY * MM5_10_ACC_QUANT;
169}
170
172 float accX = getShiftedLSB_intel(frame, 4);
173 efiPrintf("CAN_rx MM5_10_ROLL_X %f", accX);
174
175 engine->sensors.accelerometer.lon = accX * MM5_10_ACC_QUANT;
176}
177
178static void processCanRxImu_BoschM5_10_Z(const CANRxFrame& frame) {
179 float accZ = getShiftedLSB_intel(frame, 4);
180 efiPrintf("CAN_rx MM5_10_Z %f", accZ);
181 engine->sensors.accelerometer.vert = accZ * MM5_10_ACC_QUANT;
182}
183
184static void processCanRxImu(const CANRxFrame& frame) {
185/*
186 if (CAN_SID(frame) == 0x130) {
187 float a = getShiftedLSB_intel(frame, 0);
188 float b = getShiftedLSB_intel(frame, 4);
189 efiPrintf("CAN_rx 130 %f %f", a, b);
190 }
191
192 if (engineConfiguration->imuType == IMU_VAG) {
193 if (CAN_SID(frame) == VAG_YAW_RATE_G_LAT) {
194 efiPrintf("CAN_rx VAG_YAW_RATE_G_LAT");
195 } else if (CAN_SID(frame) == VAG_YAW_ACCEL_G_LONG) {
196 efiPrintf("CAN_rx VAG_YAW_ACCEL_G_LONG");
197 }
198 }
199 */
200
201 if (engineConfiguration->imuType == IMU_MM5_10) {
202 if (CAN_SID(frame) == MM5_10_YAW_Y) {
204 } else if (CAN_SID(frame) == MM5_10_ROLL_X) {
206 } else if (CAN_SID(frame) == MM5_10_Z) {
208 }
209 } else if (engineConfiguration->imuType == IMU_TYPE_MB_A0065422618) {
210 if (CAN_SID(frame) == MM5_10_MB_YAW_Y_CANID) {
212 } else if (CAN_SID(frame) == MM5_10_MB_ROLL_X_CANID) {
214 }
215 }
216}
217
218extern bool verboseRxCan;
219
220void boardProcessCanRxMessage(const size_t, const CANRxFrame &, efitick_t) {
221 // this is here to indicate that migration is required
222 // todo: remove in 2026
223}
224
225std::optional<board_can_rx_type> custom_board_can_rx;
226
227void processCanRxMessage(const size_t busIndex, const CANRxFrame &frame, efitick_t nowNt) {
228 if (verboseRxCan ||
229 (engineConfiguration->verboseCan && busIndex == 0) ||
230 (engineConfiguration->verboseCan2 && busIndex == 1) ||
231#if (EFI_CAN_BUS_COUNT >= 3)
232 (engineConfiguration->verboseCan3 && busIndex == 2) ||
233#endif
234 0) {
235 printCANRxFrame(busIndex, frame);
236 }
237
238 // TODO use call_board_override
239 if (custom_board_can_rx.has_value()) {
240 custom_board_can_rx.value()(busIndex, frame, nowNt);
241 }
242
243 // see AemXSeriesWideband as an example of CanSensorBase/CanListener
244 serviceCanSubscribers(busIndex, frame, nowNt);
245
246 // todo: convert to CanListener or not?
247 //Vss is configurable, should we handle it here:
248 processCanRxVss(frame, nowNt);
249
251 // todo: convert to CanListener or not?
252 processCanRxImu(frame);
253 }
254
255/*
256static Timer dashAliveTimer;
257
258 if (CAN_EID(frame) == (int)bench_test_packet_ids_e::DASH_ALIVE) {
259 // todo: add an indicator that dash is connected?
260 dashAliveTimer.reset();
261 }
262*/
263
266
267 processLuaCan(busIndex, frame);
268
269 {
270 obdOnCanPacketRx(frame, busIndex);
271 }
272
273#if EFI_ENGINE_CONTROL
274 if (CAN_EID(frame) == GDI4_BASE_ADDRESS && frame.data8[7] == GDI4_MAGIC) {
275// efiPrintf("CAN GDI4 says hi");
277 }
278#endif // EFI_ENGINE_CONTROL
279
280 handleWidebandCan(busIndex, frame);
281#if EFI_USE_OPENBLT
282#include "openblt/efi_blt_ids.h"
283 if ((CAN_SID(frame) == BOOT_COM_CAN_RX_MSG_ID) && (frame.DLC == 2)) {
284 /* TODO: gracefull shutdown? */
285 if (((busIndex == 0) && (engineConfiguration->canOpenBLT)) ||
286 ((busIndex == 1) && (engineConfiguration->can2OpenBLT))) {
288 }
289 }
290#endif
291}
292
293#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:225
uint16_t getTwoBytesLsb(const CANRxFrame &frame, int offset)
Definition can_rx.cpp:150
void registerCanListener(CanListener &listener)
Definition can_rx.cpp:86
uint32_t getFourBytesLsb(const CANRxFrame &frame, int offset)
Definition can_rx.cpp:143
static void processCanRxImu(const CANRxFrame &frame)
Definition can_rx.cpp:184
static CanListenerTailSentinel tailSentinel
Definition can_rx.cpp:68
static void processCanRxImu_BoschM5_10_RollX(const CANRxFrame &frame)
Definition can_rx.cpp:171
static void processCanRxImu_BoschM5_10_YawY(const CANRxFrame &frame)
Definition can_rx.cpp:162
static int16_t getShiftedLSB_intel(const CANRxFrame &frame, int offset)
Definition can_rx.cpp:158
void processCanRxMessage(const size_t busIndex, const CANRxFrame &frame, efitick_t nowNt)
Definition can_rx.cpp:227
bool verboseRxCan
Definition settings.cpp:364
void printCANRxFrame(const size_t busIndex, const CANRxFrame &rx)
Definition can_rx.cpp:29
uint16_t getTwoBytesMsb(const CANRxFrame &frame, int offset)
Definition can_rx.cpp:154
void registerCanSensor(CanSensorBase &sensor)
Definition can_rx.cpp:116
void unregisterCanListener(CanListener &listener)
Definition can_rx.cpp:96
static void processCanRxImu_BoschM5_10_Z(const CANRxFrame &frame)
Definition can_rx.cpp:178
void boardProcessCanRxMessage(const size_t, const CANRxFrame &, efitick_t)
Definition can_rx.cpp:220
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
CanListener * getNext() 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:608
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)
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