gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > DS Timer question

#45235 - GPFerror - Wed Jun 08, 2005 9:26 pm

I found an example of using timers for GBA

Iv tried to convert it to DS timers, im sure that its not correct since the doubling of the clock speed so I need so help with the correct shift in the define I believe.

Thanks

Code:
#define timers2ms(tlow,thigh) ((tlow>>4)+(thigh<<12))

void StartTimers(void)
{
   TIMER0_DATA=0;
   TIMER1_DATA=0;
   TIMER0_CR=TIMER_CASCADE;
   TIMER1_CR=TIMER_DIV_1024;
}

Uint32 GetTicks(void)
{
   return timers2ms(TIMER0_DATA, TIMER1_DATA);
}

void Pause(Uint32 ms)
{
   int now;
   now=timers2ms(TIMER0_DATA, TIMER1_DATA);
   while(timers2ms(TIMER0_DATA, TIMER1_DATA)<now+ms);
}

#46136 - GPFerror - Mon Jun 20, 2005 6:24 pm

ok i finally had a chance to test it out, still dont think the shifts are correct since the original example was based on a 16384 Hz timer since the DS is around 33 MHZ timer i think I need to change the timer2ms define to account for that but im not sure how to.

I'v tested the below code, calling starttimers and then calling pause and it is pausing for a couple of seconds correctly, running in Ideas and dualis dont have the necessary hardware to test it on my DS yet though.

Thanks,
Troy

Code:
typedef unsigned int   Uint32;
#define timers2ms(tlow,thigh) ((tlow>>4)+(thigh<<12))

void StartTimers(void)
{
   TIMER0_DATA=0;
   TIMER1_DATA=0;
   TIMER0_CR=TIMER_DIV_1024;
   TIMER1_CR=TIMER_CASCADE;
}

Uint32 GetTicks(void)
{
   return timers2ms(TIMER0_DATA, TIMER1_DATA);
}

void Pause(Uint32 ms)
{
   Uint32 now;
   now=timers2ms(TIMER0_DATA, TIMER1_DATA);
   while((Uint32)timers2ms(TIMER0_DATA, TIMER1_DATA)<now+ms);
}

#46139 - DekuTree64 - Mon Jun 20, 2005 6:51 pm

I think all you need to do is
Code:
#define timers2ms(tlow,thigh) ((tlow>>5)+(thigh<<11))


Another way to do the same thing (unless the compiler decides to do a signed shift right) would be
Code:
(tlow | (thigh<<16)) >> 5

which I think is a little clearer what it means. Just puts them together into a 32-bit value, and divides by 32 (or 16 in the case of the original).
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku

#46143 - GPFerror - Mon Jun 20, 2005 8:10 pm

cool, thanks that appears to work fine in the emulators. Now of course im doing the old 1 mississippi , 2 etc :) to compare it.

Troy

#66609 - Rinky - Thu Jan 12, 2006 12:58 pm

Er... I'm lost.

I looked at DoubleC's tutorial where he sets up a timer to record from the microphone at 16kHz
TIMER0_DATA = 0xFC7F;

What I don't get is why 0xFC7F is 16kHz??? I'm told the DS uses a central timer at 33.4MHz but that isn't helping. Maybe a missed a maths lesson that I now wish I hadn't. :)

If you set
TIMER0_DATA = 1;
Then what's the frequency there? 4Hz?

I did a quick test - set Timer0 to 1 (whatever that is) and had a printf run on every IRQ. result = very very quick iterations of the printf.

Wrote a littlercounter delay i.e. incrementing a variable on_irq and only calling the pritnf when it gets to preset point. With a delay of 1000 it outputs slightly quicker than once per second.

So now I'm even more confused.

#66616 - strager - Thu Jan 12, 2006 2:15 pm

Rinky wrote:
Er... I'm lost.

I looked at DoubleC's tutorial where he sets up a timer to record from the microphone at 16kHz
TIMER0_DATA = 0xFC7F;

What I don't get is why 0xFC7F is 16kHz??? I'm told the DS uses a central timer at 33.4MHz but that isn't helping. Maybe a missed a maths lesson that I now wish I hadn't. :)


The DS's timer clock is around 33MHz, yes. The problem is that you don't know how the timer data is set up. Don't worry, I didn't know for a while, either. ;)

Simply put, the DS increments each timer's data (TIMER?_DATA) if that timer is enabled. If the timer 'overflows,' or gets reset back to 0, an interrupt is fired (if it was enabled for that timer), and all DMAs are checked to see if they depend on a timer. (I'm not sure if this is the right order of events, though. You'd have to do more research.)

So, here's a little formula to calculate the frequency from the TIMER?_DATA:
freq = cpu / (65536 - data)

If you plug in your data there, you would get:
freq ~= (33.514MHz) / (65536 - 0xFC7F)
freq ~= (33.514MHz) / (897)
freq ~= 39,177.230840580Hz
freq ~= 39kHz


This is way off of the 16kHz... Perhaps DoubleC assumed that the timers were slower?
Anyways, you can reverse the formula to calculate the data. I think that a macro is provided somewhere in nds/timers.h, called TIMER_FREQ or something similar.

Happy coding,
strager

#66619 - Rinky - Thu Jan 12, 2006 2:42 pm

Thanks Stager,

It all makes a little more sense now. Back to the playing.. er... I mean "coding". :D

#66727 - wintermute - Fri Jan 13, 2006 6:03 am

strager wrote:
Rinky wrote:
Er... I'm lost.

I looked at DoubleC's tutorial where he sets up a timer to record from the microphone at 16kHz
TIMER0_DATA = 0xFC7F;

What I don't get is why 0xFC7F is 16kHz??? I'm told the DS uses a central timer at 33.4MHz but that isn't helping. Maybe a missed a maths lesson that I now wish I hadn't. :)


The DS's timer clock is around 33MHz, yes. The problem is that you don't know how the timer data is set up. Don't worry, I didn't know for a while, either. ;)

Simply put, the DS increments each timer's data (TIMER?_DATA) if that timer is enabled. If the timer 'overflows,' or gets reset back to 0, an interrupt is fired (if it was enabled for that timer), and all DMAs are checked to see if they depend on a timer. (I'm not sure if this is the right order of events, though. You'd have to do more research.)

So, here's a little formula to calculate the frequency from the TIMER?_DATA:
freq = cpu / (65536 - data)

If you plug in your data there, you would get:
freq ~= (33.514MHz) / (65536 - 0xFC7F)
freq ~= (33.514MHz) / (897)
freq ~= 39,177.230840580Hz
freq ~= 39kHz


This is way off of the 16kHz... Perhaps DoubleC assumed that the timers were slower?
Anyways, you can reverse the formula to calculate the data. I think that a macro is provided somewhere in nds/timers.h, called TIMER_FREQ or something similar.

Happy coding,
strager


it's 0xF7CF not 0xFC7F

the timers count up each system clock, when they overflow an interrupt is generated.

0x10000 - 0xfc7f = 0x831 ( or 2097)

33514000/2097 = 15981.8789

#66759 - Rinky - Fri Jan 13, 2006 9:53 am

wintermute wrote:
it's 0xF7CF not 0xFC7F
Whoops - typo. Well spotted. :)