API Reference: LED & Button Control¶
📌 After reading this page: You will be able to control all three onboard LEDs and three buttons using both polling and event-driven approaches. ⏱️ Estimated reading time: 15 minutes 🧰 Prerequisites: Ex.01 (polling) + Ex.02 (event-driven) + Ex.03 (long press) 🎯 Key functions:
XM_SetLedState/XM_SetLedEffect/XM_GetButtonState/XM_GetButtonEvent/XM_SetChannelLedRGB(Rev2.0)
This is the detailed reference for the onboard UI (LED, Button) control API defined in xm_api_led_btn.h.
The XM10 firmware lets you implement advanced input/output features — Blink, Click, Long Press, and more — with simple function calls, so you never need to write timer interrupts or debouncing logic yourself.
1. How It Works¶
This module is time-driven. Behind the scenes, internal Managers run continuously in the background to make everything work.
The Core Engine: XM_IO_Update()¶
- Role: This is the engine that calculates LED blink timing, analyzes button signals, removes noise (debouncing), and generates events.
- Execution: Called automatically by the system at a 1 ms (1 kHz) interval. You do not need to call it yourself, but understanding its role is important.
- Flow:
- User calls
XM_SetLedEffect→ settings are stored. XM_IO_Updateruns periodically → toggles the LED ON/OFF as time passes.- User presses a button →
XM_IO_Updatemeasures elapsed time → determines "click" or "long press" and stores the result in the event queue. - User calls
XM_GetButtonEvent→ retrieves the event from the queue and returns it.
- User calls
2. Data Structures (Enumerations)¶
All identifiers and state values are defined as enums for ease of use. Use these named constants instead of raw numbers (0, 1, 2...).
2.1. Identifiers¶
XmLedId_t¶
Identifies the Function LED to control.
typedef enum {
XM_LED_1 = 1, /**< Left LED */
XM_LED_2 = 2, /**< Center LED */
XM_LED_3 = 3 /**< Right LED */
} XmLedId_t;
XmBtnId_t¶
Identifies the Function Button to read.
typedef enum {
XM_BTN_1 = 1, /**< Left button */
XM_BTN_2 = 2, /**< Center button */
XM_BTN_3 = 3 /**< Right button */
} XmBtnId_t;
2.2. State Types¶
XmState_t¶
Represents the logical ON/OFF state of an LED or similar output.
XmBtnState_t¶
Represents the current physical press state of a button. (Abstracted away from the circuit's Active-High/Low polarity.)
typedef enum {
XM_RELEASED = 0, /**< Button is not pressed */
XM_PRESSED = 1 /**< Button is pressed */
} XmBtnState_t;
2.3. Modes & Events¶
XmLedMode_t¶
Determines the LED behavior pattern.
| Mode | Description |
|---|---|
XM_LED_OFF |
Turns the LED off. |
XM_LED_SOLID |
Keeps the LED on continuously. |
XM_LED_BLINK |
Blinks at a fixed period (50% duty cycle). |
XM_LED_HEARTBEAT |
Flashes twice in quick succession, like a heartbeat. |
XM_LED_ONESHOT |
Turns on for a set duration, then turns off automatically. (Useful for notifications.) |
XmBtnEvent_t¶
High-level events generated by analyzing button input.
| Event | Description |
|---|---|
XM_BTN_NONE |
No event detected |
XM_BTN_PRESSED |
Button was just pressed (rising edge) |
XM_BTN_RELEASED |
Button was just released (falling edge) |
XM_BTN_CLICK |
Short press and release (click) |
XM_BTN_LONG_PRESS |
Held for 1 second or more (use for mode changes, etc.) |
3. Function Reference¶
3.1. LED Control Functions¶
XM_SetLedState¶
Turns an LED on or off directly. This is the most straightforward control function.
- Syntax
- Parameters
led_id: The LED to control (XM_LED_1\~3)state: Target state (XM_ON,XM_OFF)
- Example
XM_SetLedEffect¶
Applies a special effect (such as blinking) to an LED. Once set, XM_IO_Update() drives the effect automatically — no timer code required.
- Syntax
- Parameters
led_id: The LED to controlmode: Behavior mode (XM_LED_BLINK,XM_LED_HEARTBEAT, etc.)period_ms: Period or duration of the effect, in millisecondsBLINK: Blink period (e.g., 500 = blink every 0.5 s)ONESHOT: On-time duration (e.g., 200 = stay on for 0.2 s then turn off)SOLID/OFF: Ignored (pass 0)
- Example
3.2. Button Control Functions¶
XM_GetButtonState¶
Reads the current physical state of a button in real time. (Polling approach.)
- Syntax
- Parameters
btn_id: The button to read (XM_BTN_1\~3)
- Returns:
XM_PRESSED(pressed) orXM_RELEASED(not pressed) - Example
XM_GetButtonEvent¶
Retrieves the latest event generated by a button. (Event-driven approach.)
Each event is consumed once it is read — it is removed from the internal queue (Read-Clear). Store the return value in a variable or use it directly in a switch statement.
- Syntax
- Parameters
btn_id: The button to read
- Returns: The detected event (
XM_BTN_CLICK,XM_BTN_LONG_PRESS, etc.) - Example
XmBtnEvent_t evt = XM_GetButtonEvent(XM_BTN_1); if (evt == XM_BTN_CLICK) { // Fires once when button 1 is clicked XM_SendUsbDebugMessage("Button 1 Clicked!\r\n"); } else if (evt == XM_BTN_LONG_PRESS) { // Fires once when button 1 is long-pressed XM_SendUsbDebugMessage("Button 1 Long Pressed!\r\n"); }
3.3. Channel LED (Rev2.0 Only)¶
XM_SetChannelLedRGB¶
Rev2.0 only — Not available on Rev1.1.
Controls per-channel RGB LEDs driven by the PCA9957. Use this to visually indicate the connection status of sensor modules.
- Syntax
-
Parameters
Name Description chChannel identifier ( XM_CH_LED_EMG,XM_CH_LED_FES,XM_CH_LED_IMU,XM_CH_LED_HMMG,XM_CH_LED_GRF_L,XM_CH_LED_GRF_R,XM_CH_LED_USB)rRed brightness (0–255) gGreen brightness (0–255) bBlue brightness (0–255) -
Note: Setting
r=0, g=0, b=0restores automatic system control. -
Example
3.4. System Functions¶
XM_IO_Update¶
[System-managed] The driving function that updates LED and button states.
This must be called periodically from the control-loop task (Control_Loop) — in Control_Loop or inside XM_TSM_Run — for Blink and Long Press to work correctly.
- Syntax
- Note: The system calls this automatically while it collects inputs, so end users do not normally need to call it directly.
⚠️ Common Mistakes¶
| Symptom | Cause | Fix |
|---|---|---|
| LED blink mode is set but nothing happens | XM_IO_Update is not being called (the control-loop task (Control_Loop) has stalled, or XM_TSM_Run is missing) |
The system calls it automatically — check that your user code is not stuck in an infinite loop |
GetButtonEvent returns the same event multiple times |
GetButtonEvent is being called in more than one place inside Run_Loop (concurrent Read-Clear consumers) |
Read each event channel from exactly one place |
XM_BTN_LONG_PRESS never triggers |
Hold time is less than 1 second | Hold the button for at least 1 second |
SetLedState has no effect after SetLedEffect |
Effect mode takes priority — SetLedState is ignored or overwritten |
Call SetLedEffect(LED, XM_LED_OFF, 0) to cancel the effect first |
Center/right button presses are not detected, or map to the wrong XM_BTN_N |
Built with a ZIP for the wrong board revision — the onboard button MCU pins are shifted by one position between Rev1.1 (PC10/11/12) and Rev2.0 (PC11/12/13) | Confirm your board revision from the board label, then re-import using the correct revision's ZIP (Board Revision Comparison) |
| Channel LED RGB does nothing | Using Rev1.1 — PCA9957 is not populated | Rev2.0 only — Rev1.1 has three onboard LEDs only |
ONESHOT LED does not re-fire after the first time |
This is by design (one-shot) | To re-trigger it, call SetLedEffect again on each event |
Related Examples¶
| Example | Difficulty | LED / Button Usage |
|---|---|---|
| 00_Quick_Start | Beginner | Boot sequence + toggle |
| 01_Button_LED_Basic | Beginner | Polling state mirror |
| 02_Button_LED_Event | Beginner | Event-driven + ONESHOT |
| 03_Button_LED_FSM | Intermediate | Long press + Heartbeat/Blink |
| 18_Debug_Monitor | Intermediate | Diagnostic LED patterns |