RGB LED ring patterns
Hardware and data format
Decompiled: voice-agent:0x2bf5f0 opens /dev/topleds, queries ioctl 0x80047a02, and expects 36 channels. This corresponds to 12 RGB LEDs. Updates use LEDS_WS2812B_IOCTL_MULTI_SET (check-factory-reset:0x17140 references the ioctl diagnostic).
Most ring resources contain 12 #rrggbb strings per frame:
[
{
"duration": 0.0166,
"colors": ["#aa0a00", "#710700", "#000000"]
}
]
The example is abbreviated. The shared parser is in led_animation_parser.cpp; rgb_led.cpp parses hex colors. RGB and display animations can run together but use independent device nodes.
Pattern families
| UX state | Resources |
|---|---|
| Voice lifecycle | listening_start.json, listening.json, listening_error.json, thinking_loop.json, speaking*.json |
| Setup | settings_enter.json, settings_intro.json, settings_loader_start.json, settings_loader.json, settings_receiving.json, settings_wait.json, settings_success.json |
| Microphone | mic_on.json, mic_off.json, mute_error.json, volume_mute.json |
| Volume/night mode | volume.json, volume_night.json, night_mode_start.json, night_mode_stop.json, night_mode_volume_error.json |
| Bluetooth | BT_waiting.json, BT_connected.json, BT_disconnected.json |
| Calls | call_incoming.json, call_waiting.json, call_accept.json, call_end.json |
| Alarms/timers | alarm.json, timer.json, reminder.json |
| Media | start_track.json, pause_track.json, next_track.json, prev_track.json |
| Connectivity/errors | ready.json, loading.json, connection_error.json, announcement.json, vk_notification.json |
| Stereo pairing | CC_pairdLeft_diodes.json, CC_pairdRight_diodes.json, CC_stereoLeft_v3_diodes.json, CC_stereoRight_v3_diodes.json, stereopair_success.opus |
| OTA | updateDownloadComplete_diodes.json |
| Reset | hwreset_intro.json, hwreset_done.json, factoryResetJoke_diodes.json |
The complete frame/channel/duration inventory is generated at firmware/manifest/led-inventory.tsv by summarize_led.py. All 97 RGB and segment JSON resources are also published verbatim as raw downloads. The interactive preview has been removed for now.
Volume animation
voice-agent contains dedicated classes including VolumeAnimationContinuousTop, VolumeAnimationOneShotTopSlow/Fast, VolumeChangeAnimationFast/Continuous, VolumeChangedFadeoutAnimation, and VolumeAnimationClock. Flags include volume_animation_fps, volume_animation_bezier, volume_animation_in_ms, volume_animation_out_ms, and volume_animation_still_ms.
Thus volume is not just a static selection of one JSON frame: the agent computes transitions and can react to audio level. Separate flags set minimum/maximum animation response for listening, TTS, and music.
Reset sequence
Decompiled from check-factory-reset:sub_10C00: while the user holds the reset combination, the RGB ring plays hwreset_intro.json (301 frames, approximately 5 seconds) in parallel with the display's reset icon. Successful completion switches to hwreset_done.json (123 frames, approximately 2 seconds). The agent then plays 30_reset_v3.flac and returns status 1 to S60, which creates the reset marker and reboots.
Resource limits and timing quirks
The resource set is shared with other Capsula variants and is not perfectly uniform:
alarm.json,timer.json,reminder.json,mute_error.json,night_mode_volume_error.json,volume_mute.json, andvk_notification.jsoncontain 13 colors rather than the Mini's 12.- Some files use
secondsinstead ofduration. volume.jsonuses values such as16.6, while most animations use fractions of a second.listening.jsonand several other resources have zero total duration when interpreted naively.
Decompiled: the parser accepts up to 24 RGB colors, so a 13-color file is valid input. The Mini writer at voice-agent:0x2b97f0 copies only the first 36 channel bytes. Therefore the 13th RGB color is ignored on Mini, not displayed on extra hardware.
duration is a per-frame time in seconds. seconds is a timestamp form whose next duration is the timestamp difference. An FPS supplied by the consumer overrides resource durations; this is how millisecond-looking values such as 16.6 can coexist with the same parser. Consequently the generated led-inventory.tsv is an inventory, not a claim that every file plays with one universal duration interpretation.