;
; **********************************************
; * Timer with ATtiny2313, clocked with xtal *
; * (C)2009 by http://www.avr-asm-tutorial.net *
; **********************************************
;
.nolist
.include "tn2313def.inc"
.list
;
; **********************************************
; H a r d w a r e
; **********************************************
; _______
; 1 / |20
; Reset o---| |---o VCC
; LCD-RS o---| |---o USCK/LCD-D7
; LCD-E o---| AT |---o MISO/LCD-D6
; XTAL1 o---| tiny |---o MOSI/LCD-D5
; XTAL2 o---| 2313 |---o LCD-D4
; KEY UP o---| |---o LCD-D3
;KEY DWN o---| |---o LCD-D2
;KEY STA o---| |---o LCD-D1
; OUT o---| |---o LCD-D0
; GND o---|________|---o LED-OUT
;
; Keys (active on key up):
; Up-key: 10 seconds longer
; Dwn-key: 10 seconds shorter
; Up-key while STA pressed: start/stop counting
; Dwn-key while STA pressed: write cycle length
; to EEPROM (value is read on start-up)
;
; **********************************************
; C o n s t a n t s
; **********************************************
;
.equ fclock = 2457600 ; Xtal frequency
; Hardware depending constants
.equ pbLcdRs = 0 ; Rs-Bit LCD
.equ pbLcdE = 1 ; E-Bit LCD
.equ pbOut = 5 ; Output bit
.equ pbLed = 6 ; LED port bit
.equ pbKeyUp = 2 ; Up-key
.equ pbKeyDwn = 3 ; Down-key
.equ pbKeySta = 4 ; Start/Stop-key
;
; **********************************************
; R e g i s t e r
; **********************************************
;
; Registers R0 ... R3 used in calculations
.def rCycL = R12 ; Cycle length, LSB
.def rCycH = R13 ; dto. MSB
.def rPwm = R14 ; Pwm-Value
.def rSreg = R15 ; save/restore SREG
.def rmp = R16 ; multi purpose register
.def rFlg = R17 ; Flag register
.equ bSec = 0 ; second over flag
.equ bOff = 1 ; end of time reached
.equ bOn = 2 ; start cycle
.equ bAct = 3 ; count cycle active
.equ bUpd = 4 ; update cycle display
.equ bSave = 5 ; save parameter for next start
.def rimp = R18 ; multi purpose inside ints
.def rCtrL = R24 ; LSB second counter
.def rCtrH = R25 ; MSB second counter
; X = R27:R26 = duration length
;
; ***********************************************
; R e s e t / I n t e r r u p t - V e c t o r s
; ***********************************************
;
.cseg
.org $0000
rjmp Main
rjmp Int0Isr
rjmp Int1Isr
rjmp Tc1CptIsr ; TC1Capt
rjmp Tc1CmpAIsr ; TC1CmpA
reti ; TC1Ovf
reti ; TC0Ovf
reti ; USART-RX
reti ; USART-UDRE
reti ; USART-TX
reti ; AnaComp
reti ; PCINT
rjmp Tc1CmpBIsr ; TC1CmpB
reti ; TC0CmpA
reti ; TC0CmpB
reti ; USI-Start
reti ; USI-Ovf
reti ; EEP-Rdy
reti ; WDT-Ovf
;
; **********************************************
; I n t e r r u p t S e r v i c e
; **********************************************
;
; Up key
Int0Isr:
in rSreg,SREG ; save status
sbis PIND,pbKeySta
rjmp StartStop
ldi rimp,10 ; add 10 seconds
add rCycL,rimp
ldi rimp,0
adc rCycH,rimp
sbr rFlg,1<<bUpd ; set update flag
out SREG,rSreg ; restore status
reti
; Dwn key
Int1Isr:
in rSreg,SREG ; save status
sbis PIND,pbKeySta
rjmp Save
ldi rimp,10 ; subtract 10 seconds
sub rCycL,rimp
ldi rimp,0
sbc rCycH,rimp
brcc Int1Isr1
clr rCycH
clr rCycL
Int1Isr1:
sbr rFlg,1<<bUpd ; set update flag
out SREG,rSreg ; restore status
reti
; Start/Stop pressed
StartStop:
sbrc rFlg,bAct
rjmp StartStop1
sbr rFlg,1<<bOn
out SREG,rSreg
reti
StartStop1:
sbr rFlg,1<<bOff
out SREG,rSreg
reti
; Save par pressed
sbr rFlg,bSave
out SREG,rSreg
reti
; TC1 overflow int
Tc1CptIsr:
in rSreg,SREG ; save status
sbr rFlg,1<<bSec ; set second flag
sbiw rCtrL,1 ; count down
brne Tc1CptIsr1
sbr rFlg,1<<bOff ; End of count reached
Tc1CptIsr1:
out SREG,rSreg ; restore status
reti
; TC1 Compare A Int
Tc1CmpAIsr:
cbi PORTD,pbLed ; Led green
reti
; TC1 Compare B Int
Tc1CmpBIsr:
sbi PORTD,pbLed ; Led red
reti
;
; **********************************************
; M a i n P r o g r a m I n i t
; **********************************************
;
Main:
ldi rmp,1<<CLKPCE ; set CLKPR to 1
out CLKPR,rmp
clr rmp
out CLKPR,rmp
ldi rmp,LOW(RAMEND) ; Init stack
out SPL,rmp
; Init Output
sbi DDRD,pbOut
cbi PORTD,pbOut
; Init Led output
sbi DDRD,pbLed
cbi PORTD,pbLed
; Init keys
cbi DDRD,pbKeyUp
sbi PORTD,pbKeyUp ; pull-up up-key
cbi DDRD,pbKeyDwn ; pull-up down-key
sbi PORTD,pbKeyDwn
cbi DDRD,pbKeySta ; pull-up start/stop-key
sbi PORTD,pbKeySta
; Clear flags
clr rFlg
; Init Lcd portbits
cbi PORTD,pbLcdE ; Enable
sbi DDRD,pbLcdE
cbi PORTD,pbLcdRs ; RS
sbi DDRD,pbLcdRs
ldi rmp,0xFF ; Data
out DDRB,rmp
rcall LcdInit
; Init Timer 1 second counter
ldi rmp,HIGH(38400) ; CTC after 1 sec
out ICR1H,rmp
ldi rmp,LOW(38400)
out ICR1L,rmp
ldi rmp,HIGH(38400/2) ; Turns LED green
out OCR1AH,rmp
ldi rmp,LOW(38400/2)
out OCR1AL,rmp
ldi rmp,HIGH(3*38400/4) ; Turns LED red
out OCR1BH,rmp
ldi rmp,LOW(3*38400/4)
out OCR1BL,rmp
ldi rCtrH,HIGH(10) ; set first counter
ldi rCtrL,LOW(10)
rcall Read
rcall DisplCycl
rcall SetOff ; init counter
; set external ints and sleep mode
ldi rmp,(1<<SE)|(1<<ISC01)|(1<<ISC00)|(1<<ISC11)|(1<<ISC10)
out MCUCR,rmp
ldi rmp,(1<<INT0)|(1<<INT1) ; mask ints
out GIMSK,rmp
sei
Loop:
sleep
nop ; dummy
sbrc rFlg,bOff ; switch off?
rcall SetOff
sbrc rFlg,bOn ; switch on?
rcall SetOn
sbrc rFlg,bSec
rcall SetSec
sbrc rFlg,bUpd ; update cycle length?
rcall Update
sbrc rFlg,bSave ; save parameter?
rcall Save
rjmp Loop
; End of cycle reached
SetOff:
cbr rFlg,1<<bOff ; clear flag
cbi PORTD,pbOut ; set Out Off
clr rmp
out OCR0B,rmp ; clear timer compare
cbi PORTD,pbLed ; set Led Off
ldi rmp,0 ; set mode CTC
out TCCR1A,rmp
ldi rmp,(1<<WGM13)|(1<<WGM12) ; set timer off
out TCCR1B,rmp
ldi rmp,0 ; disable timer ints
out TIMSK,rmp
cbr rFlg,1<<bAct ; clear active flag
ret
; Set cycle on
SetOn:
cbr rFlg,1<<bOn ; clear flag
sbi PORTD,pbOut
mov rCtrH,rCycH ; set timer duration
mov rCtrL,rCycL
ldi rmp,0 ; clear timer 1
out TCNT1H,rmp
out TCNT1L,rmp
ldi rmp,0 ; set mode CTC
out TCCR1A,rmp
ldi rmp,(1<<WGM13)|(1<<WGM12)|(1<<CS11)|(1<<CS10) ; set pre 64
out TCCR1B,rmp
ldi rmp,(1<<ICIE1)|(1<<OCIE1A)|(1<<OCIE1B) ; enable capture int
out TIMSK,rmp
sbi PORTD,pbLed ; LED red
sbr rFlg,1<<bAct ; set active flag
rjmp DisplTime ; display time
; Update cycle length display
Update:
cbr rFlg,1<<bUpd ; clear flag
rjmp DisplCycl
; End of second reached
SetSec:
cbr rFlg,1<<bSec ; clear flag
rjmp DisplTime
; Save parameter
Save:
cbr rFlg,1<<bSave
ldi rmp,0x40 ; write to 0040
out EEAR,rmp
cli
out EEDR,rCycL ; write low byte
sbi EECR,EEMPE
sbi EECR,EEPE
sei
Save1:
sbic EECR,EEPE
rjmp Save1
ldi rmp,0x41 ; write to 0041
out EEAR,rmp
cli
out EEDR,rCycH ; write high byte
sbi EECR,EEMPE
sbi EECR,EEPE
sei
Save2:
sbic EECR,EEPE
rjmp Save2
ret
; Read parameter
Read:
ldi rmp,0x40 ; read from Adress 0040
out EEAR,rmp
ldi rmp,1<<EERE ; read strobe
out EECR,rmp
in rCycL,EEDR ; read low byte
ldi rmp,0x41
out EEAR,rmp
ldi rmp,1<<EERE
out EECR,rmp
in rCycH,EEDR
ldi rmp,0x00
out EEAR,rmp
ret
;
; **********************************************
; C a l c u l a t i o n r o u t i n e s
; **********************************************
;
DisplTime:
ldi rmp,0xCA ; Display on line 2, col. 11
mov R0,rCtrL ; Time to R1:R0
mov R1,rCtrH
rjmp Displ
;
DisplCycl:
ldi rmp,0x8A ; Display on line 1, col. 11
mov R0,rCycL ; Cycle length to R1:R0
mov R1,rCycH
Displ:
cbi PORTD,pbLcdRs ; control
out PORTB,rmp ; set display position
rcall LcdE
rcall LcdDel40
sbi PORTD,pbLcdRs ; set display chars
clr ZH ; set 60 seconds
ldi ZL,60
clr R2
Displ1:
cp R0,ZL ; compare
cpc R1,ZH
brcs Displ2
sub R0,ZL
sbc R1,ZH
inc R2
rjmp Displ1
Displ2:
rcall Displ3
ldi rmp,':'
out PORTB,rmp
rcall LcdE
rcall LcdDel40
mov R2,R0
Displ3:
clr R1
ldi rmp,10
Displ4:
cp R2,rmp
brcs Displ5
sub R2,rmp
inc R1
rjmp Displ4
Displ5:
ldi rmp,'0'
add rmp,R1
out PORTB,rmp
rcall LcdE
rcall LcdDel40
ldi rmp,'0'
add rmp,R2
out PORTB,rmp
rcall LcdE
rjmp LcdDel40
;
; **********************************************
; L C D - R o u t i n e s
; **********************************************
;
LcdInit:
rcall LcdDel4500 ; delay 4,5 ms
cbi PORTD,pbLcdRs ; clear RS
ldi rmp,0x38 ; Setze 8 bit interface, 2 Zeilen
out PORTB,rmp ; to data output
rcall LcdE
rcall LcdDel4100 ; wait 4100 µs
rcall LcdE
rcall LcdDel100 ; wait 100 µs
rcall LcdE
rcall LcdDel100 ; wait 100 µs
ldi rmp,0x08 ; Display off
out PORTB,rmp
rcall LcdE
rcall LcdDel40 ; wait 40 µs
ldi rmp,0x01 ; clear Display
out PORTB,rmp
rcall LcdE
rcall LcdDel4500 ; wait 4,5 ms
ldi rmp,0x06 ; input mode insert, no Shift
out PORTB,rmp
rcall LcdE
rcall LcdDel40
ldi rmp,0x10 ; Display Cursor Shift
out PORTB,rmp
rcall LcdE
rcall LcdDel40 ; wait 40 µs
ldi rmp,0x02 ; Display/Cursor Home
out PORTB,rmp
rcall LcdE
rcall LcdDel1640 ; wait 1,64 ms
ldi rmp,0x0F ; Display active, Cursor on, blink
out PORTB,rmp
rcall LcdE
rcall LcdDel40 ; wait 40 µs
sbi PORTD,pbLcdRs
ldi ZH,HIGH(2*LcdText1)
ldi ZL,LOW(2*LcdText1)
rcall LcdWriteZ
ldi rmp,250
LcdInit1:
rcall LcdDel10000
dec rmp
brne LcdInit1
ldi ZH,HIGH(2*LcdText2)
ldi ZL,LOW(2*LcdText2)
LcdWriteZ:
cbi PORTD,pbLcdRs
ldi rmp,0x80
out PORTB,rmp
rcall LcdE
sbi PORTD,pbLcdRs
LcdWriteZ1:
push ZH
push ZL
rcall LcdDel40
pop ZL
pop ZH
lpm
adiw ZL,1
tst R0
breq LcdWriteZ3
ldi rmp,0x0A
cp R0,rmp
brne LcdWriteZ2
cbi PORTD,pbLcdRs
ldi rmp,0xC0
out PORTB,rmp
rcall LcdE
sbi PORTD,pbLcdRs
rjmp LcdWriteZ1
LcdWriteZ2:
out PORTB,R0
rcall LcdE
rjmp LcdWriteZ1
LcdWriteZ3:
rjmp LcdDel100
;
LcdText1:
.db "Timer ATtiny2313 DG4FAC",0x00
LcdText2:
.db "Max.time= 00:00 seconds",0x0A,"Resttime= 00:00 seconds",0x00
;
LcdE:
sbi PORTD,pbLcdE ; set enable LCD
nop ; delay four clock cycles
nop
nop
nop
cbi PORTD,pbLcdE ; clear enable LCD
ret
;
; Delay Routines for 2457600 MHz
;
LcdDel10000:
.equ nt10000 = (5 * 10000 - 16) / 8
ldi ZH,HIGH(nt10000)
ldi ZL,LOW(nt10000)
rjmp LcdDelZ
LcdDel4500:
.equ nt4500 = (5 * 4500 - 16) / 8
ldi ZH,HIGH(nt4500)
ldi ZL,LOW(nt4500)
rjmp LcdDelZ
LcdDel4100:
.equ nt4100 = (5 * 4100 - 16) / 8
ldi ZH,HIGH(nt4100)
ldi ZL,LOW(nt4100)
rjmp LcdDelZ
LcdDel1640:
.equ nt1640 = (5 * 1640 - 16) / 8
ldi ZH,HIGH(nt1640)
ldi ZL,LOW(nt1640)
rjmp LcdDelZ
LcdDel100:
.equ nt100 = (5 * 100 - 16) / 8
ldi ZH,HIGH(nt100)
ldi ZL,LOW(nt100)
rjmp LcdDelZ
LcdDel40:
.equ nt40 = (5 * 40 - 16) / 8
ldi ZH,HIGH(nt40)
ldi ZL,LOW(nt40)
nop
nop
LcdDelZ:
sbiw ZL,1
brne LcdDelZ
ret
;
; EEPROM segment
;
.ESEG
.ORG 0x0040
.DW 180
;
; End of source code
;