rusEFI
The most advanced open source ECU
Functions | Variables
lua.cpp File Reference

Functions

static Heap userHeap (luaUserHeap)
 
static void printLuaMemoryInfo ()
 
static void * myAlloc (void *, void *ptr, size_t osize, size_t nsize)
 
static int lua_setTickRate (lua_State *l)
 
static void loadLibraries (LuaHandle &ls)
 
static LuaHandle setupLuaState (lua_Alloc alloc)
 
static bool loadScript (LuaHandle &ls, const char *scriptStr)
 
static void doInteractive (LuaHandle &ls)
 
static void invokeTick (LuaHandle &ls)
 
static void resetLua ()
 
static bool runOneLua (lua_Alloc alloc, const char *script)
 
void startLua ()
 
static LuaHandle runScript (const char *script)
 
expected< float > testLuaReturnsNumberOrNil (const char *script)
 
float testLuaReturnsNumber (const char *script)
 
int testLuaReturnsInteger (const char *script)
 
void testLuaExecString (const char *script)
 
float strtof_rusefi (const char *str, char **endPtr)
 

Variables

static char luaUserHeap[LUA_USER_HEAP] SDRAM_OPTIONAL LUA_HEAD_RAM_SECTION
 
static int recentRxCount = 0
 
static int totalRxCount = 0
 
static int rxTime
 
static int luaTickPeriodUs
 
static bool interactivePending = false
 
static char interactiveCmd [100]
 
static bool needsReset = false
 
static LuaThread luaThread
 

Function Documentation

◆ doInteractive()

static void doInteractive ( LuaHandle ls)
static

Definition at line 228 of file lua.cpp.

228  {
229  if (!interactivePending) {
230  // no cmd pending, return
231  return;
232  }
233 
234  auto status = luaL_dostring(ls, interactiveCmd);
235 
236  if (0 == status) {
237  // Function call was OK, resolve return value and print it
238  if (lua_isinteger(ls, -1)) {
239  efiPrintf(TAG "interactive returned integer: %d", lua_tointeger(ls, -1));
240  } else if (lua_isnumber(ls, -1)) {
241  efiPrintf(TAG "interactive returned number: %f", lua_tonumber(ls, -1));
242  } else if (lua_isstring(ls, -1)) {
243  efiPrintf(TAG "interactive returned string: '%s'", lua_tostring(ls, -1));
244  } else if (lua_isboolean(ls, -1)) {
245  efiPrintf(TAG "interactive returned bool: %s", lua_toboolean(ls, -1) ? "true" : "false");
246  } else if (lua_isnil(ls, -1)) {
247  efiPrintf(TAG "interactive returned nil.");
248  } else {
249  efiPrintf(TAG "interactive returned nothing.");
250  }
251  } else {
252  // error with interactive command, print it
253  efiPrintf(TAG "interactive error: %s", lua_tostring(ls, -1));
254  }
255 
256  interactivePending = false;
257 
258  lua_settop(ls, 0);
259 }
static char interactiveCmd[100]
Definition: lua.cpp:226
static bool interactivePending
Definition: lua.cpp:225

Referenced by runOneLua().

Here is the caller graph for this function:

◆ invokeTick()

static void invokeTick ( LuaHandle ls)
static

Definition at line 261 of file lua.cpp.

261  {
263 
264  // run the tick function
265  lua_getglobal(ls, "onTick");
266  if (lua_isnil(ls, -1)) {
267  // TODO: handle missing tick function
268  lua_settop(ls, 0);
269  return;
270  }
271 
272  int status = lua_pcall(ls, 0, 0, 0);
273 
274  if (0 != status) {
275  // error calling hook function
276  auto errMsg = lua_tostring(ls, -1);
277  efiPrintf(TAG "error %s", errMsg);
278  lua_pop(ls, 1);
279  }
280 
281  lua_settop(ls, 0);
282 }
@ LuaTickFunction

Referenced by runOneLua().

Here is the caller graph for this function:

◆ loadLibraries()

static void loadLibraries ( LuaHandle ls)
static

Definition at line 158 of file lua.cpp.

158  {
159  constexpr luaL_Reg libs[] = {
160  // TODO: do we even need the base lib?
161  //{ LUA_GNAME, luaopen_base },
162  { LUA_MATHLIBNAME, luaopen_math },
163  };
164 
165  for (size_t i = 0; i < efi::size(libs); i++) {
166  luaL_requiref(ls, libs[i].name, libs[i].func, 1);
167  lua_pop(ls, 1);
168  }
169 }
composite packet size

Referenced by setupLuaState().

Here is the caller graph for this function:

◆ loadScript()

static bool loadScript ( LuaHandle ls,
const char *  scriptStr 
)
static

Definition at line 206 of file lua.cpp.

