Path:
Home =>
AVR overview =>
Applications =>
Dive with ATtiny13 => Software Assembler
(Diese Seite in Deutsch:
)
Software for the tumbling dice with ATtiny13
;
; **********************************************
; * Animated tumbling dice with an ATtiny13 *
; * Version 1.0 as of February 2012 *
; * (C)2012 by http://www.avr-asm-tutorial.net *
; **********************************************
;
.nolist
.include "tn13def.inc"
.list
;
; =========================
; Program characteristica
; =========================
;
; Timer 0: Prescaler = 64
; Processor clock = 1.2 MHz
; CTC-value = 6
; OC0A-Interrupt: 3125 Hz, 320 us
; 16-Bit-Counter-Overflow: 21 s
; 8-Bit-Counter-Overflow: 82 ms
; 16-Bit-Counter-High for 2 Seconds: 24
;
; ==========
; Hardware
; ==========
; _____ ______
; /1 \/ 8|
; RESET O--|RES VCC|--O VCC +3V
; | AT |
; L2/L6 O--|PB3 PB2|--O L3/L5
; | tiny |
; Taste O--|PB4 PB1|--O L1/L7
; | 13 |
; GND O--|GND PB0|--O L4
; |______________|
;
; ________________
; | |
; | L1 L5 |
; | |
; | |
; | L2 L4 L6 |
; | |
; | |
; | L3 L7 |
; |________________|
;
; ==================
; Bit-Definitions
; ==================
;
.equ bL17 = 1<<PortB1 ; Led 1 and 7
.equ bL26 = 1<<PortB3 ; Led 2 and 6
.equ bL35 = 1<<PortB2 ; Led 3 and 5
.equ bL4 = 1<<PortB0 ; Led 4
;
; ==========
; Constant
; ==========
;
; Fixed values and calculation constants
;
.equ clock = 1200000
.equ cPresc = 64
.equ cCtcA = 5
;
; ===========
; Registers
; ===========
;
.def rSreg = R15 ; SREG-interim storage
.def rmp = R16 ; Multipurpose Register outside Int
.def rFlag = R17 ; Flag register
.equ bInp = 0 ; Input Signal set
.equ bTmb = 1 ; Tumble aktice
.equ bTOW = 2 ; wait for Timeout
.equ bTO = 3 ; Time-Out is activated
.equ bTmbEn = 4 ; Tumble enabled
.equ bRpt = 5 ; Repeat pushbutton press
.def rTmb = R18 ; Number of tumbles
.def rCnt = R19 ; last value
.def rCtrL = R24 ; Counter for timing, LSB
.def rCtrH = R25 ; dto., MSB
;
; =================
; Interrupt table
; =================
;
Start:
rjmp Main
reti ; INT0
rjmp PinChg ; PCINT0
reti ; TIM0_OVF
reti ; EE_RDY
reti ; ANA_COMP
rjmp Tc0CmpA ; TIM0_COMPA
reti ; TIM0_COMPB
reti ; WDT
reti ; ADC
;
; ============================
; Interrupt Service Routines
; ============================
;
; Pin Change
;
PinChg:
in rSreg,SREG ; safe Status in register
sbic PinB,PinB4 ; check negative edge
rjmp PinChgRet
sbr rFlag,1<<bInp ; set flag
PinChgRet:
out SREG,rSreg ; restore status
reti
;
; Timer 0 Compare A
;
Tc0CmpA:
in rSreg,SREG ; safe status in register
adiw rCtrL,1 ; upward counting
brne Tc0CmpARet
sbr rFlag,1<<bTO ; aktivate timeout
Tc0CmpARet:
out SREG,rSreg ; restore status
reti
;
; ===================
; Main program Init
; ===================
;
Main:
ldi rmp, LOW(RAMEND) ; init stack pointer
out SPL,rmp
; Init port
ldi rmp,0x0F ; lower portpins as output
out DDRB,rmp
ldi rmp,0x10 ; set PB4 high, all LEDs on
out PORTB,rmp
; init pushbutton during startup
ldi rmp,8 ; 3 seconds delay
Main0:
ldi rCtrH,High(0) ; 65536 clock cycles delay
ldi rCtrL,Low(0)
Main1:
sbiw rCtrL,1 ; count down
brne Main1 ; continue delay
dec rmp
brne Main0
in rFlag,PINB ; set flags to zero
cbr rFlag,0xEF ; clear anything but Bit 4
ldi rmp,0x1F ; clear LEDs
out PORTB,rmp
Main2:
sbis PINB,4 ; wait until pushbutton not pushed any more
rjmp Main2
; Init external interrupt
ldi rmp,1<<PCINT4 ; external ints on PB4
out PCMSK,rmp
ldi rmp,1<<PCIE ; enable external ints
out GIMSK,rmp
; Init Timer
ldi rmp,5 ; Timer 0 CTC A to 6
out OCR0A,rmp
ldi rmp,1<<WGM01 ; CTC on OCR0A
out TCCR0A,rmp
ldi rmp,(1<<CS01)|(1<<CS00) ; Prescaler = 64, start timer
out TCCR0B,rmp
ldi rmp,1<<OCIE0A ; Compare match interrupt
out TIMSK0,rmp
; Sleep mode
ldi rmp,1<<SE
out MCUCR,rmp
sei
;
; ===================
; Main program loop
; ===================
Loop:
sleep
nop
sbrc rFlag,bTO
rcall TimeOut
sbrc rFlag,bTmb
rjmp Tumble
sbrc rFlag,bInp
rcall Input
rjmp Loop
;
; =============
; Subroutines
; =============
;
; Timeout
;
Timeout:
cbr rFlag,1<<bTO ; clear flag
ldi rmp,0x1F ; all LEDs off
out PORTB,rmp
ret
;
; Tumble active
;
Tumble:
tst rCtrL
brne TumbleEnd
mov rmp,rCtrH ; copy MSB counter
andi rmp,0x03 ; four loops
brne TumbleEnd
inc rCnt ; next value
cpi rCnt,6
brcs TumbleNext
clr rCnt
TumbleNext:
ldi ZH,HIGH(2*Tabelle)
ldi ZL,LOW(2*Tabelle)
add ZL,rCnt ; Add table start
ldi rmp,0
adc ZH,rmp ; Add overflow
lpm ; read byte from table
out PORTB,R0
dec rTmb ; another tumble?
brne TumbleEnd
cbr rFlag,1<<bTmb ; clear flag
TumbleEnd:
rjmp Loop
;
; Input button activated
;
Input:
cbr rFlag,1<<bInp ; clear flag
sbrs rFlag,bRpt ; repetition blocked?
rjmp Input1
cpi rCtrH,10 ; done?
brcc Input1
ret
Input1:
mov rTmb,ZL ; store tumble counter
andi rTmb,0x03 ; max four tumbles
inc rTmb ; in any case add two
inc rTmb
clr rCtrH ; clear timer counter
clr rCtrL
in rmp,TCNT0 ; read timer
mov rCnt,rmp ; copy for tumbling
ldi ZH,HIGH(2*Tabelle)
ldi ZL,LOW(2*Tabelle)
add ZL,rmp ; Add table start
ldi rmp,0
adc ZH,rmp ; Add overflow
lpm ; read byte from table
out PORTB,R0
sbr rFlag,1<<bRpt ; set repetition flag
sbrc rFlag,bTmbEn ; tumble flag?
sbr rFlag,1<<bTmb
ret
;
; =============================
; Table with die combinations
; =============================
;
; Table values
;
.equ cL1 = bL4 ; 0 = Led 4
.equ cL2 = bL17 ; 1 = Led 1 and 7
.equ cL3 = bL17 | bL4 ; 2 = Led 1, 4 and 7
.equ cL4 = bL17 | bL35 ; 3 = Led 1, 3, 5 and 7
.equ cL5 = bL17 | bL35 | bL4 ; 4 = Led 1, 3, 4, 5 and 7
.equ cL6 = bL17 | bL26 | bL35 ; 5 = Led 1, 2, 3, 5, 6 and 7
;
; Die table
;
Tabelle:
.db 0b11111-cL1,0b11111-cL4
.db 0b11111-cL5,0b11111-cL2
.db 0b11111-cL6,0b11111-cL3
.db 0b10000
;
©2012 by http://www.avr-asm-tutorial.net