GCC Code Coverage Report


Directory: ./
File: firmware/controllers/lua/lua_hooks.cpp
Date: 2025-10-03 00:57:22
Coverage Exec Excl Total
Lines: 81.8% 180 0 220
Functions: 42.0% 29 0 69
Branches: 81.8% 189 0 231
Decisions: 71.4% 20 - 28

Line Branch Decision Exec Source
1 #include "pch.h"
2
3 #include "rusefi_lua.h"
4 #include "lua_hooks.h"
5
6 #include "lua_biquad.h"
7 #include "fuel_math.h"
8 #include "airmass.h"
9 #include "lua_airmass.h"
10 #include "value_lookup.h"
11 #include "can_filter.h"
12 #include "tunerstudio.h"
13 #include "lua_pid.h"
14 #include "start_stop.h"
15 #include "tinymt32.h" // TL,DR: basic implementation of 'random'
16 #include "signaldebounce.h"
17
18 #if EFI_PROD_CODE && HW_HELLEN
19 #include "hellen_meta.h"
20 #endif
21
22 #if EFI_DAC
23 #include "dac.h"
24 #endif // EFI_DAC
25
26 #if EFI_CAN_SUPPORT || EFI_UNIT_TEST
27 #include "can_msg_tx.h"
28 #endif // EFI_CAN_SUPPORT
29 #include "settings.h"
30 #include <new>
31
32 // We don't want to try and use the STL on a microcontroller
33 #define LUAAA_WITHOUT_CPP_STDLIB
34 #include "luaaa.hpp"
35 #include "lua_hooks_util.h"
36 using namespace luaaa;
37
38 #include "script_impl.h"
39 #include "trigger_emulator_algo.h"
40
41 #if EFI_PROD_CODE
42 #include "electronic_throttle.h"
43 #endif // EFI_PROD_CODE
44
45 #if EFI_SENT_SUPPORT
46 #include "sent.h"
47 #endif // EFI_SENT_SUPPORT
48
49 1 static int lua_vin(lua_State* l) {
50 1 auto zeroBasedCharIndex = luaL_checkinteger(l, 1);
51
2/4
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 1 time.
1 if (zeroBasedCharIndex < 0 || zeroBasedCharIndex > VIN_NUMBER_SIZE) {
52 lua_pushnil(l);
53 } else {
54 1 char value = engineConfiguration->vinNumber[zeroBasedCharIndex];
55 1 lua_pushinteger(l, value);
56 }
57 1 return 1;
58 }
59
60 static int lua_readpin(lua_State* l) {
61 #if EFI_PROD_CODE
62 const char * msg = luaL_checkstring(l, 1);
63 brain_pin_e pin = parseBrainPin(msg);
64 if (!isBrainPinValid(pin)) {
65 efiPrintf("LUA: invalid pin [%s]", msg);
66 lua_pushnil(l);
67 } else {
68 int physicalValue = palReadPad(getHwPort("read", pin), getHwPin("read", pin));
69 lua_pushinteger(l, physicalValue);
70 }
71 #else
72 UNUSED(l);
73 #endif
74 return 1;
75 }
76
77 6 static int getSensor(lua_State* l, SensorType type) {
78
1/1
✓ Branch 2 taken 6 times.
6 auto result = Sensor::get(type);
79
80
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
2/2
✓ Decision 'true' taken 3 times.
✓ Decision 'false' taken 3 times.
6 if (result) {
81 // return value if valid
82
1/1
✓ Branch 1 taken 3 times.
3 lua_pushnumber(l, result.Value);
83 } else {
84 // return nil if invalid
85
1/1
✓ Branch 1 taken 3 times.
3 lua_pushnil(l);
86 }
87
88 6 return 1;
89 }
90
91 static int lua_getAuxAnalog(lua_State* l) {
92 // todo: shall we use HUMAN_OFFSET since UI goes from 1 and Lua loves going from 1?
93 auto zeroBasedSensorIndex = luaL_checkinteger(l, 1);
94
95 auto type = static_cast<SensorType>(zeroBasedSensorIndex + static_cast<int>(SensorType::AuxAnalog1));
96
97 return getSensor(l, type);
98 }
99
100 2 static int lua_getSensorByIndex(lua_State* l) {
101 2 auto zeroBasedSensorIndex = luaL_checkinteger(l, 1);
102
103 2 return getSensor(l, static_cast<SensorType>(zeroBasedSensorIndex));
104 }
105
106 6 static SensorType findSensorByName(lua_State* l, const char* name) {
107 6 SensorType type = findSensorTypeByName(name);
108
109
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 6 times.
6 if (l && type == SensorType::Invalid) {
110 luaL_error(l, "Invalid sensor type: %s", name);
111 }
112
113 6 return type;
114 }
115
116 4 static int lua_getSensorByName(lua_State* l) {
117 4 auto sensorName = luaL_checklstring(l, 1, nullptr);
118 4 SensorType type = findSensorByName(l, sensorName);
119
120 4 return getSensor(l, type);
121 }
122
123 static int lua_getSensorRaw(lua_State* l) {
124 auto zeroBasedSensorIndex = luaL_checkinteger(l, 1);
125
126 lua_pushnumber(l, Sensor::getRaw(static_cast<SensorType>(zeroBasedSensorIndex)));
127 return 1;
128 }
129
130 static int lua_hasSensor(lua_State* l) {
131 auto zeroBasedSensorIndex = luaL_checkinteger(l, 1);
132
133 lua_pushboolean(l, Sensor::hasSensor(static_cast<SensorType>(zeroBasedSensorIndex)));
134 return 1;
135 }
136
137 /**
138 * @return number of elements
139 */
140 3 uint32_t getLuaArray(lua_State* l, int paramIndex, uint8_t *data, uint32_t size) {
141 3 uint32_t result = 0;
142
143 3 luaL_checktype(l, paramIndex, LUA_TTABLE);
144 while (true) {
145 20 lua_pushnumber(l, result + 1);
146 20 auto elementType = lua_gettable(l, paramIndex);
147 20 auto val = lua_tonumber(l, -1);
148 20 lua_pop(l, 1);
149
150
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 17 times.
2/2
✓ Decision 'true' taken 3 times.
✓ Decision 'false' taken 17 times.
20 if (elementType == LUA_TNIL) {
151 // we're done, this is the end of the array.
152 3 break;
153 }
154
155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 17 times.
17 if (elementType != LUA_TNUMBER) {
156 // We're not at the end, but this isn't a number!
157 luaL_error(l, "Unexpected data at position %d: %s", result, lua_tostring(l, -1));
158 }
159
160 // This element is valid, increment DLC
161 17 result++;
162
163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 17 times.
17 if (result > size) {
164 luaL_error(l, "Input array longer than buffer");
165 }
166 else {
167 17 data[result - 1] = val;
168 }
169 17 }
170 3 return result;
171 }
172
173 #if EFI_CAN_SUPPORT || EFI_UNIT_TEST
174
175 12 static int validateCanChannelAndConvertFromHumanIntoZeroIndex(lua_State* l) {
176 12 lua_Integer channel = luaL_checkinteger(l, 1);
177
5/8
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 11 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
12 luaL_argcheck(l, channel >= 1 && channel <= CANBUS_COUNT, 1, "Invalid bus index");
178 11 return channel - HUMAN_OFFSET;
179 }
180
181 12 static int lua_txCan(lua_State* l) {
182 12 ScopePerf perf(PE::LuaOneCanTxFunction);
183 int bus;
184 int id;
185 int ext;
186 int dataIndex;
187
2/3
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 12 times.
12 if (lua_gettop(l) == 2) {
188 bus = 0;
189 id = luaL_checkinteger(l, 1);
190 ext = 0;
191 dataIndex = 2;
192 } else {
193
1/1
✓ Branch 1 taken 11 times.
12 bus = validateCanChannelAndConvertFromHumanIntoZeroIndex(l);
194
1/1
✓ Branch 1 taken 11 times.
11 id = luaL_checkinteger(l, 2);
195
1/1
✓ Branch 1 taken 11 times.
11 ext = luaL_checkinteger(l, 3);
196 11 dataIndex = 4;
197 }
198
199 // Check that ID is valid based on std vs. ext
200
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
2/2
✓ Decision 'true' taken 9 times.
✓ Decision 'false' taken 2 times.
11 if (ext == 0) {
201
2/5
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
9 luaL_argcheck(l, id <= 0x7FF, 2, "ID specified is greater than max std ID");
202 } else {
203
2/5
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
2 luaL_argcheck(l, id <= 0x1FFF'FFFF, 2, "ID specified is greater than max ext ID");
204 }
205
206 // conform ext parameter to true/false
207
1/1
✓ Branch 2 taken 9 times.
9 CanTxMessage msg(CanCategory::LUA, id, 8, bus, ext == 0 ? false : true);
208
209 // Unfortunately there is no way to inspect the length of a table,
210 // so we have to just iterate until we run out of numbers
211 9 uint8_t dlc = 0;
212
213 // todo: reduce code duplication with getLuaArray
214
1/1
✓ Branch 1 taken 8 times.
9 luaL_checktype(l, dataIndex, LUA_TTABLE);
215 while (true) {
216
1/1
✓ Branch 1 taken 31 times.
31 lua_pushnumber(l, dlc + 1);
217
1/1
✓ Branch 1 taken 31 times.
31 auto elementType = lua_gettable(l, dataIndex);
218
1/1
✓ Branch 1 taken 31 times.
31 auto val = lua_tonumber(l, -1);
219
1/1
✓ Branch 1 taken 31 times.
31 lua_pop(l, 1);
220
221
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 25 times.
2/2
✓ Decision 'true' taken 6 times.
✓ Decision 'false' taken 25 times.
31 if (elementType == LUA_TNIL) {
222 // we're done, this is the end of the array.
223 6 break;
224 }
225
226
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 24 times.
2/2
✓ Decision 'true' taken 1 time.
✓ Decision 'false' taken 24 times.
25 if (elementType != LUA_TNUMBER) {
227 // We're not at the end, but this isn't a number!
228
1/2
✓ Branch 1 taken 1 time.
✗ Branch 4 not taken.
1 luaL_error(l, "Unexpected CAN data at position %d: %s", dlc, lua_tostring(l, -1));
229 }
230
231 // This element is valid, increment DLC
232 24 dlc++;
233
234
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 23 times.
2/2
✓ Decision 'true' taken 1 time.
✓ Decision 'false' taken 23 times.
24 if (dlc > 8) {
235
0/1
✗ Branch 1 not taken.
1 luaL_error(l, "CAN frame length cannot be longer than 8");
236 }
237
238
1/1
✓ Branch 1 taken 23 times.
23 msg[dlc - 1] = val;
239 23 }
240
241
1/1
✓ Branch 1 taken 6 times.
6 msg.setDlc(dlc);
242
243 // no return value
244 6 return 0;
245 6 }
246 #endif // EFI_CAN_SUPPORT
247
248 static LuaAirmass luaAirmass;
249
250 AirmassModelBase& getLuaAirmassModel() {
251 return luaAirmass;
252 }
253
254 #if !EFI_UNIT_TEST
255 static SimplePwm pwms[LUA_PWM_COUNT];
256
257 struct P {
258 SimplePwm& pwm;
259 lua_Integer idx;
260 };
261
262 static P luaL_checkPwmIndex(lua_State* l, int pos) {
263 auto channel = luaL_checkinteger(l, pos);
264
265 // todo: what a mess :( CAN buses start at 1 and PWM channels start at 0 :(
266 // Ensure channel is valid
267 if (channel < 0 || channel >= LUA_PWM_COUNT) {
268 luaL_error(l, "setPwmDuty invalid channel %d", channel);
269 }
270
271 return { pwms[channel], channel };
272 }
273
274 #ifndef PWM_FREQ_PWM
275 #define PWM_FREQ_PWM 1000
276 #endif
277
278 void startPwm(int index, float freq, float duty) {
279 // clamp to 1..1000 hz, this line would turn 0hz on/off PWM into 1hz behind the scenes
280 freq = clampF(1, freq, 1000);
281
282 brain_pin_e pwmPin = engineConfiguration->luaOutputPins[index];
283
284 startSimplePwmExt(
285 &pwms[index], "lua", &engine->scheduler,
286 pwmPin, &enginePins.luaOutputPins[index],
287 freq, duty
288 );
289
290 efiPrintf("LUA PWM on %s at %f initial duty",
291 hwPortname(pwmPin),
292 PERCENT_MULT * duty);
293 }
294
295 static int lua_startPwm(lua_State* l) {
296 auto p = luaL_checkPwmIndex(l, 1);
297 auto freq = luaL_checknumber(l, 2);
298 auto duty = luaL_checknumber(l, 3);
299
300 if (duty < 0 || duty > PWM_MAX_DUTY) {
301 luaL_error(l, "Duty parameter should be from 0 to 1 got %f", duty);
302 return 0;
303 }
304
305 startPwm(p.idx, freq, duty);
306
307 return 0;
308 }
309
310 void luaDeInitPins() {
311 // Simply de-init all pins - when the script runs again, they will be re-init'd
312 for (size_t i = 0; i < efi::size(enginePins.luaOutputPins); i++) {
313 enginePins.luaOutputPins[i].deInit();
314 }
315 }
316
317 void setPwmDuty(int index, float duty) {
318 // clamp to 0..1
319 duty = clampF(0, duty, 1);
320
321 pwms[index].setSimplePwmDutyCycle(duty);
322 }
323
324 static int lua_setPwmDuty(lua_State* l) {
325 auto p = luaL_checkPwmIndex(l, 1);
326 auto duty = luaL_checknumber(l, 2);
327 setPwmDuty(p.idx, duty);
328
329 return 0;
330 }
331
332 static int lua_setPwmFreq(lua_State* l) {
333 auto p = luaL_checkPwmIndex(l, 1);
334 auto freq = luaL_checknumber(l, 2);
335
336 // clamp to 1..1000 hz
337 freq = clampF(1, freq, 1000);
338
339 p.pwm.setFrequency(freq);
340
341 return 0;
342 }
343
344 static int lua_getDigital(lua_State* l) {
345 auto idx = luaL_checkinteger(l, 1);
346
347 bool state = false;
348
349 switch (idx) {
350 case 0: state = engine->engineState.clutchDownState; break;
351 case 1: state = engine->engineState.clutchUpState; break;
352 case 2: state = engine->engineState.brakePedalState; break;
353 case 3: state = engine->module<AcController>().unmock().acButtonState; break;
354 default:
355 // Return nil to indicate invalid parameter
356 lua_pushnil(l);
357 return 1;
358 }
359
360 lua_pushboolean(l, state);
361 return 1;
362 }
363
364 bool getAuxDigital(int index) {
365 #if EFI_PROD_CODE
366 return efiReadPin(engineConfiguration->luaDigitalInputPins[index]);
367 #else
368 UNUSED(index);
369 return false;
370 #endif
371 }
372
373 static int lua_getAuxDigital(lua_State* l) {
374 auto idx = luaL_checkinteger(l, 1);
375 if (idx < 0 || idx >= LUA_DIGITAL_INPUT_COUNT) {
376 // Return nil to indicate invalid parameter
377 lua_pushnil(l);
378 return 1;
379 }
380
381 if (!isBrainPinValid(engineConfiguration->luaDigitalInputPins[idx])) {
382 // Return nil to indicate invalid pin
383 lua_pushnil(l);
384 return 1;
385 }
386
387 #if !EFI_SIMULATOR
388 bool state = getAuxDigital(idx);
389 lua_pushboolean(l, state);
390 #endif // !EFI_SIMULATOR
391
392 return 1;
393 }
394
395 static int lua_setDebug(lua_State* l) {
396 // wrong debug mode, ignore
397 if (engineConfiguration->debugMode != DBG_LUA) {
398 return 0;
399 }
400
401 auto idx = luaL_checkinteger(l, 1);
402 auto val = luaL_checknumber(l, 2);
403
404 // invalid index, ignore
405 if (idx < 1 || idx > 7) {
406 return 0;
407 }
408
409 auto firstDebugField = &engine->outputChannels.debugFloatField1;
410 firstDebugField[idx - 1] = val;
411
412 return 0;
413 }
414
415 #if EFI_ENGINE_CONTROL
416 static auto lua_getAirmassResolveMode(lua_State* l) {
417 if (lua_gettop(l) == 0) {
418 // zero args, return configured mode
419 return engineConfiguration->fuelAlgorithm;
420 } else {
421 return static_cast<engine_load_mode_e>(luaL_checkinteger(l, 1));
422 }
423 }
424
425 static int lua_getAirmass(lua_State* l) {
426 auto airmassMode = lua_getAirmassResolveMode(l);
427 auto airmass = getAirmassModel(airmassMode);
428
429 if (!airmass) {
430 return luaL_error(l, "null airmass");
431 }
432
433 auto rpm = Sensor::getOrZero(SensorType::Rpm);
434 auto result = airmass->getAirmass(rpm, false).CylinderAirmass;
435
436 lua_pushnumber(l, result);
437 return 1;
438 }
439
440 static int lua_setAirmass(lua_State* l) {
441 float airmass = luaL_checknumber(l, 1);
442 float engineLoadPercent = luaL_checknumber(l, 2);
443
444 airmass = clampF(0, airmass, 10);
445 engineLoadPercent = clampF(0, engineLoadPercent, 1000);
446
447 luaAirmass.setAirmass({airmass, engineLoadPercent});
448
449 return 0;
450 }
451 #endif // EFI_ENGINE_CONTROL
452
453 #endif // EFI_UNIT_TEST
454
455 // TODO: PR this back in to https://github.com/gengyong/luaaa
456 namespace LUAAA_NS {
457 template<typename TCLASS, typename ...ARGS>
458 struct PlacementConstructorCaller<TCLASS, lua_State*, ARGS...>
459 {
460 // this speciailization passes the Lua state to the constructor as first argument, as it shouldn't
461 // participate in the index generation as it's not a normal parameter passed via the Lua stack.
462
463
1/1
✓ Decision 'true' taken 2 times.
2 static TCLASS * Invoke(lua_State * state, void * mem)
464 {
465 2 return InvokeImpl(state, mem, typename make_indices<sizeof...(ARGS)>::type());
466 }
467
468 private:
469 template<std::size_t ...Ns>
470 2 static TCLASS * InvokeImpl(lua_State * state, void * mem, indices<Ns...>)
471 {
472 (void)state;
473
2/4
✓ Branch 2 taken 2 times.
✓ Branch 5 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
2 return new(mem) TCLASS(state, LuaStack<ARGS>::get(state, Ns + 1)...);
474 }
475 };
476 }
477
478 struct LuaSensor final : public StoredValueSensor {
479 LuaSensor() : LuaSensor(nullptr, "Invalid") { }
480
481 2 ~LuaSensor() {
482 2 unregister();
483 2 }
484
485 2 LuaSensor(lua_State* l, const char* name)
486 2 : StoredValueSensor(findSensorByName(l, name), MS2NT(100))
487 {
488 // do a soft collision check to avoid a fatal error from the hard check in Register()
489
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 2 times.
2 if (l && Sensor::hasSensor(type())) {
490 luaL_error(l, "Tried to create a Lua sensor of type %s, but one was already registered.", getSensorName());
491 } else {
492 2 Register();
493 2 efiPrintf("LUA registered sensor of type %s", getSensorName());
494 }
495 2 }
496
497 bool isRedundant() const override {
498 return m_isRedundant;
499 }
500
501 // do we need method defined exactly on LuaSensor for Luaa to be happy?
502 1 void setTimeout(int timeoutMs) override {
503 1 StoredValueSensor::setTimeout(timeoutMs);
504 1 }
505
506 void setRedundant(bool value) {
507 m_isRedundant = value;
508 }
509
510 1 void set(float value) {
511 1 setValidValue(value, getTimeNowNt());
512 1 }
513
514 1 void invalidate() {
515 1 StoredValueSensor::invalidate();
516 1 }
517
518 void showInfo(const char* sensorName) const override {
519 const auto value = get();
520 efiPrintf("Sensor \"%s\": Lua sensor: Valid: %s Converted value %.2f", sensorName, boolToString(value.Valid), value.Value);
521 }
522
523 private:
524 bool m_isRedundant = false;
525 };
526
527 static bool isFunction(lua_State* l, int idx) {
528 return lua_type(l, idx) == LUA_TFUNCTION;
529 }
530
531 int getLuaFunc(lua_State* l) {
532 if (!isFunction(l, 1)) {
533 return luaL_error(l, "expected function");
534 } else {
535 return luaL_ref(l, LUA_REGISTRYINDEX);
536 }
537 }
538
539 #if EFI_CAN_SUPPORT
540 int lua_canRxAdd(lua_State* l) {
541 uint32_t eid;
542
543 // defaults if not passed
544 int bus = ANY_BUS;
545 int callback = NO_CALLBACK;
546 int argumentCount = lua_gettop(l);
547
548 switch (argumentCount) {
549 case 1:
550 // handle canRxAdd(id)
551 eid = luaL_checkinteger(l, 1);
552 break;
553
554 case 2:
555 if (isFunction(l, 2)) {
556 // handle canRxAdd(id, callback)
557 eid = luaL_checkinteger(l, 1);
558 lua_remove(l, 1);
559 callback = getLuaFunc(l);
560 } else {
561 // handle canRxAdd(bus, id)
562 bus = validateCanChannelAndConvertFromHumanIntoZeroIndex(l);
563 eid = luaL_checkinteger(l, 2);
564 }
565
566 break;
567 case 3:
568 // handle canRxAdd(bus, id, callback)
569 bus = validateCanChannelAndConvertFromHumanIntoZeroIndex(l);
570 eid = luaL_checkinteger(l, 2);
571 lua_remove(l, 1);
572 lua_remove(l, 1);
573 callback = getLuaFunc(l);
574 break;
575 default:
576 return luaL_error(l, "Wrong number of arguments to canRxAdd. Got %d, expected 1, 2, or 3.", argumentCount);
577 }
578
579 addLuaCanRxFilter(eid, FILTER_SPECIFIC, bus, callback);
580
581 return 0;
582 }
583
584 int lua_canRxAddMask(lua_State* l) {
585 uint32_t eid;
586 uint32_t mask;
587
588 // defaults if not passed
589 int bus = ANY_BUS;
590 int callback = NO_CALLBACK;
591
592 switch (lua_gettop(l)) {
593 case 2:
594 // handle canRxAddMask(id, mask)
595 eid = luaL_checkinteger(l, 1);
596 mask = luaL_checkinteger(l, 2);
597 break;
598
599 case 3:
600 if (isFunction(l, 3)) {
601 // handle canRxAddMask(id, mask, callback)
602 eid = luaL_checkinteger(l, 1);
603 mask = luaL_checkinteger(l, 2);
604 lua_remove(l, 1);
605 lua_remove(l, 1);
606 callback = getLuaFunc(l);
607 } else {
608 // handle canRxAddMask(bus, id, mask)
609 bus = validateCanChannelAndConvertFromHumanIntoZeroIndex(l);
610 eid = luaL_checkinteger(l, 2);
611 mask = luaL_checkinteger(l, 3);
612 }
613
614 break;
615 case 4:
616 // handle canRxAddMask(bus, id, mask, callback)
617 bus = validateCanChannelAndConvertFromHumanIntoZeroIndex(l);
618 eid = luaL_checkinteger(l, 2);
619 mask = luaL_checkinteger(l, 3);
620 lua_remove(l, 1);
621 lua_remove(l, 1);
622 lua_remove(l, 1);
623 callback = getLuaFunc(l);
624 break;
625 default:
626 return luaL_error(l, "Wrong number of arguments to canRxAddMask. Got %d, expected 2, 3, or 4.");
627 }
628
629 addLuaCanRxFilter(eid, mask, bus, callback);
630
631 return 0;
632 }
633 #endif // EFI_CAN_SUPPORT
634
635
1/1
✓ Decision 'true' taken 309 times.
309 PUBLIC_API_WEAK void boardConfigureLuaHooks(lua_State* lState) {
636 UNUSED(lState);
637 309 }
638
639 static tinymt32_t tinymt;
640
641 309 void configureRusefiLuaHooks(lua_State* lState) {
642
1/1
✓ Branch 1 taken 309 times.
309 boardConfigureLuaHooks(lState);
643
644
1/1
✓ Branch 1 taken 309 times.
309 tinymt32_init(&tinymt, 1534525); // todo: share instance with launch_control? probably not?
645
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "random", [](lua_State* l) {
646 auto random = tinymt32_generate_float(&tinymt);
647 lua_pushnumber(l, random);
648 return 1;
649 });
650
651
1/1
✓ Branch 2 taken 309 times.
309 LuaClass<Timer> luaTimer(lState, "Timer");
652 luaTimer
653
1/1
✓ Branch 1 taken 309 times.
309 .ctor()
654 618 .fun("reset", static_cast<void (Timer::*)() >(&Timer::reset ))
655
2/2
✓ Branch 1 taken 309 times.
✓ Branch 4 taken 309 times.
309 .fun("getElapsedSeconds", static_cast<float(Timer::*)()const>(&Timer::getElapsedSeconds));
656
657
1/1
✓ Branch 2 taken 309 times.
309 LuaClass<LuaSensor> luaSensor(lState, "Sensor");
658 luaSensor
659
1/1
✓ Branch 1 taken 309 times.
309 .ctor<lua_State*, const char*>()
660
1/1
✓ Branch 1 taken 309 times.
309 .fun("set", &LuaSensor::set)
661
1/1
✓ Branch 1 taken 309 times.
309 .fun("setRedundant", &LuaSensor::setRedundant)
662
1/1
✓ Branch 1 taken 309 times.
309 .fun("setTimeout", &LuaSensor::setTimeout)
663
1/1
✓ Branch 1 taken 309 times.
309 .fun("invalidate", &LuaSensor::invalidate);
664
665 #ifndef WITH_LUA_PID
666 #define WITH_LUA_PID TRUE
667 #endif
668
669 #if WITH_LUA_PID
670
1/1
✓ Branch 2 taken 309 times.
309 LuaClass<LuaBiQuad> biQuard(lState, "Biquad");
671 biQuard
672
1/1
✓ Branch 1 taken 309 times.
309 .ctor()
673
1/1
✓ Branch 1 taken 309 times.
309 .fun("filter", &LuaBiQuad::filter)
674
1/1
✓ Branch 1 taken 309 times.
309 .fun("configureLowpass", &LuaBiQuad::configureLowpass);
675
676
1/1
✓ Branch 2 taken 309 times.
309 LuaClass<LuaPid> luaPid(lState, "Pid");
677 luaPid
678
1/1
✓ Branch 1 taken 309 times.
309 .ctor<float, float, float, float, float>()
679
1/1
✓ Branch 1 taken 309 times.
309 .fun("get", &LuaPid::get)
680
1/1
✓ Branch 1 taken 309 times.
309 .fun("setOffset", &LuaPid::setOffset)
681
1/1
✓ Branch 1 taken 309 times.
309 .fun("reset", &LuaPid::reset);
682
683
1/1
✓ Branch 2 taken 309 times.
309 LuaClass<LuaIndustrialPid> luaIndustrialPid(lState, "IndustrialPid");
684 luaIndustrialPid
685
1/1
✓ Branch 1 taken 309 times.
309 .ctor<float, float, float, float, float>()
686
1/1
✓ Branch 1 taken 309 times.
309 .fun("get", &LuaIndustrialPid::get)
687
1/1
✓ Branch 1 taken 309 times.
309 .fun("setOffset", &LuaIndustrialPid::setOffset)
688
1/1
✓ Branch 1 taken 309 times.
309 .fun("setDerivativeFilterLoss", &LuaIndustrialPid::setDerivativeFilterLoss)
689
1/1
✓ Branch 1 taken 309 times.
309 .fun("setAntiwindupFreq", &LuaIndustrialPid::setAntiwindupFreq)
690
1/1
✓ Branch 1 taken 309 times.
309 .fun("reset", &LuaIndustrialPid::reset);
691 #endif
692
693
1/1
✓ Branch 1 taken 309 times.
309 configureRusefiLuaUtilHooks(lState);
694
695
2/2
✓ Branch 1 taken 309 times.
✓ Branch 4 taken 309 times.
309 lua_register(lState, "readPin", lua_readpin);
696 #if EFI_PROD_CODE && EFI_SHAFT_POSITION_INPUT
697 lua_register(lState, "startCrankingEngine", [](lua_State* l) {
698 doStartCranking();
699 return 0;
700 });
701 #endif // EFI_PROD_CODE && EFI_SHAFT_POSITION_INPUT
702
2/2
✓ Branch 1 taken 309 times.
✓ Branch 4 taken 309 times.
309 lua_register(lState, "vin", lua_vin);
703
704
2/2
✓ Branch 1 taken 309 times.
✓ Branch 4 taken 309 times.
309 lua_register(lState, "getAuxAnalog", lua_getAuxAnalog);
705
2/2
✓ Branch 1 taken 309 times.
✓ Branch 4 taken 309 times.
309 lua_register(lState, "getSensorByIndex", lua_getSensorByIndex);
706
2/2
✓ Branch 1 taken 309 times.
✓ Branch 4 taken 309 times.
309 lua_register(lState, "getSensor", lua_getSensorByName);
707
2/2
✓ Branch 1 taken 309 times.
✓ Branch 4 taken 309 times.
309 lua_register(lState, "getSensorRaw", lua_getSensorRaw);
708
2/2
✓ Branch 1 taken 309 times.
✓ Branch 4 taken 309 times.
309 lua_register(lState, "hasSensor", lua_hasSensor);
709
710 #ifndef WITH_LUA_CONSUMPTION
711 #define WITH_LUA_CONSUMPTION TRUE
712 #endif
713
714 #if EFI_VEHICLE_SPEED && WITH_LUA_CONSUMPTION && defined (MODULE_ODOMETER)
715
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "getConsumedGrams", [](lua_State* l) {
716 lua_pushnumber(l, engine->module<TripOdometer>()->getConsumedGrams());
717 return 1;
718 });
719
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "getConsumedGramsRemainder", [](lua_State* l) {
720 lua_pushnumber(l, engine->module<TripOdometer>()->getConsumedGramsRemainder());
721 return 1;
722 });
723
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "getConsumptionGramPerSecond", [](lua_State* l) {
724 lua_pushnumber(l, engine->module<TripOdometer>()->getConsumptionGramPerSecond());
725 return 1;
726 });
727
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "resetOdometer", [](lua_State*) {
728 engine->module<TripOdometer>()->reset();
729 return 0;
730 });
731 #endif // EFI_VEHICLE_SPEED WITH_LUA_CONSUMPTION MODULE_ODOMETER
732
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
311 lua_register(lState, "table3d", [](lua_State* l) {
733 auto humanTableIdx = luaL_checkinteger(l, 1);
734 auto x = luaL_checknumber(l, 2);
735 auto y = luaL_checknumber(l, 3);
736
737 // index table, compute table lookup
738 auto result = getscriptTable(humanTableIdx - HUMAN_OFFSET)->getValue(x, y);
739
740 lua_pushnumber(l, result);
741 return 1;
742 });
743 // time since console or TunerStudio
744
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "secondsSinceTsActivity", [](lua_State* l) {
745 lua_pushinteger(l, getSecondsSinceChannelsRequest());
746 return 1;
747 });
748
749
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
310 lua_register(lState, "curve", [](lua_State* l) {
750 // index starting from 1
751 auto humanCurveIdx = luaL_checkinteger(l, 1);
752 auto x = luaL_checknumber(l, 2);
753
754 auto result = getCurveValue(humanCurveIdx - HUMAN_OFFSET, x);
755
756 lua_pushnumber(l, result);
757 return 1;
758 });
759
760 #if EFI_PROD_CODE || EFI_SIMULATOR
761 extern int luaCommandCounters[LUA_BUTTON_COUNT];
762
763 lua_register(lState, "getTsButtonCount",
764 [](lua_State* l) {
765 auto humanIndex = luaL_checkinteger(l, 1);
766 if (humanIndex < 1 || humanIndex > LUA_BUTTON_COUNT) {
767 luaL_error(l, "Invalid button index: %d", humanIndex);
768 return 0;
769 }
770 lua_pushinteger(l, luaCommandCounters[humanIndex - 1]);
771 return 1;
772 });
773 #endif // EFI_PROD_CODE || EFI_SIMULATOR
774
775 #if EFI_PROD_CODE && EFI_SENT_SUPPORT
776 lua_register(lState, "getSentValue",
777 [](lua_State* l) {
778 auto humanIndex = luaL_checkinteger(l, 1);
779 auto value = getSentValue(static_cast<SentInput>(humanIndex));
780 lua_pushnumber(l, value);
781 return 1;
782 });
783
784 lua_register(lState, "getSentValues",
785 [](lua_State* l) {
786 uint16_t sig0;
787 uint16_t sig1;
788 auto humanIndex = luaL_checkinteger(l, 1);
789 /*auto ret = */getSentValues(static_cast<SentInput>(humanIndex), &sig0, &sig1);
790 lua_pushinteger(l, sig0);
791 lua_pushinteger(l, sig1);
792 return 2;
793 });
794 #endif // EFI_SENT_SUPPORT
795
796 #if EFI_LAUNCH_CONTROL
797
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
312 lua_register(lState, "setSparkSkipRatio", [](lua_State* l) {
798 auto targetSkipRatio = luaL_checknumber(l, 1);
799 engine->engineState.luaSoftSparkSkip = targetSkipRatio;
800 engine->engineState.updateSparkSkip();
801 return 0;
802 });
803
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
312 lua_register(lState, "setSparkHardSkipRatio", [](lua_State* l) {
804 auto targetSkipRatio = luaL_checknumber(l, 1);
805 engine->engineState.luaHardSparkSkip = targetSkipRatio;
806 engine->engineState.updateSparkSkip();
807 return 0;
808 });
809
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "setLaunchTrigger", [](lua_State* l) {
810 auto value = luaL_checkinteger(l, 1);
811 engine->launchController.luaLaunchState = value;
812 return 0;
813 });
814 #endif // EFI_LAUNCH_CONTROL
815 #if EFI_ANTILAG_SYSTEM
816
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "setRollingIdleTrigger", [](lua_State* l) {
817 auto value = luaL_checkinteger(l, 1);
818 engine->antilagController.luaAntilagState = value;
819 return 0;
820 });
821 #endif // EFI_ANTILAG_SYSTEM
822
823 #if EFI_EMULATE_POSITION_SENSORS && !EFI_UNIT_TEST
824 lua_register(lState, "selfStimulateRPM", [](lua_State* l) {
825 auto rpm = luaL_checkinteger(l, 1);
826 if (rpm < 1) {
827 disableTriggerStimulator();
828 return 0;
829 }
830 if (!engine->triggerCentral.directSelfStimulation) {
831 enableTriggerStimulator();
832 }
833 setTriggerEmulatorRPM(rpm);
834 return 0;
835 });
836 #endif // EFI_UNIT_TEST
837
838 /**
839 * same exact could be accomplished via LuaSensor just with more API
840 */
841
2/6
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
309 lua_register(lState, "setLuaGauge", [](lua_State* l) {
842 auto index = luaL_checkinteger(l, 1) - 1;
843 auto value = luaL_checknumber(l, 2);
844 if (index < 0 || index >= LUA_GAUGE_COUNT)
845 return 0;
846 extern StoredValueSensor luaGauges[LUA_GAUGE_COUNT];
847 luaGauges[index].setValidValue(value, getTimeNowNt());
848 return 0;
849 });
850
851
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "enableCanTx", [](lua_State* l) {
852 engine->allowCanTx = lua_toboolean(l, 1);
853 return 0;
854 });
855
856
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "enableCanRxWorkaround", [](lua_State*) {
857 // that's about global_can_data
858 engineConfiguration->luaCanRxWorkaround = true;
859 return 0;
860 });
861 // high-performance CANbus should be done on F7+, let's preserve couple of priceless bytes on F4
862 #if !defined(STM32F4)
863 #if EFI_CAN_SUPPORT
864 lua_register(lState, "getCanRxDropped", [](lua_State* l) {
865 auto count = getLuaCanRxDropped();
866 lua_pushinteger(l, count);
867 return 1;
868 });
869 #endif // EFI_CAN_SUPPORT
870
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "disableExtendedCanBroadcast", [](lua_State*) {
871 // that's about global_can_data
872 engineConfiguration->enableExtendedCanBroadcast = false;
873 return 0;
874 });
875
2/4
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
309 lua_register(lState, "getCanBaudRate", [](lua_State* l) {
876 auto index = luaL_checkinteger(l, 1);
877 if (index == 1) {
878 lua_pushinteger(l, engineConfiguration->canBaudRate);
879 } else {
880 lua_pushinteger(l, engineConfiguration->can2BaudRate);
881 }
882 return 1;
883 });
884 #endif // STM32F4
885
886 #if !defined(STM32F4) || defined(WITH_LUA_GET_GPPWM_STATE)
887
2/4
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
✗ Branch 11 not taken.
✗ Branch 17 not taken.
309 lua_register(lState, "getGpPwm", [](lua_State* l) {
888 auto index = luaL_checkinteger(l, 1);
889 // this works due to updateGppwm being invoked from periodicSlowCallback
890 auto result = engine->outputChannels.gppwmOutput[index];
891 lua_pushnumber(l, result);
892 return 1;
893 });
894 #endif
895
896 #if EFI_ELECTRONIC_THROTTLE_BODY && EFI_PROD_CODE
897 lua_register(lState, "getEtbTarget", [](lua_State* l) {
898 auto controller = engine->etbControllers[0];
899 assertNotNull(controller, 0);
900 auto result = controller->getCurrentTarget();
901 lua_pushnumber(l, result);
902 return 1;
903 });
904 lua_register(lState, "restartEtb", [](lua_State*) {
905 // this is about Lua sensor acting in place of real analog PPS sensor
906 // todo: smarter implementation
907 doInitElectronicThrottle(true); // lame, we run with 'isStartupInit=true' in order to reset, NOT COOL
908 return 0;
909 });
910 #endif // EFI_ELECTRONIC_THROTTLE_BODY
911
912 // checksum stuff
913
7/7
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
✓ Branch 12 taken 3 times.
✓ Branch 15 taken 3 times.
✓ Branch 18 taken 3 times.
✓ Branch 21 taken 3 times.
✓ Branch 24 taken 3 times.
315 lua_register(lState, "crc8_j1850", [](lua_State* l) {
914 uint8_t data[8];
915 uint32_t length = getLuaArray(l, 1, data, sizeof(data));
916 auto trimLength = luaL_checkinteger(l, 2);
917 int crc = crc8(data, minI(length, trimLength));
918
919 lua_pushinteger(l, crc);
920 return 1;
921 });
922
923 #if EFI_BOOST_CONTROL
924
2/4
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
✗ Branch 12 not taken.
✗ Branch 16 not taken.
309 lua_register(lState, "setBoostTargetAdd", [](lua_State* l) {
925 engine->module<BoostController>().unmock().luaTargetAdd = luaL_checknumber(l, 1);
926 return 0;
927 });
928
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "setBoostTargetMult", [](lua_State* l) {
929 engine->module<BoostController>().unmock().luaTargetMult = luaL_checknumber(l, 1);
930 return 0;
931 });
932
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "setBoostDutyAdd", [](lua_State* l) {
933 engine->module<BoostController>().unmock().luaOpenLoopAdd = luaL_checknumber(l, 1);
934 return 0;
935 });
936 #endif // EFI_BOOST_CONTROL
937 #if EFI_IDLE_CONTROL
938
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "setIdleAdd", [](lua_State* l) {
939 engine->module<IdleController>().unmock().luaAdd = luaL_checknumber(l, 1);
940 return 0;
941 });
942
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "setIdleRpm", [](lua_State* l) {
943 auto rpm = luaL_checknumber(l, 1);
944 setLinearCurve(config->cltIdleRpm, rpm, rpm, 1);
945 return 0;
946 });
947 #endif
948
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "setTimingAdd", [](lua_State* l) {
949 engine->ignitionState.luaTimingAdd = luaL_checknumber(l, 1);
950 return 0;
951 });
952 #ifndef DISABLE_LUA_SET_TIMING_MULT
953
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "setTimingMult", [](lua_State* l) {
954 engine->ignitionState.luaTimingMult = luaL_checknumber(l, 1);
955 return 0;
956 });
957 #endif // !defined(DISABLE_LUA_SET_TIMING_MULT)
958 #ifndef DISABLE_LUA_SET_FUEL_ADD
959
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
311 lua_register(lState, "setFuelAdd", [](lua_State* l) {
960 engine->engineState.lua.fuelAdd = luaL_checknumber(l, 1);
961 return 0;
962 });
963 #endif // !defined(DISABLE_LUA_SET_FUEL_ADD)
964
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "setFuelMult", [](lua_State* l) {
965 engine->engineState.lua.fuelMult = luaL_checknumber(l, 1);
966 return 0;
967 });
968 #if EFI_ELECTRONIC_THROTTLE_BODY && EFI_PROD_CODE
969 lua_register(lState, "setEtbAdd", [](lua_State* l) {
970 auto luaAdjustment = luaL_checknumber(l, 1);
971
972 setEtbLuaAdjustment(luaAdjustment);
973
974 return 0;
975 });
976 lua_register(lState, "setEwgAdd", [](lua_State* l) {
977 auto luaAdjustment = luaL_checknumber(l, 1);
978
979 setEwgLuaAdjustment(luaAdjustment);
980
981 return 0;
982 });
983 lua_register(lState, "setEtbDisabled", [](lua_State* l) {
984 engine->engineState.lua.luaDisableEtb = lua_toboolean(l, 1);
985 return 0;
986 });
987 #endif // EFI_ELECTRONIC_THROTTLE_BODY
988 #if EFI_PROD_CODE
989 lua_register(lState, "setIgnDisabled", [](lua_State* l) {
990 engine->engineState.lua.luaIgnCut = lua_toboolean(l, 1);
991 return 0;
992 });
993 lua_register(lState, "setFuelDisabled", [](lua_State* l) {
994 engine->engineState.lua.luaFuelCut = lua_toboolean(l, 1);
995 return 0;
996 });
997 lua_register(lState, "setDfcoDisabled", [](lua_State* l) {
998 engine->engineState.lua.disableDecelerationFuelCutOff = lua_toboolean(l, 1);
999 return 0;
1000 });
1001 #endif // EFI_PROD_CODE
1002
1003
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
371 lua_register(lState, "setClutchUpState", [](lua_State* l) {
1004 engine->engineState.lua.clutchUpState = lua_toboolean(l, 1);
1005 return 0;
1006 });
1007
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
371 lua_register(lState, "setClutchDownState", [](lua_State* l) {
1008 engine->engineState.lua.clutchDownState = lua_toboolean(l, 1);
1009 return 0;
1010 });
1011
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "setBrakePedalState", [](lua_State* l) {
1012 engine->engineState.lua.brakePedalState = lua_toboolean(l, 1);
1013 return 0;
1014 });
1015
1016
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "setAcRequestState", [](lua_State* l) {
1017 engine->engineState.lua.acRequestState = lua_toboolean(l, 1);
1018 return 0;
1019 });
1020
1021 #if !defined(STM32F4)
1022
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "getTorque", [](lua_State* l) {
1023 auto rpm = Sensor::getOrZero(SensorType::Rpm);
1024 auto tps = Sensor::getOrZero(SensorType::Tps1);
1025
1026 auto result = interpolate3d(
1027 config->torqueTable,
1028 config->torqueLoadBins, tps,
1029 config->torqueRpmBins, rpm
1030 );
1031 lua_pushnumber(l, result);
1032 return 1;
1033 });
1034 #endif
1035
1036
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
374 lua_register(lState, "setTorqueReductionState", [](lua_State* l) {
1037 engine->engineState.lua.torqueReductionState = lua_toboolean(l, 1);
1038 return 0;
1039 });
1040
1041
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
311 lua_register(lState, "getCalibration", [](lua_State* l) {
1042 auto propertyName = luaL_checklstring(l, 1, nullptr);
1043 auto result = getConfigValueByName(propertyName);
1044 lua_pushnumber(l, result);
1045 return 1;
1046 });
1047
1048 #if EFI_TUNER_STUDIO && (EFI_PROD_CODE || EFI_SIMULATOR)
1049 lua_register(lState, "getOutput", [](lua_State* l) {
1050 auto propertyName = luaL_checklstring(l, 1, nullptr);
1051 // fresh values need to be requested explicitly, there is no periodic invocation of that method
1052 updateTunerStudioState();
1053 auto result = getOutputValueByName(propertyName);
1054 lua_pushnumber(l, result);
1055 return 1;
1056 });
1057 #endif // EFI_PROD_CODE || EFI_SIMULATOR
1058
1059 #if EFI_SHAFT_POSITION_INPUT
1060
2/6
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
309 lua_register(lState, "getEngineState", [](lua_State* l) {
1061 spinning_state_e state = engine->rpmCalculator.getState();
1062 int luaStateCode;
1063 if (state == STOPPED) {
1064 luaStateCode = 0;
1065 } else if (state == RUNNING) {
1066 luaStateCode = 2;
1067 } else {
1068 // spinning-up or cranking
1069 luaStateCode = 1;
1070 }
1071 lua_pushinteger(l, luaStateCode);
1072 return 1;
1073 });
1074 #endif //EFI_SHAFT_POSITION_INPUT
1075
1076
4/6
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
✓ Branch 14 taken 1 time.
✗ Branch 15 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 time.
310 lua_register(lState, "setCalibration", [](lua_State* l) {
1077 auto propertyName = luaL_checklstring(l, 1, nullptr);
1078 auto value = luaL_checknumber(l, 2);
1079 auto incrementVersion = lua_toboolean(l, 3);
1080 bool isGoodName = setConfigValueByName(propertyName, value);
1081 if (isGoodName) {
1082 efiPrintf("LUA: applying [%s][%f]", propertyName, value);
1083 } else {
1084 efiPrintf("LUA: invalid calibration key [%s]", propertyName);
1085 }
1086 if (incrementVersion) {
1087 incrementGlobalConfigurationVersion("lua");
1088 }
1089 return 0;
1090 });
1091
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, CMD_BURNCONFIG, [](lua_State*) {
1092 requestBurn();
1093 return 0;
1094 });
1095
1096
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "getGlobalConfigurationVersion", [](lua_State* l) {
1097 lua_pushinteger(l, engine->getGlobalConfigurationVersion());
1098 return 1;
1099 });
1100
1101
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "setAcDisabled", [](lua_State* l) {
1102 auto value = lua_toboolean(l, 1);
1103 engine->module<AcController>().unmock().isDisabledByLua = value;
1104 return 0;
1105 });
1106
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
309 lua_register(lState, "getTimeSinceAcToggleMs", [](lua_State* l) {
1107 float result = engine->module<AcController>().unmock().timeSinceStateChange.getElapsedSeconds() * 1000;
1108 lua_pushnumber(l, result);
1109 return 1;
1110 });
1111
1112 #if !EFI_UNIT_TEST
1113 lua_register(lState, "startPwm", lua_startPwm);
1114 lua_register(lState, "setPwmDuty", lua_setPwmDuty);
1115 lua_register(lState, "setPwmFreq", lua_setPwmFreq);
1116 lua_register(lState, "getFan", [](lua_State* l) {
1117 lua_pushboolean(l, enginePins.fanRelay.getLogicValue());
1118 return 1;
1119 });
1120 lua_register(lState, "getFan2", [](lua_State* l) {
1121 lua_pushboolean(l, enginePins.fanRelay2.getLogicValue());
1122 return 1;
1123 });
1124 lua_register(lState, "getAcRelay", [](lua_State* l) {
1125 lua_pushboolean(l, enginePins.acRelay.getLogicValue());
1126 return 1;
1127 });
1128 lua_register(lState, "getDigital", lua_getDigital);
1129 lua_register(lState, "getAuxDigital", lua_getAuxDigital);
1130 lua_register(lState, "setDebug", lua_setDebug);
1131 #if EFI_ENGINE_CONTROL
1132 lua_register(lState, "getAirmass", lua_getAirmass);
1133 lua_register(lState, "setAirmass", lua_setAirmass);
1134 #endif // EFI_ENGINE_CONTROL
1135
1136
1137 #ifndef WITH_LUA_STOP_ENGINE
1138 #define WITH_LUA_STOP_ENGINE TRUE
1139 #endif
1140
1141 #if WITH_LUA_STOP_ENGINE
1142 lua_register(lState, "isFirmwareError", [](lua_State* l) {
1143 lua_pushboolean(l, hasFirmwareError());
1144 return 1;
1145 });
1146 #if EFI_SHAFT_POSITION_INPUT
1147 lua_register(lState, "stopEngine", [](lua_State*) {
1148 doScheduleStopEngine(StopRequestedReason::Lua);
1149 return 0;
1150 });
1151 lua_register(lState, "isEngineStopRequested", [](lua_State* l) {
1152 bool result = getLimpManager()->shutdownController.isEngineStop(getTimeNowNt());
1153 lua_pushboolean(l, result);
1154 return 1;
1155 });
1156 lua_register(lState, "getTimeSinceTriggerEventMs", [](lua_State* l) {
1157 int result = engine->triggerCentral.m_lastEventTimer.getElapsedUs() / 1000;
1158 lua_pushinteger(l, result);
1159 return 1;
1160 });
1161 #endif // EFI_SHAFT_POSITION_INPUT
1162 #endif // WITH_LUA_STOP_ENGINE
1163
1164 #if EFI_CAN_SUPPORT
1165 lua_register(lState, "canRxAdd", lua_canRxAdd);
1166 lua_register(lState, "canRxAddMask", lua_canRxAddMask);
1167 #endif // EFI_CAN_SUPPORT
1168 #endif // not EFI_UNIT_TEST
1169
1170 #if EFI_CAN_SUPPORT || EFI_UNIT_TEST
1171
2/2
✓ Branch 1 taken 309 times.
✓ Branch 4 taken 309 times.
309 lua_register(lState, "txCan", lua_txCan);
1172 #endif
1173
1174 #if EFI_PROD_CODE
1175 /* todo: hasCriticalReportFile method #7291
1176 lua_register(lState, "hasCriticalReportFile", [](lua_State*) {
1177 // todo: actual method to scan SD card for error report files
1178 lua_pushinteger(l, hasCriticalReportFile());
1179 return 1;
1180 }
1181 */
1182 #endif // EFI_PROD_CODE
1183
1184 #if EFI_PROD_CODE && HW_HELLEN
1185 lua_register(lState, "hellenEnablePower", [](lua_State*) {
1186 hellenEnableEn("Lua");
1187 return 0;
1188 });
1189 lua_register(lState, "hellenDisablePower", [](lua_State*) {
1190 hellenDisableEn("Lua");
1191 return 0;
1192 });
1193 #endif // HW_HELLEN
1194
1195 #if EFI_DAC
1196 lua_register(lState, "setDacVoltage", [](lua_State* l) {
1197 auto channel = luaL_checkinteger(l, 1);
1198 auto voltage = luaL_checknumber(l, 2);
1199 setDacVoltage(channel, voltage);
1200 return 0;
1201 });
1202 #endif // EFI_DAC
1203
1204
1/1
✓ Branch 2 taken 309 times.
309 LuaClass<SignalDebounce> luaDebounce(lState, "SignalDebounce");
1205 luaDebounce
1206
1/1
✓ Branch 1 taken 309 times.
309 .ctor<float>()
1207
1/1
✓ Branch 1 taken 309 times.
309 .fun("set", &SignalDebounce::set)
1208
1/1
✓ Branch 1 taken 309 times.
309 .fun("get", &SignalDebounce::get);
1209
1210 #if EFI_UNIT_TEST
1211
2/2
✓ Branch 3 taken 309 times.
✓ Branch 6 taken 309 times.
322 lua_register(lState, "advanceTimeUs", [](lua_State *l){
1212 auto us = luaL_checknumber(l, 1);
1213 advanceTimeUs(us);
1214 return 0;
1215 });
1216 #endif // EFI_UNIT_TEST
1217 309 }
1218