This document is a developer- and AI-oriented overview of the repository. It summarizes current structure and runtime behavior based on the implementation in this repo.
moddable-m5chain is a Moddable SDK module for controlling M5Chain devices over a UART bus. It handles scanning, initialization, serial-bus polling, sample notification, and event dispatch, then exposes device-specific APIs via feature mixins.
- Packet framing + parsing via
sendPacket/waitForPacket - Type-based device instantiation via
createM5ChainDevice - Automatic re-scan when
ENUM_PLEASE (0xFC)arrives (debounced) - Feature composition via
withDeviceFeatures(...) - Poll loop runs only while at least one device has
onSampleset - Sample-capable public APIs follow the ECMA-419 Sensor pattern:
onSamplenotifies, andsample()returns the latest value
src/m5chain/m5chain.ts(bus communication, scan/re-scan, poll loop, dispatch)src/m5chain/createM5ChainDevice.ts(device type -> class mapping)src/m5chain/m5chainDevices/m5chainDevice.ts(base class + feature composition)src/m5chain/m5chainDevices/m5chainBus.ts(bus-typed device placeholder)
src/m5chain/m5chainDevices/m5chainEncoder.tssrc/m5chain/m5chainDevices/m5chainAngle.tssrc/m5chain/m5chainDevices/m5chainKey.tssrc/m5chain/m5chainDevices/m5chainJoyStick.tssrc/m5chain/m5chainDevices/m5chainToF.ts
src/m5chain/deviceFeatures/hasLed.tssrc/m5chain/deviceFeatures/hasKey.tssrc/m5chain/deviceFeatures/canSample.ts
src/m5chain/manifest.jsonsrc/m5chain/manifest_module.jsonsrc/m5chain/manifest_include.jsonsrc/m5chain/manifest_chain_base.jsonexamples/manifest.jsonexamples/main.ts
examples/basic/mod.jsexamples/led/mod.js
| Device | One-line Summary | Protocol PDF |
|---|---|---|
| Encoder | Rotary encoder with RGB LED + key + sample support | M5Stack-Chain-Encoder-Protocol-EN.pdf |
| Angle | Angle sensor with RGB LED + sample support | M5Stack-Chain-Angle-Protocol-EN.pdf |
| Key | Single key with RGB LED | M5Stack-Chain-Key-Protocol-EN.pdf |
| JoyStick | 2-axis joystick with RGB LED + key + sample support | M5Stack-Chain-Joystick-Protocol-EN.pdf |
| ToF | Time-of-Flight distance sensor | M5Stack-Chain-ToF-Protocol-EN.pdf |
createM5ChainDevice selects a device class by DEVICE_TYPE and returns an instance.
Each concrete class composes feature mixins via withDeviceFeatures(...).
HasLed: RGB LED APIHasKey: key state/config API + key event callbackCanSample:onSamplenotification +sample()accessor + bus sample-read integration
- Public sample-capable device APIs use sample terminology:
CanSample,onSample,sample(),hasOnSample(). onSamplecallbacks receive no value argument. Inside the callback, usethis.sample()to read the latest sample.sample()is synchronous and returns the latest cached value. The UART request happens in the internal poll loop throughreadSample().- Angle, JoyStick, and ToF dispatch
onSampleevery poll cycle with the latest value. - Encoder dispatches
onSampleonly when the encoder value changes. Itssample()value is the delta from the previous encoder value. - Internal bus scheduling may keep poll terminology (
#pollLoop,pollingInterval, logs) because the implementation periodically checks devices over the serial bus.
Packets use this frame:
- Header:
0xAA 0x55 - Length: 2 bytes, little-endian (
id/cmd/data/crcbyte count) - Payload:
id,cmd,data...,crc8 - Footer:
0x55 0xAA
sendAndWait(id, cmd, ...) resolves only when both id and cmd match the response frame.
This prevents misrouting when delayed packets arrive.
sequenceDiagram
participant App
participant M5Chain
participant UART
App->>M5Chain: new M5Chain({ transmit, receive })
App->>M5Chain: start()
M5Chain->>UART: HEARTBEAT
UART-->>M5Chain: ok
M5Chain->>UART: ENUM (device count)
UART-->>M5Chain: count
loop each device id
M5Chain->>UART: GET_DEVICE_TYPE(id)
UART-->>M5Chain: type
M5Chain->>M5Chain: createM5ChainDevice(type)
M5Chain->>UART: GET_UID (device.init)
UART-->>M5Chain: uid
end
M5Chain-->>App: onDeviceListChanged(devices)
sequenceDiagram
participant Device
participant M5Chain
Device-->>M5Chain: ENUM_PLEASE (0xFC)
M5Chain->>M5Chain: debounce (500ms)
M5Chain->>M5Chain: stop poll loop
M5Chain->>M5Chain: call onDisconnected() for old devices
M5Chain->>M5Chain: scan again
M5Chain-->>App: onDeviceListChanged(devices)
sequenceDiagram
participant M5Chain
participant Device
loop while at least one device.hasOnSample()
M5Chain->>Device: readSample()
Device-->>M5Chain: value or undefined
M5Chain-->>Device: dispatchOnSample(value)
end
import M5Chain from "m5chain";
const m5chain = new M5Chain({ transmit, receive });
m5chain.onDeviceListChanged = (devices) => {
for (const device of devices) {
// attach device-specific callbacks by device.type
}
};
m5chain.start();When asking for changes, the following expectations apply:
- This repository is a user-facing library for developers who use
m5chain; prioritize APIs and behavior that are easy to understand and use from an application. - When making changes, consider both the end-user experience of the library and the maintainability for developers working on this repository.
- Refactors are welcome.
- Please commit and report in clean, sensible units.
- Breaking API changes are acceptable.
- If code changes, update documentation accordingly.
- For implementation changes, run
npm run formatandnpm run lint, then address reported lint findings. - After modifying this repository, verify that Moddable builds pass with:
mcconfig -d -m -p esp32/m5atom_matrix -t build ./examples/manifest.jsonmcrun -d -m -p esp32/m5atom_matrix -t build ./examples/basic/manifest.json
- To verify runtime behavior on hardware with a debugger, run
mcconfigwith-dland without-t build, for example:mcconfig -dl -m -p esp32/m5atom_matrix ./examples/manifest.json
-t buildverifies the build only. It does not flash the device or enterxsdb.- The
-dloption startsxsdb, a debugger that can be used similarly togdb. Use thehelpcommand insidexsdbfor command details. - Use
xsdbto confirm the app starts without errors and emits the expected logs. - If
mcconfig -dlreports#xsbug-log missing modules! Did you npm install?, install the Moddable log tool dependencies with:pushd $MODDABLE/tools/xsbug-log && npm install && popd
- When verification is complete, exit
xsdbwithquit. - Do not leave debugger/logging processes running in the background. After using
mcconfig -dl,xsbug-log,serial2xsbug, orxsdb, confirm that no related process is still listening on the xsbug port, for example:lsof -nP -iTCP:5002 -sTCP:LISTEN
- If a leftover
xsbug-log,serial2xsbug, orxsdbprocess remains, terminate it before reporting completion. Background debugger processes make the current hardware/debug state hard to understand for the next operator.