BlinkenArea - GitList
Repositories
Blog
Wiki
bulb
Code
Commits
Branches
Tags
Search
Tree:
a40d3a7
Branches
Tags
master
petaflot
1.0.0
1.1.0
1.1.1
bulb
firmware
bulb.asm
change firmware to match new switch in schematic, use mode switch to lock current animation
Stefan Schuermans
commited
a40d3a7
at 2012-06-10 10:55:19
bulb.asm
Blame
History
Raw
; bulb - BlinkenArea ultimate logo board ; version 1.1.0 date 2012-06-10 ; Copyright (C) 2011-2012 Stefan Schuermans <stefan@blinkenarea.org> ; Copyleft: GNU public license - http://www.gnu.org/copyleft/gpl.html ; ATtiny2313A, clock frequency: 8 MHz (internal oscillator) ; PA0: unused ; PA1: unused ; PA2: reset ; PB0: column 0 output (output, low) ; PB1: column 1 output (output, low) ; PB2: column 2 output (output, low) ; PB3: column 3 output (output, low) ; PB4: column 4 output (output, low) ; PB5: column 5 output (output, low) ; PB6: column 6 output (output, low) ; PB7: unused (input, pull-up enabled) ; PD0: row 0 output (output, high) ; PD1: row 1 output (output, high) ; PD2: row 2 output (output, high) ; PD3: row 3 output (output, high) ; PD4: row 4 output (output, high) ; PD5: row 5 output (output, high) ; PD6: mode switch (input, pull-up enabled) .INCLUDE "tn2313def.inc" ; IO pins .equ COL_PORT = PORTB ; column outputs .equ ROW_PORT = PORTD ; row outputs .equ MODE_SW_PIN = PIND .equ MODE_SW_BIT = 6 ; general purpose registers .def TMP = r16 .def CNT = r17 .def DATA = r18 .DSEG .ORG 0x060 ; current frame FRAME: .BYTE 42 .MACRO breqx brne NE rjmp @0 NE: .ENDM ; multiple rcalls in a row ; parameters: label, N .MACRO rcall_N .IF @1 > 0 rcall @0 rcall_N @0, @1 - 1 .ENDIF .ENDM ; check if to turn on pixel in subframe ; parameter: grayscale value (1..15) ; input: X = ptr to pixel data (0..7), ; DATA[7-1] = other pixels ; output: X = ptr to pixel data of next pixel, ; DATA.7 = if _not_ to turn on pixel, DATA.[6-0] = old DATA[7-1] ; changes: TMP, DATA, X ; cycles: 4 .MACRO PIXEL ld TMP,X+ cpi TMP,@0 ror DATA .ENDM ; output row (black/white) ; parameter: grayscale value (1..15) ; input: X = ptr to pixel data (0..15) ; output: - ; changes: TMP, DATA ; cycles: 32 .MACRO ROW_BW PIXEL @0 ; pixel 0 PIXEL @0 ; pixel 1 PIXEL @0 ; pixel 2 PIXEL @0 ; pixel 3 PIXEL @0 ; pixel 4 PIXEL @0 ; pixel 5 PIXEL @0 ; pixel 6 subi XL,7 ; XH not there on ATtiny2313 lsr DATA ; ensure remaining bit stays high ; (pull-up for unused pin) com DATA out COL_PORT,DATA .ENDM ; wait n * 64 cycles ; parameter: n ; input: - ; output: - ; changes: TMP ; cycles: n * 64 .MACRO WAIT64_N .IF @0 > 0 rcall WAIT64 WAIT64_N @0 - 1 .ENDIF .ENDM ; output row for grayscale (black/white) and wait ; parameter: grayscale value (1..15) ; input: X = ptr to pixel data (0..15) ; output: - ; changes: TMP, DATA ; cycles: 32 + (grayscale - 1) * 64 .MACRO ROW_BW_WAIT ROW_BW @0 WAIT64_N @0 - 1 .ENDM ; turn off row (with same timing as ROW_BW) ; input: - ; output: - ; changes: TMP ; cycles: 32 .MACRO ROW_OFF ldi TMP,10 ROW_OFF_LOOP: dec TMP brne ROW_OFF_LOOP ldi TMP,0x80 ; ensure remaining bit stays high ; (pull-up for unused pin) out COL_PORT,TMP .ENDM ; play an animation N times (mode 0) or infinitely (mode 1) ; parameters: animation function, N .MACRO PL_ANIM PL_ANIM_LOOP: rcall_N @0, @1 - 1 sbic MODE_SW_PIN,MODE_SW_BIT rjmp PL_ANIM_LOOP .ENDM .CSEG .ORG 0x000 rjmp ENTRY ; RESET reti ; INT0 reti ; INT1 reti ; TIMER1_CAPT reti ; TIMER1_COMPA reti ; TIMER1_OVF reti ; TIMER0_OVF reti ; USART0_RX reti ; USART0_UDRE reti ; USART0_TX reti ; ANALOG_COMP reti ; PC_INT0 reti ; TIMER1_COMPB reti ; TIMER0_COMPA reti ; TIMER0_COMPB reti ; USI_START reti ; USI_OVERFLOW reti ; EE_READY reti ; WDT reti ; PC_INT1 reti ; PC_INT2 ; code entry point ENTRY: ; set system clock prescaler to 1:1 ldi TMP,1<<CLKPCE out CLKPR,TMP ldi TMP,0 out CLKPR,TMP ; initialize output ports ldi TMP,0x00 ; PA[01] to output, low out PORTA,TMP ldi TMP,0x03 out DDRA,TMP ldi TMP,0x80 ; PB[0-6] to output, low - PB7 to input, pull-up enabled out PORTB,TMP ldi TMP,0x7F out DDRB,TMP ldi TMP,0x7F ; PD[0-5] to output, high - PD6 to input, pull-up enabled out PORTD,TMP ldi TMP,0x3F out DDRD,TMP ; initialize stack pointer ldi TMP,RAMEND out SPL,TMP ; enable watchdog (64ms) wdr ldi TMP,1<<WDCE|1<<WDE out WDTCR,TMP ldi TMP,1<<WDE|1<<WDP1 out WDTCR,TMP wdr ; disable analog comparator ldi TMP,1<<ACD out ACSR,TMP ; jump to main program rjmp MAIN ; wait 64 cycles ; input: - ; output: - ; changes: TMP ; cycles: 64 (including rcall and ret) WAIT64: ldi TMP,19 WAIT64_LOOP: dec TMP brne WAIT64_LOOP ; done ret ; output row (grayscales) ; input: X = ptr to pixel data (0..15) ; output: - ; changes: TMP, DATA ; cycles: 7269 (including rcall and ret) ROW_GRAY: ROW_BW_WAIT 1 ROW_BW_WAIT 2 ROW_BW_WAIT 3 ROW_BW_WAIT 4 ROW_BW_WAIT 5 ROW_BW_WAIT 6 ROW_BW_WAIT 7 ROW_BW_WAIT 8 ROW_BW_WAIT 9 ROW_BW_WAIT 10 ROW_BW_WAIT 11 ROW_BW_WAIT 12 ROW_BW_WAIT 13 ROW_BW_WAIT 14 ROW_BW_WAIT 15 ROW_OFF ; done ret ; output a frame ; input: FRAME = pixel data (0..15) ; output: - ; changes: TMP, CNT, DATA, X ; cycles: 43682 (including rcall and ret) ; time: 5.5ms OUT_FRAME: wdr ldi XL,low(FRAME) ; ptr to pixel data ; XH not there on ATtiny2313 ldi CNT,0x01 ; bitmask loop over rows OUT_FRAME_LOOP: mov TMP,CNT ; select row com TMP andi TMP,0x3F ori TMP,0x40 ; ensure bit 6 stays high ; (pull-up for switch input) out ROW_PORT,TMP rcall ROW_GRAY ; display row subi XL,-7 ; ptr to next row ; XH not there on ATtiny2313 lsl CNT ; bitmask loop over rows cpi CNT,0x40 brne OUT_FRAME_LOOP ; done ret ; output a frame for some time ; input: FRAME = pixel data (0..15) ; TMP = time to show frame (1..255, in 5.5 ms steps) ; output: - ; changes: X, TMP ; time: TMP * 5.5 ms OUT_FRAME_TIME: ; output frame push TMP push CNT push DATA rcall OUT_FRAME ; 5.5 ms pop DATA pop CNT pop TMP ; loop dec TMP brne OUT_FRAME_TIME ; done ret ; clear frame ; input: - ; output: - ; changes: X, FRAME, TMP ; time: short CLEAR: ldi XL,low(FRAME) ; ptr to pixel data ; XH not there on ATtiny2313 clr TMP CLEAR_LOOP: st X+,TMP ; clear pixel cpi XL,low(FRAME)+42 ; bottom of loop ; XH not there on ATtiny2313 brne CLEAR_LOOP ; done ret ; set frame to solid color ; input: DATA = value (0..15) ; output: - ; changes: X, FRAME ; time: short SET_COLOR: ldi XL,low(FRAME) ; ptr to pixel data ; XH not there on ATtiny2313 SET_COLOR_LOOP: st X+,DATA ; set pixel value cpi XL,low(FRAME)+42 ; bottom of loop ; XH not there on ATtiny2313 brne SET_COLOR_LOOP ; done ret ; set pixel ; input: CNT = pixel number (0..41, nothing is done for 42..255) ; DATA = value (0..15) ; output: - ; changes: X, FRAME, TMP ; time: short SET_PIXEL: cpi CNT,42 ; invalid pixel number -> done brsh SET_PIXEL_END ldi XL,low(FRAME) ; ptr to pixel (base + offset) add XL,CNT ; XH not there on ATtiny2313 st X,DATA ; set pixel SET_PIXEL_END: ; done ret ; draw worm ; input: CNT = head of worm (0..55) ; output: - ; changes: X, FRAME, TMP, DATA ; time: short DRAW_WORM: cpi CNT,56 ; invalid head pos -> done brsh DRAW_WORM_END ldi XL,low(FRAME)+1 ; ptr to before head add XL,CNT ; XH not there on ATtiny2313 ldi DATA,15 ; head is full on cpi CNT,42 ; head pos in frame -> go brlo DRAW_WORM_LOOP mov TMP,CNT ; TMP := invisible pixels subi TMP,41 sub XL,TMP ; skip invisible pixels sub DATA,TMP ; XH not there on ATtiny2313 DRAW_WORM_LOOP: st -X,DATA ; set pixel, go back cpi XL,low(FRAME) ; 1st pixel -> done breq DRAW_WORM_END ; XH not there on ATtiny2313 dec DATA ; next pixel darker brne DRAW_WORM_LOOP ; loop DRAW_WORM_END: ; done ret ; draw backwards worm ; input: CNT = tail of worm (0..55) ; output: - ; changes: X, FRAME, TMP, DATA ; time: short DRAW_BW_WORM: cpi CNT,56 ; invalid tail pos -> done brsh DRAW_BW_WORM_END ldi XL,low(FRAME)+1 ; ptr to before tail add XL,CNT ; XH not there on ATtiny2313 ldi DATA,1 ; tail is minimum on cpi CNT,42 ; tail pos in frame -> go brlo DRAW_BW_WORM_LOOP mov TMP,CNT ; TMP := invisible pixels subi TMP,41 sub XL,TMP ; skip invisible pixels add DATA,TMP ; XH not there on ATtiny2313 DRAW_BW_WORM_LOOP: st -X,DATA ; set pixel, go back cpi XL,low(FRAME) ; 1st pixel -> done breq DRAW_BW_WORM_END ; XH not there on ATtiny2313 inc DATA ; next pixel brighter cpi DATA,16 ; loop brne DRAW_BW_WORM_LOOP DRAW_BW_WORM_END: ; done ret ; blink animation ; input: - ; output: - ; changes: X, FRAME, CNT, DATA, TMP ANIM_BLINK: ; off ldi DATA,0 ; minimum color rcall SET_COLOR ; paint ldi TMP,100 ; show frame 550 ms rcall OUT_FRAME_TIME ; on ldi DATA,15 ; maximum color rcall SET_COLOR ; paint ldi TMP,100 ; show frame 550 ms rcall OUT_FRAME_TIME ; done ret ; fade up and down animation ; input: - ; output: - ; changes: X, FRAME, CNT, DATA, TMP ANIM_FADE: ; fade up ldi DATA,0 ; start dark ANIM_FADE_UP: rcall SET_COLOR ; paint ldi TMP,10 ; show frame 55 ms rcall OUT_FRAME_TIME inc DATA ; fade up cpi DATA,15 ; loop until almost full on brne ANIM_FADE_UP ; fade down ANIM_FADE_DOWN: rcall SET_COLOR ; paint ldi TMP,10 ; show frame 55 ms rcall OUT_FRAME_TIME dec DATA ; fade up cpi DATA,255 ; loop until full off brne ANIM_FADE_DOWN ; done ret ; flicker animation ; input: - ; output: - ; changes: X, FRAME, CNT, DATA, TMP ANIM_FLICKER: ; even pixels rcall CLEAR ; clear ldi DATA,15 ; even pixels to maximum ldi CNT,0 ANIM_FLICKER_EVEN: rcall SET_PIXEL subi CNT,-2 ; move two pixels cpi CNT,42 ; loop brlo ANIM_FLICKER_EVEN ldi TMP,40 ; show frame 220 ms rcall OUT_FRAME_TIME ; odd pixels rcall CLEAR ; clear ldi DATA,15 ; odd pixels to maximum ldi CNT,1 ANIM_FLICKER_ODD: rcall SET_PIXEL subi CNT,-2 ; move two pixels cpi CNT,42 ; loop brlo ANIM_FLICKER_ODD ldi TMP,40 ; show frame 220 ms rcall OUT_FRAME_TIME ; done ret ; wobble animation ; input: - ; output: - ; changes: X, FRAME, CNT, DATA, TMP ANIM_WOBBLE: ; even pixels up, odd pixels down ldi DATA,0 ; even pixels start dark ANIM_WOBBLE_UP: ldi CNT,0 ANIM_WOBBLE_UP_DRAW: rcall SET_PIXEL inc CNT ; next pixel ldi TMP,0x0F ; invert color eor DATA,TMP cpi CNT,42 ; loop brlo ANIM_WOBBLE_UP_DRAW ldi TMP,10 ; show frame 55 ms rcall OUT_FRAME_TIME inc DATA ; next color: brighter cpi DATA,16 brlo ANIM_WOBBLE_UP ; even pixels down, odd pixels up ldi DATA,15 ; even pixels start full ANIM_WOBBLE_DOWN: ldi CNT,0 ANIM_WOBBLE_DOWN_DRAW: rcall SET_PIXEL inc CNT ; next pixel ldi TMP,0x0F ; invert color eor DATA,TMP cpi CNT,42 ; loop brlo ANIM_WOBBLE_DOWN_DRAW ldi TMP,10 ; show frame 55 ms rcall OUT_FRAME_TIME dec DATA ; next color: darker cpi DATA,16 brlo ANIM_WOBBLE_DOWN ; done ret ; run animation ; input: - ; output: - ; changes: X, FRAME, CNT, DATA, TMP ANIM_RUN: ldi CNT,255 ; start before 1st pixel ANIM_RUN_LOOP: rcall CLEAR ; clear ldi DATA,15 ; current pixel full on rcall SET_PIXEL ldi TMP,10 ; show frame 55 ms rcall OUT_FRAME_TIME inc CNT ; next pixel cpi CNT,43 ; loop until after last pixel brne ANIM_RUN_LOOP ; done ret ; backwards run animation ; input: - ; output: - ; changes: X, FRAME, CNT, DATA, TMP ANIM_BW_RUN: ldi CNT,42 ; start after last pixel ANIM_BW_RUN_LOOP: rcall CLEAR ; clear ldi DATA,15 ; current pixel full on rcall SET_PIXEL ldi TMP,10 ; show frame 55 ms rcall OUT_FRAME_TIME dec CNT ; previous pixel cpi CNT,255 ; loop until before 1st pixel brne ANIM_BW_RUN_LOOP ; done ret ; worm animation ; input: - ; output: - ; changes: X, FRAME, CNT, DATA, TMP ANIM_WORM: ldi CNT,255 ; worm starts before 1st pixel ANIM_WORM_LOOP: rcall CLEAR ; draw worm rcall DRAW_WORM ldi TMP,10 ; show frame 55 ms rcall OUT_FRAME_TIME inc CNT ; advance worm cpi CNT,57 ; loop until has exits brne ANIM_WORM_LOOP ; done ret ; backwards worm animation ; input: - ; output: - ; changes: X, FRAME, CNT, DATA, TMP ANIM_BW_WORM: ldi CNT,56 ; worm starts behind frame ; head not yet visible ANIM_BW_WORM_LOOP: rcall CLEAR ; draw backwards worm rcall DRAW_BW_WORM ldi TMP,10 ; show frame 55 ms rcall OUT_FRAME_TIME dec CNT ; advance worm backwards cpi CNT,254 ; loop until worm has exited brne ANIM_BW_WORM_LOOP ; done ret ; main program MAIN: wdr ; initialization MAIN_LOOP: wdr ; main loop PL_ANIM ANIM_BLINK,3 PL_ANIM ANIM_WORM,3 PL_ANIM ANIM_FLICKER,10 PL_ANIM ANIM_BW_RUN,3 PL_ANIM ANIM_FADE,2 PL_ANIM ANIM_BW_WORM,3 PL_ANIM ANIM_WOBBLE,5 PL_ANIM ANIM_RUN,3 ; bottom of main loop rjmp MAIN_LOOP