Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions components/common/app_claw/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,15 @@ menu "App Claw Config"
Enable the UART Lua driver and keep app_claw's direct dependency
on lua_driver_uart when Lua capability is enabled.

config APP_CLAW_LUA_DRIVER_TWAI
bool "Enable TWAI Lua driver"
default y if SOC_TWAI_SUPPORTED
default n
help
Enable the TWAI Lua driver (Two-Wire Automotive Interface / CAN bus)
and keep app_claw's direct dependency on lua_driver_twai when Lua
capability is enabled. Defaults to n on chips without TWAI hardware.

comment "--- Higher-level modules (lua_module) ---"

config APP_CLAW_LUA_MODULE_AUDIO
Expand Down Expand Up @@ -346,13 +355,6 @@ menu "App Claw Config"
Enable the LED strip Lua module and keep app_claw's direct dependency
on lua_module_led_strip when Lua capability is enabled.

config APP_CLAW_LUA_MODULE_LVGL
bool "Enable LVGL Lua module"
default n
help
Enable the LVGL Lua module and keep app_claw's direct dependency
on lua_module_lvgl when Lua capability is enabled.

config APP_CLAW_LUA_MODULE_MAGNETOMETER
bool "Enable magnetometer Lua module"
default n
Expand Down
31 changes: 14 additions & 17 deletions components/common/app_claw/app_lua_modules.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
#if CONFIG_APP_CLAW_LUA_DRIVER_UART
#include "lua_driver_uart.h"
#endif
#if CONFIG_APP_CLAW_LUA_DRIVER_TWAI
#include "lua_driver_twai.h"
#endif

/* --- lua_module (higher-level modules) --- */
#if CONFIG_APP_CLAW_LUA_MODULE_AUDIO && defined(CONFIG_ESP_BOARD_DEV_AUDIO_CODEC_SUPPORT)
Expand Down Expand Up @@ -88,9 +91,6 @@
#if CONFIG_APP_CLAW_LUA_MODULE_LED_STRIP
#include "lua_module_led_strip.h"
#endif
#if CONFIG_APP_CLAW_LUA_MODULE_LVGL
#include "lua_module_lvgl.h"
#endif
#if CONFIG_APP_CLAW_LUA_MODULE_MAGNETOMETER
#include "lua_module_magnetometer.h"
#endif
Expand Down Expand Up @@ -284,6 +284,14 @@ static esp_err_t app_lua_register_uart(const char *fatfs_base_path)
}
#endif

#if CONFIG_APP_CLAW_LUA_DRIVER_TWAI
static esp_err_t app_lua_register_twai(const char *fatfs_base_path)
{
(void)fatfs_base_path;
return lua_driver_twai_register();
}
#endif

/* --- lua_module register wrappers --- */

#if CONFIG_APP_CLAW_LUA_MODULE_AUDIO && defined(CONFIG_ESP_BOARD_DEV_AUDIO_CODEC_SUPPORT)
Expand Down Expand Up @@ -422,14 +430,6 @@ static esp_err_t app_lua_register_led_strip(const char *fatfs_base_path)
}
#endif

#if CONFIG_APP_CLAW_LUA_MODULE_LVGL
static esp_err_t app_lua_register_lvgl(const char *fatfs_base_path)
{
(void)fatfs_base_path;
return lua_module_lvgl_register();
}
#endif