206  {
207  efiPrintf(TAG "loading script length: %d...", efiStrlen(scriptStr));
208 
209  if (0 != luaL_dostring(ls, scriptStr)) {
210  efiPrintf(TAG "ERROR loading script: %s", lua_tostring(ls, -1));
211  lua_pop(ls, 1);
212  return false;
213  }
214 
215  efiPrintf(TAG "script loaded successfully!");
216 
217 #if EFI_PROD_CODE
219 #endif // EFI_PROD_CODE
220 
221  return true;
222 }
static void printLuaMemoryInfo()
Definition: lua.cpp:115

Referenced by runOneLua(), runScript(), and testLuaExecString().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ lua_setTickRate()

static int lua_setTickRate ( lua_State *  l)
static

Definition at line 147 of file lua.cpp.

147  {
148  float freq = luaL_checknumber(l, 1);
149 
150  // For instance BMW does 100 CAN messages per second on some IDs, let's allow at least twice that speed
151  // Limit to 1..200 hz
152  freq = clampF(1, freq, 200);
153 
154  luaTickPeriodUs = 1000000.0f / freq;
155  return 0;
156 }
static int luaTickPeriodUs
Definition: lua.cpp:145

Referenced by setupLuaState().

Here is the caller graph for this function:

◆ myAlloc()

static void * myAlloc ( void *  ,
void *  ptr,
size_t  osize,
size_t  nsize 
)
static

Definition at line 122 of file lua.cpp.

122  {
123  if (engineConfiguration->debugMode == DBG_LUA) {
125  }
126 
127  return userHeap.realloc(ptr, osize, nsize);
128 }
TunerStudioOutputChannels outputChannels
Definition: engine.h:99
Engine * engine
static Heap userHeap(luaUserHeap)
engine_configuration_s * engineConfiguration

Referenced by runScript(), and testLuaExecString().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ printLuaMemoryInfo()

static void printLuaMemoryInfo ( )
static

Definition at line 115 of file lua.cpp.

115  {
116  auto heapSize = userHeap.size();
117  auto memoryUsed = userHeap.used();
118  float pct = 100.0f * memoryUsed / heapSize;
119  efiPrintf("Lua memory heap usage: %d / %d bytes = %.1f%%", memoryUsed, heapSize, pct);
120 }

Referenced by loadScript(), and startLua().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ resetLua()

static void resetLua ( )
static

Definition at line 290 of file lua.cpp.

290  {
291  engine->module<AcController>().unmock().isDisabledByLua = false;
292 #if EFI_CAN_SUPPORT
293  resetLuaCanRx();
294 #endif // EFI_CAN_SUPPORT
295 
296  // De-init pins, they will reinit next start of the script.
297  luaDeInitPins();
298 }
void resetLuaCanRx()
Definition: can_filter.cpp:24
constexpr auto & module()
Definition: engine.h:177
void luaDeInitPins()
Definition: lua_hooks.cpp:303

Referenced by runOneLua().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ runOneLua()

static bool runOneLua ( lua_Alloc  alloc,
const char *  script 
)
static

Definition at line 310 of file lua.cpp.

310  {
311  needsReset = false;
312 
313  auto ls = setupLuaState(alloc);
314 
315  // couldn't start Lua interpreter, bail out
316  if (!ls) {
317  return false;
318  }
319 
320  // Reset default tick rate
321  luaTickPeriodUs = MS2US(100);
322 
323  if (!loadScript(ls, script)) {
324  return false;
325  }
326 
327  while (!needsReset && !chThdShouldTerminateX()) {
328  efitick_t beforeNt = getTimeNowNt();
329 #if EFI_CAN_SUPPORT
330  // First, process any pending can RX messages
333  rxTime = getTimeNowNt() - beforeNt;
334 #endif // EFI_CAN_SUPPORT
335 
336  // Next, check if there is a pending interactive command entered by the user
337  doInteractive(ls);
338 
339  invokeTick(ls);
340 
343  chThdSleep(TIME_US2I(luaTickPeriodUs));
344 
349  }
350 
351  resetLua();
352 
353  return true;
354 }
EngineState engineState
Definition: engine.h:315
efitick_t getTimeNowNt()
Definition: efitime.cpp:19
static bool loadScript(LuaHandle &ls, const char *scriptStr)
Definition: lua.cpp:206
static int recentRxCount
Definition: lua.cpp:33
static void doInteractive(LuaHandle &ls)
Definition: lua.cpp:228
static LuaHandle setupLuaState(lua_Alloc alloc)
Definition: lua.cpp:171
static int rxTime
Definition: lua.cpp:35
static int totalRxCount
Definition: lua.cpp:34
static void invokeTick(LuaHandle &ls)
Definition: lua.cpp:261
static void resetLua()
Definition: lua.cpp:290
static bool needsReset
Definition: lua.cpp:301
int doLuaCanRx(LuaHandle &ls)
Definition: lua_can_rx.cpp:159
bool getAuxDigital(int index)
Definition: lua_hooks.cpp:362
Here is the call graph for this function:

