All pastes #471652 Raw Edit

Someone

public text v1 · immutable
·published 2007-05-05 01:20 UTC
rendered paste body
; ATtiny15L LED blinker
; Row Control: PB5, PB4		(cathode)
; Column Ctrl: PB3, PB0, PB1	(anode)
; Button Ctrl: PB2		(INT0)
; 
; eric@elegantinvention.com
; lain<3jack

.include "tn15def.inc"

; friggin include lacks PORTB5 b/c
; external #RESET has to be disabled..
.equ	PORTB5	= 5
.equ	PB5	= 5

; define our control lines
.equ	ROW1	= PORTB5
.equ	ROW2	= PORTB4
.equ	COL1	= PORTB3
.equ	COL2	= PORTB0
.equ	COL3	= PORTB1
.equ	BTN_PIN	= PORTB2

; define our LED bit positions
.equ	LEDRT	= 0						; right top		row1,col1
.equ	LEDRM	= 1						; right middle		row1,col2
.equ	LEDRB	= 2						; right bottom		row1,col3
.equ	LEDLB	= 3						; left bottom		row2,col3
.equ	LEDLM	= 4						; left middle		row2,col2
.equ	LEDLT	= 5						; left top		row2,col1
.equ	LEDRST	= 6						; LED RESET
.equ	LEDOVF	= 7						; LED OVERFLOW

; define the bit positions for up/down/updwn modes list
.equ	LIST1	= 0						; use item 1 (top 2)
.equ	LIST2	= 1						; use item 2 (middle 2)
.equ	LIST3	= 2						; use item 3 (bottom 2)
.equ	LISTOVF	= 3						; LIST overflow
.equ	LTDIR	= 5						; LIST direction for _m_updwn
.equ	LTMISC	= 6						; unused MISC bit
.equ	LISTUNF	= 7						; LIST "underflow"

; modes
.equ 	m_cw	= 0x00
.equ	m_ball	= 0x01
.equ	m_bhalf	= 0x02
.equ	m_down	= 0x03
.equ	m_up	= 0x04
.equ	m_updwn	= 0x05
.equ	m_sleep	= 0x06

; "variables"
.def	count1	= R16					; used for the delay loop
.def	count2	= R17
.def	loops	= R18					; number of loops to perform
.def	mode	= R19					; holds the current mode
.def	temp	= R20					; temporary stuff
.def	tempi	= R21					; don't want the interrupt vector screwing with temp
.def	leds	= R22					; led status register
.def	item1	= R23					; list of states for up/down/updwn modes
.def	item2	= R24
.def	item3	= R25
.def	listp	= R26					; current list position/direction and over/under-flow flags

.cseg

.org 0
rjmp main						; reset condition
.org INT0addr
rjmp button						; button pressed (int0 vector 0x001)

.org INT_VECTORS_SIZE					; start after interrupt vectors

delay:
	ldi	count1,	0xff
	_delay_outer:
		ldi	count2,	0xff				; reload count2 for next loop
		_delay_inner:
			dec	count2				; count2--
			cpi	count2,	0x00			; if count2 != 0, keep looping
			brne _delay_inner
		dec	count1					; count1--
		cpi	count1,	0x00				; if count1 != 0, keep looping
		brne _delay_outer
	dec loops						; loops--
	cpi	loops,	0x00					; if loops != 0, keep looping
	brne delay
	ret

button:
	ldi	loops,	0x03					; wait 1.6MHz/(65025*3) = ~122ms (debounce)
	rcall delay
	sbr	leds,	(1<<LEDRST)				; enable the LEDRST condition
	inc	mode						; next mode..
	ldi	tempi,	(m_sleep + 1)
	cpse mode,	temp					; return if mode != (m_sleep + 1)
	reti
	clr	mode						; mode overflow, reset mode and return (exit sleep)
	reti

main:
	ldi	item1,	(1<<LEDRT)+(1<<LEDLT)           	; the list for up/down/updwn modes
	ldi	item2,	(1<<LEDRM)+(1<<LEDLM)
	ldi	item3,	(1<<LEDRB)+(1<<LEDLB)

	ldi	mode,	m_sleep					; set default mode
	
	ser	temp						; temp=0xff (all pins output)
	cbr	temp,	(1<<BTN_PIN)			        ; button pin is input w/ pull-up
	out	DDRB,	temp
	
	in	temp,	MCUCR					; get current MCUCR status
	sbr	temp,	(1<<SM1)+(1<<SE)		        ; enable sleep & set mode = power down mode
	cbr	temp,	(1<<SM0)
	cbr	temp,	(1<<ISC01)+(1<<ISC00)	                ; low level on BTN_PIN triggers int0
	out	MCUCR,	temp					; update MCUCR

	in	temp,	GIMSK					; grab GIMSK and enable external int0
	sbr	temp,	(1<<INT0)
	out	GIMSK,	temp

	ldi	temp,	(1<<BTN_PIN)			        ; set BTNPIN=1 for PORTB for pull-up!!
	out	PORTB,	temp

	sei							; global interrupt enable

	sleep							; sleep and wait for button press


idle:
	ldi	loops,	0x02					; wait ~80ms between updating leds..
	rcall delay

	rcall update_leds					; actually update the led i/o pins (delayed)

	cpi	mode,	m_cw					; if mode == m_cw
	breq _m_cw
	cpi	mode,	m_ball					; if mode == m_ball
	breq _m_ball
	cpi mode,	m_bhalf					; if mode == m_bhalf
	breq _m_bhalf
	cpi	mode,	m_down					; if mode == m_down
	breq _m_down_pre
	cpi mode,	m_up					; if mode == m_up
	breq _m_up_pre
	cpi	mode,	m_updwn					; if mode == m_updwn
	breq _m_updwn_pre

	ldi	temp,	(1<<BTN_PIN)			        ; make sure BTNPIN=1 for pull-up before sleep!
	out	PORTB,	temp					; this will also disable the LEDs

	sleep							; else: sleep

	rjmp idle