#if CONFIG_APP_CLAW_LUA_MODULE_MAGNETOMETER
static esp_err_t app_lua_register_magnetometer(const char *fatfs_base_path)
{
Expand Down Expand Up @@ -483,6 +483,9 @@ static const app_lua_module_entry_t s_lua_module_entries[] = {
#endif
#if CONFIG_APP_CLAW_LUA_DRIVER_UART
{ "uart", "UART", app_lua_register_uart },
#endif
#if CONFIG_APP_CLAW_LUA_DRIVER_TWAI
{ "twai", "TWAI", app_lua_register_twai },
#endif
/* --- lua_module (higher-level modules) --- */
#if CONFIG_APP_CLAW_LUA_MODULE_AUDIO && defined(CONFIG_ESP_BOARD_DEV_AUDIO_CODEC_SUPPORT)
Expand Down Expand Up @@ -536,9 +539,6 @@ static const app_lua_module_entry_t s_lua_module_entries[] = {
#if CONFIG_APP_CLAW_LUA_MODULE_LED_STRIP
{ "led_strip", "LED Strip", app_lua_register_led_strip },
#endif
#if CONFIG_APP_CLAW_LUA_MODULE_LVGL
{ "lvgl", "LVGL", app_lua_register_lvgl },
#endif
#if CONFIG_APP_CLAW_LUA_MODULE_MAGNETOMETER
{ "magnetometer", "Magnetometer", app_lua_register_magnetometer },
#endif
Expand Down Expand Up @@ -628,9 +628,6 @@ static const app_lua_module_info_t s_lua_module_infos[] = {
#if CONFIG_APP_CLAW_LUA_MODULE_LED_STRIP
{ "led_strip", "LED Strip" },
#endif
#if CONFIG_APP_CLAW_LUA_MODULE_LVGL
{ "lvgl", "LVGL" },
#endif
#if CONFIG_APP_CLAW_LUA_MODULE_MAGNETOMETER
{ "magnetometer", "Magnetometer" },
#endif
Expand Down
12 changes: 6 additions & 6 deletions components/common/app_claw/idf_component.yml
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,12 @@ dependencies:
- if: $CONFIG{APP_CLAW_LUA_DRIVER_UART} == True
path: ../../lua_modules/lua_driver_uart

lua_driver_twai:
rules:
- if: $CONFIG{APP_CLAW_CAP_LUA} == True
- if: $CONFIG{APP_CLAW_LUA_DRIVER_TWAI} == True
path: ../../lua_modules/lua_driver_twai

# --- lua_module (higher-level modules) ---

lua_module_audio:
Expand Down Expand Up @@ -259,12 +265,6 @@ dependencies:
- if: $CONFIG{APP_CLAW_LUA_MODULE_LED_STRIP} == True
path: ../../lua_modules/lua_module_led_strip

lua_module_lvgl:
rules:
- if: $CONFIG{APP_CLAW_CAP_LUA} == True
- if: $CONFIG{APP_CLAW_LUA_MODULE_LVGL} == True
path: ../../lua_modules/lua_module_lvgl

lua_module_magnetometer:
rules:
- if: $CONFIG{APP_CLAW_CAP_LUA} == True
Expand Down
12 changes: 12 additions & 0 deletions components/lua_modules/lua_driver_twai/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
idf_component_register(
SRCS
"src/lua_driver_twai.c"
INCLUDE_DIRS
"src"
REQUIRES
cap_lua
esp_driver_twai
freertos
)

idf_component_set_property(${COMPONENT_NAME} WHOLE_ARCHIVE TRUE)
70 changes: 70 additions & 0 deletions components/lua_modules/lua_driver_twai/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Lua TWAI (CAN bus)

This module exposes the ESP32 TWAI (Two-Wire Automotive Interface / CAN bus) peripheral
to Lua scripts. It wraps the ESP-IDF v6 `esp_driver_twai` API and uses a FreeRTOS queue
to buffer received frames so scripts can poll with a timeout.

## How to call
- Import it with `local twai = require("twai")`
- Create a node with `local can = twai.new(tx_gpio, rx_gpio, bitrate [, opts])`
- `tx_gpio`, `rx_gpio`: GPIO numbers for TWAI TX and RX lines
- `bitrate`: bus speed in bits/s, e.g. `125000`, `250000`, `500000`, `1000000`
- `opts` (optional table):
- `listen_only`: `true` to monitor without transmitting (default `false`)
- `loopback`: `true` for self-test mode (default `false`)
- `can:enable()` — start the node (must call before send/receive)
- `can:disable()` — stop the node (node handle is still valid)
- `can:send(id, data [, is_extended [, is_rtr]])` — transmit a frame
- `id`: 11-bit (standard) or 29-bit (extended) arbitration ID
- `data`: string of up to 8 bytes, e.g. `"\x01\x02\x03"`
- `is_extended`: `true` for 29-bit ID (default `false`)
- `is_rtr`: `true` for Remote Frame (default `false`)
- `can:receive([timeout_ms])` → table or `nil`
- `timeout_ms`: how long to wait for a frame (`0` = non-blocking, `-1` = forever)
- Returns `{id=..., data="...", extended=bool, rtr=bool}` or `nil` on timeout
- `can:status()` → `{state, tx_errors, rx_errors, tx_queue_remaining, bus_errors}`
- `state`: `"active"`, `"warning"`, `"passive"`, or `"bus_off"`
- `can:recover()` — initiate bus-off recovery
- `can:close()` — disable and delete the node, free resources

## Example: send and receive
```lua
local twai = require("twai")

local can = twai.new(10, 11, 500000)
can:enable()

-- Send a standard frame (11-bit ID)
can:send(0x123, "\x01\x02\x03\x04")

-- Send an extended frame (29-bit ID)
can:send(0x1ABCDEF, "\xFF\xFE", true)

-- Poll for an incoming frame (100 ms timeout)
local frame = can:receive(100)
if frame then
print(string.format("id=0x%X ext=%s rtr=%s data=%q",
frame.id, tostring(frame.extended), tostring(frame.rtr), frame.data))
end

local st = can:status()
print("state:", st.state, "tx_err:", st.tx_errors, "rx_err:", st.rx_errors)

can:close()
```

## Example: continuous listener
```lua
local twai = require("twai")
local can = twai.new(10, 11, 250000, {listen_only = true})
can:enable()

while true do
local f = can:receive(500)
if f then
print(string.format("[0x%03X] %s", f.id, f.data:gsub(".", function(c)
return string.format("%02X ", c:byte())
end)))
end
end
```
Loading