LED patterns

N800
The N800 has a single-colour (blue) LED behind the dpad.

N810
The N810 has an RGB LED.

File Location
The file defining patterns can be found in /etc/mce/mce.ini

An application (mcedit) for modifying LED patterns was written for the n8x0, but this will not work with the n900 due to the new mce.ini format.

An app to edit LED patterns on the N900 has just been released: "LED Pattern Editor"

Pattern Format
The patterns are broken down as follows:


 * PatternName=Priority;ScreenOn;Timeout;LEDsToMap;Engine1Pattern;Engine2Pattern

Priority
0-255, 0 is highest, 255 is lowest.

Since currently only a single pattern at a time can be displayed, this is used to assign importance to the LED patterns. Although only a single LED pattern can be displayed at any time, multiple patterns may be active, the pattern with the highest priority being displayed.

A common example of this is where the n900 is on charge, the battery is full (starting PatternBatteryFull with a priority of 40), and an SMS message is received (PatternCommunicationSMS with a priority of 30). On receipt of the SMS, the LED begins to display the flashing blue led of an SMS. Once that SMS has been dismissed, the green LED of the full battery notification is again displayed.

ScreenOn

 * 0: only show pattern when the display is off
 * 1: show pattern even when the display is on
 * 2: only show pattern when the display is off, including acting dead
 * 3: show pattern even when the display is on, including acting dead
 * 4: only show pattern if the display is off, or if in acting dead
 * 5: always show pattern, even if LED disabled

TimeOut
This is the time-out of the LED pattern in seconds. 0 for infinite, i.e. until the notification is dismissed.

If this is set to 20, the pattern will display for 20 seconds, and then stop.

LEDsToMap
There are two engines that can be used to make custom LED patterns.

r, g, or b maps the corresponding colour channel to Engine 1.

R, G, or B maps the corresponding colour channel to Engine 2.

For example, "rG" maps the red channel to Engine 1, and the green channel to Engine 2.

You should avoid mapping the same channel to both engines, for example "rR", "gG" or "bB"

Engine Pattern
This is a series of text that describes the speed and intensity of changes in the LED(s) beign managed by that particular engine. See below for a breakdown of the patterns. Each can be at most 16 commands long.

Lysti Format Engine Patterns and Commands
The LED patterns are of the form
 * 9d8040007f007f0040ff7f007f000000

Breaking this down for ease of reading we get a list of 8 commands, each of which is four characters long.
 * 9d80 4000 7f00 7f00 40ff 7f00 7f00 0000

9d80 - Refresh Engine Multiplexor
This is to be used as the first command of every pattern). If this is excluded from the pattern, the led won't flash.

40xx - Set channel brightness
Where xx are two hexadecimal digits, e.g. 00 (for a brightness of 0) or ff (for a brightness of 255).

xxyy - Adjust channel brightness
Increment or decrement the channel brightness over a period of time (xx) and a number of steps (yy).

Where xx and yy are hexadecimal digits

xx - Time (per step?)

yy - Number of steps

The following rules apply to these:
 * If xx is even, the steps are increment steps and brightness will increase.
 * If xx is odd, the steps are decrement steps and brightness will decrease.
 * If xx is between 02 and 3f, a short step time is used (granularity 0.49ms)
 * If xx is between 42 and 7f, a long step time is used (granularity 15.6ms)
 * yy can be any value between 00 and ff (0 to 255)
 * Pauses can be achieved by using 00 steps, e.g. 7f00 where, where the 7f is how long each step takes and 00 is how many increment steps to take.

The mce.ini instructions (/etc/mce/mce.ini) also state that
 * Two consecutive increment/decrement sequences are needed to cover the entire range from 0-255

However I believe this is a throwback to the older patterns, and the full range of 00 to ff is available in a single step for the number of steps, since whether these are increment or decrement steps are now handled through use of even or odd xx values.

0000 - Jump to start
Jump to the start of the pattern for this channel. You will see this at the end of most repeating patterns.

This command may not actually be needed to make the pattern repeat. If this is removed, the pattern will repeat anyway, although it's useful to have it there as an explicit command to repeat for clarity. If you wanted a pattern to run once and then terminate you would use the c000 command.

A000 .. BFFF - Branch
101 : 16bit

llllll : 6bit; Loop count, 0=infinite loop, max 63 loops

