25 float userFreq = luaL_checknumber(l, 1);
29 float freq = clampF(1, userFreq, 2000);
30 if (freq != userFreq) {
31 efiPrintf(TAG
"clamping tickrate %f", freq);
35 efiPrintf(TAG
"luaCanRxWorkaround recommended at high tick rate!");
43 constexpr luaL_Reg libs[] = {
46 { LUA_MATHLIBNAME, luaopen_math },
49 for (
size_t i = 0; i < efi::size(libs); i++) {
50 luaL_requiref(ls, libs[i].name, libs[i].func, 1);
59 criticalError(
"Failed to start Lua interpreter");
64 lua_atpanic(ls, [](lua_State* l) {
65 criticalError(
"Lua panic: %s", lua_tostring(l, -1));
81 lua_gc(ls, LUA_GCCOLLECT, 0);
85 lua_gc(ls, LUA_GCINC, 50, 1000, 9);
91 efiPrintf(TAG
"loading script length: %u...", std::strlen(scriptStr));
93 if (0 != luaL_dostring(ls, scriptStr)) {
95 efiPrintf(TAG
"ERROR loading script: %s", lua_tostring(ls, -1));
100 efiPrintf(TAG
"script loaded successfully!");
123 if (lua_isinteger(ls, -1)) {
124 efiPrintf(TAG
"interactive returned integer: %d", lua_tointeger(ls, -1));
125 }
else if (lua_isnumber(ls, -1)) {
126 efiPrintf(TAG
"interactive returned number: %f", lua_tonumber(ls, -1));
127 }
else if (lua_isstring(ls, -1)) {
128 efiPrintf(TAG
"interactive returned string: '%s'", lua_tostring(ls, -1));
129 }
else if (lua_isboolean(ls, -1)) {
130 efiPrintf(TAG
"interactive returned bool: %s", lua_toboolean(ls, -1) ?
"true" :
"false");
131 }
else if (lua_isnil(ls, -1)) {
132 efiPrintf(TAG
"interactive returned nil.");
134 efiPrintf(TAG
"interactive returned nothing.");
138 efiPrintf(TAG
"interactive error: %s", lua_tostring(ls, -1));
152 lua_getglobal(ls,
"onTick");
153 if (lua_isnil(ls, -1)) {
159 uint32_t before = port_rt_get_counter_value();
162 int status = lua_pcall(ls, 0, 0, 0);
165 uint32_t duration = port_rt_get_counter_value() - before;
171 auto errMsg = lua_tostring(ls, -1);
172 efiPrintf(TAG
"error %s", errMsg);
205static bool runOneLua(lua_Alloc alloc,
const char* script) {
222 while (!
needsReset && !chThdShouldTerminateX()) {
251void LuaThread::ThreadTask() {
252 while (!chThdShouldTerminateX()) {
256 if (usedAfterRun != 0) {
258 efiPrintf(TAG
"MEMORY LEAK DETECTED: %d bytes used after teardown", usedAfterRun);
273 chThdSleepMilliseconds(100);
312 efiPrintf(
"rx total/recent/dropped %d %d %d",
totalRxCount,
332 throw std::logic_error(
"Call to setupLuaState failed, returned null");
336 throw std::logic_error(
"Call to loadScript failed");
339 lua_getglobal(ls,
"testFunc");
340 if (lua_isnil(ls, -1)) {
341 throw std::logic_error(
"Failed to find function testFunc");
344 int status = lua_pcall(ls, 0, 1, 0);
347 std::string msg = std::string(
"lua error while running script: ") + lua_tostring(ls, -1);
348 throw std::logic_error(msg);
358 if (lua_isnil(ls, -1)) {
363 if (!lua_isnumber(ls, -1)) {
364 throw std::logic_error(
"Returned value is not a number");
368 return lua_tonumber(ls, -1);
375 if (!lua_isnumber(ls, -1)) {
376 throw new std::logic_error(
"Returned value is not a number");
380 return lua_tonumber(ls, -1);
387 if (!lua_isinteger(ls, -1)) {
388 throw std::logic_error(
"Returned value is not an integer");
391 return lua_tointeger(ls, -1);
398 throw std::logic_error(
"Call to setupLuaState failed, returned null");
402 throw std::logic_error(
"Call to loadScript failed");
413 bool afterDecimalPoint =
false;
417 *endPtr =
const_cast<char*
>(str);
420 float integerPart = 0;
421 float fractionalPart = 0;
423 while (*str !=
'\0') {
425 int digitVal = c -
'0';
427 if (c >=
'0' && c <=
'9') {
428 if (!afterDecimalPoint) {
430 integerPart = 10 * integerPart + digitVal;
433 fractionalPart = 10 * fractionalPart + digitVal;
436 }
else if (c ==
'.') {
437 afterDecimalPoint =
true;
445 *endPtr =
const_cast<char*
>(str);
449 return integerPart + fractionalPart / div;
TunerStudioOutputChannels outputChannels
constexpr auto & module()
A base class for a controller that requires its own thread.
virtual void ThreadTask()=0
void addConsoleActionS(const char *token, VoidCharPtr callback)
void addConsoleAction(const char *token, Void callback)
Register console action without parameters.
void addConsoleActionII(const char *token, VoidIntInt callback)
Register a console command with two Integer parameters.
static EngineAccessor engine
static constexpr persistent_config_s * config
static constexpr engine_configuration_s * engineConfiguration
float strtof_rusefi(const char *str, char **endPtr)
static LuaThread luaThread
static void loadLibraries(LuaHandle &ls)
static int lua_setTickRate(lua_State *l)
static bool withErrorLoading
float testLuaReturnsNumber(const char *script)
static char interactiveCmd[100]
static bool loadScript(LuaHandle &ls, const char *scriptStr)
void testLuaExecString(const char *script)
expected< float > testLuaReturnsNumberOrNil(const char *script)
static int luaTickPeriodUs
static void doInteractive(LuaHandle &ls)
static LuaHandle setupLuaState(lua_Alloc alloc)
static bool runOneLua(lua_Alloc alloc, const char *script)
static uint32_t maxLuaDuration
static void invokeTick(LuaHandle &ls)
static bool interactivePending
int testLuaReturnsInteger(const char *script)
static LuaHandle runScript(const char *script)
int doLuaCanRx(LuaHandle &ls)
size_t getLuaCanRxDropped()
void * luaHeapAlloc(void *, void *optr, size_t osize, size_t nsize)
bool getAuxDigital(int index)
void configureRusefiLuaHooks(lua_State *lState)
script_setting_t scriptSetting[SCRIPT_SETTING_COUNT]
uint32_t luaInvocationCounter
uint32_t luaLastCycleDuration