TrimuiLEDController
A application to configure the LEDs on the TrimUI Brick.
Install / Use
/learn @pierceTee/TrimuiLEDControllerREADME
TrimUI LED Controller
An application to configure the LEDs on the TrimUI Brick (smart pro support WIP).
Configure all LED brightness, color, and effect!

Installation
This application is designed for the TrimUI smart Brick emulation handheld. There has been no testing of operational safety on any other hardware.
- Stock OS: Place the
LedController.pakfolder in theAppsfolder of your SDCARD and launch from theAppsmenu. - MinUI: Place the
LedController.pakfolder in theTools/tg3040folder of your SDCARD and launch from theToolsmenu.
Usage Guide
Controls
From the configuration menu:
- DPAD UP/DOWN: Change the selected setting.
- DPAD L/R: Change the value of the selected setting.
- START: Access the start menu.
- B/POWER: Exit the application.
- L/R: Switch the active LED.
From the start menu:
- DPAD UP/DOWN: Change the selected setting.
- B/START: Return to config page.
- A: Execute selected setting.
Menu Options
- Sync LED colors: Match all LED colors to the currently selected LED.
- Turn ON all LEDs: Enable all LEDs by setting their brightness to the maximum value.
- Turn OFF all LEDs: Disable all LEDs by setting their brightness to 0.
- Enable/Disable extended colors: Toggle the ability to select colors from an extended range of RGB values.
- Enable/Disable low battery warning: Toggle the default OS behavior of flashing LEDs when the battery falls below 15%.
- Uninstall: Uninstall all services and system files, turning off the LEDs on exit.
Development Guide
All development work has been performed in a Docker container from arm64-tg3040-toolchain running on a Windows host machine. Theoretically, this should be cross-platform, but practical applicability is left to the reader.
If you want everything handled for you, run dev_scripts/make-all-packages from the root of the project directory, then navigate to the corresponding release folder.
To Build Manually:
- Pull submodules and build the
toolchains/arm64-tg3040-toolchainDocker container. - Run
dev_scripts/run-container.shto enter into thearm64-tg3040-toolchainimage. - Run
maketo build the project, thenmake packageto package it into therelease/aarch64folder. - To test the application:
- On your host machine: Select a project from
release/<host_architecture>/(e.g.,release/<host_architecture>/LedController) and run the application from the command line. - On your device:
- MinUI:
- Copy the project release
release/aarch64/LedControl.pakto<SDCARD_ROOT>/Tools/tg3040/. - On the device, navigate to
Tools, find yourLedControllerentry, and launch.
- Stock OS:
- Copy the project release
release/aarch64/LedControllerto your<SDCARD>/Apps/. - On the device, navigate to your
Led Controllerentry in the "apps" section and launch.
Although alternatives are easily attainable, the project is structured with the idea that the user will compile in the Docker container found in toolchains. From this container, you can run the application as if it were on the TrimUI device given you've connected your host display to the container (see dev_scripts/run-container.sh). You can use a tool like gdb to debug the application from your host machine by navigating to your host machine's architecture release directory and manually launching with your desired debugger. Just be aware that while all versions of the app should behave the same, this isn't guaranteed to be the same behavior you see on your TrimUI device.
Troubleshooting
- Dependency issues: Try running
make deps. - Compiler issues: Try running
dev_scripts/setup-toolchain.shfollowed bydev_scripts/setup-env.sh. - Docker issues: Try running
./toolchains/arm64-tg3040-toolchain/make shellthen./dev_scripts/run-container.sh.
References/Findings
All logic is derived from the help file found in /sys/class/led_anim/
[TRIMUI LED Animation driver]
max_scale : maximum LED brightness in dec [0 ~ tg5040 limit brightness 60]
frame : raw frames for total 23 XRGB 32bpp data
frame_hex : frames for total 23 XRGB 32bpp data in hex format "RRGGBB RRGGBB RRGGBB ... RRGGBB " end with space.
[usage of anim to function]
effect_lr: Left and right joystick LEDS effect type.
effect_l: Left joystick LEDS effect type.
effect_r: Right joystick LEDS effect type.
effect_m : middle LED effect type.
(effect_x for a trigger of effect start)
effect_names : show the effect types description.
effect_duration_lr: Left and right joystick LEDS animation durations.
effect_duration_l: Left joystick LEDS animation durations.
effect_duration_r: Right joystick LEDS animation durations.
effect_duration_m : middle LED effect duration.
effect_rgb_hex_lr: Left and right LED all target color in format "RRGGBB " end with space.
effect_rgb_hex_l: Left LED all target color in format "RRGGBB " end with space.
effect_rgb_hex_r: Right LED all target color in format "RRGGBB " end with space.
effect_rgb_hex_m: Middle LED target color in format "RRGGBB " end with space.
effect_cycles_lr: Left and right joystick LEDS animation loops.
effect_cycles_l: Left joystick LEDS animation loops.
effect_cycles_r: Right joystick LEDS animation loops.
effect_cycles_m : middle LED effect loops.
(cycles value: 0 for stop, -1 for endless loop, > 0 for loop times)
effect_enable : toggle of anim to function
[usage of framebuffer animation function !!Did not finish yet!!]
anim_frames: raw frames for total XRGB 32bpp data, buffer length 10 sec@60fps, 23 data per frame.
anim_frames_hex: same as anim_frames and use hex format "RRGGBB RRGGBB RRGGBB ... RRGGBB " end with space.
anim_frames_cycle: animation loops count
anim_frames_enable : toggle of frames anim function
anim_frames_override_m_enable: toggle of middle LED in frames anim function.
The tricky part was getting a daemon running on boot. First, systemctl isn't installed on the device so it's not as easy as starting/stopping with that. Daemons in /etc/init.d also use a different format than I've seen before, they're very primitive and seem to order themselves by a START variable (with 0 being first and running in order from there). I've done my best to run the daemon at the right time to make the changes feel seamless (i.e., the OS doesn't control the LEDs at any point) by placing the order just before the runtrimui service. Run grep -H "START=" /etc/init.d/* | awk -F 'START=' '{print $2, $0}' | sort -n | cut -d' ' -f2- on the device to see the order of boot services for more context.
Getting a functioning daemon was a bit of a pain but here are a few things that helped me see where I was going wrong:
- The brick uses an OpenWrt
/etc/rc.commonscript to 'link' 'start', 'stop', 'restart', 'reload', 'boot', 'shutdown', and 'enable' services. So using this script will ensure compatibility with whatever the OS is expecting. - Check the examples in
/etc/init.da few times and cross-reference with what/etc/rc.commonthings are a little fast and loose (printfandechoboth work? so dostart,start_service,start_service_remote, andstart_service_daemon[see/etc/init.d/log]). I should probably look into this standard to better understand what's going on under the hood.
1/12/2025: Turns out there's a directory usr/trimui/bin (should have looked at the minUI launch scripts a bit more thoroughly). In there is a script usr/trimui/bin/init_leds.sh. I'd bet we can just override this for an easy install method. There's a usr/trimui/bin/low_battery_led.sh that I should also overwrite to lock/unlock permission in toggling the LEDs.
P.s: there's loads more scripts in here, this might be the key to unlocking more functionality. UPDATE: overwriting this script didn't seem to do anything :(
Looks like MinUI actually does exactly what I'm thinking of doing here, they move usr/trimui/bin/runtrimui.sh usr/trimui/bin/runtrimui-original.sh and replace it with skeleton/BOOT/trimui/app/runtrimui.sh which then launches MinUI's .tmp_update/updater (or runtrimui-original.sh if the SDCARD isn't found).
usr/trimui/bin/trimui_inputd is the input daemon written in C so maybe this is where runtime daemons go?
Tons of more interesting things in usr/trimui, all the stock apps are in usr/trimui/apps and can easily be moved to the SDCARD for use in other OSs, alternatively we can move our app in here for a "permanent" install. usr/trimui/gamecontrollerdb.txt seemingly has the mapping of controllers to SDL inputs, if we wanted to add support for a certain controller, it would go there.
usr/trimui/lib has all the installed libraries listed here:
libSDL-1.2.so.0 libSDL_image-1.2.so.0
libSDL-1.2.so.0.11.4 libSDL_image-1.2.so.0.8.4
libSDL2-2.0.so.0 libSDL_mixer-1.2.so.0
libSDL2-2.0.so.0.3000.8 libSDL_mixer-1.2.so.0.12.0
libSDL2_image-2.0.so.0 libSDL_ttf-2.0.so.0
libSDL2_image-2.0.so.0.2.3 libSDL_ttf-2.0.so.0.10.1
libSDL2_mixer-2.0.so.0 libgamename.so
libSDL2_mixer-2.0.so.0.0.1 libshmvar.so
libSDL2_ttf-2.0.so.0 libtmenu.so
libSDL2_ttf-2.0.so.0.14.1
I wonder if we could swap in some binaries to support more applications?
Final Thoughts
Yes, this project is totally overkill. This can be done MUCH simpler as controlling the LEDs is as simple as echo-ing an integer into a few text files. But that's no fun... I was on winter break and had been meaning to dip my toes back into firmware/OS development, this project helped scratch that itch.
Much of the project time was spent building a strong framework for myself and others to continue
