![]() |
AVR applications Long timer with ATtiny13 Assembler software for the long timer |
;
; ****************************************
; * Programmable longterm interval timer *
; * ATtiny13 with a red/green LED, v1.0 *
; * (C)2021 by Gerhard Schmidt *
; ****************************************
;
.nolist
.include "tn13adef.inc" ; Define device ATtiny13A
.list
;
; Task: Decreases the brightness of a duo LED in red
; down to zero and then within 5 minutes from
; zero to full by jumpers:
; Jumper
; 0) No jumper: 30 minutes
; 1) adds 30 minutes
; 2) adds 60 minutes
; 3) adds 120 minutes.
; Selectable times:
; 0) 30 minutes (25 min. red + 5 min. green)
; 1) 60 minutes (55 min. red + 5 min. green)
; 2) 90 minutes (85 min. red + 5 min. green)
; 3) 120 minutes (115 min. red + 5 min. green)
; 4) 150 minutes (145 min. red + 5 min. green)
; 5) 180 minutes (175 min. red + 5 min. green)
; 6) 210 minutes (205 min. red + 5 min. green)
; 7) 240 minutes (235 min. red + 5 min. green)
;
; **********************************
; H A R D W A R E
; **********************************
;
; Device: ATtiny13A, Package: 8-pin-PDIP_SOIC
;
; _________
; 1 / |8
; Reset o--|RESET VCC|--o +V
; Sw3 o--|PB3 PB2|--o Sw1
; Sw2 o--|PB4 PB1|--o Anode red
; 0V o--|GND PB0|--o Anode green
; 4 |__________|5
;
; **********************************
; P O R T S A N D P I N S
; **********************************
;
.equ pOutP = PORTB ; Output port
.equ pOutD = DDRB ; Direction port
.equ pOutI = PINB ; Input port
.equ bAnGnP = PORTB0 ; Anode green output pin
.equ bAnRdP = PORTB1 ; Anode red output pin
.equ bAnGnD = DDB0 ; Anode green pin direction
.equ bAnRdD = DDB1 ; Anode red pin direction
.equ bSw1 = PORTB2 ; Switch 1 pin
.equ bSw2 = PORTB3 ; Switch 2 pin
.equ bSw3 = PORTB4 ; Switch 4 pin
;
; **********************************
; A D J U S T A B L E C O N S T
; **********************************
;
.equ clock = 1200000 ; Default clock
.equ cTimeBase = 30 ; Time slot in minutes
.equ cTimeGrn = 5 ; Time for green in minutes
.equ cPresc = 64 ; Can be 1, 8 or 64
;
; **********************************
; F I X & D E R I V. C O N S T
; **********************************
;
.equ fPwm = ((clock + 128) / 256 + cPresc/2) / cPresc ; Frequency PWM in Hz
.equ tPwm = (1000000*256*cPresc+clock/2)/clock ; PWM cycle duration in ms
.equ fColorChange = 1000*fPwm / 256 ; Color change frequency in mHz
.equ tColorChange = (256 * tPwm +500) / 1000 ; Color change time in ms
.equ cCntBase = ((cTimeBase*60*clock+cPresc/2)/cPresc+32768)/65536 ; The complete phase
.equ cCntGrn = ((cTimeGrn*60*clock+cPresc/2)/cPresc+32768)/65536 ; The green phase
.equ cCntRed = cCntBase - cCntGrn ; The red phase
;
.if (cCntBase==0)||(cCntRed==0)||(cCntGrn==0)
.error "Counter value at zero, decrease prescaler if possible"
.endif
;
; **********************************
; R E G I S T E R S
; **********************************
;
; free: R0 to R15
.def rmp = R16 ; Define multipurpose register
.def rDelayL = R17 ; Delay constant, LSB
.def rDelayH = R18 ; dto., MSB
.def rCmp = R19 ; Phase counter
; free: R20 to R23
.def rCntL = R24 ; Counter, LSB
.def rCntH = R25 ; dto., MSB
; free: R27:R26 = X
; free: R29:R28 = Y
; used: R31:R30 = Z for calculation
;
; **********************************
; S R A M
; **********************************
;
.dseg
.org SRAM_START
; No SRAM used
;
; **********************************
; C O D E
; **********************************
;
.cseg
.org 000000
;
; **********************************
; R E S E T & I N T - V E C T O R S
; **********************************
rjmp Main ; Reset vector
reti ; INT0
reti ; PCI0
rjmp Tc0OvfIsr ; OVF0
reti ; ERDY
reti ; ACI
reti ; OC0A
reti ; OC0B
reti ; WDT
reti ; ADCC
;
; **********************************
; I N T - S E R V I C E R O U T .
; **********************************
;
; TC0 overflow interrupt service routine
Tc0OvfIsr:
sbiw rCntL,1 ; Count down
brne Tc0OvfIsrRet ; Time not yet over
; Check if last period was processed
inc rCmp ; Next color intensity
out OCR0A,rCmp ; To compare A
out OCR0B,rCmp ; And to compare B
brne Tc0OvfIsrSetCnt ; Not at zero, restart counter
brts Tc0OvfIsrG2Ra ; Switch from red to green
ldi rmp,(1<<COM0B1)|(1<<COM0B0)|(1<<WGM01)|(1<<WGM00) ; Fast PWM, OC0B inverted
out TCCR0A,rmp ; To TC0 control register A
set ; Next phase: switch from red to green
ldi rDelayH,High(cCntRed) ; Load red counter value, MSB
ldi rDelayL,Low(cCntRed) ; dto., LSB
ldi ZH,High(cCntBase) ; Load base count, MSB
ldi ZL,Low(cCntBase) ; dto., LSB
in rmp,pOutI ; Read switches
sbrc rmp,2 ; Switch 2 pressed?
rjmp Tc0OvfIsrSw2 ; No
add rDelayL,ZL ; Add base count, LSB
adc rDelayH,ZH ; dto., MSB
brcs Tc0OvfIsrClrRd ; If overflow: Clear count
Tc0OvfIsrSw2:
lsl ZL ; Multiply base by 2, LSB
rol ZH ; dto., MSB
sbrc rmp,3 ; Switch 3 pressed?
rjmp Tc0OvfIsrSw3 ; No
add rDelayL,ZL ; Add doubled base, LSB
adc rDelayH,ZH ; dto., MSB
brcs Tc0OvfIsrClrRd ; If carry: Clear count
Tc0OvfIsrSw3:
lsl ZL ; Multiply base by 4, LSB
rol ZH ; dto., MSB
sbrc rmp,4 ; Switch 4 pressed?
rjmp Tc0OvfIsrSw4 ; No
add rDelayL,ZL ; Add fourfold base, LSB
adc rDelayH,ZH ; dto., MSB
brcc Tc0OvfIsrSw4 ; If not carry: do not clear count
Tc0OvfIsrClrRd:
clr rDelayH ; Overflow during adding, set max, MSB
clr rDelayL ; dto., LSB
Tc0OvfIsrSw4:
cbi pOutP,bAnGnP ; Green anode to low
rjmp Tc0OvfIsrSetCnt ; Set counter value
Tc0OvfIsrG2Ra:
; Switch from red to green
ldi rmp,(1<<COM0A1)|(1<<WGM01)|(1<<WGM00) ; Fast PWM, OC0A non-inverted
out TCCR0A,rmp ; To TC0 control register A
clt ; Next phase: switch to red
ldi rDelayH,High(cCntGrn) ; Load green delay, MSB
ldi rDelayL,Low(cCntGrn) ; dto., LSB
cbi pOutP,bAnRdP ; Red anode to low
Tc0OvfIsrSetCnt:
mov rCntH,rDelayH ; Restart down-counter, MSB
mov rCntL,rDelayL ; dto., LSB
Tc0OvfIsrRet:
reti
;
; **********************************
; M A I N P R O G R A M I N I T
; **********************************
;
Main:
; Init stack for interrupts
ldi rmp,Low(RAMEND) ; At the end of the SRAM
out SPL,rmp ; Init LSB stack pointer
; Init port pins
sbi pOutD,bAnGnD ; Direction output, green LED anode
sbi pOutD,bAnRdD ; dto., red LED
sbi pOutP,bSw1 ; Pull-Up high, switch 1
sbi pOutP,bSw2 ; Pull-Up high, switch 1
sbi pOutP,bSw3 ; Pull-Up high, switch 1
; Set first delay to minimum
ldi rDelayH,0 ; Delay value = 1, MSB
ldi rDelayL,1 ; dto., LSB
ldi rCntH,0 ; Copy delay = 1, MSB
ldi rCntL,1 ; dto., LSB
clt ; Start with switrching to red LED
; Init TC0 in PWM mode
ldi rCmp,0xFF ; Start with the highest PWM stage
out OCR0A,rCmp ; To compare A
out OCR0B,rCmp ; and to compare B
ldi rmp,(1<<WGM01)|(1<<WGM00) ; Fast PWM, OC outputs off
out TCCR0A,rmp ; To TC0 control port A
; Set prescaler value
.if cPresc == 1
ldi rmp,(1<<CS00) ; Prescaler = 1
.endif
.if cPresc == 8
ldi rmp,1<<CS01 ; Prescaler = 8
.endif
.if cPresc == 64
ldi rmp,(1<<CS01)|(1<<CS00) ; Prescaler = 64
.endif
out TCCR0B,rmp ; To TC0 control port B
ldi rmp,1<<TOIE0 ; Enable overflow interrupt
out TIMSK0,rmp ; in timer TC0 interrupt mask
; Sleep mode enable
ldi rmp,1<<SE ; Sleep idle
out MCUCR,rmp ; in Master control port
sei ; Enable interrupts
;
; **********************************
; P R O G R A M L O O P
; **********************************
;
Loop:
sleep
nop
rjmp loop
;
; End of source code
;
; Copyright information
.db "(C)2021 by Gerhard Schmidt " ; Source code readable
.db "C(2)20 1ybG reahdrS hcimtd " ; Machine code format
;