Custom RGB controller for Linux - MSI Motherboards
21-July-2020
This weekend I bought some RGB strips for my computer for $20 on Amazon. My motherboard (MSI Tomahawk B450) has RGB headers onboard, which are controlled by the NCT6795D Super I/O chip. For research and just preference lately, I have been daily driving Arch Linux, with a Windows dual boot. Unfortunately MSI does not provide software for Linux.

I decided to create an RGB controller for linux, that would preferably run as a service in the background and interactively control the LEDs. This was made a lot easier by finding a github repo (linked below) of someone who already reverse engineered MSI's windows software. They also left beautifully documented code.

The RGB header can be controlled by writing to port 4E in /dev/port, which has the memory layout as described below (courtesy of nagisa).

00...
01...
....
....
....
E0EE XX XX XXXP XX XX XXXX XX XX XXXX XX XX XX
F0RR RR RR RRGG GG GG GGBB BB BB BBXX XX TT TT
00 01 02 0304 05 06 0708 09 0A 0B0C 0D 0E 0F


Each colour channel has 4bit colour, giving me actually a lot more colour choices than the official MSI Mystic Light Windows softare. Each R, G, or B in the above table represents a single 4 bit colour frame, which the IO chip will cycle through with delay given in the locations marked T.

The location marked with T gives control over the time between frames, and the options to fade colours, and invert intensity etc. The location marked P is where pulsing can be enabled or disabled.

If you set all the colour frames to a single colour, it has the effect of making it a solid colour. I have my program right now polling the averaged CPU load from /proc/loadavg every 5 seconds, and settings the lights to a colour corresponding to the load.

A smooth colour gradient is created by choosing two colours for 0% CPU load, and 100% CPU load, and using linear interpolation to create a smooth gradient between these two colours at a given load percentage.

I have it transition from green at 0% CPU load, to red at 300% (3 threads being at 100% usage), and then from red to blue as it uses the rest of my 12 thread system. This has the effect of using almost the entire colour range, and giving me a nearly real time interactive RGB setup.

Furthermore I also implemented a night mode, which will turn the LEDs to red past 12AM (blue light hurts circadian rythm), and pulse beyond 300% CPU load.

Next steps are to make it more configurable, and possibly support other motherboard systems?

RGB setup as I compile a project on all 12 threads