TACHYON [~
FORGET WS2812.fth
pub WS2812.fth PRINT" WS2812 Intelligent RGB LED driver V1.0 141030.0900 " ;
--- NOTE: Use the latest kernel V24140928.1630 (or binary) as it has a bug fix for the WS2812 driver (msb<>lsb)
--- FONT5X7.fth is in the Tachyon Dropbox folder under extras
--- LINKS --- --- YOUTUBE LINK --- --- Propeller binary --- |
--- This section of code started off as a tidy-up of some code mindrobots was playing with from my original untested demo.
DECIMAL --- set default base to decimal
--- User define I/O parameters ---
#P24 MASK == WSTXD --- define our transmit pin as a mask
--- define length of LED string, for my matrix I have 5 strips of 8 LEDs.
5 == strips --- I have 5 strips of 8
8 strips * == ledcnt --- number of LEDs in string
ledcnt 3 * == rgbsz --- specify the size of the array as a constant
--- Setup display buffers in a data area so they are contiguous and can be handled that way
--- 3 bytes for each pixel, byte order is green,red,blue
BUFFERS ORG
rgbsz DS rgbstage
24 DS rgbgap
rgbsz DS rgbleds
24 DS rgb --- overflow for chase wraparound - could be set to more than 3
--- Setup the RUNMOD and port for the WS2812 ---
pub !WS2812
WSTXD OUTCLR --- Start a RET to synch the chips
WSTXD 4 COGREG! --- setup the I/O pin for the RUNMOD to use
[WS2812] --- select the WS2812 module for RUNMOD
;
BYTE refresh --- create a flag to indicate a synchronized refresh is requested
pub REFRESH refresh C~~ ;
--- Show the contents of rgbleds buffer on the LEDs ---
pub ?SHOW --- synchronized SHOW
refresh C@ 0EXIT --- exit and don't bother if not requested
pub SHOW
refresh C~ --- clear refresh flag and uppdate the LEDs
rgbleds rgbsz RUNMOD --- pass the address of the array and the byte count to the RUNMOD
#50 us --- WS2812 needs at least 50us to RET although there are delays elsewhere
;
pub % ( val per -- val2 ) * 100 / ;
--- COLOR Definitions ---
--- variable color control
LONG inkcol,papercol
pub INK ( colormask -- ) inkcol ! ;
pub PAPER ( colormask -- ) papercol ! ;
--- colors require an 8-bit weight and generate a color mask
--- ( weight -- color_mask )
--- Usage: <weight> <color> INK or <weight> <color> PAPER
pub RED >B 8 SHL ;
pub GREEN >B ;
pub BLUE >B 16 SHL ;
pub YELLOW DUP RED SWAP GREEN + ;
pub MAGENTA DUP RED SWAP BLUE + ;
pub WHITE DUP RED OVER BLUE + + ;
{
pub SETRGB ( weight red% green% blue% --- colormask )
4TH SWAP % BLUE 4TH ROT % GREEN + ROT ROT % RED +
;
--- These colors are expressed as percentages of RGB but are still weighted
pub AQUA 31 80 63 SETRGB ;
pub TEAL 2 93 100 SETRGB ;
pub SEPIA 37 15 7 SETRGB ;
pub CHARTREUSE 44 78 44 SETRGB ;
pub ORCHID 100 51 98 SETRGB ;
pub PINK 100 75 80 SETRGB ;
pub INDIGO 2 91 100 SETRGB ;
pub ORANGE 100 33 0 SETRGB ;
}
IFNDEF %%
pub %% SWAP 1+ * 8 SHR ;
}
pub SETRGB ( weight code -- colormask )
DUP >B 3RD %% BLUE ( w c mask )
OVER 8 SHR >B 4TH %% GREEN + ( w c mask )
SWAP 16 SHR >B 3RD %% RED + ( w mask )
NIP
;
pub AQUA &31.80.63 SETRGB ;
pub TEAL &2.93.100 SETRGB ;
pub SEPIA &37.15.7 SETRGB ;
pub CHARTREUSE &44.78.44 SETRGB ;
pub ORCHID &100.51.98 SETRGB ;
pub PINK &100.75.80 SETRGB ;
pub INDIGO &2.91.100 SETRGB ;
pub ORANGE &100.33.0 SETRGB ;
pub MALACHITE $108070 SETRGB ;
pub TURQUOISE $0FDDAF SETRGB ;
--- some color weight constants
--- Usage: WEAK RED PAPER
06 == FAINT
30 == WEAK
64 == LIGHT
128 == MEDIUM
192 == STRONG
255 == BOLD
--- Exception is BLACK without descriptor
00 == BLACK
--- words to work with the two LED color arrays
--- ACT affects the ACTive array (not used directly in this demo )
--- STG affects the staging array (used to draw the character in MATRIX )
--- LED array parameters
pub STG rgbstage rgbsz ;
pub ACT rgbleds rgbsz ;
pub LED! ( g.r.b lednum* buffer sz --- )
--- Usage: <color> led STG LED or <color> led ACT LED
--- Example: RED 4 STG LED
--- note: sz is redundant but passed as part of buffer parameter
DROP
SWAP 1 MAX ledcnt MIN 1- 3 * + --- calc address of array plus offset for LED (limit)
SWAP rgb !
rgb SWAP 3 CMOVE --- copy 3 bytes into buffer position
;
--- RELOAD the active array from the staging array
pub RELOAD
rgbstage
pub LOAD ( src -- )
rgbleds rgbsz CMOVE --- copy to the active byte array
;
--- Simple DEMO code to make RGB LEDs chase each other --
TIMER ledtimer --- create a timer structure variable (automatically linked at runtime)
WORD spd --- allow for the speed to be varied interactively
BYTE stepsz --- variable step size for unified slide or chase etc
pub (STEP) --- perform a single chase step (move to next LED )
spd W@ ledtimer TIMEOUT --- reload timer with current speed
stepsz C@
pub SSTEP ( cnt -- ) --- a manual step entry for debug
rgbleds DUP 3RD + rgbsz <CMOVE --- shift them all along (in reverse) - overflows into rgb variable
rgb rgbleds ROT CMOVE --- write last 3 bytes back to start (wrap)
REFRESH
;
--- DEBUG words to manipulate the timer and single step through the ACTIVE array
pub ANIMATE ( on/off -- ) --- stops or starts the timer using current speed
spd W@ AND ledtimer TIMEOUT
;
pub SPEED ( n -- ) --- sets a delay so a higher value is slower
1 MAX 10000 MIN spd W!
;
pub FAST 50 SPEED ;
pub SLOW 500 SPEED ;
pub FASTER spd W@ 80 % SPEED ;
pub SLOWER spd W@ 120 % SPEED ;
--- adjust the brightness of the array
pub DIMMER ( buf sz -- ) ADO I C@ DUP 2/ - I C! LOOP ;
pub BRIGHTER ( buf sz -- ) ADO I C@ DUP 2/ 1 MAX + I C! LOOP ;
pub CHASE ( --- )
3 --- step size of 3 = 1 rgb pixel
pub STEPS ( steps -- )
stepsz C!
' (STEP) ledtimer ALARM --- set countdown timer alarm action
!WS2812 --- setup WS2812 resources
STG ERASE --- erase the staging buffer
WEAK GREEN 1 STG LED! --- set first LED to GREEN
WEAK RED 2 STG LED! --- set second LED to RED
WEAK BLUE 3 STG LED! --- set third LED to BLUE
WEAK WHITE 4 STG LED! --- set fourth LED to WHITE
RELOAD --- move the staging array to the active array
FAST --- set initial chase speed
ON ANIMATE
' SHOW keypoll W! --- run the LED update in the console background
;
pub SLIDE ( --- )
1 STEPS --- step size of 1 = 1 color
;
--- MATRIX TESTS ---
( Five 8-way strips were wired up into a matrix as shown below )
--- MAINFRAME STYLE ANIMATION ---
pub (MAINFRAME) --- background timing function
RND LOAD --- just pick anywhere in memory (all mirrored)
REFRESH --- let keypoll function know to update
spd W@ ledtimer TIMEOUT --- reload timer with current speed
;
pub MAINFRAME
!WS2812
' (MAINFRAME) ledtimer ALARM --- do this in the background
1000 SPEED ON ANIMATE --- start it up
' ?SHOW keypoll W! --- and let main console cog worry about I/O
;
--- CHARACTER MATRIX TESTS ---
--- set default color for character matrix
WEAK ORANGE INK
FAINT GREEN PAPER
--- animation speed control
BYTE scspd
pub SS scspd C! ;
#50 SS --- set default animation speed
pub SCROLL1 ( -- \ scroll new character into the matrix by one colum )
rgbstage DUP #24 + #24 #10 * <CMOVE --- move all memory up by one column
rgbstage #24 ERASE
SHOW
;
pub SCROLL
6 FOR SCROLL1 scspd C@ #5000 * FOR NEXT NEXT
;
--- just a Q&D hack to read from my unoptimised font table to my WS2812 matrix configuration
pub MATCHAR ( ch -- )
DUP BL < IF DROP EXIT THEN --- skip control characters just in case
BL - 7 * FONT5X7 + ( addr ) --- calculate address of character in font table
5 0 DO --- 5 columns of 5x7 font
7 0 DO --- 7 rows high
DUP I + C@ J MASK AND 0<> --- examine next font row pixel in current column
inkcol @ AND --- convert to color or black
DUP 0= IF papercol @ OR THEN --- set background instead of just black
I J 8 * + 1+ STG LED! --- and set corresponding LED pixel in staging
LOOP
LOOP
DROP
SCROLL
REFRESH --- request a refresh (if handled)
;
pub MATCTRL ( ch -- ) --- process control characters
SWITCH
$0C CASE STG 2* ERASE BREAK --- clear the staging and screen
^R CASE MEDIUM RED INK BREAK --- just some quick little color controls
^G CASE MEDIUM GREEN INK BREAK
^B CASE MEDIUM BLUE INK BREAK
$1C CASE 10 SS BREAK --- scroll fast
$1D CASE 50 SS BREAK --- scroll normal
$1E CASE 100 SS BREAK --- scroll slow
;
--- Text output routine to direct characters to the terminal and to the matrix display
pub (MATRIX)
DUP (EMIT)
DUP BL < --- test to see if this is a control character
IF
MATCTRL --- handle control chars
ELSE
MATCHAR --- draw the character and scroll it in
THEN
;
--- Direct text output to the MATRIX display
pub MATRIX
!WS2812 ' (MATRIX) uemit W! --- make sure the WS2812 is configured and redirect output
' SHOW keypoll W! --- run the LED update in the console background (optional)
;
pub DEMO MATRIX $0C EMIT PRINT" HELLO WORLD" CON ;
]~ END
?BACKUP