Periodic timers for AVR/ESP8266/ESP32/etc
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.
 

127 lines
3.0 KiB

#pragma once
#define TIMER_STATIC __attribute__ ((unused)) static inline
#define TIMER_STATIC_ALWAYS_INLINE __attribute__ ((always_inline)) static inline
TIMER_STATIC uint16_t div1024_32_16(uint32_t in32) {
uint16_t out16;
#if defined(__AVR__)
asm volatile (
" lsr %D[in] \n\t"
" ror %C[in] \n\t"
" ror %B[in] \n\t"
" lsr %D[in] \n\t"
" ror %C[in] \n\t"
" ror %B[in] \n\t"
" mov %B[out],%C[in] \n\t"
" mov %A[out],%B[in] \n\t"
: [in] "+r" (in32),
[out] "=r" (out16)
);
#elif defined(ESP8266)
asm volatile (
" lsr %D[in] \n\t"
" ror %C[in] \n\t"
" ror %B[in] \n\t"
" lsr %D[in] \n\t"
" ror %C[in] \n\t"
" ror %B[in] \n\t"
" mov %B[out],%C[in] \n\t"
" mov %A[out],%B[in] \n\t"
: [in] "+r" (in32),
[out] "=r" (out16)
);
#else
out16 = (in32 >> 10) & 0xffff;
#endif
return out16;
}
TIMER_STATIC uint32_t milliseconds() {
return millis();
}
TIMER_STATIC uint16_t seconds() {
uint32_t ms = millis();
uint16_t s = ms / 1000;
return s;
}
TIMER_STATIC uint16_t minutes() {
uint32_t ms = millis();
uint16_t m;
m = (ms / (60000L)) & 0xffff;
return m;
}
TIMER_STATIC uint8_t hours() {
uint32_t ms = millis();
uint8_t h;
h = (ms / (3600000L)) & 0xff;
return h;
}
template<typename timeType,timeType (*timeGetter)()>
class EveryTimePeriod {
public:
timeType previous;
timeType period;
EveryTimePeriod() {
reset();
period = 1;
}
EveryTimePeriod(timeType period) {
reset();
setPeriod(period);
}
void setPeriod(timeType newPeriod) {
period = newPeriod;
}
timeType getTime() {
return reinterpret_cast<timeType>(timeGetter());
}
timeType getPeriod() {
return period;
}
timeType getElapsed() {
return getTime() - previous;
}
timeType getRemaining() {
return period - getElapsed();
}
void reset() {
previous = getTime();
}
bool ready() {
bool passed = (getElapsed() >= period);
if (passed) {
reset();
}
return passed;
}
operator bool() {
return ready();
}
};
typedef EveryTimePeriod<uint32_t,milliseconds> EveryNMilliseconds;
typedef EveryTimePeriod<uint16_t,seconds> EveryNSeconds;
typedef EveryTimePeriod<uint16_t,minutes> EveryNMinutes;
typedef EveryTimePeriod<uint8_t,hours> EveryNHours;
#define CONCAT_HELPER(x, y) x##y
#define CONCAT_MACRO(x, y) CONCAT_HELPER(x, y)
#define EVERY_N_MS(PERIOD) EVERY_N_MS_IF(CONCAT_MACRO(PER, __COUNTER__), PERIOD)
#define EVERY_N_MS_IF(NAME, PERIOD) static EveryNMilliseconds NAME(PERIOD); if (NAME)
#define EVERY_N_SECONDS(PERIOD) EVERY_N_SECONDS_IF(CONCAT_MACRO(PER, __COUNTER__), PERIOD)
#define EVERY_N_SECONDS_IF(NAME, PERIOD) static EveryNSeconds NAME(PERIOD); if (NAME)