13 #if EFI_PROD_CODE && HW_HELLEN
21 #if EFI_CAN_SUPPORT || EFI_UNIT_TEST
28 #define LUAAA_WITHOUT_CPP_STDLIB
31 using namespace luaaa;
45 auto zeroBasedCharIndex = luaL_checkinteger(l, 1);
46 if (zeroBasedCharIndex < 0 || zeroBasedCharIndex > VIN_NUMBER_SIZE) {
50 lua_pushnumber(l, value);
57 const char * msg = luaL_checkstring(l, 1);
60 efiPrintf(
"LUA: invalid pin [%s]", msg);
64 lua_pushnumber(l, physicalValue);
75 lua_pushnumber(l, result.Value);
86 auto zeroBasedSensorIndex = luaL_checkinteger(l, 1);
94 auto zeroBasedSensorIndex = luaL_checkinteger(l, 1);
103 luaL_error(l,
"Invalid sensor type: %s", name);
110 auto sensorName = luaL_checklstring(l, 1,
nullptr);
117 auto zeroBasedSensorIndex = luaL_checkinteger(l, 1);
124 auto zeroBasedSensorIndex = luaL_checkinteger(l, 1);
133 static uint32_t
getArray(lua_State* l,
int paramIndex, uint8_t *data, uint32_t
size) {
136 luaL_checktype(l, paramIndex, LUA_TTABLE);
138 lua_pushnumber(l, result + 1);
139 auto elementType = lua_gettable(l, paramIndex);
140 auto val = lua_tonumber(l, -1);
143 if (elementType == LUA_TNIL) {
148 if (elementType != LUA_TNUMBER) {
150 luaL_error(l,
"Unexpected data at position %d: %s", result, lua_tostring(l, -1));
157 luaL_error(l,
"Input array longer than buffer");
160 data[result - 1] = val;
165 #if EFI_CAN_SUPPORT || EFI_UNIT_TEST
168 lua_Integer channel = luaL_checkinteger(l, 1);
170 luaL_argcheck(l, channel == 1 || channel == 2, 1,
"only buses 1 and 2 currently supported");
171 return channel - HUMAN_OFFSET;
180 if (lua_gettop(l) == 2) {
182 id = luaL_checkinteger(l, 1);
187 id = luaL_checkinteger(l, 2);
188 ext = luaL_checkinteger(l, 3);
194 luaL_argcheck(l,
id <= 0x7FF, 2,
"ID specified is greater than max std ID");
196 luaL_argcheck(l,
id <= 0x1FFF'FFFF, 2,
"ID specified is greater than max ext ID");
207 luaL_checktype(l, dataIndex, LUA_TTABLE);
209 lua_pushnumber(l, dlc + 1);
210 auto elementType = lua_gettable(l, dataIndex);
211 auto val = lua_tonumber(l, -1);
214 if (elementType == LUA_TNIL) {
219 if (elementType != LUA_TNUMBER) {
221 luaL_error(l,
"Unexpected CAN data at position %d: %s", dlc, lua_tostring(l, -1));
228 luaL_error(l,
"CAN frame length cannot be longer than 8");
256 auto channel = luaL_checkinteger(l, pos);
260 if (channel < 0 || channel >= LUA_PWM_COUNT) {
261 luaL_error(l,
"setPwmDuty invalid channel %d", channel);
264 return {
pwms[channel], channel };
268 #define PWM_FREQ_PWM 1000
273 freq = clampF(1, freq, 1000);
283 efiPrintf(
"LUA PWM on %s at %f initial duty",
285 PERCENT_MULT *
duty);
290 auto freq = luaL_checknumber(l, 2);
291 auto duty = luaL_checknumber(l, 3);
293 if (duty < 0 || duty > PWM_MAX_DUTY) {
294 luaL_error(l,
"Duty parameter should be from 0 to 1 got %f",
duty);
319 auto duty = luaL_checknumber(l, 2);
327 auto freq = luaL_checknumber(l, 2);
330 freq = clampF(1, freq, 1000);
332 p.pwm.setFrequency(freq);
343 auto idx = luaL_checkinteger(l, 1);
358 lua_pushboolean(l,
state);
371 auto idx = luaL_checkinteger(l, 1);
372 if (idx < 0 || idx >= LUA_DIGITAL_INPUT_COUNT) {
386 lua_pushboolean(l,
state);
398 auto idx = luaL_checkinteger(l, 1);
399 auto val = luaL_checknumber(l, 2);
402 if (idx < 1 || idx > 7) {
407 firstDebugField[idx - 1] = val;
412 #if EFI_ENGINE_CONTROL
414 if (lua_gettop(l) == 0) {
427 return luaL_error(l,
"null airmass");
431 auto result = airmass->getAirmass(rpm,
false).CylinderAirmass;
433 lua_pushnumber(l, result);
438 float airmass = luaL_checknumber(l, 1);
439 float engineLoadPercent = luaL_checknumber(l, 2);
441 airmass = clampF(0, airmass, 10);
442 engineLoadPercent = clampF(0, engineLoadPercent, 1000);
454 template<
typename TCLASS,
typename ...ARGS>
455 struct PlacementConstructorCaller<TCLASS, lua_State*, ARGS...>
460 static TCLASS * Invoke(lua_State *
state,
void * mem)
462 return InvokeImpl(
state, mem,
typename make_indices<
sizeof...(ARGS)>::type());
466 template<std::size_t ...Ns>
467 static TCLASS * InvokeImpl(lua_State *
state,
void * mem, indices<Ns...>)
470 return new(mem) TCLASS(
state, LuaStack<ARGS>::get(
state, Ns + 1)...);
476 LuaSensor() : LuaSensor(nullptr,
"Invalid") { }
482 LuaSensor(lua_State* l,
const char* name)
487 luaL_error(l,
"Tried to create a Lua sensor of type %s, but one was already registered.", getSensorName());
490 efiPrintf(
"LUA registered sensor of type %s", getSensorName());
494 bool isRedundant()
const override {
495 return m_isRedundant;
499 void setTimeout(
int timeoutMs)
override {
503 void setRedundant(
bool value) {
504 m_isRedundant = value;
507 void set(
float value) {
515 void showInfo(
const char* sensorName)
const override {
516 const auto value = get();
517 efiPrintf(
"Sensor \"%s\": Lua sensor: Valid: %s Converted value %.2f", sensorName,
boolToString(value.Valid), value.Value);
521 bool m_isRedundant =
false;
524 struct LuaPid final {
527 LuaPid(
float kp,
float ki,
float kd,
float min,
float max)
530 m_params.pFactor = kp;
531 m_params.iFactor = ki;
532 m_params.dFactor = kd;
535 m_params.periodMs = 0;
536 m_params.minValue = min;
537 m_params.maxValue = max;
539 m_lastUpdate.reset();
542 float get(
float target,
float input) {
548 float dt = m_lastUpdate.getElapsedSecondsAndReset(
getTimeNowNt());
550 return m_pid.getOutput(target, input, dt);
553 void setOffset(
float offset) {
554 m_params.offset = offset;
569 struct LuaIndustrialPid final {
570 LuaIndustrialPid() =
default;
572 LuaIndustrialPid(
float kp,
float ki,
float kd,
float min,
float max)
575 m_params.pFactor = kp;
576 m_params.iFactor = ki;
577 m_params.dFactor = kd;
580 m_params.periodMs = 0;
581 m_params.minValue = min;
582 m_params.maxValue = max;
584 m_lastUpdate.reset();
587 float get(
float target,
float input) {
593 float dt = m_lastUpdate.getElapsedSecondsAndReset(
getTimeNowNt());
595 return m_pid.getOutput(target, input, dt);
598 void setOffset(
float offset) {
599 m_params.offset = offset;
603 void setDerivativeFilterLoss(
float derivativeFilterLoss) {
604 m_pid.derivativeFilterLoss = derivativeFilterLoss;
608 void setAntiwindupFreq(
float antiwindupFreq) {
609 m_pid.antiwindupFreq = antiwindupFreq;
624 return lua_type(l, idx) == LUA_TFUNCTION;
629 return luaL_error(l,
"expected function");
631 return luaL_ref(l, LUA_REGISTRYINDEX);
641 int callback = NO_CALLBACK;
643 switch (lua_gettop(l)) {
646 eid = luaL_checkinteger(l, 1);
652 eid = luaL_checkinteger(l, 1);
658 eid = luaL_checkinteger(l, 2);
665 eid = luaL_checkinteger(l, 2);
671 return luaL_error(l,
"Wrong number of arguments to canRxAdd. Got %d, expected 1, 2, or 3.");
685 int callback = NO_CALLBACK;
687 switch (lua_gettop(l)) {
690 eid = luaL_checkinteger(l, 1);
691 mask = luaL_checkinteger(l, 2);
697 eid = luaL_checkinteger(l, 1);
698 mask = luaL_checkinteger(l, 2);
705 eid = luaL_checkinteger(l, 2);
706 mask = luaL_checkinteger(l, 3);
713 eid = luaL_checkinteger(l, 2);
714 mask = luaL_checkinteger(l, 3);
721 return luaL_error(l,
"Wrong number of arguments to canRxAddMask. Got %d, expected 2, 3, or 4.");
731 luaL_checktype(l, 1, LUA_TTABLE);
732 size_t sourceIndex = luaL_checknumber(l, 2);
733 size_t destinationIndex = luaL_checknumber(l, 3);
734 size_t size = luaL_checknumber(l, 4);
735 for (
size_t i = 0;i<
size;i++) {
737 lua_rawseti(l, 1, destinationIndex + i);
747 LuaClass<Timer> luaTimer(lState,
"Timer");
750 .fun(
"reset",
static_cast<void (Timer::*)()
>(&Timer::reset ))
751 .fun(
"getElapsedSeconds",
static_cast<float(Timer::*)()const
>(&Timer::getElapsedSeconds));
753 LuaClass<LuaSensor> luaSensor(lState,
"Sensor");
755 .ctor<lua_State*,
const char*>()
756 .fun(
"set", &LuaSensor::set)
757 .fun(
"setRedundant", &LuaSensor::setRedundant)
758 .fun(
"setTimeout", &LuaSensor::setTimeout)
759 .fun(
"invalidate", &LuaSensor::invalidate);
761 LuaClass<LuaPid> luaPid(lState,
"Pid");
763 .ctor<float, float, float, float,
float>()
764 .fun(
"get", &LuaPid::get)
765 .fun(
"setOffset", &LuaPid::setOffset)
766 .fun(
"reset", &LuaPid::reset);
768 LuaClass<LuaIndustrialPid> luaIndustrialPid(lState,
"IndustrialPid");
770 .ctor<float, float, float, float,
float>()
771 .fun(
"get", &LuaIndustrialPid::get)
772 .fun(
"setOffset", &LuaIndustrialPid::setOffset)
773 .fun(
"setDerivativeFilterLoss", &LuaIndustrialPid::setDerivativeFilterLoss)
774 .fun(
"setAntiwindupFreq", &LuaIndustrialPid::setAntiwindupFreq)
775 .fun(
"reset", &LuaIndustrialPid::reset);
780 lua_register(lState,
"vin",
lua_vin);
787 lua_register(lState,
"table3d", [](lua_State* l) {
788 auto humanTableIdx = luaL_checkinteger(l, 1);
789 auto x = luaL_checknumber(l, 2);
790 auto y = luaL_checknumber(l, 3);
795 lua_pushnumber(l, result);
799 lua_register(lState,
"secondsSinceTsActivity", [](lua_State* l) {
804 lua_register(lState,
"curve", [](lua_State* l) {
806 auto humanCurveIdx = luaL_checkinteger(l, 1);
807 auto x = luaL_checknumber(l, 2);
809 auto result =
getCurveValue(humanCurveIdx - HUMAN_OFFSET, x);
811 lua_pushnumber(l, result);
816 lua_register(lState,
"getSentValue",
818 auto humanIndex = luaL_checkinteger(l, 1);
820 lua_pushnumber(l, value);
824 lua_register(lState,
"getSentValues",
828 auto humanIndex = luaL_checkinteger(l, 1);
830 lua_pushnumber(l, sig0);
831 lua_pushnumber(l, sig1);
836 #if EFI_LAUNCH_CONTROL
837 lua_register(lState,
"setSparkSkipRatio", [](lua_State* l) {
838 auto targetSkipRatio = luaL_checknumber(l, 1);
843 lua_register(lState,
"setSparkHardSkipRatio", [](lua_State* l) {
844 auto targetSkipRatio = luaL_checknumber(l, 1);
851 #if EFI_EMULATE_POSITION_SENSORS && !EFI_UNIT_TEST
852 lua_register(lState,
"selfStimulateRPM", [](lua_State* l) {
853 auto rpm = luaL_checkinteger(l, 1);
869 lua_register(lState,
"setLuaGauge", [](lua_State* l) {
870 auto index = luaL_checkinteger(l, 1) - 1;
871 auto value = luaL_checknumber(l, 2);
872 if (index < 0 || index >= LUA_GAUGE_COUNT)
879 lua_register(lState,
"enableCanTx", [](lua_State* l) {
884 #if EFI_ELECTRONIC_THROTTLE_BODY && EFI_PROD_CODE
885 lua_register(lState,
"restartEtb", [](lua_State*) {
894 lua_register(lState,
"crc8_j1850", [](lua_State* l) {
896 uint32_t length =
getArray(l, 1, data,
sizeof(data));
897 auto trimLength = luaL_checkinteger(l, 2);
898 int crc = crc8(data, minI(length, trimLength));
900 lua_pushnumber(l, crc);
904 #if EFI_BOOST_CONTROL
905 lua_register(lState,
"setBoostTargetAdd", [](lua_State* l) {
909 lua_register(lState,
"setBoostTargetMult", [](lua_State* l) {
913 lua_register(lState,
"setBoostDutyAdd", [](lua_State* l) {
919 lua_register(lState,
"setIdleAdd", [](lua_State* l) {
924 lua_register(lState,
"setTimingAdd", [](lua_State* l) {
928 lua_register(lState,
"setTimingMult", [](lua_State* l) {
932 lua_register(lState,
"setFuelAdd", [](lua_State* l) {
936 lua_register(lState,
"setFuelMult", [](lua_State* l) {
940 #if EFI_ELECTRONIC_THROTTLE_BODY && EFI_PROD_CODE
941 lua_register(lState,
"setEtbAdd", [](lua_State* l) {
950 lua_register(lState,
"setEtbDisabled", [](lua_State* l) {
954 lua_register(lState,
"setIgnDisabled", [](lua_State* l) {
960 lua_register(lState,
"setClutchUpState", [](lua_State* l) {
965 lua_register(lState,
"setBrakePedalState", [](lua_State* l) {
970 lua_register(lState,
"setAcRequestState", [](lua_State* l) {
975 lua_register(lState,
"getCalibration", [](lua_State* l) {
976 auto propertyName = luaL_checklstring(l, 1,
nullptr);
978 lua_pushnumber(l, result);
982 #if EFI_TUNER_STUDIO && (EFI_PROD_CODE || EFI_SIMULATOR)
983 lua_register(lState,
"getOutput", [](lua_State* l) {
984 auto propertyName = luaL_checklstring(l, 1,
nullptr);
988 lua_pushnumber(l, result);
993 #if EFI_SHAFT_POSITION_INPUT
994 lua_register(lState,
"getEngineState", [](lua_State* l) {
1005 lua_pushnumber(l, luaStateCode);
1010 lua_register(lState,
"setCalibration", [](lua_State* l) {
1011 auto propertyName = luaL_checklstring(l, 1,
nullptr);
1012 auto value = luaL_checknumber(l, 2);
1013 auto incrementVersion = lua_toboolean(l, 3);
1016 efiPrintf(
"LUA: applying [%s][%f]", propertyName, value);
1018 efiPrintf(
"LUA: invalid calibration key [%s]", propertyName);
1020 if (incrementVersion) {
1025 lua_register(lState, CMD_BURNCONFIG, [](lua_State* l) {
1030 lua_register(lState,
"getGlobalConfigurationVersion", [](lua_State* l) {
1035 lua_register(lState,
"setAcDisabled", [](lua_State* l) {
1036 auto value = lua_toboolean(l, 1);
1040 lua_register(lState,
"getTimeSinceAcToggleMs", [](lua_State* l) {
1042 lua_pushnumber(l, result);
1046 #if EFI_VEHICLE_SPEED
1047 lua_register(lState,
"getCurrentGear", [](lua_State* l) {
1052 lua_register(lState,
"getRpmInGear", [](lua_State* l) {
1053 auto idx = luaL_checkinteger(l, 1);
1064 lua_register(lState,
"getFan",
lua_fan);
1068 #if EFI_ENGINE_CONTROL
1073 lua_register(lState,
"stopEngine", [](lua_State*) {
1077 #if EFI_SHAFT_POSITION_INPUT
1078 lua_register(lState,
"getTimeSinceTriggerEventMs", [](lua_State* l) {
1080 lua_pushnumber(l, result);
1091 #if EFI_CAN_SUPPORT || EFI_UNIT_TEST
1092 lua_register(lState,
"txCan",
lua_txCan);
1095 #if EFI_VEHICLE_SPEED
1096 lua_register(lState,
"resetOdometer", [](lua_State*) {
1102 #if EFI_PROD_CODE && HW_HELLEN
1103 lua_register(lState,
"hellenEnablePower", [](lua_State*) {
1107 lua_register(lState,
"hellenDisablePower", [](lua_State*) {
1114 lua_register(lState,
"setDacVoltage", [](lua_State* l) {
1115 auto channel = luaL_checkinteger(l, 1);
1116 auto voltage = luaL_checknumber(l, 2);
void addLuaCanRxFilter(int32_t eid, uint32_t mask, int bus, int callback)
TriggerCentral triggerCentral
IgnitionState ignitionState
int getGlobalConfigurationVersion(void) const
RpmCalculator rpmCalculator
constexpr auto & module()
SingleTimerExecutor executor
TunerStudioOutputChannels outputChannels
RegisteredOutputPin fanRelay
OutputPin luaOutputPins[LUA_PWM_COUNT]
float getRpmInGear(size_t gear) const
void setAirmass(AirmassResult airmass)
bool getLogicValue() const
spinning_state_e getState() const
virtual bool hasSensor() const
virtual SensorResult get() const =0
virtual float getRaw() const
static float getOrZero(SensorType type)
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 setValidValue(float value, efitick_t timestamp)
virtual void setTimeout(int timeoutMs)
bool directSelfStimulation
virtual float getValue(float xColumn, float yRow) const =0
void setDacVoltage(int channel, float voltage)
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)
efitimeus_t getTimeNowUs()
void advanceTimeUs(int us)
void setEtbLuaAdjustment(percent_t pos)
void doInitElectronicThrottle()
void incrementGlobalConfigurationVersion(const char *msg)
AirmassModelBase * getAirmassModel(engine_load_mode_e mode)
void hellenEnableEn(const char *msg)
void hellenDisableEn(const char *msg)
StoredValueSensor luaGauges[]
bool efiReadPin(brain_pin_e pin)
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)
BOARD_WEAK void boardConfigureLuaHooks(lua_State *lState)
int lua_canRxAddMask(lua_State *l)
static int lua_txCan(lua_State *l)
int getLuaFunc(lua_State *l)
AirmassModelBase & getLuaAirmassModel()
void setPwmDuty(int index, float duty)
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)
static int lua_getSensorByIndex(lua_State *l)
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)
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)
static bool isFunction(lua_State *l, int idx)
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)
static uint32_t getArray(lua_State *l, int paramIndex, uint8_t *data, uint32_t size)
static int lua_vincpy(lua_State *l)
static P luaL_checkPwmIndex(lua_State *l, int pos)
void configureRusefiLuaUtilHooks(lua_State *lState)
float getOutputValueByName(const char *name)
engine_configuration_s * engineConfiguration
const char * hwPortname(brain_pin_e brainPin)
bool isBrainPinValid(brain_pin_e brainPin)
void startSimplePwmExt(SimplePwm *state, const char *msg, ExecutorInterface *executor, brain_pin_e brainPin, OutputPin *output, float frequency, float dutyCycle, pwm_gen_callback *callback)
float getCurveValue(int index, float key)
ValueProvider3D * getscriptTable(int index)
SensorType findSensorTypeByName(const char *name)
luaAdjustment("ETB: luaAdjustment", SensorCategory.SENSOR_INPUTS, FieldType.INT, 1592, 1.0, 0.0, 3.0, "per")
int getSentValues(size_t index, uint16_t *sig0, uint16_t *sig1)
float getSentValue(size_t index)
This file is about configuring engine via the human-readable protocol.
void doScheduleStopEngine()
int acSwitchLastChangeTimeMs
scaled_channel< int16_t, 2, 1 > luaTargetAdd
engine_load_mode_e fuelAlgorithm
switch_input_pin_e luaDigitalInputPins[LUA_DIGITAL_INPUT_COUNT]
output_pin_e luaOutputPins[LUA_PWM_COUNT]
void disableTriggerStimulator()
void setTriggerEmulatorRPM(int rpm)
void enableTriggerStimulator(bool incGlobalConfiguration)
void updateTunerStudioState()
int getSecondsSinceChannelsRequest()
bool setConfigValueByName(const char *name, float value)
float getConfigValueByName(const char *name)