The 'P' commands support the popular WorldSemi® WS2812
Green-Red-Blue LED protocol.
The word "emit" below means "transmits the entire data array as defined by
the pixel count out the default Port and Pins." The WS2812 default Port
and Pins are configured using EEPROM addresses 12 and 13.
The "P" command group:
P? dispays (or prints) the pixel data array contents
P?+ a "P?" option; prints in the foreground instead of the background
P?- a "P?" option; omits the "SRAM contents:" header row
P-?+ both "P?" options above; can be input in any order
P = ## where '#' is the pixel count; BYTE count = pixel count time 3
the maximum depends on the number of uVars.B[##] bytes used
the BYTE count is the first WORD in the pixel data area
PG = # set BYTE 1; clear BYTEs 2 and 3 - These 3 commands each set only
PR = # set BYTE 2; clear BYTEs 1 and 3 - one byte of an LED triplet and
PB = # set BYTE 3; clear BYTEs 1 and 2 - emit the array upon completion
PW = # sets the same value in all BYTEs (i.e., "White") and emits the array
PC = #[ #[ #]]" sets the same color triplets to all LEDs and emits the array
P0 zeroes all of the bytes in the WS2812 array but does not emit them
P0U zeroes all of the bytes in the WS2812 array and does emit them
P # = #[[,] # ...] writes one or more BYTEs into the G,R,B data array
the bytes start at the pixel number specified before "="
there are 3 BYTEs per pixel; multiple BYTEs may be entered
PU # = #[[,] # ...] same as above but also emits them
PU updates (or emits) the pixel data array out to the WS2812 LEDs
the "U" may be appended to commands which normally do not emit
PZ sleep; sends triplets of 0,0,0 to as many pixels as "P =" defined
does not change the contents of the pixel data array
this simply turns all of the defined pixels off
it may be reversed with the simple "PU" command
P@ #### validates then loads a sequencer configuration from EEPROM address ####
(after that, @ alone steps the sequencer routine one time)
Notes:
"P?+-" is the same as "P-?+", which is the same as "P-+?", etc.
"P0" is the same as "P 0"; "PU" is the same as "P U"
"PU0" is the same as "PU 0", or "P U 0", or "P 0 U"
for operators other than "=", use the "ES ### [op] #[ ...#]" syntax
>P?
SRAM contents:
>02A0: 00 00 ..
P = 8
>p?+
SRAM contents:
02A0: 18 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
02B0: 00 00 00 00 00 00 00 00-00 00 ..........
>PG = 40
p+?
SRAM contents:
02A0: 18 00 28 00 00 28 00 00-28 00 00 28 00 00 28 00 ..(..(..(..(..(.
02B0: 00 28 00 00 28 00 00 28-00 00 .(..(..(..
>PR = 0x80
>P ? -+
02A0: 18 00 00 80 00 00 80 00-00 80 00 00 80 00 00 80 ................
02B0: 00 00 80 00 00 80 00 00-80 00 ..........
>pZ ; This is a "sleep" command; no pixel data change
>p?
SRAM contents:
>02A0: 18 00 00 80 00 00 80 00-00 80 00 00 80 00 00 80 ................
02B0: 00 00 80 00 00 80 00 00-80 00 ..........
P 0
>p+?
SRAM contents:
02A0: 18 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
02B0: 00 00 00 00 00 00 00 00-00 00 ..........
>P 2 = 0x80 0 0x40 0 32 32 40 32 20 U
>P+?
SRAM contents:
02A0: 18 00 00 00 00 80 00 40-00 20 20 28 20 14 00 00 .......@. ( ...
02B0: 00 00 00 00 00 00 00 00-00 00 ..........
>
Of course, the examples shown above lose something since the actual pixel
output cannot be viewed unless a WS2812 LED string is actually connected
to the controller. EEPROM address 12 and 13 select which PORT and PINs are
those which the "P" command will cause to "wiggle" in order to emit the
tightly-timed WS2812 command sequences.
EEPROM address 12 stores the default WS2712 Port & (single) Pin:
MASK_DefPandP_PORT = B11110000 ; 0x0# = PORTA, 0x1# = PORTB, 0x2# = PORTC
MASK_DefPandP_OFF = B00001000 ; If TRUE, the next BYTE has the PIN map, else
MASK_DefPandP_PINS = B00000111 ; 0=B00000001, 1=B00000010 ... , 7=B10000000
EEPROM address 13 is used only if the prior byte's bit 3 (B00001000) is ON
bitmap of the PINs (using the prior byte's PORT) on which to emit WS2812 data
For example, to set the default output of the 'P' commands to:
only PORT C, PIN 0, use "E 12 = 0x20" or "E 12 = 0x28 0x01"
only PORT C, PIN 1, use "E 12 = 0x21" or "E 12 = 0x28 0x02"
only PORT C, PIN 2, use "E 12 = 0x22" or "E 12 = 0x28 0x04"
only PORT C, PIN 5, use "E 12 = 0x25" or "E 12 = 0x28 0x20"
PORT C, PINS 0 through 2, use "E 12 = 0x28 0x07"
PORT C, PINS 1 through 4, use "E 12 = 0x28 0x1E"
PORT C, PINS 2 through 5, use "E 12 = 0x28 0x3C"
PORT C, PINS 0 through 5, use "E 12 = 0x28 0x3F"
PORT D, PINS 0 through 7, use "E 12 = 0x38 0xFF"
Up to 480 LEDs have been configured and worked successfully, when only
the default number of uVars.B[##] variables (32) were configured.
That means that the pixel data size is 2 + 480 * 3 = 1,442 bytes.
The 328P microcontroller only has 2,048 bytes of SRAM, and 416 of them
(0x100 through 0x29F) are always used by the MIRTOS Operating System. The
pixel data array with 480 LEDs would then begin at SRAM address 0x2A0 and
end at address 0x841. The stack is initialized at 0x8FF (the address of
the last byte of SRAM), which leaves only 190 bytes (0x842 to 0x8FF) of
stack space. That is really dangerously minimal! In fact, some commands
will cause the stack to descend into that pixel configuration. Overwriting
the stack WILL cause a system crash, so be very careful about how many LEDs
are configured, particularly if over 400 or if using other features.
Most WS2812 devices encountered use Green-Red-Blue byte order, but some
have been found to use a Red-Green-Blue byte order instead. This
documentation is written with the GRB order in mind, but, in either case,
the bytes are still emitted as the same bit stream to the pin(s) selected.
How they are actually interpreted totally depends on the receiving LED
device(s).
Finally, a WS2812 (EEPROM) configuration can be validated and loaded using
the "P@ EEptr" command. The sequencer logic can then be stepped one time
using the "@" command. An example of this is as shown in the following
series of commented commands:
>DV+ ; Note that no configuration is loaded
SRAM contents:
0280: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0290: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
>P?+ ; Verify that pixels are not configured yet
SRAM contents:
02A0: 00 00 ..
>DE+ 0x240 48 ; There are 3 sequencer configurations
EEPROM contents:
0240: 00 12 3C 02 FF 20 00 FF-FF FC 28 00 1E 00 FF FF ..<.. ....(.....
0250: 08 22 3C 02 E0 40 00 D0-D0 D0 A6 00 14 00 FF FF ."<..@..........
0260: 10 E2 3C 00 00 40 00 60-AB AF C8 00 2D 00 FF A0 ..<..@.`....-...
>P@ 0x250 ; Validate & load the middle one
>dv+ ; Verify that config #2 was loaded
SRAM contents:
0280: 08 22 3C 02 E0 40 00 D0-D0 D0 A6 00 14 00 FF FF ."<..@..........
0290: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
>p+? ; No change to uVars[] yet
SRAM contents:
02A0: 00 00
>@
>; To step, the command must be "@" alone (not even "@ "!)
>p+? ; Verify initializing step occurred
SRAM contents:
02A0: C0 00 00 00 1E 00 00 2A-00 00 1B 00 00 0F 00 00 .......*........
02B0: 39 00 00 5B 00 00 B4 00-00 2C 00 00 23 00 00 06 9..[.....,..#...
02C0: 00 00 AB 00 00 3F 00 00-DF 00 00 9D 00 00 D8 00 .....?..........
02D0: 00 31 00 00 43 00 00 9B-00 00 77 00 00 3B 00 00 .1..C.....w..;..
02E0: A6 00 00 62 00 00 71 00-00 3F 00 00 1D 00 00 70 ...b..q..?.....p
02F0: 00 00 06 00 00 68 00 00-BE 00 00 C1 00 00 B2 00 .....h..........
0300: 00 31 00 00 8C 00 00 A8-00 00 38 00 00 39 00 00 .1........8..9..
0310: B2 00 00 BF 00 00 CA 00-00 CB 00 00 90 00 00 98 ................
0320: 00 00 9C 00 00 59 00 00-4D 00 00 88 00 00 54 00 .....Y..M.....T.
0330: 00 11 00 00 21 00 00 08-00 00 93 00 00 2E 00 00 ....!...........
0340: D9 00 00 70 00 00 2B 00-00 D9 00 00 67 00 00 8D ...p..+.....g...
0350: 00 00 D6 00 00 2C 00 00-6D 00 00 5B 00 00 C0 00 .....,..m..[....
0360: 00 2A .*
>@
>; Also note: no need to be logged in to sequence one step
>P?+ ; Verify that the step caused a change in pixel data
SRAM contents:
02A0: C0 00 00 00 1C 00 00 28-00 00 19 00 00 0D 00 00 .......(........
02B0: 37 00 00 59 00 00 B2 00-00 2A 00 00 21 00 00 04 7..Y.....*..!...
02C0: 00 00 A9 00 00 3D 00 00-DD 00 00 9B 00 00 D6 00 .....=..........
02D0: 00 2F 00 00 41 00 00 99-00 00 75 00 00 39 00 00 ./..A.....u..9..
02E0: A4 00 00 60 00 00 6F 00-00 3D 00 00 1B 00 00 6E ...`..o..=.....n
02F0: 00 00 04 00 00 66 00 00-BC 00 00 BF 00 00 B0 00 .....f..........
0300: 00 2F 00 00 8A 00 00 A6-00 00 36 00 00 37 00 00 ./........6..7..
0310: B0 00 00 BD 00 00 C8 00-00 C9 00 00 8E 00 00 96 ................
0320: 00 00 9A 00 00 57 00 00-4B 00 00 86 00 00 52 00 .....W..K.....R.
0330: 00 0F 00 00 1F 00 00 06-00 00 91 00 00 2C 00 00 .............,..
0340: D7 00 00 6E 00 00 29 00-00 D7 00 00 65 00 00 8B ...n..).....e...
0350: 00 00 D4 00 00 2A 00 00-6B 00 00 59 00 00 BE 00 .....*..k..Y....
0360: 00 28 .(
>P@ 0x260 ; Load the 3rd config from EEPROM
>Dv+
SRAM contents:
0280: 10 E2 3C 00 00 40 00 60-AB AF C8 00 2D 00 FF A0 ..<..@.`....-...
0290: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
>
See also:
The At or @ command page.