#include <reg52.h>

#include "Page0.h"
#include "PalmChip.h"

volatile BOOLEAN Timer_bIndicated;	// timer comes every 0.2 second
volatile BOOLEAN Sys_bHighSpeed = FALSE;
BOOLEAN Sys_bRunning;

static volatile DSHORT _iTicker;
static volatile BOOLEAN _bTicker;

static DCHAR _iTH0, _iTL0;
//static XCHAR _iSleepDivide;

// Switch program between running in program flash and in sram

void PLL1_33Mhz()
{
	Run_33Mhz();

	_iTH0 = 0x29;     // set timer 0 initial number
	_iTL0 = 0x28;
//	_iSleepDivide = 10;
}

void PLL1_46Mhz()
{
	Run_46Mhz();

	_iTH0 = 0x6f;     // set timer 0 initial number
	_iTL0 = 0x78;
//	_iSleepDivide = 16;
}

void PLL1_41Mhz()
{
	Run_41Mhz();

	_iTH0 = 0x6f;     // set timer 0 initial number
	_iTL0 = 0x78;
//	_iSleepDivide = 16;
}

void PLL1_22Mhz()	// 22.2Mhz 
{
	Run_22Mhz();

	_iTH0 = 0x6f;     // set timer 0 initial number
	_iTL0 = 0x78;
//	_iSleepDivide = 16;
}

void PLL1_40Mhz()
{
	Run_40Mhz();

//  When wait state is added, all the timers are not accurate, better not make use of it
	_iTH0 = 0xb1;     // set timer 0 initial number
	_iTL0 = 0xe0;
//	_iSleepDivide = 29;
}

void PLL1_12Mhz()
{
	Run_12Mhz();

	_iTH0 = 0xb1;     // set timer 0 initial number
	_iTL0 = 0xe0;
//	_iSleepDivide = 29;
}

void PLL1_37Mhz()	// 36.75Mhz 
{
	Run_37Mhz();

	_iTH0 = 0x58;     // set timer 0 initial number
	_iTL0 = 0x08;
//	_iSleepDivide = 14;
}

void PLL1_26Mhz()	// 25.8Mhz 
{
	Run_26Mhz();

	_iTH0 = 0x58;     // set timer 0 initial number
	_iTL0 = 0x08;
//	_iSleepDivide = 14;
}

void PLL1_11Mhz()	// 11.1Mhz 
{
	Run_11Mhz();

	_iTH0 = 0xb7;     // set timer 0 initial number
	_iTL0 = 0xbc;
//	_iSleepDivide = 33;
}

void SysSleep1Second()
{
	SysSleep(1000000);
}

void Timer0Interrupt() interrupt 1 //	using 1
{
//	DCHAR iDPS;

//	iDPS = DPS;	// Push DPS value
//	DPS = 0;

	Timer_bIndicated = TRUE;	// timer comes every 0.02 second
	if (_bTicker)
	{
		_iTicker += 20;
	}

    // set the initial number again
	TH0 = _iTH0;
    TL0 = _iTL0;

//	DPS = iDPS;	// Pop DPS value
}

void SysTickBegin()
{
	_bTicker = TRUE;
	_iTicker = 0;
}

void SysTickEnd()
{
	_bTicker = FALSE;
	DisplayVal(_iTicker, (PCCHAR)"Time used", 1);
}

void SysSetMode(UCHAR iSelectKey)
{
	DCHAR iKey;

	iKey = iSelectKey;
	switch (iKey)
	{
	case 0:
		DisplayString(g_cRestart, 0);
		UdpDebugUpdate();
		OnReboot();
		break;
	case 1:
		DisplayString((PCCHAR)"11.1M", 0);
		PLL1_11Mhz();
		break;
	case 2:
		DisplayString((PCCHAR)"12M", 0);
		PLL1_12Mhz();
		break;
	case 3:
		DisplayString((PCCHAR)"22.2M", 0);
		PLL1_22Mhz();
		break;
	case 4:
		DisplayString((PCCHAR)"25.8M", 0);
		PLL1_26Mhz();
		break;
	case 5:
		DisplayString((PCCHAR)"33M", 0);
		PLL1_33Mhz();
		break;
	case 6:
		DisplayString((PCCHAR)"36.75M+2", 0);
		PLL1_37Mhz();
		break;
	case 7:
		DisplayString((PCCHAR)"40M+11", 0);
		PLL1_40Mhz();
		break;
	case 8:
		DisplayString((PCCHAR)"41M+4", 0);
		PLL1_41Mhz();
		break;
	case 9:
		DisplayString((PCCHAR)"45.6M+5", 0);
		PLL1_46Mhz();
		break;
	}
}

void PLLInitialize()
{
	// This function is called first, so init light and timer value here
	Sys_bRunning = FALSE;
	_bTicker = FALSE;
	Timer_bIndicated = FALSE;

	XBYTE[INT_ENABLE] = 0;		// Disable all irqs;
	XBYTE[CLK_ENAB1] = 0xff;	// Enable all clock first
	XBYTE[CLK_ENAB2] = 0xff;
	XBYTE[CLK_SWITCH] = 0;

	PLL1_22Mhz();

	// Enable clock for conbuf, lcd, sdram, ext
	XBYTE[CLK_ENAB1] = CLOCK1_MASK_CON+CLOCK1_MASK_SDRAM+CLOCK1_MASK_CMDQ+CLOCK1_MASK_TOFIFO+CLOCK1_MASK_FROMFIFO+CLOCK1_MASK_DSP|CLOCK1_MASK_AC97|CLOCK1_MASK_PHILIPS;
	XBYTE[CLK_ENAB2] = CLOCK2_MASK_LCD+CLOCK2_MASK_IDMA+CLOCK2_MASK_EXTCLK+CLOCK2_MASK_FLASH1+CLOCK2_MASK_CAMERA;
}

void ControlInitialize()
{
	TMOD = 0x21;		// T/C0 function mode 1 timer; T/C1 function mode 2 timer for serial communication
    CKCON &= 0xe7;		// timer0, timer 1 count by clk/12
	TH0 = _iTH0;		// set timer 0 initial number, make it interrupt every 20ms
	TL0 = _iTL0;
	TR0 = 1;
	IP = 0;				// no interrupt has higher piority
//    IE = 0x96;		// enable timer0, serial and external 1 interrupts; EA = 1, ES = 1, EX1 = 1, ET0 = 1
	ET0 = 1;
	EX1 = 1;
	EA = 1;
	// This function is called just before the main loop
	Sys_bRunning = TRUE;
}

