GP32 Clock Versus Tick Count .. Again ;)


skeezix

Internal Development
Joined
Mar 11, 2003
Messages
8,070
Website
www.codejedi.com
I'm sure this topic has been done to death, but I figure I've got to get auto-frameskip in for craigix one of these days (CaSTaway/GP).

Hmm, I suck; I was sure I used a table, but I didn't.. I cheaped out with an if-block nabbed partly from someone else:

if ( ac == cl_66 ) {
GpClockSpeedChange(67800000, 0x69032, 3);
//GpClockSpeedChange(66000000, 0x24001, 2);
} else if ( ac == cl_99 ) {
GpClockSpeedChange( 99000000, 0x19001, 2); // or mode 3?
} else if ( ac == cl_132 ) {
GpClockSpeedChange(132000000, 0x24001, 2); /* 132MHz? */
} else if ( ac == cl_150 ) {
GpClockSpeedChange( 150000000, 0x2a001, 3); // Thanks [SoD]Thor!
} else if ( ac == cl_156 ) {
GpClockSpeedChange( 156000000, 0x2c001, 3); // Thanks [SoD]Thor!
} else if ( ac == cl_160 ) {
GpClockSpeedChange ( 160000000, 0x48011, 3 ); // Thanks [SoD]Thor!
} else if ( ac == cl_166 ) {
GpClockSpeedChange ( 166000000, 0x4b011, 3 ); // pllset tool
}

It really should be something like this..

typedef struct {
char *c_name;
unsigned long int c_a, c_b;
unsigned char c_c;
unsigned int c_ticks_per_second;
} clock_t;

clock_t clocks[] = {
{ "66MHz", 67800000, 0x69032, 3, 67800000 },
// etc
{ NULL, 0, 0, 0, 0 }
};

I'm sure everyone else has a table like that.

So ..

Anyone have a nice collection of setting to GpClockSpeed.. that shows the 3 settings and what resulting tick count you get?

I'd like to make a good solid re-usable .c file for setting rate, from 40MHz to 220MHz say.

jeff
 
Hi skeezix, if you download mr.mirko's sdk. He has a "*very*" comprehensive list. Just check in the lib.src/common directory. Its all in the gp_cpuspeed.c file.

Code:
/*
 * CPU setup - gp_cpuspeed.c
 *
 * Copyright (C) 2003,2004 Mirko Roller <mirko@mirkoroller.de>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Changelog:
 *
 *  21 Aug 2004 - Mirko Roller <mirko@mirkoroller.de>
 *   first release 
 *
 */


/*
MCLK is the main clock for the CPU                (160Mhz maximum)
HCLK is the clock for the system bus (SDRAM LCD)  (133Mhz maximum)
PCLK is the clock for the peripherals (UARTs, SMC, IIS, timers etc) (66Mhz maximum)

The values for clk_mode are:
0 HCLK = MCLK,     PCLK = MCLK
1 HCLK = MCLK,     PCLK = MCLK / 2
2 HCLK = MCLK / 2, PCLK = MCLK / 2
3 HCLK = MCLK / 2, PCLK = MCLK / 4
*/

// 40Mhz mode
static int CLKDIV =0x48013;
static int MCLK   =40000000;
static int CLKMODE=0;
static int HCLK   =40000000;
static int PCLK   =40000000;

int gp_getPCLK(){
   return PCLK;
}

int gp_getHCLK(){
   return HCLK;
}

