rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
lua_hooks.cpp
Go to the documentation of this file.
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
16#if EFI_PROD_CODE && HW_HELLEN
17#include "hellen_meta.h"
18#endif
19
20#if EFI_DAC
21#include "dac.h"
22#endif // EFI_DAC
23
24#if EFI_CAN_SUPPORT || EFI_UNIT_TEST
25#include "can_msg_tx.h"
26#endif // EFI_CAN_SUPPORT
27#include "settings.h"
28#include <new>
29
30// We don't want to try and use the STL on a microcontroller
31#define LUAAA_WITHOUT_CPP_STDLIB
32#include "luaaa.hpp"
33#include "lua_hooks_util.h"
34using namespace luaaa;
35
36#include "script_impl.h"
38
39#if EFI_PROD_CODE
40#include "electronic_throttle.h"
41#endif // EFI_PROD_CODE
42
43#if EFI_SENT_SUPPORT
44#include "sent.h"
45#endif // EFI_SENT_SUPPORT
46
47static int lua_vin(lua_State* l) {
48 auto zeroBasedCharIndex = luaL_checkinteger(l, 1);
49 if (zeroBasedCharIndex < 0 || zeroBasedCharIndex > VIN_NUMBER_SIZE) {
50 lua_pushnil(l);
51 } else {
52 char value = engineConfiguration->vinNumber[zeroBasedCharIndex];
53 lua_pushnumber(l, value);
54 }
55 return 1;
56}
57
58static int lua_readpin(lua_State* l) {
59#if EFI_PROD_CODE
60 const char * msg = luaL_checkstring(l, 1);
62 if (!isBrainPinValid(pin)) {
63 efiPrintf("LUA: invalid pin [%s]", msg);
64 lua_pushnil(l);
65 } else {
66 int physicalValue = palReadPad(getHwPort("read", pin), getHwPin("read", pin));
67 lua_pushnumber(l, physicalValue);
68 }
69#endif
70 return 1;
71}
72
73static int getSensor(lua_State* l, SensorType type) {
74 auto result = Sensor::get(type);
75
76 if (result) {
77 // return value if valid
78 lua_pushnumber(l, result.Value);
79 } else {
80 // return nil if invalid
81 lua_pushnil(l);
82 }
83
84 return 1;
85}
86
87static int lua_getAuxAnalog(lua_State* l) {
88 // todo: shall we use HUMAN_OFFSET since UI goes from 1 and Lua loves going from 1?
89 auto zeroBasedSensorIndex = luaL_checkinteger(l, 1);
90
91 auto type = static_cast<SensorType>(zeroBasedSensorIndex + static_cast<int>(SensorType::AuxAnalog1));
92
93 return getSensor(l, type);
94}
95
96static int lua_getSensorByIndex(lua_State* l) {
97 auto zeroBasedSensorIndex = luaL_checkinteger(l, 1);
98
99 return getSensor(l, static_cast<SensorType>(zeroBasedSensorIndex));
100}
101
102static SensorType findSensorByName(lua_State* l, const char* name) {
103 SensorType type = findSensorTypeByName(name);
104
105 if (l && type == SensorType::Invalid) {
106 luaL_error(l, "Invalid sensor type: %s", name);
107 }
108
109 return type;
110}
111
112static int lua_getSensorByName(lua_State* l) {
113 auto sensorName = luaL_checklstring(l, 1, nullptr);
114 SensorType type = findSensorByName(l, sensorName);
115
116 return getSensor(l, type);
117}
118
119static int lua_getSensorRaw(lua_State* l) {
120 auto zeroBasedSensorIndex = luaL_checkinteger(l, 1);
121
122 lua_pushnumber(l, Sensor::getRaw(static_cast<SensorType>(zeroBasedSensorIndex)));
123 return 1;
124}
125
126static int lua_hasSensor(lua_State* l) {
127 auto zeroBasedSensorIndex = luaL_checkinteger(l, 1);
128
129 lua_pushboolean(l, Sensor::hasSensor(static_cast<SensorType>(zeroBasedSensorIndex)));
130 return 1;
131}
132
133/**
134 * @return number of elements
135 */
136uint32_t getLuaArray(lua_State* l, int paramIndex, uint8_t *data, uint32_t size) {
137 uint32_t result = 0;
138
139 luaL_checktype(l, paramIndex, LUA_TTABLE);
140 while (true) {
141 lua_pushnumber(l, result + 1);
142 auto elementType = lua_gettable(l, paramIndex);
143 auto val = lua_tonumber(l, -1);
144 lua_pop(l, 1);
145
146 if (elementType == LUA_TNIL) {
147 // we're done, this is the end of the array.
148 break;
149 }
150
151 if (elementType != LUA_TNUMBER) {
152 // We're not at the end, but this isn't a number!
153 luaL_error(l, "Unexpected data at position %d: %s", result, lua_tostring(l, -1));
154 }
155
156 // This element is valid, increment DLC
157 result++;
158
159 if (result > size) {
160 luaL_error(l, "Input array longer than buffer");
161 }
162
163 data[result - 1] = val;
164 }
165 return result;
166}
167
168#if EFI_CAN_SUPPORT || EFI_UNIT_TEST
169
171 lua_Integer channel = luaL_checkinteger(l, 1);
172 // TODO: support multiple channels
173 luaL_argcheck(l, channel == 1 || channel == 2, 1, "only buses 1 and 2 currently supported");
174 return channel - HUMAN_OFFSET;
175}
176
177static int lua_txCan(lua_State* l) {
179 int bus;
180 int id;
181 int ext;
182 int dataIndex;
183 if (lua_gettop(l) == 2) {
184 bus = 0;
185 id = luaL_checkinteger(l, 1);
186 ext = 0;
187 dataIndex = 2;
188 } else {
190 id = luaL_checkinteger(l, 2);
191 ext = luaL_checkinteger(l, 3);
192 dataIndex = 4;
193 }
194
195 // Check that ID is valid based on std vs. ext
196 if (ext == 0) {
197 luaL_argcheck(l, id <= 0x7FF, 2, "ID specified is greater than max std ID");
198 } else {
199 luaL_argcheck(l, id <= 0x1FFF'FFFF, 2, "ID specified is greater than max ext ID");
200 }
201
202 // conform ext parameter to true/false
203 CanTxMessage msg(CanCategory::LUA, id, 8, bus, ext == 0 ? false : true);
204
205 // Unfortunately there is no way to inspect the length of a table,
206 // so we have to just iterate until we run out of numbers
207 uint8_t dlc = 0;
208
209 // todo: reduce code duplication with getLuaArray
210 luaL_checktype(l, dataIndex, LUA_TTABLE);
211 while (true) {
212 lua_pushnumber(l, dlc + 1);
213 auto elementType = lua_gettable(l, dataIndex);
214 auto val = lua_tonumber(l, -1);
215 lua_pop(l, 1);
216
217 if (elementType == LUA_TNIL) {
218 // we're done, this is the end of the array.
219 break;
220 }
221
222 if (elementType != LUA_TNUMBER) {
223 // We're not at the end, but this isn't a number!
224 luaL_error(l, "Unexpected CAN data at position %d: %s", dlc, lua_tostring(l, -1));
225 }
226
227 // This element is valid, increment DLC
228 dlc++;
229
230 if (dlc > 8) {
231 luaL_error(l, "CAN frame length cannot be longer than 8");
232 }
233
234 msg[dlc - 1] = val;
235 }
236
237 msg.setDlc(dlc);
238
239 // no return value
240 return 0;
241}
242#endif // EFI_CAN_SUPPORT
243
245
249
250#if !EFI_UNIT_TEST
251static SimplePwm pwms[LUA_PWM_COUNT];
252
253struct P {
254 SimplePwm& pwm;
255 lua_Integer idx;
256};
257
258static P luaL_checkPwmIndex(lua_State* l, int pos) {
259 auto channel = luaL_checkinteger(l, pos);
260
261 // todo: what a mess :( CAN buses start at 1 and PWM channels start at 0 :(
262 // Ensure channel is valid
263 if (channel < 0 || channel >= LUA_PWM_COUNT) {
264 luaL_error(l, "setPwmDuty invalid channel %d", channel);
265 }
266
267 return { pwms[channel], channel };
268}
269
270#ifndef PWM_FREQ_PWM
271#define PWM_FREQ_PWM 1000
272#endif
273
274void startPwm(int index, float freq, float duty) {
275 // clamp to 1..1000 hz, this line would turn 0hz on/off PWM into 1hz behind the scenes
276 freq = clampF(1, freq, 1000);
277
279
281 &pwms[index], "lua", &engine->scheduler,
282 pwmPin, &enginePins.luaOutputPins[index],
283 freq, duty
284 );
285
286 efiPrintf("LUA PWM on %s at %f initial duty",
287 hwPortname(pwmPin),
288 PERCENT_MULT * duty);
289}
290
291static int lua_startPwm(lua_State* l) {
292 auto p = luaL_checkPwmIndex(l, 1);
293 auto freq = luaL_checknumber(l, 2);
294 auto duty = luaL_checknumber(l, 3);
295
296 if (duty < 0 || duty > PWM_MAX_DUTY) {
297 luaL_error(l, "Duty parameter should be from 0 to 1 got %f", duty);
298 return 0;
299 }
300
301 startPwm(p.idx, freq, duty);
302
303 return 0;
304}
305
307 // Simply de-init all pins - when the script runs again, they will be re-init'd
308 for (size_t i = 0; i < efi::size(enginePins.luaOutputPins); i++) {
310 }
311}
312
313void setPwmDuty(int index, float duty) {
314 // clamp to 0..1
315 duty = clampF(0, duty, 1);
316
318}
319
320static int lua_setPwmDuty(lua_State* l) {
321 auto p = luaL_checkPwmIndex(l, 1);
322 auto duty = luaL_checknumber(l, 2);
323 setPwmDuty(p.idx, duty);
324
325 return 0;
326}
327
328static int lua_setPwmFreq(lua_State* l) {
329 auto p = luaL_checkPwmIndex(l, 1);
330 auto freq = luaL_checknumber(l, 2);
331
332 // clamp to 1..1000 hz
333 freq = clampF(1, freq, 1000);
334
335 p.pwm.setFrequency(freq);
336
337 return 0;
338}
339
340static int lua_fan(lua_State* l) {
341 lua_pushboolean(l, enginePins.fanRelay.getLogicValue());
342 return 1;
343}
344
345static int lua_getDigital(lua_State* l) {
346 auto idx = luaL_checkinteger(l, 1);
347
348 bool state = false;
349
350 switch (idx) {
351 case 0: state = engine->engineState.clutchDownState; break;
352 case 1: state = engine->engineState.clutchUpState; break;
353 case 2: state = engine->engineState.brakePedalState; break;
354 case 3: state = engine->module<AcController>().unmock().acButtonState; break;
355 default:
356 // Return nil to indicate invalid parameter
357 lua_pushnil(l);
358 return 1;
359 }
360
361 lua_pushboolean(l, state);
362 return 1;
363}
364
365bool getAuxDigital(int index) {
366#if EFI_PROD_CODE
368#else
369 return false;
370#endif
371}
372
373static 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
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
395static 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
416static auto lua_getAirmassResolveMode(lua_State* l) {
417 if (lua_gettop(l) == 0) {
418 // zero args, return configured mode
420 } else {
421 return static_cast<engine_load_mode_e>(luaL_checkinteger(l, 1));
422 }
423}
424
425static 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
434 auto result = airmass->getAirmass(rpm, false).CylinderAirmass;
435
436 lua_pushnumber(l, result);
437 return 1;
438}
439
440static 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
456namespace 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 static TCLASS * Invoke(lua_State * state, void * mem)
464 {
465 return InvokeImpl(state, mem, typename make_indices<sizeof...(ARGS)>::type());
466 }
467
468 private:
469 template<std::size_t ...Ns>
470 static TCLASS * InvokeImpl(lua_State * state, void * mem, indices<Ns...>)
471 {
472 (void)state;
473 return new(mem) TCLASS(state, LuaStack<ARGS>::get(state, Ns + 1)...);
474 }
475 };
476}
477
478struct LuaSensor final : public StoredValueSensor {
479 LuaSensor() : LuaSensor(nullptr, "Invalid") { }
480
481 ~LuaSensor() {
482 unregister();
483 }
484
485 LuaSensor(lua_State* l, const char* name)
486 : 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 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 Register();
493 efiPrintf("LUA registered sensor of type %s", getSensorName());
494 }
495 }
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 void setTimeout(int timeoutMs) override {
504 }
505
506 void setRedundant(bool value) {
507 m_isRedundant = value;
508 }
509
510 void set(float value) {
511 setValidValue(value, getTimeNowNt());
512 }
513
514 void invalidate() {
516 }
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
523private:
524 bool m_isRedundant = false;
525};
526
527static bool isFunction(lua_State* l, int idx) {
528 return lua_type(l, idx) == LUA_TFUNCTION;
529}
530
531int 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
540int 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
547 switch (lua_gettop(l)) {
548 case 1:
549 // handle canRxAdd(id)
550 eid = luaL_checkinteger(l, 1);
551 break;
552
553 case 2:
554 if (isFunction(l, 2)) {
555 // handle canRxAdd(id, callback)
556 eid = luaL_checkinteger(l, 1);
557 lua_remove(l, 1);
558 callback = getLuaFunc(l);
559 } else {
560 // handle canRxAdd(bus, id)
562 eid = luaL_checkinteger(l, 2);
563 }
564
565 break;
566 case 3:
567 // handle canRxAdd(bus, id, callback)
569 eid = luaL_checkinteger(l, 2);
570 lua_remove(l, 1);
571 lua_remove(l, 1);
572 callback = getLuaFunc(l);
573 break;
574 default:
575 return luaL_error(l, "Wrong number of arguments to canRxAdd. Got %d, expected 1, 2, or 3.");
576 }
577
578 addLuaCanRxFilter(eid, FILTER_SPECIFIC, bus, callback);
579
580 return 0;
581}
582
583int lua_canRxAddMask(lua_State* l) {
584 uint32_t eid;
585 uint32_t mask;
586
587 // defaults if not passed
588 int bus = ANY_BUS;
589 int callback = NO_CALLBACK;
590
591 switch (lua_gettop(l)) {
592 case 2:
593 // handle canRxAddMask(id, mask)
594 eid = luaL_checkinteger(l, 1);
595 mask = luaL_checkinteger(l, 2);
596 break;
597
598 case 3:
599 if (isFunction(l, 3)) {
600 // handle canRxAddMask(id, mask, callback)
601 eid = luaL_checkinteger(l, 1);
602 mask = luaL_checkinteger(l, 2);
603 lua_remove(l, 1);
604 lua_remove(l, 1);
605 callback = getLuaFunc(l);
606 } else {
607 // handle canRxAddMask(bus, id, mask)
609 eid = luaL_checkinteger(l, 2);
610 mask = luaL_checkinteger(l, 3);
611 }
612
613 break;
614 case 4:
615 // handle canRxAddMask(bus, id, mask, callback)
617 eid = luaL_checkinteger(l, 2);
618 mask = luaL_checkinteger(l, 3);
619 lua_remove(l, 1);
620 lua_remove(l, 1);
621 lua_remove(l, 1);
622 callback = getLuaFunc(l);
623 break;
624 default:
625 return luaL_error(l, "Wrong number of arguments to canRxAddMask. Got %d, expected 2, 3, or 4.");
626 }
627
628 addLuaCanRxFilter(eid, mask, bus, callback);
629
630 return 0;
631}
632#endif // EFI_CAN_SUPPORT
633
634PUBLIC_API_WEAK void boardConfigureLuaHooks(lua_State* lState) { }
635
636void configureRusefiLuaHooks(lua_State* lState) {
638
639 LuaClass<Timer> luaTimer(lState, "Timer");
640 luaTimer
641 .ctor()
642 .fun("reset", static_cast<void (Timer::*)() >(&Timer::reset ))
643 .fun("getElapsedSeconds", static_cast<float(Timer::*)()const>(&Timer::getElapsedSeconds));
644
645 LuaClass<LuaSensor> luaSensor(lState, "Sensor");
646 luaSensor
647 .ctor<lua_State*, const char*>()
648 .fun("set", &LuaSensor::set)
649 .fun("setRedundant", &LuaSensor::setRedundant)
650 .fun("setTimeout", &LuaSensor::setTimeout)
651 .fun("invalidate", &LuaSensor::invalidate);
652
653#ifndef WITH_LUA_PID
654#define WITH_LUA_PID TRUE
655#endif
656
657#if WITH_LUA_PID
658 LuaClass<LuaBiQuad> biQuard(lState, "Biquad");
659 biQuard
660 .ctor()
661 .fun("filter", &LuaBiQuad::filter)
662 .fun("configureLowpass", &LuaBiQuad::configureLowpass);
663
664 LuaClass<LuaPid> luaPid(lState, "Pid");
665 luaPid
666 .ctor<float, float, float, float, float>()
667 .fun("get", &LuaPid::get)
668 .fun("setOffset", &LuaPid::setOffset)
669 .fun("reset", &LuaPid::reset);
670
671 LuaClass<LuaIndustrialPid> luaIndustrialPid(lState, "IndustrialPid");
672 luaIndustrialPid
673 .ctor<float, float, float, float, float>()
674 .fun("get", &LuaIndustrialPid::get)
675 .fun("setOffset", &LuaIndustrialPid::setOffset)
676 .fun("setDerivativeFilterLoss", &LuaIndustrialPid::setDerivativeFilterLoss)
677 .fun("setAntiwindupFreq", &LuaIndustrialPid::setAntiwindupFreq)
678 .fun("reset", &LuaIndustrialPid::reset);
679#endif
680
682
683 lua_register(lState, "readPin", lua_readpin);
684#if EFI_PROD_CODE && EFI_SHAFT_POSITION_INPUT
685 lua_register(lState, "startCrankingEngine", [](lua_State* l) {
687 return 0;
688 });
689#endif // EFI_PROD_CODE && EFI_SHAFT_POSITION_INPUT
690 lua_register(lState, "vin", lua_vin);
691
692 lua_register(lState, "getAuxAnalog", lua_getAuxAnalog);
693 lua_register(lState, "getSensorByIndex", lua_getSensorByIndex);
694 lua_register(lState, "getSensor", lua_getSensorByName);
695 lua_register(lState, "getSensorRaw", lua_getSensorRaw);
696 lua_register(lState, "hasSensor", lua_hasSensor);
697
698#ifndef WITH_LUA_CONSUMPTION
699#define WITH_LUA_CONSUMPTION TRUE
700#endif
701
702#if EFI_VEHICLE_SPEED && WITH_LUA_CONSUMPTION
703 lua_register(lState, "getConsumedGrams", [](lua_State* l) {
704 lua_pushnumber(l, engine->module<TripOdometer>()->getConsumedGrams());
705 return 1;
706 });
707 lua_register(lState, "getConsumedGramsRemainder", [](lua_State* l) {
708 lua_pushnumber(l, engine->module<TripOdometer>()->getConsumedGramsRemainder());
709 return 1;
710 });
711 lua_register(lState, "getConsumptionGramPerSecond", [](lua_State* l) {
712 lua_pushnumber(l, engine->module<TripOdometer>()->getConsumptionGramPerSecond());
713 return 1;
714 });
715 lua_register(lState, "resetOdometer", [](lua_State*) {
716 engine->module<TripOdometer>()->reset();
717 return 0;
718 });
719#endif // EFI_VEHICLE_SPEED
720 lua_register(lState, "table3d", [](lua_State* l) {
721 auto humanTableIdx = luaL_checkinteger(l, 1);
722 auto x = luaL_checknumber(l, 2);
723 auto y = luaL_checknumber(l, 3);
724
725 // index table, compute table lookup
726 auto result = getscriptTable(humanTableIdx - HUMAN_OFFSET)->getValue(x, y);
727
728 lua_pushnumber(l, result);
729 return 1;
730 });
731 // time since console or TunerStudio
732 lua_register(lState, "secondsSinceTsActivity", [](lua_State* l) {
733 lua_pushnumber(l, getSecondsSinceChannelsRequest());
734 return 1;
735 });
736
737 lua_register(lState, "curve", [](lua_State* l) {
738 // index starting from 1
739 auto humanCurveIdx = luaL_checkinteger(l, 1);
740 auto x = luaL_checknumber(l, 2);
741
742 auto result = getCurveValue(humanCurveIdx - HUMAN_OFFSET, x);
743
744 lua_pushnumber(l, result);
745 return 1;
746 });
747
748#if EFI_PROD_CODE && EFI_SENT_SUPPORT
749 lua_register(lState, "getSentValue",
750 [](lua_State* l) {
751 auto humanIndex = luaL_checkinteger(l, 1);
752 auto value = getSentValue(static_cast<SentInput>(humanIndex));
753 lua_pushnumber(l, value);
754 return 1;
755 });
756
757 lua_register(lState, "getSentValues",
758 [](lua_State* l) {
759 uint16_t sig0;
760 uint16_t sig1;
761 auto humanIndex = luaL_checkinteger(l, 1);
762 /*auto ret = */getSentValues(static_cast<SentInput>(humanIndex), &sig0, &sig1);
763 lua_pushnumber(l, sig0);
764 lua_pushnumber(l, sig1);
765 return 2;
766 });
767#endif // EFI_SENT_SUPPORT
768
769#if EFI_LAUNCH_CONTROL
770 lua_register(lState, "setSparkSkipRatio", [](lua_State* l) {
771 auto targetSkipRatio = luaL_checknumber(l, 1);
772 engine->engineState.luaSoftSparkSkip = targetSkipRatio;
774 return 0;
775 });
776 lua_register(lState, "setSparkHardSkipRatio", [](lua_State* l) {
777 auto targetSkipRatio = luaL_checknumber(l, 1);
778 engine->engineState.luaHardSparkSkip = targetSkipRatio;
780 return 0;
781 });
782#endif // EFI_LAUNCH_CONTROL
783
784#if EFI_EMULATE_POSITION_SENSORS && !EFI_UNIT_TEST
785 lua_register(lState, "selfStimulateRPM", [](lua_State* l) {
786 auto rpm = luaL_checkinteger(l, 1);
787 if (rpm < 1) {
789 return 0;
790 }
793 }
795 return 0;
796 });
797#endif // EFI_UNIT_TEST
798
799 /**
800 * same exact could be accomplished via LuaSensor just with more API
801 */
802 lua_register(lState, "setLuaGauge", [](lua_State* l) {
803 auto index = luaL_checkinteger(l, 1) - 1;
804 auto value = luaL_checknumber(l, 2);
805 if (index < 0 || index >= LUA_GAUGE_COUNT)
806 return 0;
807 extern StoredValueSensor luaGauges[LUA_GAUGE_COUNT];
808 luaGauges[index].setValidValue(value, getTimeNowNt());
809 return 0;
810 });
811
812 lua_register(lState, "enableCanTx", [](lua_State* l) {
813 engine->allowCanTx = lua_toboolean(l, 1);
814 return 0;
815 });
816
817#if EFI_ELECTRONIC_THROTTLE_BODY && EFI_PROD_CODE
818 lua_register(lState, "getEtbTarget", [](lua_State* l) {
819 auto controller = engine->etbControllers[0];
820 assertNotNull(controller, 0);
821 auto result = controller->getCurrentTarget();
822 lua_pushnumber(l, result);
823 return 1;
824 });
825 lua_register(lState, "restartEtb", [](lua_State*) {
826 // this is about Lua sensor acting in place of real analog PPS sensor
827 // todo: smarter implementation
829 return 0;
830 });
831#endif // EFI_ELECTRONIC_THROTTLE_BODY
832
833 // checksum stuff
834 lua_register(lState, "crc8_j1850", [](lua_State* l) {
835 uint8_t data[8];
836 uint32_t length = getLuaArray(l, 1, data, sizeof(data));
837 auto trimLength = luaL_checkinteger(l, 2);
838 int crc = crc8(data, minI(length, trimLength));
839
840 lua_pushnumber(l, crc);
841 return 1;
842 });
843
844#if EFI_BOOST_CONTROL
845 lua_register(lState, "setBoostTargetAdd", [](lua_State* l) {
846 engine->module<BoostController>().unmock().luaTargetAdd = luaL_checknumber(l, 1);
847 return 0;
848 });
849 lua_register(lState, "setBoostTargetMult", [](lua_State* l) {
850 engine->module<BoostController>().unmock().luaTargetMult = luaL_checknumber(l, 1);
851 return 0;
852 });
853 lua_register(lState, "setBoostDutyAdd", [](lua_State* l) {
854 engine->module<BoostController>().unmock().luaOpenLoopAdd = luaL_checknumber(l, 1);
855 return 0;
856 });
857#endif // EFI_BOOST_CONTROL
858#if EFI_IDLE_CONTROL
859 lua_register(lState, "setIdleAdd", [](lua_State* l) {
860 engine->module<IdleController>().unmock().luaAdd = luaL_checknumber(l, 1);
861 return 0;
862 });
863#endif
864 lua_register(lState, "setTimingAdd", [](lua_State* l) {
865 engine->ignitionState.luaTimingAdd = luaL_checknumber(l, 1);
866 return 0;
867 });
868 lua_register(lState, "setTimingMult", [](lua_State* l) {
869 engine->ignitionState.luaTimingMult = luaL_checknumber(l, 1);
870 return 0;
871 });
872 lua_register(lState, "setFuelAdd", [](lua_State* l) {
873 engine->engineState.lua.fuelAdd = luaL_checknumber(l, 1);
874 return 0;
875 });
876 lua_register(lState, "setFuelMult", [](lua_State* l) {
877 engine->engineState.lua.fuelMult = luaL_checknumber(l, 1);
878 return 0;
879 });
880#if EFI_ELECTRONIC_THROTTLE_BODY && EFI_PROD_CODE
881 lua_register(lState, "setEtbAdd", [](lua_State* l) {
882 auto luaAdjustment = luaL_checknumber(l, 1);
883
885
886 return 0;
887 });
888 lua_register(lState, "setEtbDisabled", [](lua_State* l) {
889 engine->engineState.lua.luaDisableEtb = lua_toboolean(l, 1);
890 return 0;
891 });
892#endif // EFI_ELECTRONIC_THROTTLE_BODY
893#if EFI_PROD_CODE
894 lua_register(lState, "setIgnDisabled", [](lua_State* l) {
895 engine->engineState.lua.luaIgnCut = lua_toboolean(l, 1);
896 return 0;
897 });
898 lua_register(lState, "setFuelDisabled", [](lua_State* l) {
899 engine->engineState.lua.luaFuelCut = lua_toboolean(l, 1);
900 return 0;
901 });
902 lua_register(lState, "setDfcoDisabled", [](lua_State* l) {
904 return 0;
905 });
906#endif // EFI_PROD_CODE
907
908 lua_register(lState, "setClutchUpState", [](lua_State* l) {
909 engine->engineState.lua.clutchUpState = lua_toboolean(l, 1);
910 return 0;
911 });
912 lua_register(lState, "setClutchDownState", [](lua_State* l) {
913 engine->engineState.lua.clutchDownState = lua_toboolean(l, 1);
914 return 0;
915 });
916 lua_register(lState, "setBrakePedalState", [](lua_State* l) {
917 engine->engineState.lua.brakePedalState = lua_toboolean(l, 1);
918 return 0;
919 });
920
921 lua_register(lState, "setAcRequestState", [](lua_State* l) {
922 engine->engineState.lua.acRequestState = lua_toboolean(l, 1);
923 return 0;
924 });
925
926 lua_register(lState, "setTorqueReductionState", [](lua_State* l) {
927 engine->engineState.lua.torqueReductionState = lua_toboolean(l, 1);
928 return 0;
929 });
930
931 lua_register(lState, "getCalibration", [](lua_State* l) {
932 auto propertyName = luaL_checklstring(l, 1, nullptr);
933 auto result = getConfigValueByName(propertyName);
934 lua_pushnumber(l, result);
935 return 1;
936 });
937
938#if EFI_TUNER_STUDIO && (EFI_PROD_CODE || EFI_SIMULATOR)
939 lua_register(lState, "getOutput", [](lua_State* l) {
940 auto propertyName = luaL_checklstring(l, 1, nullptr);
941 // fresh values need to be requested explicitly, there is no periodic invocation of that method
943 auto result = getOutputValueByName(propertyName);
944 lua_pushnumber(l, result);
945 return 1;
946 });
947#endif // EFI_PROD_CODE || EFI_SIMULATOR
948
949#if EFI_SHAFT_POSITION_INPUT
950 lua_register(lState, "getEngineState", [](lua_State* l) {
952 int luaStateCode;
953 if (state == STOPPED) {
954 luaStateCode = 0;
955 } else if (state == RUNNING) {
956 luaStateCode = 2;
957 } else {
958 // spinning-up or cranking
959 luaStateCode = 1;
960 }
961 lua_pushnumber(l, luaStateCode);
962 return 1;
963 });
964#endif //EFI_SHAFT_POSITION_INPUT
965
966 lua_register(lState, "setCalibration", [](lua_State* l) {
967 auto propertyName = luaL_checklstring(l, 1, nullptr);
968 auto value = luaL_checknumber(l, 2);
969 auto incrementVersion = lua_toboolean(l, 3);
970 bool isGoodName = setConfigValueByName(propertyName, value);
971 if (isGoodName) {
972 efiPrintf("LUA: applying [%s][%f]", propertyName, value);
973 } else {
974 efiPrintf("LUA: invalid calibration key [%s]", propertyName);
975 }
976 if (incrementVersion) {
978 }
979 return 0;
980 });
981 lua_register(lState, CMD_BURNCONFIG, [](lua_State* l) {
982 requestBurn();
983 return 0;
984 });
985
986 lua_register(lState, "getGlobalConfigurationVersion", [](lua_State* l) {
987 lua_pushnumber(l, engine->getGlobalConfigurationVersion());
988 return 1;
989 });
990
991 lua_register(lState, "setAcDisabled", [](lua_State* l) {
992 auto value = lua_toboolean(l, 1);
993 engine->module<AcController>().unmock().isDisabledByLua = value;
994 return 0;
995 });
996 lua_register(lState, "getTimeSinceAcToggleMs", [](lua_State* l) {
997 float result = engine->module<AcController>().unmock().timeSinceStateChange.getElapsedSeconds() * 1000;
998 lua_pushnumber(l, result);
999 return 1;
1000 });
1001
1002#if !EFI_UNIT_TEST
1003 lua_register(lState, "startPwm", lua_startPwm);
1004 lua_register(lState, "setPwmDuty", lua_setPwmDuty);
1005 lua_register(lState, "setPwmFreq", lua_setPwmFreq);
1006
1007 lua_register(lState, "getFan", lua_fan);
1008 lua_register(lState, "getDigital", lua_getDigital);
1009 lua_register(lState, "getAuxDigital", lua_getAuxDigital);
1010 lua_register(lState, "setDebug", lua_setDebug);
1011#if EFI_ENGINE_CONTROL
1012 lua_register(lState, "getAirmass", lua_getAirmass);
1013 lua_register(lState, "setAirmass", lua_setAirmass);
1014#endif // EFI_ENGINE_CONTROL
1015
1016
1017#ifndef WITH_LUA_STOP_ENGINE
1018#define WITH_LUA_STOP_ENGINE TRUE
1019#endif
1020
1021#if WITH_LUA_STOP_ENGINE
1022 lua_register(lState, "isFirmwareError", [](lua_State* l) {
1023 lua_pushboolean(l, hasFirmwareError());
1024 return 1;
1025 });
1026#if EFI_SHAFT_POSITION_INPUT
1027 lua_register(lState, "stopEngine", [](lua_State*) {
1029 return 0;
1030 });
1031 lua_register(lState, "isEngineStopRequested", [](lua_State* l) {
1033 lua_pushboolean(l, result);
1034 return 1;
1035 });
1036 lua_register(lState, "getTimeSinceTriggerEventMs", [](lua_State* l) {
1037 int result = engine->triggerCentral.m_lastEventTimer.getElapsedUs() / 1000;
1038 lua_pushnumber(l, result);
1039 return 1;
1040 });
1041#endif // EFI_SHAFT_POSITION_INPUT
1042#endif // WITH_LUA_STOP_ENGINE
1043
1044#if EFI_CAN_SUPPORT
1045 lua_register(lState, "canRxAdd", lua_canRxAdd);
1046 lua_register(lState, "canRxAddMask", lua_canRxAddMask);
1047#endif // EFI_CAN_SUPPORT
1048#endif // not EFI_UNIT_TEST
1049
1050#if EFI_CAN_SUPPORT || EFI_UNIT_TEST
1051 lua_register(lState, "txCan", lua_txCan);
1052#endif
1053
1054#if EFI_PROD_CODE
1055 /* todo: hasCriticalReportFile method #7291
1056 lua_register(lState, "hasCriticalReportFile", [](lua_State*) {
1057 // todo: actual method to scan SD card for error report files
1058 lua_pushnumber(l, hasCriticalReportFile());
1059 return 1;
1060 }
1061*/
1062#endif // EFI_PROD_CODE
1063
1064#if EFI_PROD_CODE && HW_HELLEN
1065 lua_register(lState, "hellenEnablePower", [](lua_State*) {
1066 hellenEnableEn("Lua");
1067 return 0;
1068 });
1069 lua_register(lState, "hellenDisablePower", [](lua_State*) {
1070 hellenDisableEn("Lua");
1071 return 0;
1072 });
1073#endif // HW_HELLEN
1074
1075#if EFI_DAC
1076 lua_register(lState, "setDacVoltage", [](lua_State* l) {
1077 auto channel = luaL_checkinteger(l, 1);
1078 auto voltage = luaL_checknumber(l, 2);
1079 setDacVoltage(channel, voltage);
1080 return 0;
1081 });
1082#endif // EFI_DAC
1083
1084}
uint16_t channel
Definition adc_inputs.h:105
void addLuaCanRxFilter(int32_t eid, uint32_t mask, int bus, int callback)
Timer timeSinceStateChange
Definition ac_control.h:16
void setDlc(uint8_t dlc)
TriggerCentral triggerCentral
Definition engine.h:299
IgnitionState ignitionState
Definition engine.h:221
bool allowCanTx
Definition engine.h:107
int getGlobalConfigurationVersion(void) const
Definition engine.cpp:286
SingleTimerExecutor scheduler
Definition engine.h:252
EngineState engineState
Definition engine.h:325
RpmCalculator rpmCalculator
Definition engine.h:287
IEtbController * etbControllers[ETB_COUNT]
Definition engine.h:119
TunerStudioOutputChannels outputChannels
Definition engine.h:102
constexpr auto & module()
Definition engine.h:187
RegisteredOutputPin fanRelay
Definition efi_gpio.h:86
OutputPin luaOutputPins[LUA_PWM_COUNT]
Definition efi_gpio.h:99
void updateSparkSkip()
Definition engine2.cpp:84
ShutdownController shutdownController
void setAirmass(AirmassResult airmass)
Definition lua_airmass.h:11
void deInit()
Definition efi_gpio.cpp:788
bool getLogicValue() const
Definition efi_gpio.cpp:653
spinning_state_e getState() const
bool Register()
Definition sensor.cpp:131
virtual bool hasSensor() const
Definition sensor.h:141
virtual SensorResult get() const =0
virtual bool isRedundant() const
Definition sensor.h:155
virtual float getRaw() const
Definition sensor.h:148
static float getOrZero(SensorType type)
Definition sensor.h:83
const char * getSensorName() const
Definition sensor.h:130
SensorType type() const
Definition sensor.h:162
void unregister()
Definition sensor.cpp:135
bool isEngineStop(efitick_t nowNt) const
void setSimplePwmDutyCycle(float dutyCycle) override
Base class for sensors that compute a value on one thread, and want to make it available to consumers...
void showInfo(const char *sensorName) const override
void setValidValue(float value, efitick_t timestamp)
virtual void setTimeout(int timeoutMs)
SensorResult get() const final override
float getConsumedGramsRemainder() const
float getConsumptionGramPerSecond() const
uint32_t getConsumedGrams() const
virtual float getValue(float xColumn, float yRow) const =0
void setDacVoltage(int channel, float voltage)
Definition dac.cpp:59
EnginePins enginePins
Definition efi_gpio.cpp:24
ioportid_t getHwPort(const char *msg, brain_pin_e brainPin)
brain_pin_e parseBrainPin(const char *str)
ioportmask_t getHwPin(const char *msg, brain_pin_e brainPin)
const char * boolToString(bool value)
Definition efilib.cpp:18
efitick_t getTimeNowNt()
Definition efitime.cpp:19
void setEtbLuaAdjustment(percent_t pos)
void doInitElectronicThrottle()
LimpManager * getLimpManager()
Definition engine.cpp:585
static Engine *const engine
Definition engine.h:389
void incrementGlobalConfigurationVersion(const char *msg)
static constexpr engine_configuration_s * engineConfiguration
AirmassModelBase * getAirmassModel(engine_load_mode_e mode)
void hellenEnableEn(const char *msg)
void hellenDisableEn(const char *msg)
StoredValueSensor luaGauges[]
Definition init_aux.cpp:21
bool efiReadPin(brain_pin_e pin)
Definition io_pins.cpp:89
static int lua_setPwmFreq(lua_State *l)
void startPwm(int index, float freq, float duty)
static auto lua_getAirmassResolveMode(lua_State *l)
static int lua_readpin(lua_State *l)
Definition lua_hooks.cpp:58
PUBLIC_API_WEAK void boardConfigureLuaHooks(lua_State *lState)
int lua_canRxAddMask(lua_State *l)
static int lua_txCan(lua_State *l)
int getLuaFunc(lua_State *l)
void setPwmDuty(int index, float duty)
uint32_t getLuaArray(lua_State *l, int paramIndex, uint8_t *data, uint32_t size)
static int lua_setAirmass(lua_State *l)
static SimplePwm pwms[LUA_PWM_COUNT]
static int lua_getDigital(lua_State *l)
bool getAuxDigital(int index)
static int lua_getAuxDigital(lua_State *l)
static SensorType findSensorByName(lua_State *l, const char *name)
static LuaAirmass luaAirmass
static int lua_getAuxAnalog(lua_State *l)
Definition lua_hooks.cpp:87
static int lua_getSensorByIndex(lua_State *l)
Definition lua_hooks.cpp:96
void configureRusefiLuaHooks(lua_State *lState)
static int validateCanChannelAndConvertFromHumanIntoZeroIndex(lua_State *l)
static int lua_fan(lua_State *l)
static int lua_hasSensor(lua_State *l)
static int lua_getSensorByName(lua_State *l)
AirmassModelBase & getLuaAirmassModel()
static int lua_getAirmass(lua_State *l)
static int lua_setPwmDuty(lua_State *l)
static int lua_getSensorRaw(lua_State *l)
static int getSensor(lua_State *l, SensorType type)
Definition lua_hooks.cpp:73
static bool isFunction(lua_State *l, int idx)
void luaDeInitPins()
int lua_canRxAdd(lua_State *l)
static int lua_setDebug(lua_State *l)
static int lua_startPwm(lua_State *l)
static int lua_vin(lua_State *l)
Definition lua_hooks.cpp:47
static P luaL_checkPwmIndex(lua_State *l, int pos)
void configureRusefiLuaUtilHooks(lua_State *lState)
float getOutputValueByName(const char *name)
@ LuaOneCanTxFunction
const char * hwPortname(brain_pin_e brainPin)
bool isBrainPinValid(brain_pin_e brainPin)
void startSimplePwmExt(SimplePwm *state, const char *msg, Scheduler *executor, brain_pin_e brainPin, OutputPin *output, float frequency, float dutyCycle, pwm_gen_callback *callback)
spinning_state_e
@ RUNNING
@ STOPPED
engine_load_mode_e
SentInput
float getCurveValue(int index, float key)
ValueProvider3D * getscriptTable(int index)
SensorType findSensorTypeByName(const char *name)
Definition sensor.cpp:259
static ScState state
SensorType
Definition sensor_type.h:18
luaAdjustment("ETB: luaAdjustment", SensorCategory.SENSOR_INPUTS, FieldType.INT, 1656, 1.0, 0.0, 3.0, "%")
float getSentValue(SentInput input)
Definition sent.cpp:134
int getSentValues(SentInput input, uint16_t *sig0, uint16_t *sig1)
Definition sent.cpp:152
This file is about configuring engine via the human-readable protocol.
void doScheduleStopEngine()
void doStartCranking()
brain_pin_e pin
Definition stm32_adc.cpp:15
void configureLowpass(float samplingFrequency, float cutoffFrequency)
Definition lua_biquad.h:17
float filter(float input)
Definition lua_biquad.h:9
void setOffset(float offset)
Definition lua_pid.h:79
void setDerivativeFilterLoss(float derivativeFilterLoss)
Definition lua_pid.h:84
void setAntiwindupFreq(float antiwindupFreq)
Definition lua_pid.h:89
float get(float target, float input)
Definition lua_pid.h:68
float get(float target, float input)
Definition lua_pid.h:23
void reset()
Definition lua_pid.h:39
void setOffset(float offset)
Definition lua_pid.h:34
scaled_channel< int16_t, 2, 1 > luaTargetAdd
switch_input_pin_e luaDigitalInputPins[LUA_DIGITAL_INPUT_COUNT]
static float duty
composite packet size
void disableTriggerStimulator()
void setTriggerEmulatorRPM(int rpm)
void enableTriggerStimulator(bool incGlobalConfiguration)
void requestBurn()
void updateTunerStudioState()
int getSecondsSinceChannelsRequest()
bool setConfigValueByName(const char *name, float value)
float getConfigValueByName(const char *name)