rusEFI
The most advanced open source ECU
can_bench_test.cpp
Go to the documentation of this file.
1 
2 #include "pch.h"
3 #include "bench_test.h"
4 #include "board_id.h"
5 #include "can_bench_test.h"
6 #include "can_msg_tx.h"
7 #include "can_common.h"
8 #include "frequency_sensor.h"
9 #include "settings.h"
10 #include "gpio/gpio_ext.h"
11 
12 #define TRUNCATE_TO_BYTE(i) ((i) & 0xff)
13 // raw values are 0..5V, convert it to 8-bit (0..255)
14 #define RAW_TO_BYTE(v) TRUNCATE_TO_BYTE((int)(v * 255.0 / 5.0))
15 
16 /**
17  * QC direct output control API is used by https://github.com/rusefi/stim test device
18  * quite different from bench testing user functionality: QC direct should never be engaged on a real vehicle
19  * Once QC direct control mode is activated the only way out is to reboot the unit!
20  */
22 
23 static void directWritePad(Gpio pin, int value) {
24  if (!isBrainPinValid(pin)) {
25  criticalError("QC of invalid pin %d", (int)pin);
26  return;
27  }
28 
29 #if EFI_GPIO_HARDWARE && EFI_PROD_CODE
30  if (brain_pin_is_onchip(pin)) {
31  palWritePad(getHwPort("can_write", pin), getHwPin("can_write", pin), value);
32  } else {
33 #if (BOARD_EXT_GPIOCHIPS > 0)
34  gpiochips_writePad(pin, value);
35 #endif
36  }
37 #endif // EFI_GPIO_HARDWARE && EFI_PROD_CODE
38 }
39 
40 static void qcSetEtbState(uint8_t dcIndex, uint8_t direction) {
42  const dc_io *io = &engineConfiguration->etbIo[dcIndex];
43  Gpio controlPin = io->controlPin;
44  directWritePad(controlPin, 1);
46  // TLE7209 and L6205
47  // let's force proper pin mode to work around potentially uninitialized subsystem
48  efiSetPadModeWithoutOwnershipAcquisition("QC_ETB_1", io->directionPin1, PAL_MODE_OUTPUT_PUSHPULL);
49  efiSetPadModeWithoutOwnershipAcquisition("QC_ETB_2", io->directionPin2, PAL_MODE_OUTPUT_PUSHPULL);
50 
51  directWritePad(io->directionPin1, direction);
52  directWritePad(io->directionPin2, !direction);
53  } else {
54  // TLE9201 and VNH2SP30
55  efiSetPadModeWithoutOwnershipAcquisition("QC_ETB", controlPin, PAL_MODE_OUTPUT_PUSHPULL);
56  directWritePad(io->directionPin1, direction);
57  directWritePad(io->disablePin, 0); // disable pin is inverted - here we ENABLE. direct pin access due to qcDirectPinControlMode
58  }
59 }
60 
61 #if EFI_CAN_SUPPORT
62 
63 static void setPin(const CANRxFrame& frame, int value) {
64  int outputIndex = frame.data8[2];
65  if (outputIndex >= getBoardMetaOutputsCount()) {
66  criticalError("QC pin index %d", outputIndex);
67  return;
68  }
69 #if EFI_GPIO_HARDWARE && EFI_PROD_CODE
70  Gpio* boardOutputs = getBoardMetaOutputs();
71  criticalAssertVoid(boardOutputs != nullptr, "outputs not defined");
72  Gpio pin = boardOutputs[outputIndex];
73 
74  int hwIndex = brainPin_to_index(pin);
75  if (engine->pinRepository.getBrainUsedPin(hwIndex) == nullptr) {
76  // if pin is assigned we better configure it
77  efiSetPadModeWithoutOwnershipAcquisition("QC_SET", pin, PAL_MODE_OUTPUT_PUSHPULL);
78  }
79 
80  directWritePad(pin, value);
81 #endif // EFI_GPIO_HARDWARE && EFI_PROD_CODE
82 }
83 
85 #if EFI_SHAFT_POSITION_INPUT
86  CanTxMessage msg(CanCategory::BENCH_TEST, (int)bench_test_packet_ids_e::EVENT_COUNTERS, 8, /*bus*/0, /*isExtended*/true);
87 
92 
93  msg[0] = TRUNCATE_TO_BYTE(primaryRise + primaryFall);
94  msg[1] = TRUNCATE_TO_BYTE(secondaryRise + secondaryFall);
95 
96  for (int camIdx = 0; camIdx < 4; camIdx++) {
97  int vvtRise = 0, vvtFall = 0;
98  if (camIdx < CAM_INPUTS_COUNT) {
99  vvtRise = engine->triggerCentral.vvtEventRiseCounter[camIdx];
100  vvtFall = engine->triggerCentral.vvtEventFallCounter[camIdx];
101  }
102 
103  msg[2 + camIdx] = TRUNCATE_TO_BYTE(vvtRise + vvtFall);
104  }
105 
107  msg[6] = TRUNCATE_TO_BYTE(vehicleSpeedSensor.eventCounter);
108 #endif // EFI_SHAFT_POSITION_INPUT
109 }
110 
112  CanTxMessage msg(CanCategory::BENCH_TEST, (int)bench_test_packet_ids_e::BUTTON_COUNTERS, 8, /*bus*/0, /*isExtended*/true);
113  msg[0] = TRUNCATE_TO_BYTE(engine->brakePedalSwitchedState.getCounter());
114  msg[1] = TRUNCATE_TO_BYTE(engine->clutchUpSwitchedState.getCounter());
115  msg[2] = TRUNCATE_TO_BYTE(engine->acButtonSwitchedState.getCounter());
116  // todo: start button
117 }
118 
120  CanTxMessage msg(CanCategory::BENCH_TEST, (int)bench_test_packet_ids_e::BUTTON_COUNTERS, 8, /*bus*/0, /*isExtended*/true);
121  for (int i =0;i<LUA_DIGITAL_INPUT_COUNT;i++) {
122  msg[i] = TRUNCATE_TO_BYTE(engine->luaDigitalInputState[i].state.getCounter());
123  }
124 }
125 
127  const float values_1[] = {
136  };
137 
138  const float values_2[] = {
147  };
148  static_assert(efi::size(values_1) <= 8);
149  static_assert(efi::size(values_2) <= 8);
150 
151 
152  // send the first packet
153  {
154  CanTxMessage msg(CanCategory::BENCH_TEST, (int)bench_test_packet_ids_e::RAW_ANALOG_1, 8, /*bus*/0, /*isExtended*/true);
155  for (size_t valueIdx = 0; valueIdx < efi::size(values_1); valueIdx++) {
156  msg[valueIdx] = RAW_TO_BYTE(values_1[valueIdx]);
157  }
158  }
159  {
160  CanTxMessage msg(CanCategory::BENCH_TEST, (int)bench_test_packet_ids_e::RAW_ANALOG_2, 8, /*bus*/0, /*isExtended*/true);
161  for (size_t valueIdx = 0; valueIdx < efi::size(values_2); valueIdx++) {
162  msg[valueIdx] = RAW_TO_BYTE(values_2[valueIdx]);
163  }
164  }
165 }
166 
167 static void sendOutBoardMeta() {
168 #if EFI_PROD_CODE
169  CanTxMessage msg(CanCategory::BENCH_TEST, (int)bench_test_packet_ids_e::IO_META_INFO, 8, /*bus*/0, /*isExtended*/true);
170  msg[0] = (int)bench_test_magic_numbers_e::BENCH_HEADER;
171  msg[1] = 0;
172  msg[2] = getBoardMetaOutputsCount();
174  msg[4] = getBoardMetaDcOutputsCount();
175 #endif // EFI_PROD_CODE
176 }
177 
179 #if EFI_PROD_CODE
180  CanTxMessage msg(CanCategory::BENCH_TEST, (int)bench_test_packet_ids_e::BOARD_STATUS, 8, /*bus*/0, /*isExtended*/true);
181 
182  int boardId = getBoardId();
183  msg[0] = TRUNCATE_TO_BYTE(boardId >> 8);
184  msg[1] = TRUNCATE_TO_BYTE(boardId);
185 
186  int numSecondsSinceReset = getTimeNowS();
187  msg[2] = TRUNCATE_TO_BYTE(numSecondsSinceReset >> 16);
188  msg[3] = TRUNCATE_TO_BYTE(numSecondsSinceReset >> 8);
189  msg[4] = TRUNCATE_TO_BYTE(numSecondsSinceReset);
190 
191  int engineType = (int) engineConfiguration->engineType;
192  msg[5] = engineType >> 8;
193  msg[6] = engineType;
195 #endif // EFI_PROD_CODE
196 }
197 
198 static void sendPinStatePackets(int pinToggleCounter, uint32_t durationsInStateMs[2]) {
199  CanTxMessage msg(CanCategory::BENCH_TEST, (int)bench_test_packet_ids_e::PIN_STATE, 8, /*bus*/0, /*isExtended*/true);
200  msg[0] = TRUNCATE_TO_BYTE(pinToggleCounter >> 8);
201  msg[1] = TRUNCATE_TO_BYTE(pinToggleCounter);
202 
203  for (int i = 0, mIdx = 2; i < 2; i++) {
204  msg[mIdx++] = TRUNCATE_TO_BYTE(durationsInStateMs[i] >> 16);
205  msg[mIdx++] = TRUNCATE_TO_BYTE(durationsInStateMs[i] >> 8);
206  msg[mIdx++] = TRUNCATE_TO_BYTE(durationsInStateMs[i]);
207  }
208 }
209 
210 // bench test fuel pump pin #5603
211 static void sendPinStatePackets(bench_mode_e benchModePinIdx) {
212  OutputPin *pin = enginePins.getOutputPinForBenchMode(benchModePinIdx);
213  if (pin == nullptr)
214  return;
215 #if EFI_SIMULATOR
216  sendPinStatePackets(pin->pinToggleCounter, pin->durationsInStateMs);
217 #endif // EFI_SIMULATOR
218 }
219 
221  uint32_t savedDurationsInStateMs[2];
224 }
225 
226 static void resetPinStats(bench_mode_e benchModePinIdx) {
227  OutputPin *pin = enginePins.getOutputPinForBenchMode(benchModePinIdx);
228 
229  if (pin == nullptr)
230  return;
231 
232 #if EFI_SIMULATOR
233  pin->resetToggleStats();
234 #endif // EFI_SIMULATOR
235 }
236 
237 /*board public API*/bool withHwQcActivity = false;
238 
239 void processCanQcBenchTest(const CANRxFrame& frame) {
240  if (CAN_EID(frame) != (int)bench_test_packet_ids_e::IO_CONTROL) {
241  return;
242  }
243  if (frame.data8[0] != (int)bench_test_magic_numbers_e::BENCH_HEADER) {
244  return;
245  }
246  withHwQcActivity = true;
247  bench_test_io_control_e command = (bench_test_io_control_e)frame.data8[1];
248  if (command == bench_test_io_control_e::CAN_BENCH_GET_COUNT) {
250  } else if (command == bench_test_io_control_e::CAN_QC_OUTPUT_CONTROL_SET) {
251  // see also "bench_setpin" console command
252  qcDirectPinControlMode = true;
253  setPin(frame, 1);
254  } else if (command == bench_test_io_control_e::CAN_QC_OUTPUT_CONTROL_CLEAR) {
255  qcDirectPinControlMode = true;
256  setPin(frame, 0);
257  } else if (command == bench_test_io_control_e::CAN_QC_ETB) {
258  uint8_t dcIndex = frame.data8[2];
259  uint8_t direction = frame.data8[3];
260  qcSetEtbState(dcIndex, direction);
261  } else if (command == bench_test_io_control_e::CAN_BENCH_SET_ENGINE_TYPE) {
262  int eType = frame.data8[2];
263  // todo: fix firmware for 'false' to be possible - i.e. more of properties should be applied on the fly
264  setEngineType(eType, true);
265 #if EFI_PROD_CODE
266  scheduleReboot();
267 #endif // EFI_PROD_CODE
268 } else if (command == bench_test_io_control_e::CAN_BENCH_START_PIN_TEST) {
269  bench_mode_e benchModePinIdx = (bench_mode_e)frame.data8[2];
270  // ignore previous pin state and stats
271  resetPinStats(benchModePinIdx);
272  } else if (command == bench_test_io_control_e::CAN_BENCH_END_PIN_TEST) {
274  } else if (command == bench_test_io_control_e::CAN_BENCH_EXECUTE_BENCH_TEST) {
275  int benchCommandIdx = frame.data8[2];
276  handleBenchCategory(benchCommandIdx);
277  } else if (command == bench_test_io_control_e::CAN_BENCH_QUERY_PIN_STATE) {
278  bench_mode_e benchModePinIdx = (bench_mode_e)frame.data8[2];
279  sendPinStatePackets(benchModePinIdx);
280  }
281 }
282 #endif // EFI_CAN_SUPPORT
283 
285  addConsoleActionII("qc_etb", [](int index, int direction) {
286  qcSetEtbState(index, direction);
287  });
288 }
int getSavedBenchTestPinStates(uint32_t durationsInStateMs[2])
Definition: bench_test.cpp:424
static uint32_t savedDurationsInStateMs[2]
Definition: bench_test.cpp:67
void handleBenchCategory(uint16_t index)
Definition: bench_test.cpp:338
static int savedPinToggleCounter
Definition: bench_test.cpp:66
Utility methods related to bench testing.
board_id_t getBoardId()
Definition: board_id.cpp:14
void sendQcBenchButtonCounters()
static void setPin(const CANRxFrame &frame, int value)
void processCanQcBenchTest(const CANRxFrame &frame)
static void qcSetEtbState(uint8_t dcIndex, uint8_t direction)
void sendQcBenchBoardStatus()
void sendQcBenchRawAnalogValues()
bool qcDirectPinControlMode
static void sendSavedBenchStatePackets()
void initQcBenchControls()
static void directWritePad(Gpio pin, int value)
static void sendOutBoardMeta()
bool withHwQcActivity
static void resetPinStats(bench_mode_e benchModePinIdx)
void sendQcBenchAuxDigitalCounters()
static void sendPinStatePackets(int pinToggleCounter, uint32_t durationsInStateMs[2])
void sendQcBenchEventCounters()
TriggerCentral triggerCentral
Definition: engine.h:286
SwitchedState brakePedalSwitchedState
Definition: engine.h:187
SwitchedState clutchUpSwitchedState
Definition: engine.h:186
SwitchedState acButtonSwitchedState
Definition: engine.h:188
SimpleSwitchedState luaDigitalInputState[LUA_DIGITAL_INPUT_COUNT]
Definition: engine.h:189
PinRepository pinRepository
Definition: engine.h:116
OutputPin * getOutputPinForBenchMode(bench_mode_e idx)
Definition: efi_gpio.cpp:350
Single output pin reference and state.
Definition: efi_output.h:50
const char *& getBrainUsedPin(size_t idx)
virtual float getRaw() const
Definition: sensor.h:157
SwitchedState state
Definition: efi_output.h:37
uint16_t getCounter()
Definition: efi_output.cpp:19
int getHwEventCounter(int index) const
int vvtEventFallCounter[CAM_INPUTS_COUNT]
int vvtEventRiseCounter[CAM_INPUTS_COUNT]
void addConsoleActionII(const char *token, VoidIntInt callback)
Register a console command with two Integer parameters.
Gpio
int gpiochips_writePad(brain_pin_e pin, int value)
Set value to gpio of gpiochip.
Definition: core.cpp:335
EnginePins enginePins
Definition: efi_gpio.cpp:24
ioportid_t getHwPort(const char *msg, brain_pin_e brainPin)
ioportmask_t getHwPin(const char *msg, brain_pin_e brainPin)
efitimesec_t getTimeNowS()
Current system time in seconds (32 bits)
Definition: efitime.cpp:42
void scheduleReboot()
Definition: rusefi.cpp:158
Engine * engine
bench_mode_e
Definition: engine_types.h:494
int getBoardMetaOutputsCount()
Gpio * getBoardMetaOutputs()
int getBoardMetaDcOutputsCount()
int getBoardMetaLowSideOutputsCount()
FrequencySensor vehicleSpeedSensor(SensorType::VehicleSpeed, MS2NT(500))
void efiSetPadModeWithoutOwnershipAcquisition(const char *msg, brain_pin_e brainPin, iomode_t mode)
Definition: io_pins.cpp:61
engine_configuration_s * engineConfiguration
int brainPin_to_index(Gpio brainPin)
bool brain_pin_is_onchip(brain_pin_e brainPin)
bool isBrainPinValid(brain_pin_e brainPin)
@ AcceleratorPedalPrimary
@ AcceleratorPedalSecondary
void setEngineType(int value, bool isWriteToFlash)
Definition: settings.cpp:874
This file is about configuring engine via the human-readable protocol.
@ SHAFT_SECONDARY_RISING
@ SHAFT_SECONDARY_FALLING
@ SHAFT_PRIMARY_FALLING
@ SHAFT_PRIMARY_RISING
brain_pin_e pin
Definition: stm32_adc.cpp:15
uint8_t data8[8]
Frame data.
Definition: can_mocks.h:55
composite packet size