GameBoy Advance Programming Timers
Common Practice Game timing is normally synchronized with the vertical blank. For certain applications such as precise DMA transfers involving sound, timers are used. Timers are also sometimes used in profiling studies, that is, determining how much time is spent in executing different portions of code.
GBA Timers Trigger an event after a duration, or hold the elapsed time since started 4 timers available 4 different speeds/frequencies –each timer can use any frequency Can be chained together to create longer timers
Timer Layout FREQOVIRON REG_TMxCNT REG_TMxD
Timer Registers ● Timer register holds number of elapsed timer ticks – 16 bits – 0 through ticks, then overflow or reset ● Timer control register sets frequency, overflow, and enables timers
REG_TMxCNT ● Bits 0-1: Frequency ● See next slides ● 2: Toggle overflow from previous timer #define TM_CASCADE (1<<2) ● 6: Generate interrupt when timer register is full #define TM_IRQ (1<<6) ● 7: Enable timer #define TM_ON (1<<7)
Frequency, etc. Bits 0-1# cyclesFrequencyPeriod clock cycle 2 24 Hz or 16,777,216 Hz ns Hz or 262,144 Hz 3.811μs Hz or 65,536 Hz μs or 16,384 Hz μs
Frequency ● Timer frequencies are distinct from the four timers – Any of the four timers can use any of the four frequencies
Timer Frequency Selection #define TM_FREQ_1 0 #define TM_FREQ_64 1 #define TM_FREQ_256 2 #define TM_FREQ_1024 3
Polling vs. Interrupts ● Polling - start a timer, then check the value in the timer register after doing some stuff – Find out how long a function takes to execute – Useful for development and optimization ● Interrupts – you are alerted by interrupt event whenever a certain amount of time has passed – Good for doing tasks at a precise time – or repeating a task at even intervals – Hybrid? - Sound devices can be set to play a sample each time a certain timer hits 0
Initial Timer Values ● Give timers a value other than zero to start counting from – Precisely control how long before the timer overflows ● Can only initialize the value of a disabled timer ● A timer initialized to a value will reset to that value (not zero) when it overflows
Timer Trix Suppose you wanted a timer to go off after just 1024 cycles? Using TM_FREQ_1024 that's just one tick So you could set the value to be unsigned: 0xFFFF or Which is what? (think two's complement)
Conceptually REG_TMxD When you store a value in any timer REG_TMxD the timer takes on that value and also stores that "reset" value elsewhere. When the timer reaches 0 (by counting up) the timer is automatically reinitialized to the "reset " value. At any time the current value of the timer may be read from REG_TMxD reset value Reinitialized at 0
Problem Set up a 1 Hz timer, that is it will 'tick' every second
Recall The clock frequency is 2 24, or 1024*0x4000. By setting timer 2 to TM_FREQ_1024 and to start at −0x4000, the cascading timer 3 will effectively be a 1 Hz counter.
Code REG_TM0CNT = 0; // Turn off timer 0 REG_TM1CNT = 0; // Turn off timer 1 REG_TM2CNT = 0; // Turn off timer 2 REG_TM3CNT = 0; // Turn off timer 3 REG_TM2D = -0x4000; // 1 sec* REG_TM2CNT = TM_IRQ | TM_FREQ_1024 | TM_ON; REG_IE = REG_IE | INT_T2;
Problem Set up a timer to fire an interrupt every minute
void int_in_one_minute(void) { REG_TM0CNT = 0; // Turn off timer 0 REG_TM1CNT = 0; // Turn off timer 1 REG_TM0D = -0x4000; REG_TM1D = -60; // 60 secs = 1 minute REG_TM0CNT = TM_FREQ_1024 | TM_ON; REG_TM1CNT = TM_IRQ | TM_CASCADE | TM_ON; }
One Additional Trick! void handler(void) {... // REF_IF = REG_IF; REG_IF = INT_TM1;... }
Addresses #define REG_TM0CNT *(volatile u16*)0x #define REG_TM1CNT *(volatile u16*)0x #define REG_TM2CNT *(volatile u16*)0x400010A #define REG_TM3CNT *(volatile u16*)0x400010E #define REG_TM0D *(volatile u16*)0x #define REG_TM1D *(volatile u16*)0x #define REG_TM2D *(volatile u16*)0x #define REG_TM3D *(volatile u16*)0x400010C To find the value of a timer, check the number stored in REG_TMxD
Questions?