gameboy advance programming timers. common practice game timing is normally synchronized with the...
TRANSCRIPT
GameBoy AdvanceProgramming
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
0 0 0 0 0 0 0 0 0000000000000000
REG_TMxCNT REG_TMxD
0 0 0 0 0 0 0 0 0000000000000000
0 0 0 0 0 0 0 0 0000000000000000
0 0 0 0 0 0 0 0 0000000000000000
0
1
2
3
Timer Registers
● Timer register holds number of elapsed timer ticks– 16 bits– 0 through 65535 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 # cycles Frequency Period
00 11 clock cycle
224 Hz or
16,777,216 Hz
59.604ns
01 64 218 Hz or
262,144 Hz
3.811μs
10 256 216 Hz or 65,536 Hz
15.259μs
11 1024 214 or
16,384 Hz
59.382μ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 65535
Which is what? (think two's complement)
Conceptually
0000000000000000
REG_TMxD
0000000000000000When 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 224, 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*)0x4000102#define REG_TM1CNT *(volatile u16*)0x4000106#define REG_TM2CNT *(volatile u16*)0x400010A#define REG_TM3CNT *(volatile u16*)0x400010E
#define REG_TM0D *(volatile u16*)0x4000100#define REG_TM1D *(volatile u16*)0x4000104#define REG_TM2D *(volatile u16*)0x4000108#define REG_TM3D *(volatile u16*)0x400010C
• To find the value of a timer, check the number stored in REG_TMxD
Questions?