Expand description
Module to interface with the GBA’s four timer units.
Similar to the background layers and DMA units, there are four timer units and they’re numbered 0 through 3.
There’s two hardware addresses that control each timer.
- The timer’s high address is the
TimerControl
bits. - The timer’s low address is a
u16
which reads the timer’s “count” value, but writes the timer’s “reload” value. In this crate we actually represent that as two separate MMIO controls for improved code clarity. Just be aware that in mGBA’s debugger and in other documentation you’ll see it as a single address.
When a timer is disabled, it will continue to read the count value that it stopped at.
Reloading
When the timer goes from disabled to enabled, or when the timer overflows, the last set reload value is copied to the counter value.
Ticking
When a timer is enabled, the timer will tick every so often. Each tick increases the counter value by 1. The rate at which the timer ticks depends on the timer’s configuration:
- If the
cascade
bit is set the timer will tick once per overflow of the next lower timer. For example, if timer 3 is set to cascade, it will tick once per overflow of timer 2. Note that timer 0 ignores the cascade bit, since it doesn’t have a “next lower” timer. - Otherwise, the timer ticks every one or more CPU cycles, according to the
TimerScale
set in thescale
field.
Overflows
When a timer would tick above u16::MAX
then an overflow occurs. This can
trigger an interrupt, and will also cause the timer to copy its reload value
into its counter.
If you want a timer to overflow every x
ticks (where x
is non-zero),
then use the wrapping_neg
method to easily get the
right reload value to set:
let x = 7_u16;
TIMER0_RELOAD.write(x.wrapping_neg());
Using Cascade To Pause A Timer
When a timer goes from disabled to enabled it will reset the counter value
to the reload value. If you want to temporarily pause a timer without
having the counter value get reset when you resume the timer you can instead
set the cascade
bit of the timer while the next lower timer is
disabled. This keeps the timer “active” but prevents it from ticking.
When you turn off cascade mode the timer will resume ticking from the
current counter value.
Note that this doesn’t work for timer 0, because that timer ignores the cascade bit.