├── README.md ├── SimpleTimer.cpp └── SimpleTimer.h /README.md: -------------------------------------------------------------------------------- 1 | # SimpleTimer for Arduino 2 | 3 | This is a fork of the SimpleTimer library from Marcello Romani (http://playground.arduino.cc/Code/SimpleTimer). Sadly there is no original repository to apply pull requests. 4 | 5 | ## Additional Features 6 | 7 | * Support lambda-expressions / std::function callbacks 8 | -------------------------------------------------------------------------------- /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(unsigned 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(unsigned long d, timer_callback f) { 159 | return setTimer(d, f, RUN_FOREVER); 160 | } 161 | 162 | 163 | int SimpleTimer::setTimeout(unsigned 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 | } 242 | -------------------------------------------------------------------------------- /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 | #ifndef __AVR__ 32 | #include 33 | #endif // __AVR__ 34 | 35 | #if defined(ARDUINO) && ARDUINO >= 100 36 | #include 37 | #else 38 | #include 39 | #endif 40 | 41 | #ifndef __AVR__ 42 | typedef std::function timer_callback; 43 | #else 44 | typedef void (*timer_callback)(); 45 | #endif // __AVR__ 46 | 47 | class SimpleTimer { 48 | 49 | public: 50 | // maximum number of timers 51 | const static int MAX_TIMERS = 10; 52 | 53 | // setTimer() constants 54 | const static int RUN_FOREVER = 0; 55 | const static int RUN_ONCE = 1; 56 | 57 | // constructor 58 | SimpleTimer(); 59 | 60 | // this function must be called inside loop() 61 | void run(); 62 | 63 | // call function f every d milliseconds 64 | int setInterval(unsigned long d, timer_callback f); 65 | 66 | // call function f once after d milliseconds 67 | int setTimeout(unsigned long d, timer_callback f); 68 | 69 | // call function f every d milliseconds for n times 70 | int setTimer(unsigned long d, timer_callback f, int n); 71 | 72 | // destroy the specified timer 73 | void deleteTimer(int numTimer); 74 | 75 | // restart the specified timer 76 | void restartTimer(int numTimer); 77 | 78 | // returns true if the specified timer is enabled 79 | boolean isEnabled(int numTimer); 80 | 81 | // enables the specified timer 82 | void enable(int numTimer); 83 | 84 | // disables the specified timer 85 | void disable(int numTimer); 86 | 87 | // enables the specified timer if it's currently disabled, 88 | // and vice-versa 89 | void toggle(int numTimer); 90 | 91 | // returns the number of used timers 92 | int getNumTimers(); 93 | 94 | // returns the number of available timers 95 | int getNumAvailableTimers() { return MAX_TIMERS - numTimers; }; 96 | 97 | private: 98 | // deferred call constants 99 | const static int DEFCALL_DONTRUN = 0; // don't call the callback function 100 | const static int DEFCALL_RUNONLY = 1; // call the callback function but don't delete the timer 101 | const static int DEFCALL_RUNANDDEL = 2; // call the callback function and delete the timer 102 | 103 | // find the first available slot 104 | int findFirstFreeSlot(); 105 | 106 | // value returned by the millis() function 107 | // in the previous run() call 108 | unsigned long prev_millis[MAX_TIMERS]; 109 | 110 | // pointers to the callback functions 111 | timer_callback callbacks[MAX_TIMERS]; 112 | 113 | // delay values 114 | unsigned long delays[MAX_TIMERS]; 115 | 116 | // number of runs to be executed for each timer 117 | int maxNumRuns[MAX_TIMERS]; 118 | 119 | // number of executed runs for each timer 120 | int numRuns[MAX_TIMERS]; 121 | 122 | // which timers are enabled 123 | boolean enabled[MAX_TIMERS]; 124 | 125 | // deferred function call (sort of) - N.B.: this array is only used in run() 126 | int toBeCalled[MAX_TIMERS]; 127 | 128 | // actual number of timers in use 129 | int numTimers; 130 | }; 131 | 132 | #endif 133 | --------------------------------------------------------------------------------