diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2017-03-10 11:23:46 -0500 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2017-03-10 13:31:38 -0500 |
commit | 16e3dbb18c9a99ee9a22a65046f0111d9339d390 (patch) | |
tree | 91546fb0715d52b94c55007ffebf3b4964825b4e /src/avr | |
parent | a38437f378ece33cb762b482120be629c78d3540 (diff) | |
download | kutter-16e3dbb18c9a99ee9a22a65046f0111d9339d390.tar.gz kutter-16e3dbb18c9a99ee9a22a65046f0111d9339d390.tar.xz kutter-16e3dbb18c9a99ee9a22a65046f0111d9339d390.zip |
avr: Optimize 16bit timer upscaling
The hardware timer overflow bit can be used to optimize the conversion
from 16bit timers to 32bit timers.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'src/avr')
-rw-r--r-- | src/avr/timer.c | 46 |
1 files changed, 24 insertions, 22 deletions
diff --git a/src/avr/timer.c b/src/avr/timer.c index 3744351d..a6da9b4f 100644 --- a/src/avr/timer.c +++ b/src/avr/timer.c @@ -83,20 +83,29 @@ DECL_INIT(timer_init); * 32bit timer wrappers ****************************************************************/ -static uint32_t timer_last; +static uint16_t timer_high; -// Return the 32bit current time given the 16bit current time. -static __always_inline uint32_t -calc_time(uint32_t last, uint16_t cur) +// Return the current time (in absolute clock ticks). +uint32_t +timer_read_time(void) { union u32_u16_u { struct { uint16_t lo, hi; }; uint32_t val; } calc; - calc.val = last; - if (cur < calc.lo) + irqstatus_t flag = irq_save(); + calc.val = timer_get(); + calc.hi = timer_high; + if (!(TIFR1 & (1<<TOV1))) { + irq_restore(flag); + return calc.val; + } + // Hardware timer has overflowed - update overflow counter + TIFR1 = 1<<TOV1; + timer_high = calc.hi + 1; + irq_restore(flag); + if (calc.lo < 0x8000) calc.hi++; - calc.lo = cur; return calc.val; } @@ -104,18 +113,11 @@ calc_time(uint32_t last, uint16_t cur) void timer_periodic(void) { - timer_last = calc_time(timer_last, timer_get()); -} - -// Return the current time (in absolute clock ticks). -uint32_t -timer_read_time(void) -{ - irqstatus_t flag = irq_save(); - uint16_t cur = timer_get(); - uint32_t last = timer_last; - irq_restore(flag); - return calc_time(last, cur); + if (TIFR1 & (1<<TOV1)) { + // Hardware timer has overflowed - update overflow counter + TIFR1 = 1<<TOV1; + timer_high++; + } } #define TIMER_MIN_TICKS 100 @@ -126,11 +128,11 @@ timer_read_time(void) uint8_t timer_set_next(uint32_t next) { - uint16_t cur = timer_get(); - if ((int16_t)(OCR1A - cur) < 0 && !(TIFR1 & (1<<OCF1A))) + uint32_t cur = timer_read_time(); + if ((int16_t)(OCR1A - (uint16_t)cur) < 0 && !(TIFR1 & (1<<OCF1A))) // Already processing timer irqs try_shutdown("timer_set_next called during timer dispatch"); - uint32_t mintime = calc_time(timer_last, cur + TIMER_MIN_TICKS); + uint32_t mintime = cur + TIMER_MIN_TICKS; if (sched_is_before(mintime, next)) { timer_set_clear(next); return 0; |