◆ runScript()

static LuaHandle runScript ( const char *  script)
static

Definition at line 442 of file lua.cpp.

442  {
443  auto ls = setupLuaState(myAlloc);
444 
445  if (!ls) {
446  throw std::logic_error("Call to setupLuaState failed, returned null");
447  }
448 
449  if (!loadScript(ls, script)) {
450  throw std::logic_error("Call to loadScript failed");
451  }
452 
453  lua_getglobal(ls, "testFunc");
454  if (lua_isnil(ls, -1)) {
455  throw std::logic_error("Failed to find function testFunc");
456  }
457 
458  int status = lua_pcall(ls, 0, 1, 0);
459 
460  if (0 != status) {
461  std::string msg = std::string("lua error while running script: ") + lua_tostring(ls, -1);
462  throw std::logic_error(msg);
463  }
464 
465  return ls;
466 }
static void * myAlloc(void *, void *ptr, size_t osize, size_t nsize)
Definition: lua.cpp:122

Referenced by testLuaReturnsInteger(), testLuaReturnsNumber(), and testLuaReturnsNumberOrNil().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setupLuaState()

static LuaHandle setupLuaState ( lua_Alloc  alloc)
static

Definition at line 171 of file lua.cpp.

171  {
172  LuaHandle ls = lua_newstate(alloc, NULL);
173 
174  if (!ls) {
175  criticalError("Failed to start Lua interpreter");
176 
177  return nullptr;
178  }
179 
180  lua_atpanic(ls, [](lua_State* l) {
181  criticalError("Lua panic: %s", lua_tostring(l, -1));
182 
183  // hang the lua thread
184  while (true) ;
185 
186  return 0;
187  });
188 
189  // Load Lua's own libraries
190  loadLibraries(ls);
191 
192  // Load rusEFI hooks
193  lua_register(ls, "setTickRate", lua_setTickRate);
195 
196  // run a GC cycle
197  lua_gc(ls, LUA_GCCOLLECT, 0);
198 
199  // set GC settings
200  // see https://www.lua.org/manual/5.4/manual.html#2.5.1
201  lua_gc(ls, LUA_GCINC, 50, 1000, 9);
202 
203  return ls;
204 }
static void loadLibraries(LuaHandle &ls)
Definition: lua.cpp:158
static int lua_setTickRate(lua_State *l)
Definition: lua.cpp:147
void configureRusefiLuaHooks(lua_State *lState)
Definition: lua_hooks.cpp:744

Referenced by runOneLua(), runScript(), and testLuaExecString().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ startLua()

void startLua ( )

Definition at line 386 of file lua.cpp.

386  {
387 #if defined(STM32F4) && !defined(EFI_IS_F42x)
388  // we need this on microRusEFI for sure
389  // definitely should NOT have this on Proteus
390  // on Hellen a bit of open question what's the best track
391  // cute hack: let's check at runtime if you are a lucky owner of microRusEFI with extra RAM and use that extra RAM for extra Lua
392  if (isStm32F42x()) {
393  char *buffer = (char *)0x20020000;
394  userHeap.reinit(buffer, 60000);
395  }
396 #endif // STM32F4
397 
398 #if LUA_USER_HEAP > 1
399 #if EFI_CAN_SUPPORT
400  initLuaCanRx();
401 #endif // EFI_CAN_SUPPORT
402 
403  addConsoleActionII("set_lua_setting", [](int index, int value) {
404  engineConfiguration->scriptSetting[index] = value;
405  });
406 
407  luaThread.start();
408 
409  addConsoleActionS("lua", [](const char* str){
410  if (interactivePending) {
411  return;
412  }
413 
414  strncpy(interactiveCmd, str, sizeof(interactiveCmd) - 1);
415  interactiveCmd[sizeof(interactiveCmd) - 1] = '\0';
416 
417  interactivePending = true;
418  });
419 
420  addConsoleAction("luareset", [](){
421  needsReset = true;
422  });
423 
424  addConsoleAction("luamemory", [](){
425  efiPrintf("rx total/recent %d %d", totalRxCount,
426  recentRxCount);
427  efiPrintf("luaCycle %dus including luaRxTime %dus", NT2US(engine->outputChannels.luaLastCycleDuration),
428  NT2US(rxTime));
429 
431  });
432 #endif
433 }
bool isStm32F42x(void)
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 LuaThread luaThread
Definition: lua.cpp:383
void initLuaCanRx()
Definition: lua_can_rx.cpp:169
script_setting_t scriptSetting[SCRIPT_SETTING_COUNT]
static BigBufferHandle buffer

