initial version of firmware
Stefan Schuermans authored 5 years ago
|
1) ; Chaosknoten - animated logo board
2) ; Copyright (C) 2019 Stefan Schuermans <stefan@blinkenarea.org>
3) ; Copyleft: GNU public license - http://www.gnu.org/copyleft/gpl.html
4)
5) ; ATtiny2313A, clock frequency: 8 MHz (internal oscillator)
6)
7) ; PA0: unused
8) ; PA1: unused
9) ; PA2: reset
10) ; PB0: column 0 output (output, low)
11) ; PB1: column 1 output (output, low)
12) ; PB2: column 2 output (output, low)
13) ; PB3: column 3 output (output, low)
14) ; PB4: column 4 output (output, low)
15) ; PB5: column 5 output (output, low)
16) ; PB6: column 6 output (output, low)
17) ; PB7: unused (input, pull-up enabled)
18) ; PD0: row 0 output (output, high)
19) ; PD1: row 1 output (output, high)
20) ; PD2: row 2 output (output, high)
21) ; PD3: row 3 output (output, high)
22) ; PD4: row 4 output (output, high)
23) ; PD5: row 5 output (output, high)
24) ; PD6: mode switch (input, pull-up enabled)
25)
26)
27)
28) .INCLUDE "tn2313def.inc"
29)
30)
31)
32) ; IO pins
33) .equ COL_PORT = PORTB ; column outputs
34) .equ ROW_PORT = PORTD ; row outputs
35) .equ MODE_SW_PIN = PIND
36) .equ MODE_SW_BIT = 6
37)
38)
39)
40) ; general purpose registers
41) .def TMP = r16
42) .def TMP2 = r17
43) .def CNT = r18
44) .def DATA = r19
45) .def GRAY = r20
46)
47) ; current mode
48) .def MODE = r21
49) .equ MODE_ALL = 0 ; play all animations
50) .equ MODE_SINGLE = 1 ; play single animation only
51) .equ MODE_UNKNOWN = 0xFF ; unknown mode
52)
53) ; current animation number and iterations
54) .def ANI_NO = r22
55) .def ANI_IT = r23
56)
57)
58)
59) .DSEG
60) .ORG 0x060
61)
62)
63)
64) ; current frame
65) FRAME: .BYTE 42
66)
67)
68)
69) .CSEG
70) .ORG 0x000
71) rjmp ENTRY ; RESET
72) reti ; INT0
73) reti ; INT1
74) reti ; TIMER1_CAPT
75) reti ; TIMER1_COMPA
76) reti ; TIMER1_OVF
77) reti ; TIMER0_OVF
78) reti ; USART0_RX
79) reti ; USART0_UDRE
80) reti ; USART0_TX
81) reti ; ANALOG_COMP
82) reti ; PC_INT0
83) reti ; TIMER1_COMPB
84) reti ; TIMER0_COMPA
85) reti ; TIMER0_COMPB
86) reti ; USI_START
87) reti ; USI_OVERFLOW
88) reti ; EE_READY
89) reti ; WDT
90) reti ; PC_INT1
91) reti ; PC_INT2
92)
93)
94)
95) ; code entry point
96) ENTRY:
97) ; set system clock prescaler to 1:1
98) ldi TMP,1<<CLKPCE
99) out CLKPR,TMP
100) ldi TMP,0
101) out CLKPR,TMP
102) ; initialize output ports
103) ldi TMP,0x00 ; PA[01] to output, low
104) out PORTA,TMP
105) ldi TMP,0x03
106) out DDRA,TMP
107) ldi TMP,0x80 ; PB[0-6] to output, low - PB7 to input, pull-up enabled
108) out PORTB,TMP
109) ldi TMP,0x7F
110) out DDRB,TMP
111) ldi TMP,0x7F ; PD[0-5] to output, high - PD6 to input, pull-up enabled
112) out PORTD,TMP
113) ldi TMP,0x3F
114) out DDRD,TMP
115) ; initialize stack pointer
116) ldi TMP,RAMEND
117) out SPL,TMP
118) ; enable watchdog (64ms)
119) wdr
120) ldi TMP,1<<WDCE|1<<WDE
121) out WDTCR,TMP
122) ldi TMP,1<<WDE|1<<WDP1
123) out WDTCR,TMP
124) wdr
125) ; disable analog comparator
126) ldi TMP,1<<ACD
127) out ACSR,TMP
128) ; jump to main program
129) rjmp MAIN
130)
131)
132)
133) ; wait 61 cycles
134) ; input: -
135) ; output: -
136) ; changes: TMP
137) ; cycles: 61 (including rcall and ret)
138) WAIT61:
139) ldi TMP,18
140) WAIT61_LOOP:
141) dec TMP
142) brne WAIT61_LOOP
143) ; done
144) ret
145)
146)
147)
148) ; output row for grayscale (black/white) and wait
149) ; input: X = ptr to pixel data (0..15)
150) ; GRAY = grayscale value (1..15)
151) ; output: -
152) ; changes: TMP, TMP2, DATA
153) ; cycles: GRAY * 64 + 1 (including rcall and ret)
154) ROW_BW_WAIT:
155) ; get data for LEDs
156) ldi TMP2,7 ; 7 pixels
157) ROW_BW_WAIT_PIXEL:
158) ld TMP,X+ ; get pixel value
159) cp TMP,GRAY ; compare with grayscale value
160) ror DATA ; store result as output bit
161) dec TMP2 ; next pixel
162) brne ROW_BW_WAIT_PIXEL
163) ; restore data pointer
164) subi XL,7 ; XH not there on ATtiny2313
165) ; output
166) lsr DATA ; ensure remaining bit stays high
167) ; (pull-up for unused pin)
168) com DATA
169) out COL_PORT,DATA
170) ; wait 5 + (GRAY - 1) * 64
171) mov TMP2,GRAY
172) rjmp ROW_BW_WAIT_LOOP_ENTRY
173) ROW_BW_WAIT_LOOP:
174) rcall WAIT61
175) ROW_BW_WAIT_LOOP_ENTRY:
176) dec TMP2
177) brne ROW_BW_WAIT_LOOP
178) ret
179)
180)
181)
182) ; turn off row (with same timing as ROW_BW_WAIT)
183) ; input: -
184) ; output: -
185) ; changes: TMP
186) ; cycles: 60 (including rcall and ret)
187) ROW_OFF:
188) ldi TMP,17
189) ROW_OFF_LOOP:
190) dec TMP
191) brne ROW_OFF_LOOP
192) ldi TMP,0x80 ; ensure remaining bit stays high
193) ; (pull-up for unused pin)
194) out COL_PORT,TMP
195) ret
196)
197)
198)
199) ; output row (grayscales)
200) ; input: X = ptr to pixel data (0..15)
201) ; output: -
202) ; changes: TMP, TMP2, DATA
203) ; cycles: 7822 (including rcall and ret)
204) ; time: 1ms
205) ROW_GRAY:
206) ldi GRAY,1
207) ROW_GRAY_LOOP:
208) rcall ROW_BW_WAIT
209) inc GRAY
210) cpi GRAY,16
211) brlo ROW_GRAY_LOOP
212) rcall ROW_OFF
213) ; done
214) ret
215)
216)
217)
218) ; output a frame
219) ; input: FRAME = pixel data (0..15)
220) ; output: -
221) ; changes: TMP, TMP2, CNT, DATA, X
222) ; time: 6ms
223) OUT_FRAME:
224) wdr
225) ldi XL,low(FRAME) ; ptr to pixel data
226) ; XH not there on ATtiny2313
227) ldi CNT,0x01 ; bitmask loop over rows
228) OUT_FRAME_LOOP:
229) mov TMP,CNT ; select row
230) com TMP
231) andi TMP,0x3F
232) ori TMP,0x40 ; ensure bit 6 stays high
233) ; (pull-up for switch input)
234) out ROW_PORT,TMP
235) rcall ROW_GRAY ; display row
236) subi XL,-7 ; ptr to next row
237) ; XH not there on ATtiny2313
238) lsl CNT ; bitmask loop over rows
239) cpi CNT,0x40
240) brne OUT_FRAME_LOOP
241) ; done
242) ret
243)
244)
245)
246) ; output a frame for some time
247) ; input: FRAME = pixel data (0..15)
248) ; TMP = time to show frame (1..255, in 6 ms steps)
249) ; output: -
250) ; changes: X, TMP, TMP2
251) ; time: TMP * 6 ms
252) OUT_FRAME_TIME:
253) ; output frame
254) push TMP
255) push CNT
256) push DATA
257) rcall OUT_FRAME ; 6 ms
258) pop DATA
259) pop CNT
260) pop TMP
261) ; loop
262) dec TMP
263) brne OUT_FRAME_TIME
264) ; done
265) ret
266)
267)
268)
269) ; clear frame
270) ; input: -
271) ; output: -
272) ; changes: X, FRAME, TMP
273) ; time: short
274) CLEAR:
275) ldi XL,low(FRAME) ; ptr to pixel data
276) ; XH not there on ATtiny2313
277) clr TMP
278) CLEAR_LOOP:
279) st X+,TMP ; clear pixel
280) cpi XL,low(FRAME)+42 ; bottom of loop
281) ; XH not there on ATtiny2313
282) brne CLEAR_LOOP
283) ; done
284) ret
285)
286)
287)
288) ; set frame to solid color
289) ; input: DATA = value (0..15)
290) ; output: -
291) ; changes: X, FRAME
292) ; time: short
293) SET_COLOR:
294) ldi XL,low(FRAME) ; ptr to pixel data
295) ; XH not there on ATtiny2313
296) SET_COLOR_LOOP:
297) st X+,DATA ; set pixel value
298) cpi XL,low(FRAME)+42 ; bottom of loop
299) ; XH not there on ATtiny2313
300) brne SET_COLOR_LOOP
301) ; done
302) ret
303)
304)
305)
306) ; set pixel
307) ; input: CNT = pixel number (0..41, nothing is done for 42..255)
308) ; DATA = value (0..15)
309) ; output: -
310) ; changes: X, FRAME, TMP
311) ; time: short
312) SET_PIXEL:
313) cpi CNT,42 ; invalid pixel number -> done
314) brsh SET_PIXEL_END
315) ldi XL,low(FRAME) ; ptr to pixel (base + offset)
316) add XL,CNT ; XH not there on ATtiny2313
317) st X,DATA ; set pixel
318) SET_PIXEL_END:
319) ; done
320) ret
321)
322)
323)
324) ; draw worm
325) ; input: CNT = head of worm (0..55)
326) ; output: -
327) ; changes: X, FRAME, TMP, DATA
328) ; time: short
329) DRAW_WORM:
330) cpi CNT,56 ; invalid head pos -> done
331) brsh DRAW_WORM_END
332) ldi XL,low(FRAME)+1 ; ptr to before head
333) add XL,CNT ; XH not there on ATtiny2313
334) ldi DATA,15 ; head is full on
335) cpi CNT,42 ; head pos in frame -> go
336) brlo DRAW_WORM_LOOP
337) mov TMP,CNT ; TMP := invisible pixels
338) subi TMP,41
339) sub XL,TMP ; skip invisible pixels
340) sub DATA,TMP ; XH not there on ATtiny2313
341) DRAW_WORM_LOOP:
342) st -X,DATA ; set pixel, go back
343) cpi XL,low(FRAME) ; 1st pixel -> done
344) breq DRAW_WORM_END ; XH not there on ATtiny2313
345) dec DATA ; next pixel darker
346) brne DRAW_WORM_LOOP ; loop
347) DRAW_WORM_END:
348) ; done
349) ret
350)
351)
352)
353) ; draw backwards worm
354) ; input: CNT = tail of worm (0..55)
355) ; output: -
356) ; changes: X, FRAME, TMP, DATA
357) ; time: short
358) DRAW_BW_WORM:
359) cpi CNT,56 ; invalid tail pos -> done
360) brsh DRAW_BW_WORM_END
361) ldi XL,low(FRAME)+1 ; ptr to before tail
362) add XL,CNT ; XH not there on ATtiny2313
363) ldi DATA,1 ; tail is minimum on
364) cpi CNT,42 ; tail pos in frame -> go
365) brlo DRAW_BW_WORM_LOOP
366) mov TMP,CNT ; TMP := invisible pixels
367) subi TMP,41
368) sub XL,TMP ; skip invisible pixels
369) add DATA,TMP ; XH not there on ATtiny2313
370) DRAW_BW_WORM_LOOP:
371) st -X,DATA ; set pixel, go back
372) cpi XL,low(FRAME) ; 1st pixel -> done
373) breq DRAW_BW_WORM_END ; XH not there on ATtiny2313
374) inc DATA ; next pixel brighter
375) cpi DATA,16 ; loop
376) brne DRAW_BW_WORM_LOOP
377) DRAW_BW_WORM_END:
378) ; done
379) ret
380)
381)
382)
383) ; blink animation
384) ; input: -
385) ; output: -
386) ; changes: X, FRAME, CNT, DATA, TMP, TMP2
387) ANIM_BLINK:
388) ; off
389) ldi DATA,0 ; minimum color
390) rcall SET_COLOR ; paint
391) ldi TMP,100 ; show frame 600 ms
392) rcall OUT_FRAME_TIME
393) ; on
394) ldi DATA,15 ; maximum color
395) rcall SET_COLOR ; paint
396) ldi TMP,100 ; show frame 600 ms
397) rcall OUT_FRAME_TIME
398) ; done
399) ret
400)
401)
402)
403) ; fade up and down animation
404) ; input: -
405) ; output: -
406) ; changes: X, FRAME, CNT, DATA, TMP, TMP2
407) ANIM_FADE:
408) ; fade up
409) ldi DATA,0 ; start dark
410) ANIM_FADE_UP:
411) rcall SET_COLOR ; paint
412) ldi TMP,10 ; show frame 60 ms
413) rcall OUT_FRAME_TIME
414) inc DATA ; fade up
415) cpi DATA,15 ; loop until almost full on
416) brne ANIM_FADE_UP
417) ; fade down
418) ANIM_FADE_DOWN:
419) rcall SET_COLOR ; paint
420) ldi TMP,10 ; show frame 60 ms
421) rcall OUT_FRAME_TIME
422) dec DATA ; fade up
423) cpi DATA,255 ; loop until full off
424) brne ANIM_FADE_DOWN
425) ; done
426) ret
427)
428)
429)
430) ; flicker animation
431) ; input: -
432) ; output: -
433) ; changes: X, FRAME, CNT, DATA, TMP, TMP2
434) ANIM_FLICKER:
435) ; even pixels
436) rcall CLEAR ; clear
437) ldi DATA,15 ; even pixels to maximum
438) ldi CNT,0
439) ANIM_FLICKER_EVEN:
440) rcall SET_PIXEL
441) subi CNT,-2 ; move two pixels
442) cpi CNT,42 ; loop
443) brlo ANIM_FLICKER_EVEN
444) ldi TMP,40 ; show frame 240 ms
445) rcall OUT_FRAME_TIME
446) ; odd pixels
447) rcall CLEAR ; clear
448) ldi DATA,15 ; odd pixels to maximum
449) ldi CNT,1
450) ANIM_FLICKER_ODD:
451) rcall SET_PIXEL
452) subi CNT,-2 ; move two pixels
453) cpi CNT,42 ; loop
454) brlo ANIM_FLICKER_ODD
455) ldi TMP,40 ; show frame 240 ms
456) rcall OUT_FRAME_TIME
457) ; done
458) ret
459)
460)
461)
462) ; wobble animation
463) ; input: -
464) ; output: -
465) ; changes: X, FRAME, CNT, DATA, TMP, TMP2
466) ANIM_WOBBLE:
467) ; even pixels up, odd pixels down
468) ldi DATA,0 ; even pixels start dark
469) ANIM_WOBBLE_UP:
470) ldi CNT,0
471) ANIM_WOBBLE_UP_DRAW:
472) rcall SET_PIXEL
473) inc CNT ; next pixel
474) ldi TMP,0x0F ; invert color
475) eor DATA,TMP
476) cpi CNT,42 ; loop
477) brlo ANIM_WOBBLE_UP_DRAW
478) ldi TMP,10 ; show frame 60 ms
479) rcall OUT_FRAME_TIME
480) inc DATA ; next color: brighter
481) cpi DATA,16
482) brlo ANIM_WOBBLE_UP
483) ; even pixels down, odd pixels up
484) ldi DATA,15 ; even pixels start full
485) ANIM_WOBBLE_DOWN:
486) ldi CNT,0
487) ANIM_WOBBLE_DOWN_DRAW:
488) rcall SET_PIXEL
489) inc CNT ; next pixel
490) ldi TMP,0x0F ; invert color
491) eor DATA,TMP
492) cpi CNT,42 ; loop
493) brlo ANIM_WOBBLE_DOWN_DRAW
494) ldi TMP,10 ; show frame 60 ms
495) rcall OUT_FRAME_TIME
496) dec DATA ; next color: darker
497) cpi DATA,16
498) brlo ANIM_WOBBLE_DOWN
499) ; done
500) ret
501)
502)
503)
504) ; run animation
505) ; input: -
506) ; output: -
507) ; changes: X, FRAME, CNT, DATA, TMP, TMP2
508) ANIM_RUN:
509) ldi CNT,255 ; start before 1st pixel
510) ANIM_RUN_LOOP:
511) rcall CLEAR ; clear
512) ldi DATA,15 ; current pixel full on
513) rcall SET_PIXEL
514) ldi TMP,10 ; show frame 60 ms
515) rcall OUT_FRAME_TIME
516) inc CNT ; next pixel
517) cpi CNT,43 ; loop until after last pixel
518) brne ANIM_RUN_LOOP
519) ; done
520) ret
521)
522)
523)
524) ; backwards run animation
525) ; input: -
526) ; output: -
527) ; changes: X, FRAME, CNT, DATA, TMP, TMP2
528) ANIM_BW_RUN:
529) ldi CNT,42 ; start after last pixel
530) ANIM_BW_RUN_LOOP:
531) rcall CLEAR ; clear
532) ldi DATA,15 ; current pixel full on
533) rcall SET_PIXEL
534) ldi TMP,10 ; show frame 60 ms
535) rcall OUT_FRAME_TIME
536) dec CNT ; previous pixel
537) cpi CNT,255 ; loop until before 1st pixel
538) brne ANIM_BW_RUN_LOOP
539) ; done
540) ret
541)
542)
543)
544) ; worm animation
545) ; input: -
546) ; output: -
547) ; changes: X, FRAME, CNT, DATA, TMP, TMP2
548) ANIM_WORM:
549) ldi CNT,255 ; worm starts before 1st pixel
550) ANIM_WORM_LOOP:
551) rcall CLEAR ; draw worm
552) rcall DRAW_WORM
553) ldi TMP,10 ; show frame 60 ms
554) rcall OUT_FRAME_TIME
555) inc CNT ; advance worm
556) cpi CNT,57 ; loop until has exits
557) brne ANIM_WORM_LOOP
558) ; done
559) ret
560)
561)
562)
563) ; backwards worm animation
564) ; input: -
565) ; output: -
566) ; changes: X, FRAME, CNT, DATA, TMP, TMP2
567) ANIM_BW_WORM:
568) ldi CNT,56 ; worm starts behind frame
569) ; head not yet visible
570) ANIM_BW_WORM_LOOP:
571) rcall CLEAR ; draw backwards worm
572) rcall DRAW_BW_WORM
573) ldi TMP,10 ; show frame 60 ms
574) rcall OUT_FRAME_TIME
575) dec CNT ; advance worm backwards
576) cpi CNT,254 ; loop until worm has exited
577) brne ANIM_BW_WORM_LOOP
578) ; done
579) ret
580)
581)
|