See examples of usage in draw-snake2 and draw-together.
At present, there is no support in the touch module for this,
only via the message parser.
* a ws2812 framebuffer object into which all drawing should happen. This
framebuffer should be closed over in any timer callbacks.
-* a color parameter, expressed as three arguments 0-255: green, red, blue
- (as per ws2812 byte ordering).
+* A color palette array. Each entry is a string of three, where the bytes
+ form the green, red, and blue color values (0-255), as per ws2812 byte
+ ordering. Most drawings will simply use entry 1.
``lamp-touch.lua`` (see below) knows the naming scheme used by ``init2.lua``
and so walks the list of files on the system looking for files whose name
-return function(t,fb,g,r,b)
+return function(t,fb,p)
fb:fill(0,0,0)
- local c = string.char(g,r,b)
+ local c = p[1]
local ft = { [1] = function() fb:set(2,c) fb:set(9,0,0,0) fb:set(10,c) fb:set(17,0,0,0) fb:set(18,c) fb:set(14,c) fb:set(15,0,0,0) fb:set(22,c) fb:set(23,0,0,0) fb:set(26,c) end, --start flapping
[2] = function() fb:set(2,0,0,0) fb:set(3,c)
fb:set(6,0,0,0) fb:set(27,c) fb:set(5,c)
ix = (ix == 4 and 1) or ix + 1
dodraw()
end)
- end
\ No newline at end of file
+ end
-- 24 o W W W W W W o
--
-return function(t,fb,g,r,b)
+return function(t,fb,p)
fb:fill(0,0,0)
-- static base
local i,v
for i,v in ipairs({18,23,26,27,28,29,30,31}) do fb:set(v,2,2,1) end -- whiteish (W)
for i,v in ipairs({10,15,19,20,21,22}) do fb:set(v,1,1,1) end -- dim white (w)
+ local g = p[1]:byte(1)
+ local r = p[1]:byte(2)
+ local b = p[1]:byte(3)
+
local cmax = math.max(r,g,b)
-- off channels stay off, on channels stay on, just minimally dim
-- x o o x o o x o
-- x o o o o x x o
-- o x o o x o o x
-return function(t,fb,g,r,b)
+return function(t,fb,p)
fb:fill(0,0,0)
- local c = string.char(g,r,b)
+ local c = p[1]
fb:set( 2,c) fb:set( 5,c) fb:set( 8,c)
fb:set( 9,c) fb:set(12,c) fb:set(15,c)
fb:set(17,c) fb:set(22,c) fb:set(23,c)
-return function(t,fb,g,r,b) fb:fill(g,r,b) end
+return function(t,fb,p) fb:fill(p[1]:byte(1),p[1]:byte(2),p[1]:byte(3)) end
-- 24 o o l o f f f o
--
-return function(t,fb,g,r,b)
+return function(t,fb,p)
fb:fill(0,0,0)
- local c = string.char(g,r,b)
+ local c = p[1]
+ local g = c:byte(1)
+ local r = c:byte(2)
+ local b = c:byte(3)
local cdim = string.char(math.floor((g+1)/2),math.floor((r+1)/2),math.floor((b+1)/2))
for i,v in ipairs({17,18,19,20}) do fb:set(v,0xf,0,0) end -- stem (s)
-- 16 o o o o o o o o
-- 24 o o o x x o o o
--
-return function(t,fb,g,r,b)
- local c = string.char(g,r,b)
+return function(t,fb,p)
+ local c = p[1]
local i,v
fb:fill(0,0,0)
for i,v in ipairs({2,7,9,11,14,16,28,29}) do fb:set(v,c) end
-return function(t,fb,g,r,b)
+return function(t,fb,p)
fb:fill(0,0,0)
- local c = string.char(g,r,b)
+ local c = p[1]
fb:set( 3,c) fb:set( 5,c)
fb:set(10,c) fb:set(11,c) fb:set(12,c) fb:set(13,c) fb:set(14,c)
fb:set(19,c) fb:set(20,c) fb:set(21,c)
-return function(t,fb,g,r,b)
- local c = string.char(g,r,b)
+return function(t,fb,p)
+ local c = p[1]
local ft = { [1] = function() fb:set(11,c) fb:set(13,c) end, -- side chambers
[2] = function() fb:set(11,0,0,0) fb:set(20,c) fb:set(13,0,0,0) end, -- bottom chamber
[3] = function() fb:set(20,0,0,0) end, -- empty
-- 0 x 0 - - x - -
-- 1 0 1 x x - - -
-- - - - - - x - -
-return function(t,fb,g,r,b)
+return function(t,fb,p)
fb:fill(0,0,0)
local ix = 1
- local c = string.char(g,r,b)
+ local c = p[1]
fb:set( 2,c) fb:set( 9,c) fb:set(10,c)
fb:set(11,c) fb:set(14,c) fb:set(18,c) fb:set(20,c)
fb:set(21,c) fb:set(30,c)
-return function(t,fb,g,r,b)
+return function(t,fb,p)
local ix = 1
- local c = string.char(g,r,b)
+ local c = p[1]
fb:fill(0,0,0)
t:register(50,tmr.ALARM_AUTO,function()
fb:fade(2); fb:set(ix,c); dodraw()
--
-return function(t,fb,g,r,b)
+return function(t,fb,p)
local ix = 2 -- since we start effectively in state 1...
- local c = string.char(g,r,b)
+ local c = p[1]
local z = string.char(0,0,0)
local ft = { -- open mouth
[1] = function() fb:set(16,z) fb:set(24,z) fb:set(9,c) fb:set(17,c) fb:set(2,c) fb:set(26,c) end
- return function(t,fb,g,r,b)
+ return function(t,fb,p)
fb:fill(0,0,0)
- local c = string.char(g,r,b)
+ local c = p[1]
fb:set( 2,c) fb:set( 3,c) fb:set( 6,c) fb:set( 7,c)
fb:set( 9,c) fb:set(12,c) fb:set(13,c) fb:set(16,c)
fb:set(17,c) fb:set(20,c) fb:set(21,c) fb:set(24,c)
-return function(t,fb,g,r,b)
+return function(t,fb,p)
fb:fill(0,0,0)
local ix = 0
- local c = string.char(g,r,b)
+ local c = p[1]
fb:set( 2,c) fb:set( 3,c) fb:set( 6,c) fb:set( 7,c)
fb:set( 9,c) fb:set(12,c) fb:set(13,c) fb:set(16,c)
fb:set(17,c) fb:set(19,c) fb:set(20,c) fb:set(21,c)
-return function(t,fb,g,r,b)
+return function(t,fb,p)
fb:fill(0,0,0)
local ix = 0
- local c = string.char(g,r,b)
+ local c = p[1]
local x = string.char(0,0,0)
fb:set( 3,c) fb:set( 8,c) fb:set(10,c) fb:set(15,c)
fb:set(17,c) fb:set(18,c) fb:set(22,c) fb:set(23,c)
-return function(t,fb,g,r,b)
+return function(t,fb,p)
local ix = 0
- local c = string.char(g,r,b)
+ local c = p[1]
fb:fill(0,0,0)
fb:set(25,c) fb:set(26,c) fb:set(19,c) fb:set(28,c) fb:set(29,c) fb:set(30,c)
fb:set(23,c) fb:set(15,c) fb:set(7,c) fb:set(8,c)
-- a more curious snake with occasional red "heart" nearby
--
+-- Palette: snake, heart
+--
+--
-- 1 2 3 4 5 6 7 8
-- 00 o o o o o h x h
-- 08 o o o o o e x o
-- 16 w w w w o o x o
-- 24 w w w w x x x o
--
-return function(t,fb,g,r,b)
+return function(t,fb,p)
local ix = 2 -- since we start effectively in state 1...
- local c = string.char(g,r,b)
+ local c = p[1]
+ local h = p[2] or string.char(0,15,0) -- heart defaults red
local z = string.char(0,0,0)
local ft = { -- flatten out
[1] = function() fb:set(25,c) fb:set(27,c) fb:set(17,z) fb:set(19,z) end
-- look forward
, [3] = function() fb:set(6,z) fb:set(8,c) end
-- heart on (like what we see)
- , [4] = function() fb:set(14,0,15,0) end
+ , [4] = function() fb:set(14,h) end
-- slither 1
, [5] = function() fb:set(20,c) fb:set(28,z) end
-- slither 2
-return function(t,fb,g,r,b)
- local c = string.char(g,r,b)
+return function(t,fb,p)
+ local c = p[1]
+ local g = p[1]:byte(1)
+ local r = p[1]:byte(2)
+ local b = p[1]:byte(3)
local cmax = math.max(r,g,b)
local i,v
for i,v in ipairs{...} do fb:set(v,ag,ar,ab) end
end
- local function drawEq() for i,v in ipairs({3,6}) do fb:set(v,g,r,b) end end
+ local function drawEq() for i,v in ipairs({3,6}) do fb:set(v,c) end end
local function drawTwinkleEyes() drawbiased(3,6) end
local ft = { [0] = drawEq, drawEq, drawTwinkleEyes }
fb:fill(0,0,0)
-- Two hands animate together, heartbeat, then repeat at offset (to average
-- out the symmetry breaking)
-
+--
+-- Palette: together, left, right
+--
-- 1 2 3 4 5 6 7 8 -- 1 2 3 4 5 6 7 8 -- 1 2 3 4 5 6 7 8
-- 00 o 1 o o o o 1 o -- 00 o o 2 o o 2 o o -- 00 o o 3 o 3 o o o
-- 08 1 o o o o o o 1 -- 08 o 2 o o o o 2 o -- 08 o 3 o 3 o 3 o o
-- (or shifted right one)
-return function(t,fb,g,r,b)
+return function(t,fb,p)
local k,v
- local c = string.char(g,r,b)
+ local c = p[1]
+ local c2 = p[2] or c
+ local c3 = p[3] or c
local offset = 0
local ft = {
-- animate together
- function() fb:fill(0,0,0) for k,v in ipairs({2,7,9,16,18,23,27,30}) do fb:set(v,c) end end,
+ function() fb:fill(0,0,0)
+ for k,v in ipairs({2,9,18,27}) do fb:set(v,c2) end -- left
+ for k,v in ipairs({7,16,23,30}) do fb:set(v,c3) end -- right
+ end,
function() end,
- function() fb:fill(0,0,0) for k,v in ipairs({3,6,10,15,19,22,28,29}) do fb:set(v,c) end end,
+ function() fb:fill(0,0,0)
+ for k,v in ipairs({3,10,19,28}) do fb:set(v,c2) end -- left
+ for k,v in ipairs({6,15,22,29}) do fb:set(v,c3) end -- right
+ end,
function() end,
+ function() fb:fill(0,0,0)
+ for k,v in ipairs({3,10,19}) do fb:set(v+offset,c2) end -- left
+ for k,v in ipairs({5,14,21}) do fb:set(v+offset,c3) end -- right
+ for k,v in ipairs({12,28}) do fb:set(v+offset,c) end -- both
+ end,
+ -- all the both color
function() fb:fill(0,0,0) for k,v in ipairs({3,5,10,12,14,19,21,28}) do fb:set(v+offset,c) end end,
- function() end,
-- beat
function() fb:set(11+offset,c) fb:set(13+offset,c) end,
function() fb:set(11+offset,0,0,0) fb:set(13+offset,0,0,0) fb:set(20+offset,c) end,
-return function(t,fb,g,r,b)
+return function(t,fb,p)
fb:fill(0,0,0)
- local c = string.char(g,r,b)
+ local c = p[1]
fb:set( 1,c) fb:set( 4,c) fb:set( 5,c) fb:set( 8,c)
fb:set(10,c) fb:set(11,c) fb:set(14,c) fb:set(15,c)
fb:set(18,c) fb:set(19,c) fb:set(22,c) fb:set(23,c)
isTouch = false
pendRemoteMsg = nil
-local function drawfailsafe(t,fb,g,r,b) fb:fill(g,r,b) end
+local function drawfailsafe(t,fb,p) fb:fill(p[1]:byte(1),p[1]:byte(2),p[1]:byte(3)) end
function loaddrawfn(name)
local f = loadfile (string.format("draw-%s.lc",name))
local fn = f and f()
['end'] = function() return true end,
-- in means to queue up a timer pointing at a label (which must already be known)
- ['in'] = function(s,ls)
+ ['in'] = function(s,ls,p)
local d,l = s:match("^(%d+)%s+(.*)")
if d and ls[l] then
s = ls[l]
remoteqtmrs[tn] = t
t:alarm(d,tmr.ALARM_SINGLE,function()
remoteqtmrs[tn] = nil
- intloop(s,ls)
+ intloop(s,ls,p)
end)
end
end,
+ ['color'] = function(s,_,p)
+ local ix,r,g,b = s:match("^(%w+)%s+(%x+)%s+(%x+)%s+(%x+)%s*$")
+ ix = tonumber(ix)
+ if ix then
+ g = (tonumber(g,16)) or 1; r = (tonumber(r,16)) or 1; b = (tonumber(b,16)) or 1
+ p[ix] = string.char(g,r,b)
+ end
+ end,
+
-- draw is the real reason we're here
- ['draw'] = function(s)
+ ['draw'] = function(s,_,p)
-- engage a drawing function and post a time event to pop the fifo
-- on the next tick (for, e.g., delay's use). This is done on a
-- callback to prevent deep stacks.
local m,r,g,b = s:match("^(%w+)%s+(%x+)%s+(%x+)%s+(%x+)%s*$")
if m then
g = (tonumber(g,16)) or 0; r = (tonumber(r,16)) or 0; b = (tonumber(b,16)) or 0
+ p[1] = string.char(g,r,b)
remotetmr:unregister()
- loaddrawfn(m)(remotetmr,remotefb,g,r,b)
+ loaddrawfn(m)(remotetmr,remotefb,p)
remotetmr:start()
dodraw()
end
}
-- loop over all ;-delimited statements in the message and fire them off.
-function intloop(msg,labels)
+function intloop(msg,labels,palette)
local c,as
for c,as in msg:gmatch("(%w*)%s*([^;]*);%s*") do
- if c and vt[c] then if vt[c](as,labels) then break end end
+ if c and vt[c] then if vt[c](as,labels,palette) then break end end
end
end
end
end
- intloop(msg,labels)
+ intloop(msg,labels,{})
end
if ledfb == touchfb then
touchtmr:unregister()
touchlastfn = touchfns[touchfnix]
- loaddrawfn(touchlastfn)(touchtmr,touchfb,touchcolorvec(touchcolor)); dodraw()
+ loaddrawfn(touchlastfn)(touchtmr,touchfb,{string.char(touchcolorvec(touchcolor))}); dodraw()
touchtmr:start()
end
end