Lua rx callback (#4387)
* s * mask, callback * support 8 different signatures * make the compiler happy about unrechable code * s * make the compiler happy about unreachable code * guard * changelog
This commit is contained in:
parent
dece77ddf1
commit
ada1ba6b56
|
@ -30,6 +30,7 @@ Release template (copy/paste this for new release):
|
|||
- microRusEFI and Proteus F4 have CAN OpenBLT bootloader #4199 #4230
|
||||
- counter-noise measure for custom skipped trigger wheels #4375
|
||||
- Write hard faults to backup ram, print on next boot #4324
|
||||
- Many more options for Lua CAN rx filters/callbacks #4387
|
||||
|
||||
### Fixed
|
||||
- Lua CAN reception fixed for 11-bit IDs where the frame would be received, but a corrupt ID was passed to the handler function. #4321
|
||||
|
|
|
@ -6,23 +6,35 @@
|
|||
|
||||
static constexpr size_t maxFilterCount = 48;
|
||||
|
||||
size_t filterCount = 0;
|
||||
int32_t luaCanRxIds[maxFilterCount] = {0};
|
||||
struct Filter {
|
||||
int32_t Id;
|
||||
int32_t Mask;
|
||||
|
||||
static bool shouldRxCanFrame(const CANRxFrame& frame) {
|
||||
int Bus;
|
||||
int Callback;
|
||||
};
|
||||
|
||||
size_t filterCount = 0;
|
||||
Filter filters[maxFilterCount];
|
||||
|
||||
static Filter* getFilterForFrame(size_t busIndex, const CANRxFrame& frame) {
|
||||
for (size_t i = 0; i < filterCount; i++) {
|
||||
int32_t id = luaCanRxIds[i];
|
||||
if (CAN_ID(frame) == id) {
|
||||
return true;
|
||||
auto& filter = filters[i];
|
||||
|
||||
if ((CAN_ID(frame) & filter.Mask) == filter.Id) {
|
||||
if (filter.Bus == -1 || filter.Bus == busIndex) {
|
||||
return &filter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Stores information about one received CAN frame: which bus, plus the actual frame
|
||||
struct CanFrameData {
|
||||
uint8_t BusIndex;
|
||||
int Callback;
|
||||
CANRxFrame Frame;
|
||||
};
|
||||
|
||||
|
@ -34,8 +46,10 @@ chibios_rt::Mailbox<CanFrameData*, canFrameCount> freeBuffers;
|
|||
chibios_rt::Mailbox<CanFrameData*, canFrameCount> filledBuffers;
|
||||
|
||||
void processLuaCan(const size_t busIndex, const CANRxFrame& frame) {
|
||||
auto filter = getFilterForFrame(busIndex, frame);
|
||||
|
||||
// Filter the frame if we aren't listening for it
|
||||
if (!shouldRxCanFrame(frame)) {
|
||||
if (!filter) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -57,6 +71,7 @@ void processLuaCan(const size_t busIndex, const CANRxFrame& frame) {
|
|||
// Copy the frame in to the buffer
|
||||
frameBuffer->BusIndex = busIndex;
|
||||
frameBuffer->Frame = frame;
|
||||
frameBuffer->Callback = filter->Callback;
|
||||
|
||||
{
|
||||
// Push the frame in to the queue under lock
|
||||
|
@ -66,7 +81,14 @@ void processLuaCan(const size_t busIndex, const CANRxFrame& frame) {
|
|||
}
|
||||
|
||||
static void handleCanFrame(LuaHandle& ls, CanFrameData* data) {
|
||||
lua_getglobal(ls, "onCanRx");
|
||||
if (data->Callback == -1) {
|
||||
// No callback, use catch-all function
|
||||
lua_getglobal(ls, "onCanRx");
|
||||
} else {
|
||||
// Push the specified callback on to the stack
|
||||
lua_rawgeti(ls, LUA_REGISTRYINDEX, data->Callback);
|
||||
}
|
||||
|
||||
if (lua_isnil(ls, -1)) {
|
||||
// no rx function, ignore
|
||||
efiPrintf("LUA CAN rx missing function onCanRx");
|
||||
|
@ -144,18 +166,21 @@ void initLuaCanRx() {
|
|||
|
||||
void resetLuaCanRx() {
|
||||
// Clear all lua filters - reloading the script will reinit them
|
||||
memset(luaCanRxIds, 0, sizeof(luaCanRxIds));
|
||||
filterCount = 0;
|
||||
}
|
||||
|
||||
void addLuaCanRxFilter(int32_t eid) {
|
||||
void addLuaCanRxFilter(int32_t eid, uint32_t mask, int bus, int callback) {
|
||||
if (filterCount >= maxFilterCount) {
|
||||
firmwareError(OBD_PCM_Processor_Fault, "Too many Lua CAN RX filters");
|
||||
}
|
||||
|
||||
efiPrintf("Added Lua CAN RX filter: %d", eid);
|
||||
efiPrintf("Added Lua CAN RX filter id 0x%x mask 0x%x with%s custom function", eid, mask, (callback == -1 ? "out" : ""));
|
||||
|
||||
filters[filterCount].Id = eid;
|
||||
filters[filterCount].Mask = mask;
|
||||
filters[filterCount].Bus = bus;
|
||||
filters[filterCount].Callback = callback;
|
||||
|
||||
luaCanRxIds[filterCount] = eid;
|
||||
filterCount++;
|
||||
}
|
||||
|
||||
|
|
|
@ -448,6 +448,113 @@ private:
|
|||
pid_s m_params;
|
||||
};
|
||||
|
||||
static bool isFunction(lua_State* l, int idx) {
|
||||
return lua_type(l, idx) == LUA_TFUNCTION;
|
||||
}
|
||||
|
||||
int getLuaFunc(lua_State* l) {
|
||||
if (!isFunction(l, 1)) {
|
||||
return luaL_error(l, "expected function");
|
||||
} else {
|
||||
return luaL_ref(l, LUA_REGISTRYINDEX);
|
||||
}
|
||||
}
|
||||
|
||||
#if EFI_CAN_SUPPORT
|
||||
int lua_canRxAdd(lua_State* l) {
|
||||
uint32_t eid;
|
||||
|
||||
// defaults if not passed
|
||||
int bus = -1;
|
||||
int callback = -1;
|
||||
|
||||
switch (lua_gettop(l)) {
|
||||
case 1:
|
||||
// handle canRxAdd(id)
|
||||
eid = luaL_checkinteger(l, 1);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (isFunction(l, 2)) {
|
||||
// handle canRxAdd(id, callback)
|
||||
eid = luaL_checkinteger(l, 1);
|
||||
lua_remove(l, 1);
|
||||
callback = getLuaFunc(l);
|
||||
} else {
|
||||
// handle canRxAdd(bus, id)
|
||||
bus = luaL_checkinteger(l, 1);
|
||||
eid = luaL_checkinteger(l, 2);
|
||||
}
|
||||
|
||||
break;
|
||||
case 3:
|
||||
// handle canRxAdd(bus, id, callback)
|
||||
bus = luaL_checkinteger(l, 1);
|
||||
eid = luaL_checkinteger(l, 2);
|
||||
lua_remove(l, 1);
|
||||
lua_remove(l, 1);
|
||||
callback = getLuaFunc(l);
|
||||
break;
|
||||
default:
|
||||
return luaL_error(l, "Wrong number of arguments to canRxAdd. Got %d, expected 1, 2, or 3.");
|
||||
}
|
||||
|
||||
addLuaCanRxFilter(eid, 0x1FFFFFFF, bus, callback);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_canRxAddMask(lua_State* l) {
|
||||
uint32_t eid;
|
||||
uint32_t mask;
|
||||
|
||||
// defaults if not passed
|
||||
int bus = -1;
|
||||
int callback = -1;
|
||||
|
||||
switch (lua_gettop(l)) {
|
||||
case 2:
|
||||
// handle canRxAddMask(id, mask)
|
||||
eid = luaL_checkinteger(l, 1);
|
||||
mask = luaL_checkinteger(l, 2);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (isFunction(l, 3)) {
|
||||
// handle canRxAddMask(id, mask, callback)
|
||||
eid = luaL_checkinteger(l, 1);
|
||||
mask = luaL_checkinteger(l, 2);
|
||||
lua_remove(l, 1);
|
||||
lua_remove(l, 1);
|
||||
callback = getLuaFunc(l);
|
||||
} else {
|
||||
// handle canRxAddMask(bus, id, mask)
|
||||
bus = luaL_checkinteger(l, 1);
|
||||
eid = luaL_checkinteger(l, 2);
|
||||
mask = luaL_checkinteger(l, 3);
|
||||
}
|
||||
|
||||
break;
|
||||
case 4:
|
||||
// handle canRxAddMask(bus, id, mask, callback)
|
||||
bus = luaL_checkinteger(l, 1);
|
||||
eid = luaL_checkinteger(l, 2);
|
||||
mask = luaL_checkinteger(l, 3);
|
||||
lua_remove(l, 1);
|
||||
lua_remove(l, 1);
|
||||
lua_remove(l, 1);
|
||||
callback = getLuaFunc(l);
|
||||
break;
|
||||
default:
|
||||
return luaL_error(l, "Wrong number of arguments to canRxAddMask. Got %d, expected 2, 3, or 4.");
|
||||
}
|
||||
|
||||
addLuaCanRxFilter(eid, mask, bus, callback);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif // EFI_CAN_SUPPORT
|
||||
|
||||
void configureRusefiLuaHooks(lua_State* l) {
|
||||
LuaClass<Timer> luaTimer(l, "Timer");
|
||||
luaTimer
|
||||
|
@ -707,12 +814,8 @@ void configureRusefiLuaHooks(lua_State* l) {
|
|||
|
||||
|
||||
#if EFI_CAN_SUPPORT
|
||||
lua_register(l, "canRxAdd", [](lua_State* l) {
|
||||
auto eid = luaL_checkinteger(l, 1);
|
||||
addLuaCanRxFilter(eid);
|
||||
|
||||
return 0;
|
||||
});
|
||||
lua_register(l, "canRxAdd", lua_canRxAdd);
|
||||
lua_register(l, "canRxAddMask", lua_canRxAddMask);
|
||||
#endif // EFI_CAN_SUPPORT
|
||||
#endif // not EFI_UNIT_TEST
|
||||
}
|
||||
|
|
|
@ -61,7 +61,8 @@ void initLuaCanRx();
|
|||
// Called when the user script is unloaded, resets any CAN rx filters
|
||||
void resetLuaCanRx();
|
||||
// Adds a frame ID to listen to
|
||||
void addLuaCanRxFilter(int32_t eid);
|
||||
void addLuaCanRxFilter(int32_t eid, uint32_t mask, int bus, int callback);
|
||||
|
||||
// Called from the Lua loop to process any pending CAN frames
|
||||
void doLuaCanRx(LuaHandle& ls);
|
||||
// Called from the CAN RX thread to queue a frame for Lua consumption
|
||||
|
|
Loading…
Reference in New Issue