Teensy 4.1 core updated for C++20
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.

276 lines
6.2KB

  1. /* EventResponder - Simple event-based programming for Arduino
  2. * Copyright 2017 Paul Stoffregen
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining
  5. * a copy of this software and associated documentation files (the
  6. * "Software"), to deal in the Software without restriction, including
  7. * without limitation the rights to use, copy, modify, merge, publish,
  8. * distribute, sublicense, and/or sell copies of the Software, and to
  9. * permit persons to whom the Software is furnished to do so, subject to
  10. * the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be
  13. * included in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  19. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  20. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22. * SOFTWARE.
  23. */
  24. /* EventResponder is an experimental API, almost certain to
  25. * incompatibly change as it develops. Please understand any
  26. * programs you write now using EventResponder may need to be
  27. * updated as EventResponder develops.
  28. *
  29. * Please post EventResponder post your feedback here:
  30. * https://forum.pjrc.com/threads/44723-Arduino-Events
  31. */
  32. #include "EventResponder.h"
  33. EventResponder * EventResponder::firstYield = nullptr;
  34. EventResponder * EventResponder::lastYield = nullptr;
  35. EventResponder * EventResponder::firstInterrupt = nullptr;
  36. EventResponder * EventResponder::lastInterrupt = nullptr;
  37. bool EventResponder::runningFromYield = false;
  38. // TODO: interrupt disable/enable needed in many places!!!
  39. void EventResponder::triggerEventNotImmediate()
  40. {
  41. if (_pending) {
  42. // already triggered
  43. return;
  44. }
  45. if (_type == EventTypeYield) {
  46. // normal type, called from yield()
  47. if (firstYield == nullptr) {
  48. _next = nullptr;
  49. _prev = nullptr;
  50. firstYield = this;
  51. lastYield = this;
  52. } else {
  53. _next = nullptr;
  54. _prev = lastYield;
  55. _prev->_next = this;
  56. lastYield = this;
  57. }
  58. } else if (_type == EventTypeInterrupt) {
  59. // interrupt, called from software interrupt
  60. if (firstInterrupt == nullptr) {
  61. _next = nullptr;
  62. _prev = nullptr;
  63. firstInterrupt = this;
  64. lastInterrupt = this;
  65. } else {
  66. _next = nullptr;
  67. _prev = lastInterrupt;
  68. _prev->_next = this;
  69. lastInterrupt = this;
  70. }
  71. // TODO set interrupt pending
  72. } else {
  73. // detached, easy :-)
  74. }
  75. _pending = true;
  76. }
  77. void pendablesrvreq_isr(void)
  78. {
  79. EventResponder::runFromInterrupt();
  80. }
  81. void EventResponder::runFromInterrupt()
  82. {
  83. // FIXME: this will fail if the handler function triggers
  84. // its own or other EventResponder instances. The list will
  85. // change while we're holding a pointers to it.
  86. for (EventResponder *first=firstInterrupt; first; first = first->_next) {
  87. first->_pending = false;
  88. (*(first->_function))(*first);
  89. }
  90. firstInterrupt = nullptr;
  91. lastInterrupt = nullptr;
  92. }
  93. bool EventResponder::clearEvent()
  94. {
  95. if (_pending) {
  96. if (_type == EventTypeYield) {
  97. if (_prev) {
  98. _prev->_next = _next;
  99. } else {
  100. firstYield = _next;
  101. }
  102. if (_next) {
  103. _next->_prev = _prev;
  104. } else {
  105. lastYield = _prev;
  106. }
  107. } else if (_type == EventTypeInterrupt) {
  108. if (_prev) {
  109. _prev->_next = _next;
  110. } else {
  111. firstInterrupt = _next;
  112. }
  113. if (_next) {
  114. _next->_prev = _prev;
  115. } else {
  116. lastInterrupt = _prev;
  117. }
  118. }
  119. _pending = false;
  120. return true;
  121. }
  122. return false;
  123. }
  124. void EventResponder::detach()
  125. {
  126. if (_type == EventTypeYield) {
  127. if (_pending) {
  128. if (_prev) {
  129. _prev->_next = _next;
  130. } else {
  131. firstYield = _next;
  132. }
  133. if (_next) {
  134. _next->_prev = _prev;
  135. } else {
  136. lastYield = _prev;
  137. }
  138. }
  139. _type = EventTypeDetached;
  140. } else if (_type == EventTypeInterrupt) {
  141. if (_pending) {
  142. if (_prev) {
  143. _prev->_next = _next;
  144. } else {
  145. firstInterrupt = _next;
  146. }
  147. if (_next) {
  148. _next->_prev = _prev;
  149. } else {
  150. lastInterrupt = _prev;
  151. }
  152. }
  153. _type = EventTypeDetached;
  154. }
  155. }
  156. //-------------------------------------------------------------
  157. MillisTimer * MillisTimer::list = nullptr;
  158. void MillisTimer::begin(unsigned long milliseconds, EventResponderRef event)
  159. {
  160. end();
  161. if (!milliseconds) return;
  162. _event = &event;
  163. _ms = milliseconds;
  164. _reload = 0;
  165. addToList();
  166. }
  167. void MillisTimer::beginRepeat(unsigned long milliseconds, EventResponderRef event)
  168. {
  169. end();
  170. if (!milliseconds) return;
  171. _event = &event;
  172. _ms = milliseconds;
  173. _reload = milliseconds;
  174. addToList();
  175. }
  176. void MillisTimer::addToList()
  177. {
  178. if (list == nullptr) {
  179. // list is empty, easy case
  180. _next = nullptr;
  181. _prev = nullptr;
  182. list = this;
  183. } else if (_ms < list->_ms) {
  184. // this timer triggers before any on the list
  185. _next = list;
  186. _prev = nullptr;
  187. list->_prev = this;
  188. list = this;
  189. } else {
  190. // add this timer somewhere after the first already on the list
  191. MillisTimer *timer = list;
  192. while (timer->_next) {
  193. _ms -= timer->_ms;
  194. timer = timer->_next;
  195. if (_ms < timer->_ms) {
  196. // found the right place in the middle of list
  197. _next = timer;
  198. _prev = timer->_prev;
  199. timer->_prev = this;
  200. _prev->_next = this;
  201. isQueued = true;
  202. return;
  203. }
  204. }
  205. // add this time at the end of the list
  206. _ms -= timer->_ms;
  207. _next = nullptr;
  208. _prev = timer;
  209. timer->_next = this;
  210. }
  211. isQueued = true;
  212. }
  213. void MillisTimer::end()
  214. {
  215. if (isQueued) {
  216. if (_next) {
  217. _next->_prev = _prev;
  218. }
  219. if (_prev) {
  220. _prev->_next = _next;
  221. } else {
  222. list = _next;
  223. }
  224. isQueued = false;
  225. }
  226. }
  227. void MillisTimer::runFromTimer()
  228. {
  229. MillisTimer *timer = list;
  230. while (timer) {
  231. if (timer->_ms > 0) {
  232. timer->_ms--;
  233. break;
  234. } else {
  235. MillisTimer *next = timer->_next;
  236. if (next) next->_prev = nullptr;
  237. list = next;
  238. timer->isQueued = false;
  239. EventResponderRef event = *(timer->_event);
  240. event.triggerEvent(0, timer);
  241. if (timer->_reload) {
  242. timer->_ms = timer->_reload;
  243. timer->addToList();
  244. }
  245. timer = list;
  246. }
  247. }
  248. }
  249. extern "C" volatile uint32_t systick_millis_count;
  250. void systick_isr(void)
  251. {
  252. systick_millis_count++;
  253. MillisTimer::runFromTimer();
  254. }