experiments with Pylontech/GroWatt PV tech
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

250 lines
5.6 KiB

  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. #include "SimpleTimer.h"
  26. // Select time function:
  27. //static inline unsigned long elapsed() { return micros(); }
  28. static inline unsigned long elapsed() { return millis(); }
  29. SimpleTimer::SimpleTimer()
  30. : numTimers (-1)
  31. {
  32. }
  33. void SimpleTimer::init() {
  34. unsigned long current_millis = elapsed();
  35. for (int i = 0; i < MAX_TIMERS; i++) {
  36. enabled[i] = false;
  37. callbacks[i] = 0; // if the callback pointer is zero, the slot is free, i.e. doesn't "contain" any timer
  38. prev_millis[i] = current_millis;
  39. numRuns[i] = 0;
  40. }
  41. numTimers = 0;
  42. }
  43. void SimpleTimer::run() {
  44. int i;
  45. unsigned long current_millis;
  46. // get current time
  47. current_millis = elapsed();
  48. for (i = 0; i < MAX_TIMERS; i++) {
  49. toBeCalled[i] = DEFCALL_DONTRUN;
  50. // no callback == no timer, i.e. jump over empty slots
  51. if (callbacks[i]) {
  52. // is it time to process this timer ?
  53. // see http://arduino.cc/forum/index.php/topic,124048.msg932592.html#msg932592
  54. if (current_millis - prev_millis[i] >= delays[i]) {
  55. // update time
  56. //prev_millis[i] = current_millis;
  57. prev_millis[i] += delays[i];
  58. // check if the timer callback has to be executed
  59. if (enabled[i]) {
  60. // "run forever" timers must always be executed
  61. if (maxNumRuns[i] == RUN_FOREVER) {
  62. toBeCalled[i] = DEFCALL_RUNONLY;
  63. }
  64. // other timers get executed the specified number of times
  65. else if (numRuns[i] < maxNumRuns[i]) {
  66. toBeCalled[i] = DEFCALL_RUNONLY;
  67. numRuns[i]++;
  68. // after the last run, delete the timer
  69. if (numRuns[i] >= maxNumRuns[i]) {
  70. toBeCalled[i] = DEFCALL_RUNANDDEL;
  71. }
  72. }
  73. }
  74. }
  75. }
  76. }
  77. for (i = 0; i < MAX_TIMERS; i++) {
  78. switch(toBeCalled[i]) {
  79. case DEFCALL_DONTRUN:
  80. break;
  81. case DEFCALL_RUNONLY:
  82. (*callbacks[i])();
  83. break;
  84. case DEFCALL_RUNANDDEL:
  85. (*callbacks[i])();
  86. deleteTimer(i);
  87. break;
  88. }
  89. }
  90. }
  91. // find the first available slot
  92. // return -1 if none found
  93. int SimpleTimer::findFirstFreeSlot() {
  94. int i;
  95. // all slots are used
  96. if (numTimers >= MAX_TIMERS) {
  97. return -1;
  98. }
  99. // return the first slot with no callback (i.e. free)
  100. for (i = 0; i < MAX_TIMERS; i++) {
  101. if (callbacks[i] == 0) {
  102. return i;
  103. }
  104. }
  105. // no free slots found
  106. return -1;
  107. }
  108. int SimpleTimer::setTimer(long d, timer_callback f, int n) {
  109. int freeTimer;
  110. if (numTimers < 0) {
  111. init();
  112. }
  113. freeTimer = findFirstFreeSlot();
  114. if (freeTimer < 0) {
  115. return -1;
  116. }
  117. if (f == NULL) {
  118. return -1;
  119. }
  120. delays[freeTimer] = d;
  121. callbacks[freeTimer] = f;
  122. maxNumRuns[freeTimer] = n;
  123. enabled[freeTimer] = true;
  124. prev_millis[freeTimer] = elapsed();
  125. numTimers++;
  126. return freeTimer;
  127. }
  128. int SimpleTimer::setInterval(long d, timer_callback f) {
  129. return setTimer(d, f, RUN_FOREVER);
  130. }
  131. int SimpleTimer::setTimeout(long d, timer_callback f) {
  132. return setTimer(d, f, RUN_ONCE);
  133. }
  134. void SimpleTimer::deleteTimer(int timerId) {
  135. if (timerId >= MAX_TIMERS) {
  136. return;
  137. }
  138. // nothing to delete if no timers are in use
  139. if (numTimers == 0) {
  140. return;
  141. }
  142. // don't decrease the number of timers if the
  143. // specified slot is already empty
  144. if (callbacks[timerId] != NULL) {
  145. callbacks[timerId] = 0;
  146. enabled[timerId] = false;
  147. toBeCalled[timerId] = DEFCALL_DONTRUN;
  148. delays[timerId] = 0;
  149. numRuns[timerId] = 0;
  150. // update number of timers
  151. numTimers--;
  152. }
  153. }
  154. // function contributed by code@rowansimms.com
  155. void SimpleTimer::restartTimer(int numTimer) {
  156. if (numTimer >= MAX_TIMERS) {
  157. return;
  158. }
  159. prev_millis[numTimer] = elapsed();
  160. }
  161. boolean SimpleTimer::isEnabled(int numTimer) {
  162. if (numTimer >= MAX_TIMERS) {
  163. return false;
  164. }
  165. return enabled[numTimer];
  166. }
  167. void SimpleTimer::enable(int numTimer) {
  168. if (numTimer >= MAX_TIMERS) {
  169. return;
  170. }
  171. enabled[numTimer] = true;
  172. }
  173. void SimpleTimer::disable(int numTimer) {
  174. if (numTimer >= MAX_TIMERS) {
  175. return;
  176. }
  177. enabled[numTimer] = false;
  178. }
  179. void SimpleTimer::toggle(int numTimer) {
  180. if (numTimer >= MAX_TIMERS) {
  181. return;
  182. }
  183. enabled[numTimer] = !enabled[numTimer];
  184. }
  185. int SimpleTimer::getNumTimers() {
  186. return numTimers;
  187. }