├── .gitignore ├── README ├── SimpleTimer.cpp └── SimpleTimer.h /.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfturcot/SimpleTimer/b30890b8f7046bf3b0258e5870e5dda78ac5c71a/.gitignore -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Visit this page for more information: 2 | http://playground.arduino.cc/Code/SimpleTimer -------------------------------------------------------------------------------- /SimpleTimer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SimpleTimer.cpp 3 | * 4 | * SimpleTimer - A timer library for Arduino. 5 | * Author: mromani@ottotecnica.com 6 | * Copyright (c) 2010 OTTOTECNICA Italy 7 | * 8 | * This library is free software; you can redistribute it 9 | * and/or modify it under the terms of the GNU Lesser 10 | * General Public License as published by the Free Software 11 | * Foundation; either version 2.1 of the License, or (at 12 | * your option) any later version. 13 | * 14 | * This library is distributed in the hope that it will 15 | * be useful, but WITHOUT ANY WARRANTY; without even the 16 | * implied warranty of MERCHANTABILITY or FITNESS FOR A 17 | * PARTICULAR PURPOSE. See the GNU Lesser General Public 18 | * License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser 21 | * General Public License along with this library; if not, 22 | * write to the Free Software Foundation, Inc., 23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | */ 25 | 26 | 27 | #include "SimpleTimer.h" 28 | 29 | 30 | // Select time function: 31 | //static inline unsigned long elapsed() { return micros(); } 32 | static inline unsigned long elapsed() { return millis(); } 33 | 34 | 35 | SimpleTimer::SimpleTimer() { 36 | unsigned long current_millis = elapsed(); 37 | 38 | for (int i = 0; i < MAX_TIMERS; i++) { 39 | enabled[i] = false; 40 | callbacks[i] = 0; // if the callback pointer is zero, the slot is free, i.e. doesn't "contain" any timer 41 | prev_millis[i] = current_millis; 42 | numRuns[i] = 0; 43 | } 44 | 45 | numTimers = 0; 46 | } 47 | 48 | 49 | void SimpleTimer::run() { 50 | int i; 51 | unsigned long current_millis; 52 | 53 | // get current time 54 | current_millis = elapsed(); 55 | 56 | for (i = 0; i < MAX_TIMERS; i++) { 57 | 58 | toBeCalled[i] = DEFCALL_DONTRUN; 59 | 60 | // no callback == no timer, i.e. jump over empty slots 61 | if (callbacks[i]) { 62 | 63 | // is it time to process this timer ? 64 | // see http://arduino.cc/forum/index.php/topic,124048.msg932592.html#msg932592 65 | 66 | if (current_millis - prev_millis[i] >= delays[i]) { 67 | 68 | // update time 69 | //prev_millis[i] = current_millis; 70 | prev_millis[i] += delays[i]; 71 | 72 | // check if the timer callback has to be executed 73 | if (enabled[i]) { 74 | 75 | // "run forever" timers must always be executed 76 | if (maxNumRuns[i] == RUN_FOREVER) { 77 | toBeCalled[i] = DEFCALL_RUNONLY; 78 | } 79 | // other timers get executed the specified number of times 80 | else if (numRuns[i] < maxNumRuns[i]) { 81 | toBeCalled[i] = DEFCALL_RUNONLY; 82 | numRuns[i]++; 83 | 84 | // after the last run, delete the timer 85 | if (numRuns[i] >= maxNumRuns[i]) { 86 | toBeCalled[i] = DEFCALL_RUNANDDEL; 87 | } 88 | } 89 | } 90 | } 91 | } 92 | } 93 | 94 | for (i = 0; i < MAX_TIMERS; i++) { 95 | switch(toBeCalled[i]) { 96 | case DEFCALL_DONTRUN: 97 | break; 98 | 99 | case DEFCALL_RUNONLY: 100 | (*callbacks[i])(); 101 | break; 102 | 103 | case DEFCALL_RUNANDDEL: 104 | (*callbacks[i])(); 105 | deleteTimer(i); 106 | break; 107 | } 108 | } 109 | } 110 | 111 | 112 | // find the first available slot 113 | // return -1 if none found 114 | int SimpleTimer::findFirstFreeSlot() { 115 | int i; 116 | 117 | // all slots are used 118 | if (numTimers >= MAX_TIMERS) { 119 | return -1; 120 | } 121 | 122 | // return the first slot with no callback (i.e. free) 123 | for (i = 0; i < MAX_TIMERS; i++) { 124 | if (callbacks[i] == 0) { 125 | return i; 126 | } 127 | } 128 | 129 | // no free slots found 130 | return -1; 131 | } 132 | 133 | 134 | int SimpleTimer::setTimer(long d, timer_callback f, int n) { 135 | int freeTimer; 136 | 137 | freeTimer = findFirstFreeSlot(); 138 | if (freeTimer < 0) { 139 | return -1; 140 | } 141 | 142 | if (f == NULL) { 143 | return -1; 144 | } 145 | 146 | delays[freeTimer] = d; 147 | callbacks[freeTimer] = f; 148 | maxNumRuns[freeTimer] = n; 149 | enabled[freeTimer] = true; 150 | prev_millis[freeTimer] = elapsed(); 151 | 152 | numTimers++; 153 | 154 | return freeTimer; 155 | } 156 | 157 | 158 | int SimpleTimer::setInterval(long d, timer_callback f) { 159 | return setTimer(d, f, RUN_FOREVER); 160 | } 161 | 162 | 163 | int SimpleTimer::setTimeout(long d, timer_callback f) { 164 | return setTimer(d, f, RUN_ONCE); 165 | } 166 | 167 | 168 | void SimpleTimer::deleteTimer(int timerId) { 169 | if (timerId >= MAX_TIMERS) { 170 | return; 171 | } 172 | 173 | // nothing to delete if no timers are in use 174 | if (numTimers == 0) { 175 | return; 176 | } 177 | 178 | // don't decrease the number of timers if the 179 | // specified slot is already empty 180 | if (callbacks[timerId] != NULL) { 181 | callbacks[timerId] = 0; 182 | enabled[timerId] = false; 183 | toBeCalled[timerId] = DEFCALL_DONTRUN; 184 | delays[timerId] = 0; 185 | numRuns[timerId] = 0; 186 | 187 | // update number of timers 188 | numTimers--; 189 | } 190 | } 191 | 192 | 193 | // function contributed by code@rowansimms.com 194 | void SimpleTimer::restartTimer(int numTimer) { 195 | if (numTimer >= MAX_TIMERS) { 196 | return; 197 | } 198 | 199 | prev_millis[numTimer] = elapsed(); 200 | } 201 | 202 | 203 | boolean SimpleTimer::isEnabled(int numTimer) { 204 | if (numTimer >= MAX_TIMERS) { 205 | return false; 206 | } 207 | 208 | return enabled[numTimer]; 209 | } 210 | 211 | 212 | void SimpleTimer::enable(int numTimer) { 213 | if (numTimer >= MAX_TIMERS) { 214 | return; 215 | } 216 | 217 | enabled[numTimer] = true; 218 | } 219 | 220 | 221 | void SimpleTimer::disable(int numTimer) { 222 | if (numTimer >= MAX_TIMERS) { 223 | return; 224 | } 225 | 226 | enabled[numTimer] = false; 227 | } 228 | 229 | 230 | void SimpleTimer::toggle(int numTimer) { 231 | if (numTimer >= MAX_TIMERS) { 232 | return; 233 | } 234 | 235 | enabled[numTimer] = !enabled[numTimer]; 236 | } 237 | 238 | 239 | int SimpleTimer::getNumTimers() { 240 | return numTimers; 241 | } -------------------------------------------------------------------------------- /SimpleTimer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SimpleTimer.h 3 | * 4 | * SimpleTimer - A timer library for Arduino. 5 | * Author: mromani@ottotecnica.com 6 | * Copyright (c) 2010 OTTOTECNICA Italy 7 | * 8 | * This library is free software; you can redistribute it 9 | * and/or modify it under the terms of the GNU Lesser 10 | * General Public License as published by the Free Software 11 | * Foundation; either version 2.1 of the License, or (at 12 | * your option) any later version. 13 | * 14 | * This library is distributed in the hope that it will 15 | * be useful, but WITHOUT ANY WARRANTY; without even the 16 | * implied warranty of MERCHANTABILITY or FITNESS FOR A 17 | * PARTICULAR PURPOSE. See the GNU Lesser General Public 18 | * License for more details. 19 | * 20 | * You should have received a copy of the GNU Lesser 21 | * General Public License along with this library; if not, 22 | * write to the Free Software Foundation, Inc., 23 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 | * 25 | */ 26 | 27 | 28 | #ifndef SIMPLETIMER_H 29 | #define SIMPLETIMER_H 30 | 31 | #if defined(ARDUINO) && ARDUINO >= 100 32 | #include 33 | #else 34 | #include 35 | #endif 36 | 37 | typedef void (*timer_callback)(void); 38 | 39 | class SimpleTimer { 40 | 41 | public: 42 | // maximum number of timers 43 | const static int MAX_TIMERS = 10; 44 | 45 | // setTimer() constants 46 | const static int RUN_FOREVER = 0; 47 | const static int RUN_ONCE = 1; 48 | 49 | // constructor 50 | SimpleTimer(); 51 | 52 | // this function must be called inside loop() 53 | void run(); 54 | 55 | // call function f every d milliseconds 56 | int setInterval(long d, timer_callback f); 57 | 58 | // call function f once after d milliseconds 59 | int setTimeout(long d, timer_callback f); 60 | 61 | // call function f every d milliseconds for n times 62 | int setTimer(long d, timer_callback f, int n); 63 | 64 | // destroy the specified timer 65 | void deleteTimer(int numTimer); 66 | 67 | // restart the specified timer 68 | void restartTimer(int numTimer); 69 | 70 | // returns true if the specified timer is enabled 71 | boolean isEnabled(int numTimer); 72 | 73 | // enables the specified timer 74 | void enable(int numTimer); 75 | 76 | // disables the specified timer 77 | void disable(int numTimer); 78 | 79 | // enables the specified timer if it's currently disabled, 80 | // and vice-versa 81 | void toggle(int numTimer); 82 | 83 | // returns the number of used timers 84 | int getNumTimers(); 85 | 86 | // returns the number of available timers 87 | int getNumAvailableTimers() { return MAX_TIMERS - numTimers; }; 88 | 89 | private: 90 | // deferred call constants 91 | const static int DEFCALL_DONTRUN = 0; // don't call the callback function 92 | const static int DEFCALL_RUNONLY = 1; // call the callback function but don't delete the timer 93 | const static int DEFCALL_RUNANDDEL = 2; // call the callback function and delete the timer 94 | 95 | // find the first available slot 96 | int findFirstFreeSlot(); 97 | 98 | // value returned by the millis() function 99 | // in the previous run() call 100 | unsigned long prev_millis[MAX_TIMERS]; 101 | 102 | // pointers to the callback functions 103 | timer_callback callbacks[MAX_TIMERS]; 104 | 105 | // delay values 106 | long delays[MAX_TIMERS]; 107 | 108 | // number of runs to be executed for each timer 109 | int maxNumRuns[MAX_TIMERS]; 110 | 111 | // number of executed runs for each timer 112 | int numRuns[MAX_TIMERS]; 113 | 114 | // which timers are enabled 115 | boolean enabled[MAX_TIMERS]; 116 | 117 | // deferred function call (sort of) - N.B.: this array is only used in run() 118 | int toBeCalled[MAX_TIMERS]; 119 | 120 | // actual number of timers in use 121 | int numTimers; 122 | }; 123 | 124 | #endif --------------------------------------------------------------------------------