sssssss : 7 bit; Step number; Value to store to PC (0-95 actual progspace of LP5523 of 96 16bit commands. [Unclear if that's absolute address, or probably offset to start of program space assigned to the particular engine])

c000 - End pattern execution
(also d000 = with hw INT; c800/d800 = with PC reset. INT might serve to signal end-of-pattern to main CPU ->*)

The pattern is terminated without repeating. It is important to note here that although that pattern has stopped, it is still active *) until the Timeout time has passed. As a consequence of this any higher priority patterns (patterns with a lower priority value, since 0 is the highest and 255 is the lowest) will not be displayed until the pattern has fully expired. In the case that the timeout is 0, it will not display until the notification is dismissed.

Sending and receiving engine triggers
Further complexity in patterns can be added through use of triggers. This is especially useful if we want to synchronise the two engines in time, for example to wait until the LED has turned red before turning it immediately to green. Rather than waste time with steps doing nothing, we can simply wait for a trigger to be received from the other engine.

The following pattern does exactly that:
 * PatternTest=29;1;0;rG;9d80400008ffe0044000c000;9d80e08040ffc000

e002, e004, e008 - Send engine trigger
e002 - Send trigger to engine 1

e004 - Send trigger to engine 2

e008 - Send trigger to engine 3 (used by keyboard backlight)

A signal is sent from the current engine to signal another engine.

Although the trigger information for engine 3 is listed we have no control over the keyboard LED, so it has no effect. Attempting to add a pattern for engine 3 after the pattern for engine 2 causes the pattern to no longer function.

e080, e100, e200 - Wait for engine trigger
e080 - Wait for trigger from engine 1

e100 - Wait for trigger from engine 2

e200 - Wait for trigger from engine 3 (used by keyboard backlight)

Although the trigger information for engine 3 is listed we have no control over the keyboard LED, so it has no effect. Attempting to add a pattern for engine 3 after the pattern for engine 2 causes the pattern to no longer function.

Default LED Patterns for Nokia N900
PatternError=0;5;0;r;9d8040007f007f0040ff7f007f000000;9d800000 PatternDeviceOn=254;0;0;rgb;9d804000422043207f100000;9d800000 PatternDeviceSoftOff=253;0;0;rg;9d804000423f433f7f100000;9d800000 PatternPowerOn=9;3;0;rgb;9d80400042ff02ffc000;9d800000 PatternPowerOff=10;3;0;rgb;9d80400001ff43ff7f007f00c000;9d800000 PatternCommunicationCall=30;1;0;b;9d80400002ff03ff02ff03ff71080000;9d800000 PatternCommunicationIM=30;1;0;b;9d80400002ff03ff02ff03ff71080000;9d800000 PatternCommunicationSMS=30;1;0;b;9d80400002ff03ff02ff03ff71080000;9d800000 PatternCommunicationEmail=30;1;0;b;9d80400002ff03ff02ff03ff71080000;9d800000 PatternCommonNotification=30;1;0;b;9d80400002ff03ff02ff03ff71080000;9d800000 PatternWebcamActive=20;1;0;r;9d80400004ffc0000000;9d800000 PatternBatteryCharging=50;4;0;rg;9d804000427f0d7f7f007f0042000000;9d800000 PatternBatteryFull=40;4;0;g;9d80407f0000;9d800000

Community-Made Patterns
Please note that these patterns should all be on one line. They can also be used for any notification.

A traffic-light battery charging pattern, courtesy of blue_led PatternBatteryCharging=50;4;0;Rg;9d80407f7f00e0047f0040007f007f007f00407f7f00e0047f007f000000;9d804000e080407fe0800000

A police-siren style pattern, idea by mihapodb. This pattern cuts quickly between blue and red. PatternCommunicationEmail=30;1;0;rB;9d8040ff7f00e00440007f000000;9d80e08040ff7f0040000000

A police-siren style pattern, idea by villo. This pattern fades between red and blue. PatternCommunicationEmail=30;1;0;rB;9d8004ff05ffe004e1000000;9d80e08004ff05ffe0020000

Cehteh's patterns with some comments

Slow dark glowing in cyan, never goes fully off, so you can locate the device in the dark: PatternDeviceOn=254;0;0;gb;9d804001620863087f007f007f007f007f007f007f007f007f007f007f000000;9d800000

Slow dark glowing in yellow, never goes fully off, so you can locate the device in the dark: PatternBatteryCharging=50;3;0;rg;9d804001427f0d7f7f007f0042000000;9d800000

Slow dark glowing in white, never goes fully off, so you can locate the device in the dark: PatternBatteryFull=40;3;0;rgb;9d804001620863087f007f007f007f007f007f007f007f007f007f007f000000;9d800000

White, bright flashing (must be enabled in 'LEDPatterns=' ?): PatternExample=42;1;30;rgb;9d8040007f007f0040ff42000000;9d800000

Step by step instructions
cp /etc/mce/mce.ini /etc/mce/mce.ini_old [LEDPatternLystiRX51] initctl stop mce; sleep 2; initctl start mce
 * Open terminal
 * Gain Root access
 * Make a backup (not necessary!) from original mce.ini -file, for example:
 * Open /etc/mce/mce.ini with a text editor (nano, vim, leafpad...)
 * Search for a line:
 * Make your changes to the lines below
 * Save
 * Restart mce -process. Either reboot or type to terminal:

Please note: restarting mce several times in 2 minutes will cause the n900 to think there is a problem with mce, and not restart it. The initctl program will inform you of this. When it does, simply wait a while before trying again.

Low Level
The N900 has a LP5521 programmable three channel controller LED Driver which handles the leds. (actually it has a LP5523 it seems, which has 3 engines like LP5521 but can drive 9 LEDs via a multiplexer)

The controller can be programmed via "/sys/class/i2c-adapter/i2c-2/2-0032" (FIXME: is this stable?). In that directory there are three files corresponding to the three channels: engine1_mode, engine2_mode and engine3_mode. Each file "stores" one of "run", "load", "disabled" (it seems that there is another mode "direct" but it doesn't work): After that, when the state is changed to "run", the program will be ran by the controller.
 * run: The program runs
 * disabled: The channel is disabled - not running
 * load: In that state, there are two more files in that directory:
 * engine1_leds is in the form "0000rgb00" (9 digits, "1" or "0"), where rgb control which leds should participate. The 6 "0" in the above pattern correspond to the 6 kbd white leds controlled by mce via engine3, so readout of engine3_leds gives 111100011 ;-)
 * engine1_load accepts a string as specified above (e.g. 9d804000427f0d7f7f007f0042000000). LP5523 has an absolute storage of 96 steps a 16bits, which can dynamically partitioned between the three engines. (ToDo: check if driver supports >16 instructions / machine)

In order for the leds to work, the led_current of the appropriate leds need to be set to non-zero values. This is accomplished by writing to files leds:lp5523:[bgr]/led_current under the same directory. Perhaps (?) not or values are suitable.

NOTE: There must be a delay (how much? The specs of LP5521 mentions it) between writes to sysfs files.