void gp_setCpuspeed(int freq) {
  switch (freq) {
     // overclocking 
     case 168: { CLKDIV=0x14000; MCLK=168000000; CLKMODE=3; break;}
     case 172: { CLKDIV=0x23010; MCLK=172000000; CLKMODE=3; break;}
     case 176: { CLKDIV=0x24010; MCLK=176000000; CLKMODE=3; break;}
     case 180: { CLKDIV=0x16000; MCLK=180000000; CLKMODE=3; break;}
     case 184: { CLKDIV=0x26010; MCLK=184000000; CLKMODE=3; break;}
     case 188: { CLKDIV=0x27010; MCLK=188000000; CLKMODE=3; break;}
     case 192: { CLKDIV=0x18000; MCLK=192000000; CLKMODE=3; break;}
     case 196: { CLKDIV=0x29010; MCLK=196000000; CLKMODE=3; break;}
     case 200: { CLKDIV=0x2A010; MCLK=200000000; CLKMODE=3; break;}
     case 204: { CLKDIV=0x2b010; MCLK=204000000; CLKMODE=3; break;}
     case 208: { CLKDIV=0x2c010; MCLK=208000000; CLKMODE=3; break;}
     case 212: { CLKDIV=0x2d010; MCLK=212000000; CLKMODE=3; break;}
     case 216: { CLKDIV=0x2e010; MCLK=216000000; CLKMODE=3; break;}
     case 220: { CLKDIV=0x2f010; MCLK=220000000; CLKMODE=3; break;}
     case 224: { CLKDIV=0x30010; MCLK=224000000; CLKMODE=3; break;}
     case 228: { CLKDIV=0x1e000; MCLK=228000000; CLKMODE=3; break;}
     case 232: { CLKDIV=0x32010; MCLK=232000000; CLKMODE=3; break;}
     case 236: { CLKDIV=0x33010; MCLK=236000000; CLKMODE=3; break;}
     case 240: { CLKDIV=0x20000; MCLK=240000000; CLKMODE=3; break;}
     case 244: { CLKDIV=0x35010; MCLK=244000000; CLKMODE=3; break;}
     case 248: { CLKDIV=0x36010; MCLK=248000000; CLKMODE=3; break;}
     case 252: { CLKDIV=0x22000; MCLK=252000000; CLKMODE=3; break;}
     case 256: { CLKDIV=0x38010; MCLK=256000000; CLKMODE=3; break;}
     
     // normal
     case 166: { CLKDIV=0x4B011; MCLK=166000000; CLKMODE=3; break;}
     case 164: { CLKDIV=0x4a011; MCLK=164000000; CLKMODE=3; break;}
     case 160: { CLKDIV=0x48011; MCLK=160000000; CLKMODE=3; break;}
     case 156: { CLKDIV=0x2c001; MCLK=156000000; CLKMODE=3; break;}
     case 144: { CLKDIV=0x28001; MCLK=144000000; CLKMODE=3; break;}
     case 133: { CLKDIV=0x3a011; MCLK=132000000; CLKMODE=3; break;}
     case 100: { CLKDIV=0x2b011; MCLK=102000000; CLKMODE=2; break;}
     case  66: { CLKDIV=0x25002; MCLK= 67500000; CLKMODE=2; break;}
     case  50: { CLKDIV=0x2a012; MCLK= 50000000; CLKMODE=0; break;}
     case  40: { CLKDIV=0x48013; MCLK= 40000000; CLKMODE=0; break;}
     case  33: { CLKDIV=0x25003; MCLK= 33750000; CLKMODE=0; break;}
     case  22: { CLKDIV=0x33023; MCLK= 22125000; CLKMODE=0; break;}
  }
   if (CLKMODE==0) {HCLK=MCLK ;PCLK=MCLK ;}
   if (CLKMODE==1) {HCLK=MCLK ;PCLK=MCLK/2;}
   if (CLKMODE==2) {HCLK=MCLK/2;PCLK=MCLK/2;}
   if (CLKMODE==3) {HCLK=MCLK/2;PCLK=MCLK/4;}
   _cpu_speed(MCLK,CLKDIV,CLKMODE);
   gp_initButton();  // Init the Buttons to input
}

void gp_Reset() {
   gp_setCpuspeed(66);
   asm volatile("swi #4\n");
}
 
The trick however is .. how many ticks per clock setting? Setting the clock rate is easy ;)

ie:
case 216: { CLKDIV=0x2e010; MCLK=216000000; CLKMODE=3; break;}

In this case the ticks per second is exactly what?

Thats the trick :) Its not hard to figure out I think, but I've forgotten the rule of thumb. Does the GpTickCountGet() return in terms of PCLK or which..

jeff
 
I'm not sure that you can easily calculate ticks for different clock settings. I use this RTC code instead (works perfectly for all clock speeds) -

gp_timer.c :
Code:
// idea and first written, Jouni Korhonen
// rewritten and extended (c)2004 Mirko Roller

#include "gp32mm.h"

char in_use=0;
u32 rGLOBALCOUNTER;

void RTCInt(void) __attribute__ ((interrupt ("IRQ")));

void RTCInt(void) {
   rGLOBALCOUNTER++;
}


void setupRTCInt( void ) {
   // enable RTC
   rCLKCON |= 0x800;
   //
   // The CPU clock indepentent RTC Timer
   //
   // The ticnt register 0x15700044 (32 bit) offers:
   //
   // BIT   7: 0=disable 1=enable timer
   // BIT 0-6: tick time count value 1-127
   //
   // %10000000 should result in a 1/128 timer, but is not working
   // %10000001 result in 1/64 timer
   // %11111111 result in 1/1  timer

   rTICINT = 0x81;
   //(*(volatile unsigned char *)rTICINT) = 0x81;
   rGLOBALCOUNTER = 0;
}


