/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See the file COPYING * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * Copyright (C) 2010 Frank van Maarseveen */ #include #include #include #include "common.h" #include "bits.h" #include "boot.h" #include "timer0.h" /* * Timer/Counter0 implements two timestamp counters. An 8 bits wide 16usec * resolution timestamp counter is provided by TCNT0 using the 4 MHz system * clock divided by 64 (prescaler). It must not be written. * The "Timer/Counter0 Compare Match A" interrupt is used for implementing * a 32 bits wide millisecond resolution timestamp counter. */ void t0_init(void) { OCR0A = TCNT0 + T0_MS; TCCR0B = _BV(CS01) | _BV(CS00); /* 4MHz/64 */ BIT_SET(TIMSK, OCIE0A); } void t0_cleanup(void) { BIT_CLR(TIMSK, OCIE0A); TCCR0B = 0; } /* * Note that SPM page erase/write will halt the CPU for about 4 ms: they * cannot be timed this way and break subsequent t0_ms* calls until after * the first Timer/Counter0 Compare Match A interrupt or reinitialization. * * time: 10 us (estimation based on 40 words of code and 4MHz clock). */ static uint32_t millisec; ISR(TIMER0_COMPA_vect) { ++millisec; OCR0A += T0_MS; } /* * Return the elapsed time in milliseconds. Usage: * * uint32_t start = t0_ms(0); * ... * elapsed = t0_ms(start); */ __attribute__((noinline)) uint32_t t0_ms(uint32_t start) { uint32_t ms; uint8_t sreg; saveicli(sreg); ms = millisec; restorei(sreg); return ms - start; } /* * Wait `ms' milliseconds. The argument must not exceed 0x80000000. */ void t0_mswait(uint32_t ms) { uint32_t t; t = t0_ms(0) + ms; while ((int32_t)t0_ms(t) < 0) ; }