Blynk library for embedded hardware. Works with Arduino, ESP8266, Raspberry Pi, Intel Edison/Galileo, LinkIt ONE, Particle Core/Photon, Energia, ARM mbed, etc. http://www.blynk.cc/

Dependents:   Blynk_RBL_BLE_Nano Blynk_MicroBit Blynk_Serial Blynk_RBL_BLE_Nano

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BlynkTimer.cpp Source File

BlynkTimer.cpp

00001 /*
00002  * SimpleTimer.cpp
00003  *
00004  * SimpleTimer - A timer library for Arduino.
00005  * Author: mromani@ottotecnica.com
00006  * Copyright (c) 2010 OTTOTECNICA Italy
00007  *
00008  * Callback function parameters added & compiler warnings
00009  * removed by Bill Knight <billk@rosw.com> 20March2017
00010  *
00011  * This library is free software; you can redistribute it
00012  * and/or modify it under the terms of the GNU Lesser
00013  * General Public License as published by the Free Software
00014  * Foundation; either version 2.1 of the License, or (at
00015  * your option) any later version.
00016  *
00017  * This library is distributed in the hope that it will
00018  * be useful, but WITHOUT ANY WARRANTY; without even the
00019  * implied warranty of MERCHANTABILITY or FITNESS FOR A
00020  * PARTICULAR PURPOSE.  See the GNU Lesser General Public
00021  * License for more details.
00022  *
00023  * You should have received a copy of the GNU Lesser
00024  * General Public License along with this library; if not,
00025  * write to the Free Software Foundation, Inc.,
00026  * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
00027  */
00028 
00029 
00030 #include "Blynk/BlynkTimer.h"
00031 #include <string.h>
00032 
00033 // Select time function:
00034 //static inline unsigned long elapsed() { return micros(); }
00035 static inline unsigned long elapsed() { return BlynkMillis(); }
00036 
00037 
00038 SimpleTimer::SimpleTimer()
00039     : numTimers (-1)
00040 {
00041 }
00042 
00043 void SimpleTimer::init() {
00044     unsigned long current_millis = elapsed();
00045 
00046     for (int i = 0; i < MAX_TIMERS; i++) {
00047         memset(&timer[i], 0, sizeof (timer_t));
00048         timer[i].prev_millis = current_millis;
00049     }
00050 
00051     numTimers = 0;
00052 }
00053 
00054 
00055 void SimpleTimer::run() {
00056     int i;
00057     unsigned long current_millis;
00058 
00059     // get current time
00060     current_millis = elapsed();
00061 
00062     for (i = 0; i < MAX_TIMERS; i++) {
00063 
00064         timer[i].toBeCalled = DEFCALL_DONTRUN;
00065 
00066         // no callback == no timer, i.e. jump over empty slots
00067         if (timer[i].callback != NULL) {
00068 
00069             // is it time to process this timer ?
00070             // see http://arduino.cc/forum/index.php/topic,124048.msg932592.html#msg932592
00071 
00072             if ((current_millis - timer[i].prev_millis) >= timer[i].delay) {
00073 
00074                 // update time
00075                 timer[i].prev_millis += timer[i].delay;
00076 
00077                 // check if the timer callback has to be executed
00078                 if (timer[i].enabled) {
00079 
00080                     // "run forever" timers must always be executed
00081                     if (timer[i].maxNumRuns == RUN_FOREVER) {
00082                         timer[i].toBeCalled = DEFCALL_RUNONLY;
00083                     }
00084                     // other timers get executed the specified number of times
00085                     else if (timer[i].numRuns < timer[i].maxNumRuns) {
00086                         timer[i].toBeCalled = DEFCALL_RUNONLY;
00087                         timer[i].numRuns++;
00088 
00089                         // after the last run, delete the timer
00090                         if (timer[i].numRuns >= timer[i].maxNumRuns) {
00091                             timer[i].toBeCalled = DEFCALL_RUNANDDEL;
00092                         }
00093                     }
00094                 }
00095             }
00096         }
00097     }
00098 
00099     for (i = 0; i < MAX_TIMERS; i++) {
00100         if (timer[i].toBeCalled == DEFCALL_DONTRUN)
00101             continue;
00102 
00103         if (timer[i].hasParam)
00104             (*(timer_callback_p)timer[i].callback)(timer[i].param);
00105         else
00106             (*(timer_callback)timer[i].callback)();
00107 
00108         if (timer[i].toBeCalled == DEFCALL_RUNANDDEL)
00109             deleteTimer(i);
00110     }
00111 }
00112 
00113 
00114 // find the first available slot
00115 // return -1 if none found
00116 int SimpleTimer::findFirstFreeSlot() {
00117     // all slots are used
00118     if (numTimers >= MAX_TIMERS) {
00119         return -1;
00120     }
00121 
00122     // return the first slot with no callback (i.e. free)
00123     for (int i = 0; i < MAX_TIMERS; i++) {
00124         if (timer[i].callback == NULL) {
00125             return i;
00126         }
00127     }
00128 
00129     // no free slots found
00130     return -1;
00131 }
00132 
00133 
00134 int SimpleTimer::setupTimer(unsigned long d, void* f, void* p, bool h, unsigned n) {
00135     int freeTimer;
00136 
00137     if (numTimers < 0) {
00138         init();
00139     }
00140 
00141     freeTimer = findFirstFreeSlot();
00142     if (freeTimer < 0) {
00143         return -1;
00144     }
00145 
00146     if (f == NULL) {
00147         return -1;
00148     }
00149 
00150     timer[freeTimer].delay = d;
00151     timer[freeTimer].callback = f;
00152     timer[freeTimer].param = p;
00153     timer[freeTimer].hasParam = h;
00154     timer[freeTimer].maxNumRuns = n;
00155     timer[freeTimer].enabled = true;
00156     timer[freeTimer].prev_millis = elapsed();
00157 
00158     numTimers++;
00159 
00160     return freeTimer;
00161 }
00162 
00163 
00164 int SimpleTimer::setTimer(unsigned long d, timer_callback f, unsigned n) {
00165   return setupTimer(d, (void *)f, NULL, false, n);
00166 }
00167 
00168 int SimpleTimer::setTimer(unsigned long d, timer_callback_p f, void* p, unsigned n) {
00169   return setupTimer(d, (void *)f, p, true, n);
00170 }
00171 
00172 int SimpleTimer::setInterval(unsigned long d, timer_callback f) {
00173     return setupTimer(d, (void *)f, NULL, false, RUN_FOREVER);
00174 }
00175 
00176 int SimpleTimer::setInterval(unsigned long d, timer_callback_p f, void* p) {
00177   return setupTimer(d, (void *)f, p, true, RUN_FOREVER);
00178 }
00179 
00180 int SimpleTimer::setTimeout(unsigned long d, timer_callback f) {
00181     return setupTimer(d, (void *)f, NULL, false, RUN_ONCE);
00182 }
00183 
00184 int SimpleTimer::setTimeout(unsigned long d, timer_callback_p f, void* p) {
00185   return setupTimer(d, (void *)f, p, true, RUN_ONCE);
00186 }
00187 
00188 bool SimpleTimer::changeInterval(unsigned numTimer, unsigned long d) {
00189     if (numTimer >= MAX_TIMERS) {
00190         return false;
00191     }
00192 
00193     // Updates interval of existing specified timer
00194     if (timer[numTimer].callback != NULL) {
00195         timer[numTimer].delay = d;
00196         timer[numTimer].prev_millis = elapsed();
00197         return true;
00198     }
00199     // false return for non-used numTimer, no callback
00200     return false;
00201 }
00202 
00203 void SimpleTimer::deleteTimer(unsigned timerId) {
00204     if (timerId >= MAX_TIMERS) {
00205         return;
00206     }
00207 
00208     // nothing to delete if no timers are in use
00209     if (numTimers == 0) {
00210         return;
00211     }
00212 
00213     // don't decrease the number of timers if the
00214     // specified slot is already empty
00215     if (timer[timerId].callback != NULL) {
00216         memset(&timer[timerId], 0, sizeof (timer_t));
00217         timer[timerId].prev_millis = elapsed();
00218 
00219         // update number of timers
00220         numTimers--;
00221     }
00222 }
00223 
00224 
00225 // function contributed by code@rowansimms.com
00226 void SimpleTimer::restartTimer(unsigned numTimer) {
00227     if (numTimer >= MAX_TIMERS) {
00228         return;
00229     }
00230 
00231     timer[numTimer].prev_millis = elapsed();
00232 }
00233 
00234 
00235 bool SimpleTimer::isEnabled(unsigned numTimer) {
00236     if (numTimer >= MAX_TIMERS) {
00237         return false;
00238     }
00239 
00240     return timer[numTimer].enabled;
00241 }
00242 
00243 
00244 void SimpleTimer::enable(unsigned numTimer) {
00245     if (numTimer >= MAX_TIMERS) {
00246         return;
00247     }
00248 
00249     timer[numTimer].enabled = true;
00250 }
00251 
00252 
00253 void SimpleTimer::disable(unsigned numTimer) {
00254     if (numTimer >= MAX_TIMERS) {
00255         return;
00256     }
00257 
00258     timer[numTimer].enabled = false;
00259 }
00260 
00261 void SimpleTimer::enableAll() {
00262     // Enable all timers with a callback assigned (used)
00263     for (int i = 0; i < MAX_TIMERS; i++) {
00264         if (timer[i].callback != NULL && timer[i].numRuns == RUN_FOREVER) {
00265             timer[i].enabled = true;
00266         }
00267     }
00268 }
00269 
00270 void SimpleTimer::disableAll() {
00271     // Disable all timers with a callback assigned (used)
00272     for (int i = 0; i < MAX_TIMERS; i++) {
00273         if (timer[i].callback != NULL && timer[i].numRuns == RUN_FOREVER) {
00274             timer[i].enabled = false;
00275         }
00276     }
00277 }
00278 
00279 void SimpleTimer::toggle(unsigned numTimer) {
00280     if (numTimer >= MAX_TIMERS) {
00281         return;
00282     }
00283 
00284     timer[numTimer].enabled = !timer[numTimer].enabled;
00285 }
00286 
00287 
00288 unsigned SimpleTimer::getNumTimers() {
00289     return numTimers;
00290 }