Referenced by commonEarlyInit().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ strtof_rusefi()

float strtof_rusefi ( const char *  str,
char **  endPtr 
)

Definition at line 526 of file lua.cpp.

526  {
527  bool afterDecimalPoint = false;
528  float div = 1; // Divider to place digits after the decimal point
529 
530  if (endPtr) {
531  *endPtr = const_cast<char*>(str);
532  }
533 
534  float integerPart = 0;
535  float fractionalPart = 0;
536 
537  while (*str != '\0') {
538  char c = *str;
539  int digitVal = c - '0';
540 
541  if (c >= '0' && c <= '9') {
542  if (!afterDecimalPoint) {
543  // Integer part
544  integerPart = 10 * integerPart + digitVal;
545  } else {
546  // Fractional part
547  fractionalPart = 10 * fractionalPart + digitVal;
548  div *= 10;
549  }
550  } else if (c == '.') {
551  afterDecimalPoint = true;
552  } else {
553  break;
554  }
555 
556  str++;
557 
558  if (endPtr) {
559  *endPtr = const_cast<char*>(str);
560  }
561  }
562 
563  return integerPart + fractionalPart / div;
564 }

◆ testLuaExecString()

void testLuaExecString ( const char *  script)

Definition at line 508 of file lua.cpp.

508  {
509  auto ls = setupLuaState(myAlloc);
510 
511  if (!ls) {
512  throw std::logic_error("Call to setupLuaState failed, returned null");
513  }
514 
515  if (!loadScript(ls, script)) {
516  throw std::logic_error("Call to loadScript failed");
517  }
518 }
Here is the call graph for this function:

◆ testLuaReturnsInteger()

int testLuaReturnsInteger ( const char *  script)

Definition at line 497 of file lua.cpp.

497  {
498  auto ls = runScript(script);
499 
500  // pop the return value;
501  if (!lua_isinteger(ls, -1)) {
502  throw std::logic_error("Returned value is not an integer");
503  }
504 
505  return lua_tointeger(ls, -1);
506 }
static LuaHandle runScript(const char *script)
Definition: lua.cpp:442
Here is the call graph for this function:

◆ testLuaReturnsNumber()

float testLuaReturnsNumber ( const char *  script)

Definition at line 485 of file lua.cpp.

485  {
486  auto ls = runScript(script);
487 
488  // check the return value
489  if (!lua_isnumber(ls, -1)) {
490  throw new std::logic_error("Returned value is not a number");
491  }
492 
493  // pop the return value
494  return lua_tonumber(ls, -1);
495 }
Here is the call graph for this function:

◆ testLuaReturnsNumberOrNil()

expected<float> testLuaReturnsNumberOrNil ( const char *  script)

Definition at line 468 of file lua.cpp.

468  {
469  auto ls = runScript(script);
470 
471  // check nil return first
472  if (lua_isnil(ls, -1)) {
473  return unexpected;
474  }
475 
476  // If not nil, it should be a number
477  if (!lua_isnumber(ls, -1)) {
478  throw std::logic_error("Returned value is not a number");
479  }
480 
481  // pop the return value
482  return lua_tonumber(ls, -1);
483 }
Here is the call graph for this function:

◆ userHeap()

static Heap userHeap ( luaUserHeap  )
static

Referenced by myAlloc(), printLuaMemoryInfo(), and startLua().

Here is the caller graph for this function:

Variable Documentation

◆ interactiveCmd

char interactiveCmd[100]
static

Definition at line 226 of file lua.cpp.

Referenced by doInteractive(), and startLua().

◆ interactivePending

bool interactivePending = false
static

Definition at line 225 of file lua.cpp.

Referenced by doInteractive(), and startLua().

◆ LUA_HEAD_RAM_SECTION

char luaUserHeap [LUA_USER_HEAP] SDRAM_OPTIONAL LUA_HEAD_RAM_SECTION
static

Definition at line 29 of file lua.cpp.

◆ luaThread

LuaThread luaThread
static

Definition at line 383 of file lua.cpp.

Referenced by startLua().

◆ luaTickPeriodUs

int luaTickPeriodUs
static

Definition at line 145 of file lua.cpp.

Referenced by lua_setTickRate(), and runOneLua().

◆ needsReset

bool needsReset = false
static

Definition at line 301 of file lua.cpp.

Referenced by runOneLua(), and startLua().

◆ recentRxCount

int recentRxCount = 0
static

Definition at line 33 of file lua.cpp.

Referenced by runOneLua(), and startLua().

◆ rxTime

int rxTime
static

Definition at line 35 of file lua.cpp.

Referenced by runOneLua(), and startLua().

◆ totalRxCount

int totalRxCount = 0
static

Definition at line 34 of file lua.cpp.

Referenced by runOneLua(), and startLua().

Go to the source code of this file.