TaskScheduler.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. // Cooperative multitasking library for Arduino version 1.51
  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. /* ============================================
  24. Cooperative multitasking library code is placed under the MIT license
  25. Copyright (c) 2015 Anatoli Arkhipenko
  26. Permission is hereby granted, free of charge, to any person obtaining a copy
  27. of this software and associated documentation files (the "Software"), to deal
  28. in the Software without restriction, including without limitation the rights
  29. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  30. copies of the Software, and to permit persons to whom the Software is
  31. furnished to do so, subject to the following conditions:
  32. The above copyright notice and this permission notice shall be included in
  33. all copies or substantial portions of the Software.
  34. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  35. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  36. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  37. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  38. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  39. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  40. THE SOFTWARE.
  41. ===============================================
  42. */
  43. #include <Arduino.h>
  44. #ifndef _TASKSCHEDULER_H_
  45. #define _TASKSCHEDULER_H_
  46. //#define _TASK_DEBUG
  47. //#define _TASK_TIMECRITICAL
  48. //#define _TASK_SLEEP_ON_IDLE_RUN
  49. #ifdef _TASK_SLEEP_ON_IDLE_RUN
  50. #include <avr/sleep.h>
  51. #include <avr/power.h>
  52. #endif
  53. class Task;
  54. class Scheduler {
  55. public:
  56. Scheduler();
  57. inline void init() { iFirst = NULL; iLast = NULL; iCurrent = NULL; }
  58. void addTask(Task& aTask);
  59. void deleteTask(Task& aTask);
  60. void disableAll();
  61. void enableAll();
  62. void execute();
  63. inline Task& currentTask() {return *iCurrent; }
  64. #ifdef _TASK_SLEEP_ON_IDLE_RUN
  65. void allowSleep(bool aState) { iAllowSleep = aState; }
  66. #endif
  67. private:
  68. Task *iFirst, *iLast, *iCurrent;
  69. #ifdef _TASK_SLEEP_ON_IDLE_RUN
  70. bool iAllowSleep;
  71. #endif
  72. };
  73. class Task {
  74. friend class Scheduler;
  75. public:
  76. Task(unsigned long aInterval=0, long aIterations=0, void (*aCallback)()=NULL, Scheduler* aScheduler=NULL, boolean aEnable=false);
  77. void enable();
  78. void enableDelayed(unsigned long aDelay=0);
  79. void delay(unsigned long aDelay=0);
  80. void restart();
  81. void restartDelayed(unsigned long aDelay=0);
  82. void disable();
  83. inline bool isEnabled() { return iEnabled; }
  84. void set(unsigned long aInterval, long aIterations, void (*aCallback)());
  85. void setInterval(unsigned long aInterval);
  86. inline unsigned long getInterval() { return iInterval; }
  87. void setIterations(long aIterations);
  88. inline long getIterations() { return iIterations; }
  89. inline void setCallback(void (*aCallback)()) { iCallback = aCallback; }
  90. inline void disableOnLastIteration(bool aBool) { iDisableOnLastIteration = aBool; } // default is false
  91. #ifdef _TASK_TIMECRITICAL
  92. inline long getOverrun() { return iOverrun; }
  93. #endif
  94. inline bool isFirstIteration() { return (iIterations >= iSetIterations-1); }
  95. inline bool isLastIteration() { return (iIterations == 0); }
  96. private:
  97. void reset();
  98. volatile bool iEnabled;
  99. volatile bool iDisableOnLastIteration;
  100. volatile unsigned long iInterval;
  101. volatile unsigned long iPreviousMillis;
  102. #ifdef _TASK_TIMECRITICAL
  103. volatile long iOverrun;
  104. #endif
  105. volatile long iIterations;
  106. long iSetIterations;
  107. void (*iCallback)();
  108. Task *iPrev, *iNext;
  109. Scheduler *iScheduler;
  110. };
  111. #endif /* _TASKSCHEDULER_H_ */