void InstallRTC( void ) {
   gp_disableIRQ();
   gp_installSWIIRQ(8,RTCInt);
   gp_enableIRQ();
}

u32 gp_getRTC() {
   return rGLOBALCOUNTER;
}

void gp_initRTC() {
   if (in_use == 0) {
      setupRTCInt();
      InstallRTC();
      in_use=1;
   }
}

void gp_clearRTC() {
   rGLOBALCOUNTER=0;
}
gp_irq.S:
Code:
                .global gp_enableIRQ
                .global gp_disableIRQ
                .global gp_installSWIIRQ
                .global gp_removeSWIIRQ


gp_enableIRQ:
                STMDB    r13!,{r0,lr}
                MRS      r0,CPSR
                BIC      r0,r0,#0x80
                MSR      CPSR,r0
                LDMIA    r13!,{r0,pc}
                @MOV      pc,lr

gp_disableIRQ:
                STMDB    r13!,{r0,lr}
                MRS      r0,CPSR
                ORR      r0,r0,#0xc0
                MSR      CPSR,r0
                LDMIA    r13!,{r0,pc}
                @MOV      pc,lr
gp_installSWIIRQ:
                STMDB    r13!,{r14}
                SWI      0x9
                LDMIA    r13!,{pc}

gp_removeSWIIRQ:
                STMDB    r13!,{r14}
                SWI      0xa
                LDMIA    r13!,{pc}
and the bits needed out of gp32mm.h:
Code:
#define rCLKCON         (*(volatile unsigned *)0x1480000c)
#define rTICINT         (*(volatile unsigned char *)0x15700044)
 
Nice. I'll digest and work it over.. thanks for laying it out so well :)

Gotta get my GP32 fix.. most fun mobile platform to develop games on :)

jeff
 
Just a little question... How often is the interrupt called using rTICINT = 0x81; ???
 
mATkEUpON posted on Dec 7 2004 at 03:32 PM said:
Just a little question... How often is the interrupt called using rTICINT = 0x81; ???


watch 3 lines above rTICINT = 0x81;

hehe
 
Last edited by a moderator:
Yes but I meant for an actual second.

I know that it's a 1/64 timer, so it will be called every 64 ticks... But are those ticks 1 millisecond ???
 
mATkEUpON posted on Dec 7 2004 at 06:15 PM said:
Yes but I meant for an actual second.

I know that it's a 1/64 timer, so it will be called every 64 ticks... But are those ticks 1 millisecond ???
It's 64 times a second.
 
Last edited by a moderator:
I fixed the tick count instead so it stays the same...

Code:
	GpClockSpeedChange(freq, magic, div);
	unsigned int pclk = GpPClkGet();

	// Repair SDK timer - it forgets to set prescaler
	//pclk/(x+1) ~= 8000*40
	//x= (pclk/(8000*40)) -1
	unsigned int prescaler0 = (pclk/(8000*40))-1;
	rTCFG0 = (rTCFG0&0xFFFFFF00)|prescaler0;
	rTCFG1 = 0x30033;

	// Repair GpTickCountGet
	// pclk/(100x) = 16
	// x = pclk/1600
	rTCNTB4 = pclk/1600;

Note you'll need to fix sound, chatboard etc. after changing pclk. e.g.

Code:
	GpPcmInit(PCM_M22, PCM_8BIT);
	preInitKbd(9600, GpPClkGet());

Probably should also do something with the display since HCLK has changed, but I'm not sure what!

Thanks,

Mark
 
If HCLK changes then the CLKVAL in LCDCON1 needs to be changed accordingly if one wishes to maintain the same frame rate -- which is not always possible though..
 
Just to note on the first question, the tick count at 44MHz is close (if not at) 1 tick per millisecond. Just take the ratio of <current-clock-speed> / 44 when calculating what a "millisecond" truly is.

And if you don't like Mirko's SDK for some reason, you can pull a similiar function out of my code found here which uses the Gamepark SDK: http://www.gp32x.de/board/index.php?showtopic=14027
 
Last edited by a moderator:
mr.spiv posted on Dec 8 2004 at 09:50 AM said:
If HCLK changes then the CLKVAL in LCDCON1 needs to be changed accordingly if one wishes to maintain the same frame rate -- which is not always possible though..

Thanks. I'll add that to my clock change function in my next release...

Mark
 
Last edited by a moderator:
Back
Top