Line |
Branch |
Decision |
Exec |
Source |
1 |
|
|
|
/* |
2 |
|
|
|
* file can_bench_test.cpp |
3 |
|
|
|
* see also https://github.com/rusefi/rusefi/wiki/CAN BENCH_TEST_BASE_ADDRESS 0x770000 |
4 |
|
|
|
* |
5 |
|
|
|
* primary recipient is https://github.com/rusefi/rusefi-hardware/tree/main/digital-inputs/firmware |
6 |
|
|
|
* |
7 |
|
|
|
* todo: shall we not broadcast by default but wait until stim firmware wakes us up? |
8 |
|
|
|
*/ |
9 |
|
|
|
|
10 |
|
|
|
#include "pch.h" |
11 |
|
|
|
#include "bench_test.h" |
12 |
|
|
|
#include "board_id.h" |
13 |
|
|
|
#include "can_bench_test.h" |
14 |
|
|
|
#include "can_msg_tx.h" |
15 |
|
|
|
#include "can_common.h" |
16 |
|
|
|
#include "frequency_sensor.h" |
17 |
|
|
|
#include "settings.h" |
18 |
|
|
|
#include "gpio/gpio_ext.h" |
19 |
|
|
|
|
20 |
|
|
|
#ifdef HW_HELLEN |
21 |
|
|
|
#include "hellen_meta.h" |
22 |
|
|
|
#endif // HW_HELLEN |
23 |
|
|
|
|
24 |
|
|
|
extern PinRepository pinRepository; |
25 |
|
|
|
|
26 |
|
|
|
// todo: WHAT?! document why do we manually truncate higher bits? |
27 |
|
|
|
#define TRUNCATE_TO_BYTE(i) ((i) & 0xff) |
28 |
|
|
|
// raw values are 0..5V, convert it to 8-bit (0..255) |
29 |
|
|
|
#define RAW_TO_BYTE(v) TRUNCATE_TO_BYTE((int)(v * 255.0 / 5.0)) |
30 |
|
|
|
|
31 |
|
|
|
#if EFI_PROD_CODE |
32 |
|
|
|
/** |
33 |
|
|
|
* QC direct output control API is used by https://github.com/rusefi/stim test device |
34 |
|
|
|
* quite different from bench testing user functionality: QC direct should never be engaged on a real vehicle |
35 |
|
|
|
* Once QC direct control mode is activated the only way out is to reboot the unit! |
36 |
|
|
|
*/ |
37 |
|
|
|
static bool qcDirectPinControlMode = false; |
38 |
|
|
|
#endif |
39 |
|
|
|
|
40 |
|
|
39029 |
/*board public API*/bool isHwQcMode() { |
41 |
|
|
|
#if EFI_PROD_CODE |
42 |
|
|
|
return qcDirectPinControlMode; |
43 |
|
|
|
#else |
44 |
|
|
39029 |
return false; |
45 |
|
|
|
#endif // EFI_PROD_CODE |
46 |
|
|
|
} |
47 |
|
|
|
|
48 |
|
|
✗ |
void setHwQcMode() { |
49 |
|
|
|
#if EFI_PROD_CODE |
50 |
|
|
|
qcDirectPinControlMode = true; |
51 |
|
|
|
#if HW_HELLEN |
52 |
|
|
|
if (!getHellenBoardEnabled()) { |
53 |
|
|
|
hellenEnableEn("HW QC"); |
54 |
|
|
|
} |
55 |
|
|
|
#endif // HW_HELLEN |
56 |
|
|
|
#endif // EFI_PROD_CODE |
57 |
|
|
✗ |
} |
58 |
|
|
|
|
59 |
|
|
|
#if EFI_CAN_SUPPORT |
60 |
|
|
|
|
61 |
|
|
|
static void directWritePad(Gpio pin, int value, const char *msg = "") { |
62 |
|
|
|
if (!isBrainPinValid(pin)) { |
63 |
|
|
|
criticalError("QC of invalid pin %d %s", (int)pin, msg); |
64 |
|
|
|
return; |
65 |
|
|
|
} |
66 |
|
|
|
|
67 |
|
|
|
#if EFI_GPIO_HARDWARE && EFI_PROD_CODE |
68 |
|
|
|
if (brain_pin_is_onchip(pin)) { |
69 |
|
|
|
palWritePad(getHwPort("can_write", pin), getHwPin("can_write", pin), value); |
70 |
|
|
|
} else { |
71 |
|
|
|
#if (BOARD_EXT_GPIOCHIPS > 0) |
72 |
|
|
|
gpiochips_writePad(pin, value); |
73 |
|
|
|
#endif |
74 |
|
|
|
} |
75 |
|
|
|
#endif // EFI_GPIO_HARDWARE && EFI_PROD_CODE |
76 |
|
|
|
} |
77 |
|
|
|
|
78 |
|
|
|
static void qcSetEtbState(uint8_t dcIndex, uint8_t direction) { |
79 |
|
|
|
setHwQcMode(); |
80 |
|
|
|
const dc_io *io = &engineConfiguration->etbIo[dcIndex]; |
81 |
|
|
|
Gpio controlPin = io->controlPin; |
82 |
|
|
|
directWritePad(controlPin, 1, "DC control"); |
83 |
|
|
|
if (engineConfiguration->etb_use_two_wires) { |
84 |
|
|
|
// TLE7209 and L6205 |
85 |
|
|
|
// let's force proper pin mode to work around potentially uninitialized subsystem |
86 |
|
|
|
efiSetPadModeWithoutOwnershipAcquisition("QC_ETB_1", io->directionPin1, PAL_MODE_OUTPUT_PUSHPULL); |
87 |
|
|
|
efiSetPadModeWithoutOwnershipAcquisition("QC_ETB_2", io->directionPin2, PAL_MODE_OUTPUT_PUSHPULL); |
88 |
|
|
|
|
89 |
|
|
|
directWritePad(io->directionPin1, direction, "DC dir1"); |
90 |
|
|
|
directWritePad(io->directionPin2, !direction, "DC dir2"); |
91 |
|
|
|
} else { |
92 |
|
|
|
// TLE9201 and VNH2SP30 |
93 |
|
|
|
efiSetPadModeWithoutOwnershipAcquisition("QC_ETB", controlPin, PAL_MODE_OUTPUT_PUSHPULL); |
94 |
|
|
|
directWritePad(io->directionPin1, direction, "DC dir"); |
95 |
|
|
|
directWritePad(io->disablePin, 0, "DC dis"); // disable pin is inverted - here we ENABLE. direct pin access due to qcDirectPinControlMode |
96 |
|
|
|
} |
97 |
|
|
|
} |
98 |
|
|
|
|
99 |
|
|
|
static void setPin(const CANRxFrame& frame, int value) { |
100 |
|
|
|
size_t outputIndex = frame.data8[2]; |
101 |
|
|
|
if (outputIndex >= getBoardMetaOutputsCount()) { |
102 |
|
|
|
criticalError("QC pin index %d out of range", outputIndex); |
103 |
|
|
|
return; |
104 |
|
|
|
} |
105 |
|
|
|
#if EFI_GPIO_HARDWARE && EFI_PROD_CODE |
106 |
|
|
|
Gpio* boardOutputs = getBoardMetaOutputs(); |
107 |
|
|
|
criticalAssertVoid(boardOutputs != nullptr, "outputs not defined"); |
108 |
|
|
|
Gpio pin = boardOutputs[outputIndex]; |
109 |
|
|
|
|
110 |
|
|
|
int hwIndex = brainPin_to_index(pin); |
111 |
|
|
|
if (pinRepository.getBrainUsedPin(hwIndex) == nullptr) { |
112 |
|
|
|
// if pin is assigned we better configure it |
113 |
|
|
|
efiSetPadModeWithoutOwnershipAcquisition("QC_SET", pin, PAL_MODE_OUTPUT_PUSHPULL); |
114 |
|
|
|
} |
115 |
|
|
|
|
116 |
|
|
|
directWritePad(pin, value); |
117 |
|
|
|
#endif // EFI_GPIO_HARDWARE && EFI_PROD_CODE |
118 |
|
|
|
} |
119 |
|
|
|
|
120 |
|
|
|
void sendQcBenchEventCounters(size_t bus) { |
121 |
|
|
|
#if EFI_SHAFT_POSITION_INPUT |
122 |
|
|
|
CanTxMessage msg(CanCategory::BENCH_TEST, (int)bench_test_packet_ids_e::EVENT_COUNTERS, 8, bus, /*isExtended*/true); |
123 |
|
|
|
|
124 |
|
|
|
int primaryFall = engine->triggerCentral.getHwEventCounter((int)SHAFT_PRIMARY_FALLING); |
125 |
|
|
|
int primaryRise = engine->triggerCentral.getHwEventCounter((int)SHAFT_PRIMARY_RISING); |
126 |
|
|
|
int secondaryFall = engine->triggerCentral.getHwEventCounter((int)SHAFT_SECONDARY_FALLING); |
127 |
|
|
|
int secondaryRise = engine->triggerCentral.getHwEventCounter((int)SHAFT_SECONDARY_RISING); |
128 |
|
|
|
|
129 |
|
|
|
msg[0] = TRUNCATE_TO_BYTE(primaryRise + primaryFall); |
130 |
|
|
|
msg[1] = TRUNCATE_TO_BYTE(secondaryRise + secondaryFall); |
131 |
|
|
|
|
132 |
|
|
|
for (int camIdx = 0; camIdx < 4; camIdx++) { |
133 |
|
|
|
int vvtRise = 0, vvtFall = 0; |
134 |
|
|
|
if (camIdx < CAM_INPUTS_COUNT) { |
135 |
|
|
|
vvtRise = engine->triggerCentral.vvtEventRiseCounter[camIdx]; |
136 |
|
|
|
vvtFall = engine->triggerCentral.vvtEventFallCounter[camIdx]; |
137 |
|
|
|
} |
138 |
|
|
|
|
139 |
|
|
|
msg[2 + camIdx] = TRUNCATE_TO_BYTE(vvtRise + vvtFall); |
140 |
|
|
|
} |
141 |
|
|
|
|
142 |
|
|
|
extern FrequencySensor vehicleSpeedSensor; |
143 |
|
|
|
msg[6] = TRUNCATE_TO_BYTE(vehicleSpeedSensor.eventCounter); |
144 |
|
|
|
#endif // EFI_SHAFT_POSITION_INPUT |
145 |
|
|
|
} |
146 |
|
|
|
|
147 |
|
|
|
void sendQcBenchButtonCounters() { |
148 |
|
|
|
CanTxMessage msg(CanCategory::BENCH_TEST, (int)bench_test_packet_ids_e::BUTTON_COUNTERS, 8, /*bus*/0, /*isExtended*/true); |
149 |
|
|
|
msg[0] = TRUNCATE_TO_BYTE(engine->brakePedalSwitchedState.getCounter()); |
150 |
|
|
|
msg[1] = TRUNCATE_TO_BYTE(engine->clutchUpSwitchedState.getCounter()); |
151 |
|
|
|
msg[2] = TRUNCATE_TO_BYTE(engine->acButtonSwitchedState.getCounter()); |
152 |
|
|
|
// todo: start button |
153 |
|
|
|
} |
154 |
|
|
|
|
155 |
|
|
|
void sendQcBenchAuxDigitalCounters() { |
156 |
|
|
|
CanTxMessage msg(CanCategory::BENCH_TEST, (int)bench_test_packet_ids_e::AUX_DIGITAL_COUNTERS, 8, /*bus*/0, /*isExtended*/true); |
157 |
|
|
|
for (int i =0;i<LUA_DIGITAL_INPUT_COUNT;i++) { |
158 |
|
|
|
msg[i] = TRUNCATE_TO_BYTE(engine->luaDigitalInputState[i].state.getCounter()); |
159 |
|
|
|
} |
160 |
|
|
|
} |
161 |
|
|
|
|
162 |
|
|
|
void sendQcBenchRawAnalogValues(size_t bus) { |
163 |
|
|
|
const float values_1[] = { |
164 |
|
|
|
Sensor::getRaw(SensorType::Tps1Primary), |
165 |
|
|
|
Sensor::getRaw(SensorType::Tps1Secondary), |
166 |
|
|
|
Sensor::getRaw(SensorType::AcceleratorPedalPrimary), |
167 |
|
|
|
Sensor::getRaw(SensorType::AcceleratorPedalSecondary), |
168 |
|
|
|
Sensor::getRaw(SensorType::MapSlow), |
169 |
|
|
|
Sensor::getRaw(SensorType::Clt), |
170 |
|
|
|
Sensor::getRaw(SensorType::Iat), |
171 |
|
|
|
Sensor::getRaw(SensorType::BatteryVoltage), |
172 |
|
|
|
}; |
173 |
|
|
|
|
174 |
|
|
|
const float values_2[] = { |
175 |
|
|
|
Sensor::getRaw(SensorType::Tps2Primary), |
176 |
|
|
|
Sensor::getRaw(SensorType::Tps2Secondary), |
177 |
|
|
|
Sensor::getRaw(SensorType::AuxLinear1), |
178 |
|
|
|
Sensor::getRaw(SensorType::AuxLinear2), |
179 |
|
|
|
Sensor::getRaw(SensorType::OilPressure), |
180 |
|
|
|
Sensor::getRaw(SensorType::FuelPressureLow), |
181 |
|
|
|
Sensor::getRaw(SensorType::FuelPressureHigh), |
182 |
|
|
|
Sensor::getRaw(SensorType::AuxTemp1), |
183 |
|
|
|
}; |
184 |
|
|
|
const float lua_values_1[] = { |
185 |
|
|
|
Sensor::getRaw(SensorType::AuxAnalog1), |
186 |
|
|
|
Sensor::getRaw(SensorType::AuxAnalog2), |
187 |
|
|
|
Sensor::getRaw(SensorType::AuxAnalog3), |
188 |
|
|
|
Sensor::getRaw(SensorType::AuxAnalog4), |
189 |
|
|
|
Sensor::getRaw(SensorType::AuxAnalog5), |
190 |
|
|
|
Sensor::getRaw(SensorType::AuxAnalog6), |
191 |
|
|
|
Sensor::getRaw(SensorType::AuxAnalog7), |
192 |
|
|
|
Sensor::getRaw(SensorType::AuxAnalog8), |
193 |
|
|
|
}; |
194 |
|
|
|
static_assert(efi::size(values_1) <= 8); |
195 |
|
|
|
static_assert(efi::size(values_2) <= 8); |
196 |
|
|
|
static_assert(efi::size(lua_values_1) <= 8); |
197 |
|
|
|
|
198 |
|
|
|
|
199 |
|
|
|
// send the first packet |
200 |
|
|
|
{ |
201 |
|
|
|
CanTxMessage msg(CanCategory::BENCH_TEST, (int)bench_test_packet_ids_e::RAW_ANALOG_1, 8, bus, /*isExtended*/true); |
202 |
|
|
|
for (size_t valueIdx = 0; valueIdx < efi::size(values_1); valueIdx++) { |
203 |
|
|
|
msg[valueIdx] = RAW_TO_BYTE(values_1[valueIdx]); |
204 |
|
|
|
} |
205 |
|
|
|
} |
206 |
|
|
|
{ |
207 |
|
|
|
CanTxMessage msg(CanCategory::BENCH_TEST, (int)bench_test_packet_ids_e::RAW_ANALOG_2, 8, bus, /*isExtended*/true); |
208 |
|
|
|
for (size_t valueIdx = 0; valueIdx < efi::size(values_2); valueIdx++) { |
209 |
|
|
|
msg[valueIdx] = RAW_TO_BYTE(values_2[valueIdx]); |
210 |
|
|
|
} |
211 |
|
|
|
} |
212 |
|
|
|
// todo: time to extract method already? |
213 |
|
|
|
{ |
214 |
|
|
|
CanTxMessage msg(CanCategory::BENCH_TEST, (int)bench_test_packet_ids_e::RAW_LUA_ANALOG_1, 8, bus, /*isExtended*/true); |
215 |
|
|
|
for (size_t valueIdx = 0; valueIdx < efi::size(lua_values_1); valueIdx++) { |
216 |
|
|
|
msg[valueIdx] = RAW_TO_BYTE(lua_values_1[valueIdx]); |
217 |
|
|
|
} |
218 |
|
|
|
} |
219 |
|
|
|
} |
220 |
|
|
|
|
221 |
|
|
|
static void sendOutBoardMeta(size_t bus) { |
222 |
|
|
|
#if EFI_PROD_CODE |
223 |
|
|
|
CanTxMessage msg(CanCategory::BENCH_TEST, (int)bench_test_packet_ids_e::IO_META_INFO, 8, bus, /*isExtended*/true); |
224 |
|
|
|
msg[0] = (int)bench_test_magic_numbers_e::BENCH_HEADER; |
225 |
|
|
|
msg[1] = 0; |
226 |
|
|
|
msg[2] = getBoardMetaOutputsCount(); |
227 |
|
|
|
msg[3] = getBoardMetaLowSideOutputsCount(); |
228 |
|
|
|
msg[4] = getBoardMetaDcOutputsCount(); |
229 |
|
|
|
#endif // EFI_PROD_CODE |
230 |
|
|
|
} |
231 |
|
|
|
|
232 |
|
|
|
void sendQcBenchBoardStatus(size_t bus) { |
233 |
|
|
|
#if EFI_PROD_CODE |
234 |
|
|
|
CanTxMessage msg(CanCategory::BENCH_TEST, (int)bench_test_packet_ids_e::BOARD_STATUS, 8, bus, /*isExtended*/true); |
235 |
|
|
|
|
236 |
|
|
|
int boardId = getBoardId(); |
237 |
|
|
|
msg[0] = TRUNCATE_TO_BYTE(boardId >> 8); |
238 |
|
|
|
msg[1] = TRUNCATE_TO_BYTE(boardId); |
239 |
|
|
|
|
240 |
|
|
|
int numSecondsSinceReset = getTimeNowS(); |
241 |
|
|
|
msg[2] = TRUNCATE_TO_BYTE(numSecondsSinceReset >> 16); |
242 |
|
|
|
msg[3] = TRUNCATE_TO_BYTE(numSecondsSinceReset >> 8); |
243 |
|
|
|
msg[4] = TRUNCATE_TO_BYTE(numSecondsSinceReset); |
244 |
|
|
|
|
245 |
|
|
|
int engineType = (int) engineConfiguration->engineType; |
246 |
|
|
|
msg[5] = engineType >> 8; |
247 |
|
|
|
msg[6] = engineType; |
248 |
|
|
|
sendOutBoardMeta(bus); |
249 |
|
|
|
#endif // EFI_PROD_CODE |
250 |
|
|
|
} |
251 |
|
|
|
|
252 |
|
|
|
#if EFI_PROD_CODE |
253 |
|
|
|
static void sendManualPinTest(int id) { |
254 |
|
|
|
CanTxMessage msg(CanCategory::BENCH_TEST, (int)bench_test_packet_ids_e::MANUAL_PIN_TEST, 8, /*bus*/0, /*isExtended*/true); |
255 |
|
|
|
msg[0] = id; |
256 |
|
|
|
} |
257 |
|
|
|
#endif // EFI_PROD_CODE |
258 |
|
|
|
|
259 |
|
|
|
static void sendPinStatePackets(int pinToggleCounter, uint32_t durationsInStateMs[2]) { |
260 |
|
|
|
CanTxMessage msg(CanCategory::BENCH_TEST, (int)bench_test_packet_ids_e::PIN_STATE, 8, /*bus*/0, /*isExtended*/true); |
261 |
|
|
|
msg[0] = TRUNCATE_TO_BYTE(pinToggleCounter >> 8); |
262 |
|
|
|
msg[1] = TRUNCATE_TO_BYTE(pinToggleCounter); |
263 |
|
|
|
|
264 |
|
|
|
for (int i = 0, mIdx = 2; i < 2; i++) { |
265 |
|
|
|
msg[mIdx++] = TRUNCATE_TO_BYTE(durationsInStateMs[i] >> 16); |
266 |
|
|
|
msg[mIdx++] = TRUNCATE_TO_BYTE(durationsInStateMs[i] >> 8); |
267 |
|
|
|
msg[mIdx++] = TRUNCATE_TO_BYTE(durationsInStateMs[i]); |
268 |
|
|
|
} |
269 |
|
|
|
} |
270 |
|
|
|
|
271 |
|
|
|
// bench test fuel pump pin #5603 |
272 |
|
|
|
static void sendPinStatePackets(bench_mode_e benchModePinIdx) { |
273 |
|
|
|
OutputPin *pin = enginePins.getOutputPinForBenchMode(benchModePinIdx); |
274 |
|
|
|
if (pin == nullptr) |
275 |
|
|
|
return; |
276 |
|
|
|
#if EFI_SIMULATOR |
277 |
|
|
|
sendPinStatePackets(pin->pinToggleCounter, pin->durationsInStateMs); |
278 |
|
|
|
#endif // EFI_SIMULATOR |
279 |
|
|
|
} |
280 |
|
|
|
|
281 |
|
|
|
static void sendSavedBenchStatePackets() { |
282 |
|
|
|
uint32_t savedDurationsInStateMs[2]; |
283 |
|
|
|
int savedPinToggleCounter = getSavedBenchTestPinStates(savedDurationsInStateMs); |
284 |
|
|
|
sendPinStatePackets(savedPinToggleCounter, savedDurationsInStateMs); |
285 |
|
|
|
} |
286 |
|
|
|
|
287 |
|
|
|
static void resetPinStats(bench_mode_e benchModePinIdx) { |
288 |
|
|
|
OutputPin *pin = enginePins.getOutputPinForBenchMode(benchModePinIdx); |
289 |
|
|
|
|
290 |
|
|
|
if (pin == nullptr) |
291 |
|
|
|
return; |
292 |
|
|
|
|
293 |
|
|
|
#if EFI_SIMULATOR |
294 |
|
|
|
pin->resetToggleStats(); |
295 |
|
|
|
#endif // EFI_SIMULATOR |
296 |
|
|
|
} |
297 |
|
|
|
|
298 |
|
|
|
void processCanQcBenchTest(const CANRxFrame& frame) { |
299 |
|
|
|
if (CAN_EID(frame) != (int)bench_test_packet_ids_e::HW_QC_IO_CONTROL) { |
300 |
|
|
|
return; |
301 |
|
|
|
} |
302 |
|
|
|
if (frame.data8[0] != (int)bench_test_magic_numbers_e::BENCH_HEADER) { |
303 |
|
|
|
return; |
304 |
|
|
|
} |
305 |
|
|
|
setHwQcMode(); |
306 |
|
|
|
bench_test_io_control_e command = (bench_test_io_control_e)frame.data8[1]; |
307 |
|
|
|
if (command == bench_test_io_control_e::CAN_BENCH_GET_COUNT) { |
308 |
|
|
|
sendOutBoardMeta(0); |
309 |
|
|
|
} else if (command == bench_test_io_control_e::CAN_QC_OUTPUT_CONTROL_SET) { |
310 |
|
|
|
// see also "bench_setpin" console command |
311 |
|
|
|
setPin(frame, 1); |
312 |
|
|
|
} else if (command == bench_test_io_control_e::CAN_QC_OUTPUT_CONTROL_CLEAR) { |
313 |
|
|
|
setPin(frame, 0); |
314 |
|
|
|
} else if (command == bench_test_io_control_e::CAN_QC_ETB) { |
315 |
|
|
|
uint8_t dcIndex = frame.data8[2]; |
316 |
|
|
|
uint8_t direction = frame.data8[3]; |
317 |
|
|
|
qcSetEtbState(dcIndex, direction); |
318 |
|
|
|
} else if (command == bench_test_io_control_e::CAN_BENCH_SET_ENGINE_TYPE) { |
319 |
|
|
|
int eType = frame.data8[2]; |
320 |
|
|
|
// todo: fix firmware for 'false' to be possible - i.e. more of properties should be applied on the fly |
321 |
|
|
|
setEngineType(eType, true); |
322 |
|
|
|
#if EFI_PROD_CODE |
323 |
|
|
|
scheduleReboot(); |
324 |
|
|
|
#endif // EFI_PROD_CODE |
325 |
|
|
|
} else if (command == bench_test_io_control_e::CAN_BENCH_START_PIN_TEST) { |
326 |
|
|
|
bench_mode_e benchModePinIdx = (bench_mode_e)frame.data8[2]; |
327 |
|
|
|
// ignore previous pin state and stats |
328 |
|
|
|
resetPinStats(benchModePinIdx); |
329 |
|
|
|
} else if (command == bench_test_io_control_e::CAN_BENCH_END_PIN_TEST) { |
330 |
|
|
|
sendSavedBenchStatePackets(); |
331 |
|
|
|
} else if (command == bench_test_io_control_e::CAN_BENCH_EXECUTE_BENCH_TEST) { |
332 |
|
|
|
int benchCommandIdx = frame.data8[2]; |
333 |
|
|
|
handleBenchCategory(benchCommandIdx); |
334 |
|
|
|
} else if (command == bench_test_io_control_e::CAN_BENCH_QUERY_PIN_STATE) { |
335 |
|
|
|
bench_mode_e benchModePinIdx = (bench_mode_e)frame.data8[2]; |
336 |
|
|
|
sendPinStatePackets(benchModePinIdx); |
337 |
|
|
|
} |
338 |
|
|
|
} |
339 |
|
|
|
#endif // EFI_CAN_SUPPORT |
340 |
|
|
|
|
341 |
|
|
✗ |
void initQcBenchControls() { |
342 |
|
|
|
#if EFI_CAN_SUPPORT && EFI_PROD_CODE |
343 |
|
|
|
addConsoleActionII("qc_etb", [](int index, int direction) { |
344 |
|
|
|
qcSetEtbState(index, direction); |
345 |
|
|
|
}); |
346 |
|
|
|
|
347 |
|
|
|
addConsoleActionI("qc_output", [](int index) { |
348 |
|
|
|
Gpio* boardOutputs = getBoardMetaOutputs(); |
349 |
|
|
|
criticalAssertVoid(boardOutputs != nullptr, "outputs not defined"); |
350 |
|
|
|
Gpio pin = boardOutputs[index]; |
351 |
|
|
|
efiSetPadModeWithoutOwnershipAcquisition("qc_output", pin, PAL_MODE_OUTPUT_PUSHPULL); |
352 |
|
|
|
|
353 |
|
|
|
int physicalValue = palReadPad(getHwPort("read", pin), getHwPin("read", pin)); |
354 |
|
|
|
efiPrintf("original pin %s value %d", hwPortname(pin), physicalValue); |
355 |
|
|
|
palWritePad(getHwPort("write", pin), getHwPin("write", pin), 1 - physicalValue); |
356 |
|
|
|
sendManualPinTest(index); |
357 |
|
|
|
}); |
358 |
|
|
|
#endif // EFI_PROD_CODE |
359 |
|
|
✗ |
} |
360 |
|
|
|
|