} | } | ||||
//------------------------------------------------------------- | |||||
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"))); |