-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathws2812.fs
229 lines (190 loc) · 3.91 KB
/
ws2812.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
\ WS2812 Driver for lm4f120-MECRISP
\ (c)copyright 2014 by Gerald Wodni <[email protected]>
\ rewind-ssi \ clear until ws2812
compiletoflash
: init-ws-spi
SSI_CR0_SPO SSI_CR0_SPH or
4 2 init-ssi ( Initialize SSI2 with 8 data bits as master )
2 2 2 ssi-speed ( Slow Speed, 16MHz )
$F0 PORTB_AFSEL ! ( Associate Upper Nibble to Alternate Hardware )
$22220000 PORTB_PCTL ! ( Specify SSI2 as Alternate Function )
$F0 PORTB_DEN ! ( Enable Digital operation for SSI2 )
$90 PORTB_DIR ! ( Configure TX and CLK as Output )
2 enable-ssi ( Setup complete, enable SSI2 )
;
: >ws ( x -- )
ssi-wait-tx-fifo \ make sure fifo is empty
8 0 do
$8 \ push "0" ($8) on stack
over $80 and 0<> \ check msb
$E and or \ msb=1, push "1" ($E) on stack
>ssi
1 lshift
loop drop ;
: >rgb ( -- )
dup 8 rshift >ws \ green
dup 16 rshift >ws \ red
>ws ; \ blue
: n-leds ( x-color n-leds -- )
0 do
dup >rgb
loop drop ;
240 constant leds
: on $FFFFFF leds n-leds ;
: off $000000 leds n-leds ;
: red $1F0000 leds n-leds ;
: yellow $1F1F00 leds n-leds ;
: green $001F00 leds n-leds ;
: cyan $001F1F leds n-leds ;
: blue $00001F leds n-leds ;
: magenta $1F001F leds n-leds ;
: white $1F1F1F leds n-leds ;
: latch 50 us ;
: flash on latch off ;
: bill leds 0 do
$FF0000 >rgb
$FFFF00 >rgb
$00FF00 >rgb
$0000FF >rgb
$FFFFFF >rgb
loop ;
30 constant cols
8 constant rows
cols rows * constant leds
leds 4 * constant led-buffer-size
cols 4 * constant row-size
row-size 2/ constant row-size/2
led-buffer-size buffer: led-buffer
\ wave-like pattern
: buffer-wave
led-buffer led-buffer-size bounds do
i 2 rshift $F and i !
4 +loop ;
: buffer! ( x-color -- )
led-buffer led-buffer-size bounds do
dup i !
4 +loop drop ;
: buffer-off
led-buffer led-buffer-size bounds do
$0 i !
4 +loop ;
: led-n ( n-index -- a-addr ) inline
4 * led-buffer + ;
: led-n! ( x-color n-index -- ) inline
led-n ! ;
: led-xy ( n-x n-y -- index ) inline
cols * + ;
: xy! ( x-color n-x n-y -- )
over 0 cols between
over 0 rows between
and if \ only draw in buffer region
led-xy led-n!
else
2drop
then ;
: xy@ ( n-x n-y -- x-color )
led-xy led-n @ ;
: init-line
8 0 do
$0F0000 i 30 * i + led-n!
loop ;
: runner
led-buffer led-buffer-size 4 -
bounds
over over @ >r >r
do
i 4 + @
i !
4 +loop
r> r> swap !
;
\ linear flush in one sequence
: l-flush cr
led-buffer led-buffer-size bounds do
i @ >rgb
4 +loop ;
: row-bounds ( n -- )
row-size * \ row offset
led-buffer + \ total offset
row-size bounds ;
\ write line
: row>rgb ( a-addr-start a-addr-end -- )
do
i @ >rgb
4 +loop ;
\ write reversed
: -row>rgb ( a-addr-start a-addr-end -- )
swap
4 -
do
i @ >rgb
-4 +loop ;
\ flush in one long zig-zag-sequence, takes about 10ms
: lz-flush ( -- )
0 7 do
i row-bounds
i 1 and if
-row>rgb
else
row>rgb
then
-1 +loop
;
: r-row-bounds ( n -- )
row-size * \ row offset
led-buffer + \ total offset
row-size/2 bounds ;
: l-row-bounds ( n -- )
row-size * \ row offset
led-buffer + \ total offset
row-size/2 + \ add half row
row-size/2 bounds ;
\ flush 2 zig-zags
: z-flush ( -- )
0 7 do
i r-row-bounds
i 1 and if
row>rgb
else
-row>rgb
then
-1 +loop
0 7 do
i l-row-bounds
i 1 and if
row>rgb
else
-row>rgb
then
-1 +loop
;
\ mirror-flush 2 zig-zags
: mz-flush ( -- )
0 7 do
i l-row-bounds
i 1 and if
-row>rgb
else
row>rgb
then
-1 +loop
0 7 do
i r-row-bounds
i 1 and if
-row>rgb
else
row>rgb
then
-1 +loop
;
' z-flush variable flush-target
: flush flush-target @ execute ;
: init-ws
init-ws-spi
off
buffer-wave \ draw wave background
init-line \ draw red diagonal line
$000F00 0 led-n! \ make first pixel green
flush ;
: init init init-delay init-ws ;
init-ws