/**************************************************************************** * * Delay.c * * Routines for waiting various amounts of time. * ****************************************************************************/ #include "Config.h" #include "Delay.h" #include "Timer.h" #include #include #if defined( __AVR_LIBC_VERSION__ ) # include #else #include #endif #define LOOPS_PER_MS (CFG_CPU_CLOCK/1000/4) #define LOOPS_PER_US (LOOPS_PER_MS/1000) volatile uint16_t gTickCount = 0; /* spin for us microseconds */ void us_spin(unsigned short us) { if (!us) return; /* the inner loop takes 4 cycles per iteration */ __asm__ __volatile__ ( "1: \n" " ldi r26, %3 \n" " ldi r27, %2 \n" "2: sbiw r26, 1 \n" " brne 2b \n" " sbiw %0, 1 \n" " brne 1b \n" : "=w" (us) : "w" (us), "i" (LOOPS_PER_US >> 8), "i" (0xff & LOOPS_PER_US) ); } /* spin for ms milliseconds */ void ms_spin(unsigned short ms) { if (!ms) return; /* the inner loop takes 4 cycles per iteration */ __asm__ __volatile__ ( "1: \n" " ldi r26, %3 \n" " ldi r27, %2 \n" "2: sbiw r26, 1 \n" " brne 2b \n" " sbiw %0, 1 \n" " brne 1b \n" : "=w" (ms) : "w" (ms), "i" (LOOPS_PER_MS >> 8), "i" (0xff & LOOPS_PER_MS) ); } /***************************************************************************/ /** * Delays for a multiple of 100 microseconds. */ void Delay100uSec ( uint8_t num100uSec /**< Number of 100 microsecond units to delay */ ) { while ( num100uSec > 0 ) { us_spin( 100 ); num100uSec--; } } // Delay100uSec /***************************************************************************/ /** * Delays for a multiple of 10 microseconds. */ void Delay10uSec ( uint8_t num10uSec /**< Number of 10 microsecond units to delay */ ) { while ( num10uSec > 0 ) { us_spin( 10 ); num10uSec--; } } // Delay10uSec /***************************************************************************/ /** * Delays for a multiple of 100 milliseconds. */ void Delay100mSec ( uint8_t num100mSec /**< Number of 100 microsecond units to delay */ ) { while ( num100mSec > 0 ) { ms_spin( 100 ); num100mSec--; } } // Delay100mSec /***************************************************************************/ /** * Delays for a multiple of 10 milliseconds. */ void Delay10mSec ( uint8_t num10mSec /**< Number of 10 microsecond units to delay */ ) { while ( num10mSec > 0 ) { ms_spin( 10 ); num10mSec--; } } // Delay10mSec /***************************************************************************/ /** * Delays for a multiple of 1 milliseconds. */ void Delay1mSec ( uint8_t num1mSec /**< Number of 10 microsecond units to delay */ ) { while ( num1mSec > 0 ) { ms_spin( 1 ); num1mSec--; } } // Delay1mSec /***************************************************************************/ /** * Timer 0 interrupt handler */ SIGNAL(SIG_OVERFLOW0) /* signal handler for tcnt0 overflow interrupt */ { static int microTick = 0; if ( ++microTick >= 10 ) { microTick = 0; gTickCount++; } // We want our timer tick to interrupt once a millisecond. // If we use 16 MHz/64 then we get 250000 counts/second. So setting // things up to overflow after 250 will give us 1000 overflows/second // // For CFG_CPU_CLOCK = 16 MHz, 16,000,000 / 64 / 1000 = 250 // For // 256 - 250 = 6 #define OVERFLOW_COUNT ( CFG_CPU_CLOCK / 1000 / 64 ) TCNT0 = (uint8_t) -OVERFLOW_COUNT; } // Timer 0 Overflow /***************************************************************************/ /** * InitTimer */ void InitTimer( void ) { TCCR0 = TIMER0_CLOCK_SEL_DIV_64; // Divide by 64 TCNT0 = 0; // Enable Timer 0 interrupt timer_enable_int( 1 << TOIE0 ); sei(); } // InitTimer /***************************************************************************/ /** * Wait for Timer 0 to rollover */ void WaitForTimer0Rollover( void ) { uint16_t prevCount = gTickCount; while ( gTickCount == prevCount ) { ; } } // WaitForTimer0Rollover