TaskScheduler.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // Cooperative multitasking library for Arduino version 1.6
  2. // Copyright (c) 2015 Anatoli Arkhipenko
  3. //
  4. // Changelog:
  5. // 2015-02-24 - Initial release
  6. // 2015-02-28 - added delay() and disableOnLastIteration() functions
  7. // 2015-03-25 - changed scheduler execute() function for a more precise delay calculation:
  8. // 1. Do not delay if any of the tasks ran (making request for immediate execution redundant)
  9. // 2. Delay is invoked only if none of the tasks ran
  10. // 3. Delay is based on the min anticipated wait until next task _AND_ the runtime of execute function itself.
  11. // 2015-05-11 - added restart() and restartDelayed() functions to restart tasks which are on hold after running all iterations
  12. // 2015-05-19 - completely removed delay from the scheduler since there are no power saving there. using 1 ms sleep instead
  13. // v1.41:
  14. // 2015-09-15 - more careful placement of AVR-specific includes for sleep functions (compatibility with DUE)
  15. // sleep on idle run is no longer a default and should be explicitly compiled with _TASK_SLEEP_ON_IDLE_RUN defined
  16. // v1.50:
  17. // 2015-09-20 - access to currently executing task (for callback functions)
  18. // 2015-09-20 - pass scheduler as a parameter to the task constructor to append the task to the end of the chain
  19. // 2015-09-20 - option to create a task already enabled
  20. // v1.51:
  21. // 2015-09-21 - bug fix: incorrect handling of active tasks via set() and setIterations().
  22. // Thanks to Hannes Morgenstern for catching this one
  23. // v1.6:
  24. // 2015-09-22 - revert back to having all tasks disable on last iteration.
  25. // 2015-09-22 - deprecated disableOnLastIteration method as a result
  26. // 2015-09-22 - created a separate branch 'disable-on-last-iteration' for this
  27. /* ============================================
  28. Cooperative multitasking library code is placed under the MIT license
  29. Copyright (c) 2015 Anatoli Arkhipenko
  30. Permission is hereby granted, free of charge, to any person obtaining a copy
  31. of this software and associated documentation files (the "Software"), to deal
  32. in the Software without restriction, including without limitation the rights
  33. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  34. copies of the Software, and to permit persons to whom the Software is
  35. furnished to do so, subject to the following conditions:
  36. The above copyright notice and this permission notice shall be included in
  37. all copies or substantial portions of the Software.
  38. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  39. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  40. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  41. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  42. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  43. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  44. THE SOFTWARE.
  45. ===============================================
  46. */
  47. #include <Arduino.h>
  48. #ifndef _TASKSCHEDULER_H_
  49. #define _TASKSCHEDULER_H_
  50. //#define _TASK_DEBUG
  51. //#define _TASK_TIMECRITICAL
  52. //#define _TASK_SLEEP_ON_IDLE_RUN
  53. #ifdef _TASK_SLEEP_ON_IDLE_RUN
  54. #include <avr/sleep.h>
  55. #include <avr/power.h>
  56. #endif
  57. class Task;
  58. class Scheduler {
  59. public:
  60. Scheduler();
  61. inline void init() { iFirst = NULL; iLast = NULL; iCurrent = NULL; }
  62. void addTask(Task& aTask);
  63. void deleteTask(Task& aTask);
  64. void disableAll();
  65. void enableAll();
  66. void execute();
  67. inline Task& currentTask() {return *iCurrent; }
  68. #ifdef _TASK_SLEEP_ON_IDLE_RUN
  69. void allowSleep(bool aState) { iAllowSleep = aState; }
  70. #endif
  71. private:
  72. Task *iFirst, *iLast, *iCurrent;
  73. #ifdef _TASK_SLEEP_ON_IDLE_RUN
  74. bool iAllowSleep;
  75. #endif
  76. };
  77. class Task {
  78. friend class Scheduler;
  79. public:
  80. Task(unsigned long aInterval=0, long aIterations=0, void (*aCallback)()=NULL, Scheduler* aScheduler=NULL, boolean aEnable=false);
  81. void enable();
  82. void enableDelayed(unsigned long aDelay=0);
  83. void delay(unsigned long aDelay=0);
  84. void restart();
  85. void restartDelayed(unsigned long aDelay=0);
  86. void disable();
  87. inline bool isEnabled() { return iEnabled; }
  88. void set(unsigned long aInterval, long aIterations, void (*aCallback)());
  89. void setInterval(unsigned long aInterval);
  90. inline unsigned long getInterval() { return iInterval; }
  91. void setIterations(long aIterations);
  92. inline long getIterations() { return iIterations; }
  93. inline void setCallback(void (*aCallback)()) { iCallback = aCallback; }
  94. #ifdef _TASK_TIMECRITICAL
  95. inline long getOverrun() { return iOverrun; }
  96. #endif
  97. inline bool isFirstIteration() { return (iIterations >= iSetIterations-1); }
  98. inline bool isLastIteration() { return (iIterations == 0); }
  99. private:
  100. void reset();
  101. volatile bool iEnabled;
  102. volatile unsigned long iInterval;
  103. volatile unsigned long iPreviousMillis;
  104. #ifdef _TASK_TIMECRITICAL
  105. volatile long iOverrun;
  106. #endif
  107. volatile long iIterations;
  108. long iSetIterations;
  109. void (*iCallback)();
  110. Task *iPrev, *iNext;
  111. Scheduler *iScheduler;
  112. };
  113. #endif /* _TASKSCHEDULER_H_ */