Path: Home => AVR-EN => Applications => Long timer tn13 => asm code   Diese Seite in Deutsch: Flag DE Logo
Long timer with ATtiny13 AVR applications

Long timer with ATtiny13
Assembler software for the long timer

Assembler source code for the long timer

The original assembler source code is here.

;
; ****************************************
; * 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
;



©2021 by http://www.avr-asm-tutorial.net