| } | } | ||||
| //------------------------------------------------------------- | |||||
| MillisTimer * MillisTimer::list = nullptr; | |||||
| void MillisTimer::begin(unsigned long milliseconds, EventResponderRef event) | |||||
| { | |||||
| end(); | |||||
| if (!milliseconds) return; | |||||
| _event = &event; | |||||
| _ms = milliseconds; | |||||
| _reload = 0; | |||||
| addToList(); | |||||
| } | |||||
| void MillisTimer::beginRepeat(unsigned long milliseconds, EventResponderRef event) | |||||
| { | |||||
| end(); | |||||
| if (!milliseconds) return; | |||||
| _event = &event; | |||||
| _ms = milliseconds; | |||||
| _reload = milliseconds; | |||||
| addToList(); | |||||
| } | |||||
| void MillisTimer::addToList() | |||||
| { | |||||
| if (list == nullptr) { | |||||
| // list is empty, easy case | |||||
| _next = nullptr; | |||||
| _prev = nullptr; | |||||
| list = this; | |||||
| } else if (_ms < list->_ms) { | |||||
| // this timer triggers before any on the list | |||||
| _next = list; | |||||
| _prev = nullptr; | |||||
| list->_prev = this; | |||||
| list = this; | |||||
| } else { | |||||
| // add this timer somewhere after the first already on the list | |||||
| MillisTimer *timer = list; | |||||
| while (timer->_next) { | |||||
| _ms -= timer->_ms; | |||||
| timer = timer->_next; | |||||
| if (_ms < timer->_ms) { | |||||
| // found the right place in the middle of list | |||||
| _next = timer; | |||||
| _prev = timer->_prev; | |||||
| timer->_prev = this; | |||||
| _prev->_next = this; | |||||
| isQueued = true; | |||||
| return; | |||||
| } | |||||
| } | |||||
| // add this time at the end of the list | |||||
| _ms -= timer->_ms; | |||||
| _next = nullptr; | |||||
| _prev = timer; | |||||
| timer->_next = this; | |||||
| } | |||||
| isQueued = true; | |||||
| } | |||||
| void MillisTimer::end() | |||||
| { | |||||
| if (isQueued) { | |||||
| if (_next) { | |||||
| _next->_prev = _prev; | |||||
| } | |||||
| if (_prev) { | |||||
| _prev->_next = _next; | |||||
| } else { | |||||
| list = _next; | |||||
| } | |||||
| isQueued = false; | |||||
| } | |||||
| } | |||||
| void MillisTimer::runFromTimer() | |||||
| { | |||||
| MillisTimer *timer = list; | |||||
| while (timer) { | |||||
| if (timer->_ms > 0) { | |||||
| timer->_ms--; | |||||
| break; | |||||
| } else { | |||||
| MillisTimer *next = timer->_next; | |||||
| if (next) next->_prev = nullptr; | |||||
| list = next; | |||||
| timer->isQueued = false; | |||||
| EventResponderRef event = *(timer->_event); | |||||
| event.triggerEvent(0, timer); | |||||
| if (timer->_reload) { | |||||
| timer->_ms = timer->_reload; | |||||
| timer->addToList(); | |||||
| } | |||||
| timer = list; | |||||
| } | |||||
| } | |||||
| } | |||||
| extern "C" volatile uint32_t systick_millis_count; | |||||
| void systick_isr(void) | |||||
| { | |||||
| systick_millis_count++; | |||||
| MillisTimer::runFromTimer(); | |||||
| } | |||||
| static bool runningFromYield; | static bool runningFromYield; | ||||
| }; | }; | ||||
| class MillisTimer | |||||
| { | |||||
| public: | |||||
| constexpr MillisTimer() { | |||||
| } | |||||
| ~MillisTimer() { | |||||
| end(); | |||||
| } | |||||
| void begin(unsigned long milliseconds, EventResponderRef event); | |||||
| void beginRepeat(unsigned long milliseconds, EventResponderRef event); | |||||
| void end(); | |||||
| static void runFromTimer(); | |||||
| private: | |||||
| void addToList(); | |||||
| unsigned long _ms = 0; | |||||
| unsigned long _reload = 0; | |||||
| MillisTimer *_next = nullptr; | |||||
| MillisTimer *_prev = nullptr; | |||||
| EventResponder *_event = nullptr; | |||||
| bool isQueued = false; | |||||
| static MillisTimer *list; | |||||
| }; | |||||
| #endif | #endif |
| fault_isr(); | fault_isr(); | ||||
| } | } | ||||
| extern volatile uint32_t systick_millis_count; | |||||
| void systick_default_isr(void) | |||||
| { | |||||
| systick_millis_count++; | |||||
| } | |||||
| void nmi_isr(void) __attribute__ ((weak, alias("unused_isr"))); | void nmi_isr(void) __attribute__ ((weak, alias("unused_isr"))); | ||||
| void hard_fault_isr(void) __attribute__ ((weak, alias("fault_isr"))); | void hard_fault_isr(void) __attribute__ ((weak, alias("fault_isr"))); | ||||
| void memmanage_fault_isr(void) __attribute__ ((weak, alias("fault_isr"))); | void memmanage_fault_isr(void) __attribute__ ((weak, alias("fault_isr"))); | ||||
| void svcall_isr(void) __attribute__ ((weak, alias("unused_isr"))); | void svcall_isr(void) __attribute__ ((weak, alias("unused_isr"))); | ||||
| void debugmonitor_isr(void) __attribute__ ((weak, alias("unused_isr"))); | void debugmonitor_isr(void) __attribute__ ((weak, alias("unused_isr"))); | ||||
| void pendablesrvreq_isr(void) __attribute__ ((weak, alias("unused_isr"))); | void pendablesrvreq_isr(void) __attribute__ ((weak, alias("unused_isr"))); | ||||
| void systick_isr(void) __attribute__ ((weak, alias("systick_default_isr"))); | |||||
| void systick_isr(void) __attribute__ ((weak, alias("unused_isr"))); | |||||
| void dma_ch0_isr(void) __attribute__ ((weak, alias("unused_isr"))); | void dma_ch0_isr(void) __attribute__ ((weak, alias("unused_isr"))); | ||||
| void dma_ch1_isr(void) __attribute__ ((weak, alias("unused_isr"))); | void dma_ch1_isr(void) __attribute__ ((weak, alias("unused_isr"))); |