initial version of firmware
Stefan Schuermans

Stefan Schuermans commited on 2019-06-21 21:29:31
Showing 4 changed files, with 1246 additions and 0 deletions.


import firmware from bulb project
... ...
@@ -0,0 +1,4 @@
1
+/*.cof
2
+/*.hex
3
+/*.lst
4
+/*.obj
... ...
@@ -0,0 +1,712 @@
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
+
582
+
583
+; read mode from switch and (store animation number)
584
+; input: MODE = old mode, CNT = animation number
585
+; output: MODE = new mode
586
+; changes: TMP, DATA
587
+MODE_READ:
588
+; read new mode (into DATA)
589
+        ldi     DATA,MODE_ALL
590
+        sbic    MODE_SW_PIN,MODE_SW_BIT
591
+        ldi     DATA,MODE_SINGLE
592
+; mode was changed from all to single -> save animation number
593
+        cpi     MODE,MODE_ALL           ; old mode not all -> do nothing
594
+        brne    MODE_READ_NOT_0_TO_1
595
+        cpi     DATA,MODE_SINGLE        ; new mode not single -> do nothing
596
+        brne    MODE_READ_NOT_0_TO_1
597
+        sbic    EECR,EEPE               ; EEPROM write ongoing -> do nothing
598
+        rjmp    MODE_READ_NOT_0_TO_1
599
+        ldi     TMP,0<<EEPM1|0<<EEPM0   ; set EEPROM programming mode
600
+        out     EECR,TMP
601
+        ldi     TMP,0                   ; set EEPROM address
602
+        out     EEARL,TMP
603
+        mov     TMP,CNT                 ; set EEPROM data to animation number
604
+        com     TMP                     ;   with NOTed number in upper nibble
605
+        swap    TMP
606
+        andi    TMP,0xF0
607
+        or      TMP,CNT
608
+        out     EEDR,TMP
609
+        sbi     EECR,EEMPE              ; begin writing EEPROM
610
+        sbi     EECR,EEPE
611
+MODE_READ_NOT_0_TO_1:
612
+; remember new mode (in MODE)
613
+        mov     MODE,DATA
614
+; done
615
+        ret
616
+
617
+
618
+
619
+; animation table: animation function, iteration count (<= 255)
620
+ANIM_TAB:
621
+        .dw     ANIM_BLINK
622
+        .dw     3
623
+        .dw     ANIM_WORM
624
+        .dw     3
625
+        .dw     ANIM_FLICKER
626
+        .dw     10
627
+        .dw     ANIM_BW_RUN
628
+        .dw     3
629
+        .dw     ANIM_FADE
630
+        .dw     2
631
+        .dw     ANIM_BW_WORM
632
+        .dw     3
633
+        .dw     ANIM_WOBBLE
634
+        .dw     5
635
+        .dw     ANIM_RUN
636
+        .dw     3
637
+ANIM_TAB_END:
638
+
639
+
640
+
641
+; main program
642
+MAIN:
643
+        wdr
644
+
645
+; initialization
646
+        ldi     MODE,MODE_UNKNOWN       ; unknown mode
647
+
648
+; get number of fist animation from EEPROM (into CNT)
649
+        ldi     TMP,0                   ; set EEPROM address
650
+        out     EEARL,TMP
651
+        sbi     EECR,EERE               ; start EEPROM read
652
+        in      ANI_NO,EEDR                ; get read value
653
+        mov     TMP,ANI_NO              ; check if high nibble contains NOTed
654
+        com     TMP                     ;   value
655
+        swap    TMP
656
+        cp      ANI_NO,TMP
657
+        brne    MAIN_FIRST_ANIM_INVALID
658
+        andi    ANI_NO,0x0F             ; throw away check value in high nibble
659
+        cpi     ANI_NO,(ANIM_TAB_END - ANIM_TAB) / 2
660
+        brlo    MAIN_FIRST_ANIM_OK
661
+MAIN_FIRST_ANIM_INVALID:
662
+        ldi     ANI_NO,0
663
+MAIN_FIRST_ANIM_OK:
664
+; first iteration of animation (into DATA)
665
+        ldi     ANI_IT,0
666
+
667
+; main loop
668
+MAIN_LOOP:
669
+        wdr
670
+
671
+; load pointer to animation function and repetition count from table
672
+        ldi     ZL,low(2 * ANIM_TAB)
673
+        ldi     ZH,high(2 * ANIM_TAB)
674
+        mov     TMP,ANI_NO
675
+        lsl     TMP
676
+        lsl     TMP
677
+        add     ZL,TMP
678
+        clr     TMP
679
+        adc     ZH,TMP
680
+        lpm     DATA,Z+                 ; address of function -> TMP:DATA
681
+        lpm     TMP,Z+
682
+        lpm     CNT,Z+                  ; iteration count -> CNT
683
+        mov     ZL,DATA                 ; address of function  -> Z
684
+        mov     ZH,TMP
685
+; save iteration count
686
+        push    CNT
687
+; call animation
688
+        icall
689
+; read new mode
690
+        mov     CNT,ANI_NO
691
+        rcall   MODE_READ
692
+; restore iteration count
693
+        pop     CNT
694
+
695
+; keep playing animation in single animation mode
696
+        cpi     MODE,MODE_SINGLE
697
+        breq    MAIN_NEXT_END
698
+; next iteration
699
+        inc     ANI_IT
700
+        cp      ANI_IT,CNT
701
+        brlo    MAIN_NEXT_END
702
+        clr     ANI_IT
703
+; next animation
704
+        inc     ANI_NO
705
+        cpi     ANI_NO,(ANIM_TAB_END - ANIM_TAB) / 2
706
+        brlo    MAIN_NEXT_END
707
+        clr     ANI_NO
708
+MAIN_NEXT_END:
709
+
710
+; bottom of main loop
711
+        rjmp     MAIN_LOOP
712
+
... ...
@@ -0,0 +1,48 @@
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
+# a BlinkenArea project - http://www.blinkenarea.org/
5
+
6
+NAME := Chaosknoten
7
+INC := tn2313def
8
+LFUSE := 0x64
9
+HFUSE := 0xDF
10
+EFUSE := 0xFF
11
+LOCK := 0xFC
12
+
13
+PROGRAMMER := avrisp2
14
+CONNECTION := usb
15
+DEVICE := t2313
16
+
17
+AVRA := avra
18
+AVRDUDE := avrdude
19
+
20
+AVRDUDE_CALL := $(AVRDUDE) -c $(PROGRAMMER) -P $(CONNECTION) -p $(DEVICE)
21
+
22
+SUFFIXES :=
23
+
24
+.PHONY: all prog prog_fuses prog_auto clean
25
+.SUFFIXES:
26
+.SECONDARY:
27
+
28
+all: $(NAME).hex
29
+
30
+$(NAME).hex: $(NAME).asm $(INC).inc Makefile
31
+	$(AVRA) -l $(NAME).lst $(NAME).asm
32
+
33
+prog_fuses: Makefile
34
+	$(AVRDUDE_CALL) -u -e
35
+	$(AVRDUDE_CALL) -u -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m \
36
+	                   -U efuse:w:$(EFUSE):m
37
+
38
+prog: $(NAME).hex Makefile
39
+	$(AVRDUDE_CALL) -u -e
40
+	$(AVRDUDE_CALL) -u -U flash:w:$(NAME).hex
41
+	$(AVRDUDE_CALL) -u -V -U lock:w:$(LOCK):m
42
+
43
+prog_auto: $(NAME).hex Makefile
44
+	while ! $(MAKE) prog_fuses || ! $(MAKE) prog; do echo -n; done
45
+
46
+clean:
47
+	rm -f $(addprefix $(NAME)., lst obj cof hex eep.hex)
48
+
... ...
@@ -0,0 +1,482 @@
1
+;***************************************************************************
2
+;* A P P L I C A T I O N   N O T E   F O R   T H E   A V R   F A M I L Y
3
+;* 
4
+;* Number           :AVR000
5
+;* File Name        :"tn2313def.inc"
6
+;* Title            :Register/Bit Definitions for the ATtiny2313
7
+;* Date             :03.06.17
8
+;* Version          :1.00
9
+;* Support E-mail   :avr@atmel.com
10
+;* Target MCU       :ATtiny2313
11
+;*
12
+;* DESCRIPTION
13
+;* When including this file in the assembly program file, all I/O register  
14
+;* names and I/O register bit names appearing in the data book can be used.
15
+;* In addition, the two registers forming the data pointer Z have been 
16
+;* assigned names ZL - ZH. 
17
+;*
18
+;* The Register names are represented by their hexadecimal address.
19
+;* 
20
+;* The Register Bit names are represented by their bit number (0-7).
21
+;* 
22
+;* Please observe the difference in using the bit names with instructions
23
+;* such as "sbr"/"cbr" (set/clear bit in register) and "sbrs"/"sbrc" 
24
+;* (skip if bit in register set/cleared). The following example illustrates
25
+;* this:
26
+;* 
27
+;* in   r16,PORTB       ;read PORTB latch
28
+;* sbr  r16,(1<<PB6)+(1<<PB5)   ;set PB6 and PB5 (use masks, not bit#)
29
+;* out  PORTB,r16       ;output to PORTB
30
+;*
31
+;* in   r16,TIFR        ;read the Timer Interrupt Flag Register
32
+;* sbrc r16,TOV0        ;test the overflow flag (use bit#)
33
+;* rjmp TOV0_is_set     ;jump if set
34
+;* ...                  ;otherwise do something else
35
+;*  
36
+;***************************************************************************
37
+
38
+;***** Specify Device
39
+.device ATtiny2313
40
+
41
+    
42
+;*****************************************************************************
43
+; I/O Register Definitions
44
+;*****************************************************************************
45
+
46
+.equ    SREG    = 0x3F
47
+.equ    SPL     = 0x3D
48
+.equ    OCR0B   = 0x3C
49
+.equ    GIMSK   = 0x3B
50
+.equ    EIFR    = 0x3A
51
+.equ    GIFR    = 0x3A      ; for compatibility purpose
52
+.equ    TIMSK   = 0x39       
53
+.equ    TIFR    = 0x38
54
+.equ    SPMCSR  = 0x37
55
+.equ    OCR0A   = 0x36
56
+.equ    MCUCR   = 0x35
57
+.equ    MCUSR   = 0x34
58
+.equ    TCCR0B  = 0x33
59
+.equ    TCCR0   = 0x33      ; for compatibility purpose
60
+.equ    TCNT0   = 0x32
61
+.equ    OSCCAL  = 0x31
62
+.equ    TCCR0A  = 0x30
63
+.equ    TCCR1A  = 0x2F
64
+.equ    TCCR1B  = 0x2E
65
+.equ    TCNT1H  = 0x2D
66
+.equ    TCNT1L  = 0x2C
67
+.equ    OCR1AH  = 0x2B
68
+.equ    OCR1AL  = 0x2A
69
+.equ    OCR1BH  = 0x29
70
+.equ    OCR1BL  = 0x28
71
+.equ    CLKPR   = 0x26
72
+.equ    ICR1H   = 0x25
73
+.equ    ICR1L   = 0x24
74
+.equ    SFIOR   = 0x23
75
+.equ    TCCR1C  = 0x22
76
+.equ    WDTCR   = 0x21
77
+.equ    PCMSK   = 0x20
78
+.equ    EEAR    = 0x1E      ; for compatibility purpose
79
+.equ    EEARL   = 0x1E  
80
+.equ    EEDR    = 0x1D
81
+.equ    EECR    = 0x1C
82
+.equ    PORTA   = 0x1B
83
+.equ    DDRA    = 0x1A
84
+.equ    PINA    = 0x19
85
+.equ    PORTB   = 0x18
86
+.equ    DDRB    = 0x17
87
+.equ    PINB    = 0x16
88
+.equ    GPIOR2  = 0x15
89
+.equ    GPIOR1  = 0x14
90
+.equ    GPIOR0  = 0x13
91
+.equ    PORTD   = 0x12
92
+.equ    DDRD    = 0x11
93
+.equ    PIND    = 0x10  
94
+.equ    USIDR   = 0x0F
95
+.equ    USISR   = 0x0E
96
+.equ    USICR   = 0x0D
97
+.equ    UDR     = 0x0C
98
+.equ    UCSRA   = 0x0B
99
+.equ    USR     = 0x0B      ; for compatibility purpose
100
+.equ    UCSRB   = 0x0A
101
+.equ    UCR     = 0x0A      ; for compatibility purpose
102
+.equ    UBRRL   = 0x09
103
+.equ    UBRR    = 0x09      ; for compatibility purpose
104
+.equ    ACSR    = 0x08
105
+.equ    UCSRC   = 0x03
106
+.equ    UBRRH   = 0x02
107
+.equ    DIDR    = 0x01
108
+
109
+    
110
+;*****************************************************************************
111
+; Bit Definitions
112
+;*****************************************************************************
113
+
114
+;***** SREG *******
115
+.equ I          = 7 
116
+.equ T          = 6
117
+.equ H          = 5
118
+.equ S          = 4
119
+.equ V          = 3
120
+.equ N          = 2
121
+;.equ Z          = 1
122
+.equ C          = 0
123
+
124
+;***** SPL ********
125
+.equ SP7        = 7 
126
+.equ SP6        = 6
127
+.equ SP5        = 5
128
+.equ SP4        = 4
129
+.equ SP3        = 3
130
+.equ SP2        = 2
131
+.equ SP1        = 1
132
+.equ SP0        = 0
133
+
134
+;***** GIMSK ******
135
+.equ INT1       = 7 
136
+.equ INT0       = 6  
137
+.equ PCIE       = 5
138
+
139
+;***** EIFR *******
140
+.equ INTF1      = 7
141
+.equ INTF0      = 6  
142
+.equ PCIF       = 5
143
+
144
+;***** TIMSK ******
145
+.equ TOIE1      = 7
146
+.equ OCIE1A     = 6
147
+.equ OCIE1B     = 5
148
+.equ ICIE1      = 3  
149
+.equ OCIE0B     = 2  
150
+.equ TOIE0      = 1
151
+.equ OCIE0A     = 0
152
+.equ TICIE      = 3     ; for compatibility purpose
153
+
154
+;***** TIFR *******
155
+.equ TOV1       = 7
156
+.equ OCF1A      = 6
157
+.equ OCF1B      = 5
158
+.equ ICF1       = 3  
159
+.equ OCF0B      = 2  
160
+.equ TOV0       = 1
161
+.equ OCF0A      = 0
162
+
163
+;***** SPMCSR *****
164
+.equ CTPB       = 4
165
+.equ RFLB       = 3
166
+.equ PGWRT      = 2
167
+.equ PGERS      = 1
168
+.equ SPMEN      = 0
169
+
170
+;***** MCUCR ******
171
+.equ PUD        = 7
172
+.equ SM1        = 6
173
+.equ SE         = 5
174
+.equ SM0        = 4
175
+.equ ISC11      = 3
176
+.equ ISC10      = 2
177
+.equ ISC01      = 1
178
+.equ ISC00      = 0
179
+.equ SM         = 4     ; for compatibility purpose
180
+
181
+;***** MCUSR ******
182
+.equ WDRF       = 3
183
+.equ BORF       = 2
184
+.equ EXTRF      = 1
185
+.equ PORF       = 0
186
+
187
+;***** TCCR0B *****
188
+.equ FOC0A      = 7
189
+.equ FOC0B      = 6
190
+.equ WGM02      = 3
191
+.equ CS02       = 2
192
+.equ CS01       = 1
193
+.equ CS00       = 0
194
+
195
+;***** OSCCAL *****
196
+.equ CAL6       = 6
197
+.equ CAL5       = 5
198
+.equ CAL4       = 4
199
+.equ CAL3       = 3
200
+.equ CAL2       = 2
201
+.equ CAL1       = 1
202
+.equ CAL0       = 0
203
+
204
+;***** TCCR0A *****
205
+.equ COM0A1     = 7
206
+.equ COM0A0     = 6
207
+.equ COM0B1     = 5
208
+.equ COM0B0     = 4
209
+.equ WGM01      = 1
210
+.equ WGM00      = 0
211
+
212
+;***** TCCR1A *****
213
+.equ COM1A1     = 7
214
+.equ COM1A0     = 6
215
+.equ COM1B1     = 5
216
+.equ COM1B0     = 4
217
+.equ WGM11      = 1
218
+.equ WGM10      = 0
219
+.equ PWM11      = 1     ; for compatibility purpose
220
+.equ PWM10      = 0     ; for compatibility purpose
221
+
222
+;***** TCCR1B *****
223
+.equ ICNC1      = 7
224
+.equ ICES1      = 6
225
+.equ WGM13      = 4
226
+.equ WGM12      = 3
227
+.equ CS12       = 2
228
+.equ CS11       = 1
229
+.equ CS10       = 0
230
+.equ CTC1       = 3     ; for compatibility purpose
231
+
232
+;***** CLKPR ******
233
+.equ CLKPCE     = 7 
234
+.equ CLKPS3     = 3
235
+.equ CLKPS2     = 2
236
+.equ CLKPS1     = 1
237
+.equ CLKPS0     = 0
238
+
239
+;***** SFIOR ******
240
+.equ PSR10      = 0 
241
+
242
+;***** TCCR1C *****
243
+.equ FOC1A      = 7
244
+.equ FOC1B      = 6
245
+
246
+;***** WDTCSR *****
247
+.equ WDIF       = 7
248
+.equ WDIE       = 6
249
+.equ WDP3       = 5
250
+.equ WDCE       = 4
251
+.equ WDE        = 3
252
+.equ WDP2       = 2
253
+.equ WDP1       = 1
254
+.equ WDP0       = 0
255
+.equ WDTOE      = 4     
256
+
257
+;***** PCMSK ******
258
+.equ PCINT7     = 7
259
+.equ PCINT6     = 6
260
+.equ PCINT5     = 5  
261
+.equ PCINT4     = 4
262
+.equ PCINT3     = 3
263
+.equ PCINT2     = 2
264
+.equ PCINT1     = 1
265
+.equ PCINT0     = 0
266
+
267
+;***** EECR *******
268
+.equ EEPM1      = 5
269
+.equ EEPM0      = 4
270
+.equ EERIE      = 3
271
+.equ EEMPE      = 2
272
+.equ EEPE       = 1
273
+.equ EERE       = 0
274
+; Kept for backward compatibility
275
+.equ EEMWE      = 2
276
+.equ EEWE       = 1
277
+
278
+
279
+;***** PORTA ******
280
+.equ PORTA2     = 2
281
+.equ PORTA1     = 1
282
+.equ PORTA0     = 0
283
+
284
+;***** DDRA *******
285
+.equ DDA2       = 2
286
+.equ DDA1       = 1
287
+.equ DDA0       = 0
288
+    
289
+;***** PINA *******
290
+.equ PINA2      = 2
291
+.equ PINA1      = 1
292
+.equ PINA0      = 0
293
+    
294
+;***** PORTB ******
295
+.equ PORTB7     = 7
296
+.equ PORTB6     = 6
297
+.equ PORTB5     = 5
298
+.equ PORTB4     = 4
299
+.equ PORTB3     = 3
300
+.equ PORTB2     = 2
301
+.equ PORTB1     = 1
302
+.equ PORTB0     = 0
303
+
304
+;***** DDRB *******
305
+.equ DDB7       = 7
306
+.equ DDB6       = 6
307
+.equ DDB5       = 5 
308
+.equ DDB4       = 4
309
+.equ DDB3       = 3
310
+.equ DDB2       = 2
311
+.equ DDB1       = 1
312
+.equ DDB0       = 0
313
+    
314
+;***** PINB *******
315
+.equ PINB7      = 7
316
+.equ PINB6      = 6
317
+.equ PINB5      = 5 
318
+.equ PINB4      = 4
319
+.equ PINB3      = 3
320
+.equ PINB2      = 2
321
+.equ PINB1      = 1
322
+.equ PINB0      = 0
323
+
324
+;***** PORTD ******
325
+.equ PORTD6     = 6
326
+.equ PORTD5     = 5
327
+.equ PORTD4     = 4
328
+.equ PORTD3     = 3
329
+.equ PORTD2     = 2
330
+.equ PORTD1     = 1
331
+.equ PORTD0     = 0
332
+
333
+;***** DDRD *******
334
+.equ DDD6       = 6
335
+.equ DDD5       = 5 
336
+.equ DDD4       = 4
337
+.equ DDD3       = 3
338
+.equ DDD2       = 2
339
+.equ DDD1       = 1
340
+.equ DDD0       = 0
341
+
342
+;***** PIND *******
343
+.equ PIND6      = 6
344
+.equ PIND5      = 5 
345
+.equ PIND4      = 4
346
+.equ PIND3      = 3
347
+.equ PIND2      = 2
348
+.equ PIND1      = 1
349
+.equ PIND0      = 0 
350
+
351
+;***** USISR ******
352
+.equ USISIF     = 7
353
+.equ USIOIF     = 6
354
+.equ USIPF      = 5
355
+.equ USIDC      = 4
356
+.equ USICNT3    = 3
357
+.equ USICNT2    = 2
358
+.equ USICNT1    = 1
359
+.equ USICNT0    = 0
360
+
361
+;***** USICR ******
362
+.equ USISIE     = 7
363
+.equ USIOIE     = 6
364
+.equ USIWM1     = 5
365
+.equ USIWM0     = 4
366
+.equ USICS1     = 3
367
+.equ USICS0     = 2
368
+.equ USICLK     = 1
369
+.equ USITC      = 0
370
+
371
+;***** UCSRA ******
372
+.equ RXC        = 7
373
+.equ TXC        = 6
374
+.equ UDRE       = 5
375
+.equ FE         = 4
376
+.equ DOR        = 3
377
+.equ UPE	= 2
378
+.equ PE         = 2	; for compatibility purpose
379
+.equ U2X        = 1
380
+.equ MPCM       = 0
381
+;.equ OR         = 3     ; for compatibility purpose
382
+
383
+;***** UCSRB ******
384
+.equ RXCIE      = 7 
385
+.equ TXCIE      = 6
386
+.equ UDRIE      = 5
387
+.equ RXEN       = 4
388
+.equ TXEN       = 3
389
+.equ UCSZ2      = 2
390
+.equ RXB8       = 1
391
+.equ TXB8       = 0
392
+.equ CHR9       = 2     ; for compatibility purpose
393
+    
394
+;***** ACSR *******
395
+.equ ACD        = 7  
396
+.equ ACBG       = 6
397
+.equ ACO        = 5
398
+.equ ACI        = 4
399
+.equ ACIE       = 3
400
+.equ ACIC       = 2
401
+.equ ACIS1      = 1
402
+.equ ACIS0      = 0
403
+
404
+;***** UCSRC ******
405
+.equ UMSEL      = 6 
406
+.equ UPM1       = 5
407
+.equ UPM0       = 4
408
+.equ USBS       = 3
409
+.equ UCSZ1      = 2
410
+.equ UCSZ0      = 1
411
+.equ UCPOL      = 0
412
+
413
+;***** DIDR ******
414
+.equ AIN1D      = 1
415
+.equ AIN0D      = 0
416
+
417
+;*****************************************************************************
418
+; CPU Register Declarations
419
+;*****************************************************************************
420
+
421
+.def    XL      = r26       ; X pointer low
422
+.def    XH      = r27       ; X pointer high
423
+.def    YL      = r28       ; Y pointer low
424
+.def    YH      = r29       ; Y pointer high
425
+.def    ZL      = r30       ; Z pointer low
426
+.def    ZH      = r31       ; Z pointer high
427
+
428
+
429
+;*****************************************************************************
430
+; Data Memory Declarations
431
+;*****************************************************************************
432
+
433
+.equ    RAMEND      = 0xDF  ; Highest internal data memory (SRAM) address.
434
+                            ;(128 Bytes RAM + IO + REG)
435
+.equ    EEPROMEND   = 0x7F  ; Highest EEPROM address.
436
+                            ;(128 Bytes)
437
+.equ    EEADRBITS   =   7   ; no. of bits in EEPROM address register
438
+
439
+.equ    RAM_SIZE    = 128
440
+
441
+
442
+;*****************************************************************************
443
+; Program Memory Declarations
444
+;*****************************************************************************
445
+
446
+.equ    FLASHEND    = 0x3FF ;  Highest program memory (flash) address
447
+                            ; (When addressed as 16 bit words)
448
+                            ; ( 1024 words , 2K byte ) 
449
+
450
+;**** Page Size ****
451
+.equ    PAGESIZE    = 16    ;number of WORDS in a Flash page
452
+.equ    EEPAGESIZE  =  2    ;number of WORDS in an EEPROM page
453
+
454
+;*****************************************************************************
455
+;**** Interrupt Vectors ****        
456
+;*****************************************************************************
457
+
458
+.equ    INT0addr        = 0x001     ;External Interrupt0
459
+.equ    INT1addr        = 0x002     ;External Interrupt1
460
+.equ    ICP1addr        = 0x003     ;Input capture interrupt 1
461
+.equ    OC1Aaddr        = 0x004     ;Timer/Counter1 Compare Match A     
462
+.equ    OVF1addr        = 0x005     ;Overflow1 Interrupt 
463
+.equ    OVF0addr        = 0x006     ;Overflow0 Interrupt
464
+.equ    URXC0addr       = 0x007     ;USART0 RX Complete Interrupt
465
+.equ    UDRE0addr       = 0x008     ;USART0 Data Register Empty Interrupt
466
+.equ    UTXC0addr       = 0x009     ;USART0 TX Complete Interrupt 
467
+.equ    ACIaddr         = 0x00A     ;Analog Comparator Interrupt 
468
+.equ    PCINTaddr       = 0x00B     ;Pin Change Interrupt
469
+.equ    OC1Baddr        = 0x00C     ;Timer/Counter1 Compare Match B
470
+.equ    OC0Aaddr        = 0x00D     ;Timer/Counter0 Compare Match A     
471
+.equ    OC0Baddr        = 0x00E     ;Timer/Counter0 Compare Match B     
472
+.equ    USI_STARTaddr   = 0x00F     ;USI start interrupt
473
+.equ    USI_OVFaddr     = 0x010     ;USI overflow interrupt
474
+.equ    ERDYaddr        = 0x011     ;EEPROM write complete
475
+.equ    WDTaddr         = 0x012     ;Watchdog Timer Interrupt
476
+		; for compatibility purpose
477
+.equ	URXCaddr		= 0x007		
478
+.equ	UDREaddr		= 0x008		
479
+.equ	UTXCaddr		= 0x009		
480
+
481
+;*****************************************************************************
482
+;*****************************************************************************
0 483