/* This file contains the initialization and the interrupt handler for timer 0
 * as well as a function which is intended to be used from userland to wait for
 * the timer.
 * @author Bernhard R. Fischer
 */
#include <avr/io.h>

#define OVLCNT 30


.section .text


.global init_timer
init_timer:                ; init timer 0 according to the Atmega manual
   push  r16

   clr   r16               ; set timer mode (normal)
   out   _SFR_IO_ADDR(TCCR0A),r16
   ldi   r16,0x05          ; set clock divider (/1024)
   out   _SFR_IO_ADDR(TCCR0B),r16
   clr   r16               ; set count register (256)
   out   _SFR_IO_ADDR(TCNT0),r16

   ldi   r16,1             ; enable timer interrupt
   sts   TIMSK0,r16

   ldi   r16,OVLCNT        ; copy timer counter to memory variable
   sts   tmovlcnt,r16      ; init overflow counter
   clr   r16
   sts   tmovlflag,r16     ; clear overflow flag

   pop   r16
   ret


.global t0_handler
t0_handler:                ; timer 0 interrupt handler
   push  r16               ; save system status
   in    r16,_SFR_IO_ADDR(SREG)
   push  r16

   lds   r16,tmovlcnt      ; load overflow counter and decrease
   dec   r16
   brne  .Lt0h0
   lds   r16,tmovlflag     ; increase overflow flag if counter was 0
   inc   r16
   sts   tmovlflag,r16     ; save flag back to memory
   ldi   r16,OVLCNT        ; set overflow counter to OVLCNT if it was 0
.Lt0h0:
   sts   tmovlcnt,r16      ; save overflow counter back to memory

   pop   r16               ; restore system status
   out   _SFR_IO_ADDR(SREG),r16
   pop   r16
   reti


.global wait_timer
wait_timer:                ; functions sleeps until overflow flag is not 0
   push  r16
.Lwtwait:
   lds   r16,tmovlflag     ; load flag from memory
   tst   r16               ; and test its value
   breq  .Lwtsleep
   dec   r16               ; decrease flag
   sts   tmovlflag,r16     ; and save it back to memory
   pop   r16
   ret
.Lwtsleep:
   sleep                   ; sleep if it was 0
   rjmp .Lwtwait


.section .data

tmovlcnt:                  ; overflow counter of timer 0
.space 1
tmovlflag:                 ; flag is increased of OVLCNT overflows have occured
.space 1

