/* MsTimer2.h - Using timer2 with 1ms resolution Javier Valencia https://github.com/PaulStoffregen/MsTimer2 History: 6/Jun/14 - V0.7 added support for Teensy 3.0 & 3.1 29/Dec/11 - V0.6 added support for ATmega32u4, AT90USB646, AT90USB1286 (paul@pjrc.com) some improvements added by Bill Perry note: uses timer4 on Atmega32u4 29/May/09 - V0.5 added support for Atmega1280 (thanks to Manuel Negri) 19/Mar/09 - V0.4 added support for ATmega328P (thanks to Jerome Despatis) 11/Jun/08 - V0.3 changes to allow working with different CPU frequencies added support for ATMega128 (using timer2) compatible with ATMega48/88/168/8 10/May/08 - V0.2 added some security tests and volatile keywords 9/May/08 - V0.1 released working on ATMEGA168 only This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include unsigned long MsTimer2::msecs; void (*MsTimer2::func)(); volatile unsigned long MsTimer2::count; volatile char MsTimer2::overflowing; volatile unsigned int MsTimer2::tcnt2; #if defined(__arm__) && defined(TEENSYDUINO) static IntervalTimer itimer; #endif void MsTimer2::set(unsigned long ms, void (*f)()) { float prescaler = 0.0; if (ms == 0) msecs = 1; else msecs = ms; func = f; #if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) TIMSK2 &= ~(1<= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64 TCCR2B |= (1< 16Mhz, prescaler set to 128 TCCR2B |= ((1<= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64 TCCR2 |= (1< 16Mhz, prescaler set to 128 TCCR2 |= ((1<= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64 TCCR2 |= ((1< 16Mhz, prescaler set to 256 TCCR2 |= (1<= 16000000L) { TCCR4B = (1<= 8000000L) { TCCR4B = (1<= 4000000L) { TCCR4B = (1<= 2000000L) { TCCR4B = (1<= 1000000L) { TCCR4B = (1<= 500000L) { TCCR4B = (1<= msecs && !overflowing) { overflowing = 1; count = count - msecs; // subtract ms to catch missed overflows // set to 0 if you don't want this. (*func)(); overflowing = 0; } } #if defined (__AVR__) #if defined (__AVR_ATmega32U4__) ISR(TIMER4_OVF_vect) { #else ISR(TIMER2_OVF_vect) { #endif #if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) TCNT2 = MsTimer2::tcnt2; #elif defined (__AVR_ATmega128__) TCNT2 = MsTimer2::tcnt2; #elif defined (__AVR_ATmega8__) TCNT2 = MsTimer2::tcnt2; #elif defined (__AVR_ATmega32U4__) // not necessary on 32u4's high speed timer4 #endif MsTimer2::_overflow(); } #endif // AVR