update_leds:							; update the led i/o pins based on leds register
	clr temp						; clear out temp
	sbr	temp,	(1<<BTN_PIN)			        ; this keeps it pull-up!! IMPORTANT!
	
	sbrc leds,	LEDRT					; activate the proper ROWs/COLs for
	sbr	temp,	(1<<ROW1)+(1<<COL1)		        ; the LEDs that are on
	sbrc leds,	LEDRM
	sbr	temp,	(1<<ROW1)+(1<<COL2)
	sbrc leds,	LEDRB
	sbr	temp,	(1<<ROW1)+(1<<COL3)

	sbrc leds,	LEDLT
	sbr	temp,	(1<<ROW2)+(1<<COL3)
	sbrc leds,	LEDLM
	sbr	temp,	(1<<ROW2)+(1<<COL2)
	sbrc leds,	LEDLB
	sbr	temp,	(1<<ROW2)+(1<<COL1)

	out	PORTB,	temp					; output temp on PORTB
	ret


; specific led controlling calls,

_m_cw:								; rotate the leds clockwise
	sbrs leds,	LEDRST					; don't shift if LEDRST
	lsl	leds						; left shift = cw rotate
								; LEDRST will be set if shifted too far
	sbrc leds,	LEDRST					; if LEDRST set, load the default
	ldi	leds,	(1<<LEDRT)
	cbr	leds,	(1<<LEDRST)				; clear the reset condition

	rjmp idle

_m_down_pre:
	rjmp _m_down
_m_up_pre:
	rjmp _m_up
_m_updwn_pre:
	rjmp _m_updwn

_m_ball:							; blink all
	sbrc leds,	LEDRST					; if LEDRST set, load the default
	ldi	leds,	0b00111111
	cbr	leds,	(1<<LEDRST)

	com	leds						; take the 1's complement (invert the bits)
	cbr	leds,	(1<<LEDRST)+(1<<LEDOVF)	; clear LEDRST and LEDOVF flags

	rjmp idle

_m_bhalf:							; alternate halves
	sbrc leds,	LEDRST					; if LEDRST set, load the default
	ldi	leds,	(1<<LEDRT)+(1<<LEDRM)+(1<<LEDRB)
	cbr	leds,	(1<<LEDRST)

	com	leds						; 1's complement (invert the bits)
	cbr	leds,	(1<<LEDRST)+(1<<LEDOVF)	                ; clear LEDRST and LEDOVF flags

	rjmp idle

_m_down:							; light from top to bottom, 2 at a time
	lsl	listp						; shift listp left

	mov	temp,	leds					; store leds in temp for LEDRST check later

	sbrc listp,	LISTOVF					; make sure we don't have an overflow
	sbr	listp,	(1<<LIST1)				; reset to LIST1
	cbr	listp,	(1<<LISTOVF)			        ; clear overflow even if there wasn't one
	
	sbrc temp,	LEDRST					; if LEDRST set,
	ldi	listp,	(1<<LIST1)				; then set listp to LIST1

	sbrc listp,	LIST1					; mov the proper item into the leds register
	mov	leds,	item1
	sbrc listp,	LIST2
	mov	leds,	item2
	sbrc listp,	LIST3
	mov	leds,	item3

	rjmp idle

_m_up:								; light from bottom to top, 2 at a time
	ror	listp						; right shift w/ carry the list

	mov	temp,	leds					; store leds in temp for LEDRST check later

	brcc _m_up_listunf1					; if we have an underflow
	sbr	listp,	(1<<LIST3)				; reset listp to LIST3 (default)
_m_up_listunf1:
	cbr	listp,	(1<<LISTUNF)			        ; clear the underflow even if there wasn't one

	sbrc temp,	LEDRST					; if LEDRST set, load the default
	ldi	listp,	(1<<LIST3)				; which is LIST3

	sbrc listp,	LIST1					; mov the proper item into the leds register
	mov	leds,	item1
	sbrc listp,	LIST2
	mov	leds,	item2
	sbrc listp,	LIST3
	mov	leds,	item3

	rjmp idle

_m_updwn:							; light top->bottom->top->bottom->....
	mov	temp,	listp					; listp -> temp
	cbr	listp,	(1<<LTDIR)				; clear list direction in listp

	sbrc temp,	LTDIR					; if LTDIR=1, right shift w/ carry
	ror	listp
	sbrs temp,	LTDIR					; if LTDIR=0, left shift
	lsl	listp

	sbrc listp,	LISTOVF					; make sure we don't have an overflow
	sbr	listp,	(1<<LIST3)				; reset to LIST3 if we do
	sbrc listp,	LISTOVF
	sbr	listp,	(1<<LTDIR)				; change direction, LTDIR=1  (up)
	cbr	listp,	(1<<LISTOVF)			        ; clear overflow even if there wasn't one

	brcc _m_updwn_listunf1					; if we have an underflow,
	sbr	listp,	(1<<LIST1)				; reset listp to LIST1 (default)
	cbr	listp,	(1<<LTDIR)				; change direction, LTDIR=0  (down)
_m_updwn_listunf1:
	cbr	listp,	(1<<LISTUNF)			        ; clear the underflow even if there wasn't one

	sbrc leds,	LEDRST					; if LEDRST set, load the default
	ldi	listp,	(1<<LIST1)

	sbrc listp,	LIST1					; mov the proper item into the leds register
	mov	leds,	item1
	sbrc listp,	LIST2
	mov	leds,	item2
	sbrc listp,	LIST3
	mov	leds,	item3

	rjmp idle

; eof