/* * SimpleTimer.cpp * * SimpleTimer - A timer library for Arduino. * Author: mromani@ottotecnica.com * Copyright (c) 2010 OTTOTECNICA Italy * * 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 "SimpleTimer.h" SimpleTimer::SimpleTimer() { unsigned long current_millis = millis(); for (int i = 0; i < MAX_TIMERS; i++) { enabled[i] = false; callbacks[i] = 0; // if the callback pointer is zero, the slot is free, i.e. doesn't "contain" any timer prev_millis[i] = current_millis; numRuns[i] = 0; } numTimers = 0; } void SimpleTimer::run() { int i; unsigned long current_millis; // get current time current_millis = millis(); for (i = 0; i < MAX_TIMERS; i++) { toBeCalled[i] = DEFCALL_DONTRUN; // no callback == no timer, i.e. jump over empty slots if (callbacks[i]) { // is it time to process this timer ? if (current_millis - prev_millis[i] >= delays[i]) { // update time prev_millis[i] = current_millis; // check if the timer callback has to be executed if (enabled[i]) { // "run forever" timers must always be executed if (maxNumRuns[i] == RUN_FOREVER) { toBeCalled[i] = DEFCALL_RUNONLY; } // other timers get executed the specified number of times else if (numRuns[i] < maxNumRuns[i]) { toBeCalled[i] = DEFCALL_RUNONLY; numRuns[i]++; // after the last run, delete the timer if (numRuns[i] >= maxNumRuns[i]) { toBeCalled[i] = DEFCALL_RUNANDDEL; } } } } } } for (i = 0; i < MAX_TIMERS; i++) { switch(toBeCalled[i]) { case DEFCALL_DONTRUN: break; case DEFCALL_RUNONLY: (*callbacks[i])(); break; case DEFCALL_RUNANDDEL: (*callbacks[i])(); deleteTimer(i); break; } } } // find the first available slot // return -1 if none found int SimpleTimer::findFirstFreeSlot() { int i; // all slots are used if (numTimers >= MAX_TIMERS) { return -1; } // return the first slot with no callback (i.e. free) for (i = 0; i < MAX_TIMERS; i++) { if (callbacks[i] == 0) { return i; } } // we should never reach this point... return -1; } int SimpleTimer::setTimer(long d, timer_callback f, int n) { int freeTimer; freeTimer = findFirstFreeSlot(); if (freeTimer < 0) { return -1; } delays[freeTimer] = d; callbacks[freeTimer] = f; maxNumRuns[freeTimer] = n; enabled[freeTimer] = true; prev_millis[freeTimer] = millis(); numTimers++; return freeTimer; } int SimpleTimer::setInterval(long d, timer_callback f) { return setTimer(d, f, RUN_FOREVER); } int SimpleTimer::setTimeout(long d, timer_callback f) { return setTimer(d, f, RUN_ONCE); } void SimpleTimer::deleteTimer(int numTimer) { if (numTimer >= MAX_TIMERS) { return; } // nothing to delete if no timers are in use if (numTimers == 0) { return; } callbacks[numTimer] = 0; enabled[numTimer] = false; delays[numTimer] = 0; numRuns[numTimer] = 0; // update number of timers numTimers--; } // function contributed by code@rowansimms.com void SimpleTimer::restartTimer(int numTimer) { if (numTimer >= MAX_TIMERS) { return; } prev_millis[numTimer] = millis(); } boolean SimpleTimer::isEnabled(int numTimer) { if (numTimer >= MAX_TIMERS) { return false; } return enabled[numTimer]; } void SimpleTimer::enable(int numTimer) { if (numTimer >= MAX_TIMERS) { return; } enabled[numTimer] = true; } void SimpleTimer::disable(int numTimer) { if (numTimer >= MAX_TIMERS) { return; } enabled[numTimer] = false; } void SimpleTimer::toggle(int numTimer) { if (numTimer >= MAX_TIMERS) { return; } enabled[numTimer] = !enabled[numTimer]; } int SimpleTimer::getNumTimers() { return numTimers; }