#include <intrinsics.h>

/****************************************************************************
	CPUJ[h I{[hLED_
****************************************************************************/

/* VXeRg[ */
#define SYS_SCS			((volatile unsigned int *)(0xE01FC1A0))
#define PCONP           ((volatile unsigned int *)(0xE01FC0C4))

/* NbNp[Rg[䃌WX^ */
#define CLK_PLLCON		((volatile unsigned int *)(0xE01FC080))
#define CLK_PLLCFG		((volatile unsigned int *)(0xE01FC084))
#define CLK_PLLSTAT		((volatile unsigned int *)(0xE01FC088))
#define CLK_PLLFEED		((volatile unsigned int *)(0xE01FC08C))

#define CLK_CCLKCFG		((volatile unsigned int *)(0xE01FC104))
#define CLK_USBCLKCFG	((volatile unsigned int *)(0xE01FC108))
#define CLK_CLKSRCSEL	((volatile unsigned int *)(0xE01FC10C))

/**/
#define CLKSRCSEL       ((volatile unsigned int *)(0xE01FC10C))
#define PCLKSEL0        ((volatile unsigned int *)(0xE01FC1A8))
#define PCLKSEL1        ((volatile unsigned int *)(0xE01FC1AC))

/* |[gRg[ */
#define GPIO_PINSEL3	((volatile unsigned int *)(0xE002C00C))
#define GPIO_PINMODE3	((volatile unsigned int *)(0xE002C04C))

/* FGPIORg[ */
#define FGPIO_FIO1DIR	((volatile unsigned int *)(0x3FFFC020))
#define FGPIO_FIO1MASK	((volatile unsigned int *)(0x3FFFC030))
#define FGPIO_FIO1PIN	((volatile unsigned int *)(0x3FFFC034))
#define FGPIO_FIO1CLR	((volatile unsigned int *)(0x3FFFC03C))

/* 荞݃Rg[(VIC) */
#define VIC_IntEnable   ((volatile unsigned int *)(0xFFFFF010))
#define VIC_IntSelect   ((volatile unsigned int *)(0xFFFFF00C))
#define TIMER0_INT_BIT  (0x00000010)
#define TIMER1_INT_BIT  (0x00000020)

/* Timer */
#define TIMER0_InterruptRegister    ((volatile unsigned int *)(0xE0004000))
#define TIMER0_TimerControlRegister ((volatile unsigned int *)(0xE0004004))
#define TIMER0_TimerCounter         ((volatile unsigned int *)(0xE0004008))
#define TIMER0_PrescaleRegister     ((volatile unsigned int *)(0xE000400C))
#define TIMER0_PrescaleCounter      ((volatile unsigned int *)(0xE0004010))
#define TIMER0_MatchControlRegister ((volatile unsigned int *)(0xE0004014))
#define TIMER0_MatchRegister0       ((volatile unsigned int *)(0xE0004018))

/* PWM */
#define PWM1IR                     ((volatile unsigned int *)(0xE0018000))
#define PWM1TCR                    ((volatile unsigned int *)(0xE0018004))
#define PWM1TC                     ((volatile unsigned int *)(0xE0018008))
#define PWM1PR                     ((volatile unsigned int *)(0xE001800C))
#define PWM1PC                     ((volatile unsigned int *)(0xE0018010))
#define PWM1MCR                    ((volatile unsigned int *)(0xE0018014))
#define PWM1MR0                    ((volatile unsigned int *)(0xE0018018))
#define PWM1MR1                    ((volatile unsigned int *)(0xE001801C))
#define PWM1MR2                    ((volatile unsigned int *)(0xE0018020))
#define PWM1MR3                    ((volatile unsigned int *)(0xE0018024))
#define PWM1CCR                    ((volatile unsigned int *)(0xE0018028))
#define PWM1CR0                    ((volatile unsigned int *)(0xE001802C))
#define PWM1CR1                    ((volatile unsigned int *)(0xE0018030))
#define PWM1CR2                    ((volatile unsigned int *)(0xE0018034))
#define PWM1CR3                    ((volatile unsigned int *)(0xE0018038))
#define PWM1MR4                    ((volatile unsigned int *)(0xE0018040))
#define PWM1MR5                    ((volatile unsigned int *)(0xE0018044))
#define PWM1MR6                    ((volatile unsigned int *)(0xE0018048))
#define PWM1PCR                    ((volatile unsigned int *)(0xE001804C))
#define PWM1LER                    ((volatile unsigned int *)(0xE0018050))
#define PWM1CTCR                   ((volatile unsigned int *)(0xE0018070))

void set_ratio(unsigned int value);
int ratio_table[] = {100,139,178,217,256,294,332,369,406,442,477,511,544,576,607,637,665,692,718,742,765,786,805,823,839,853,865,876,884,891,896,899,899,899,896,891,884,876,865,853,839,823,805,786,765,742,718,692,665,637,607,576,544,511,477,442,406,369,332,294,256,217,178,139};

/* CPU荞ݏ */
__irq __arm void IRQ_Handler()
{
  static int i = 0;
  static int loop = 0;
  if(loop > 0x00004000){
	set_ratio(ratio_table[i]);
	i = (i + 1) & 0x3f;
	loop = 0;
  }else{
	loop = loop + 1;
  }
}


/* FIQ荞ݏ */
__irq __arm void FIQ_Handler()
{
}

/* CPUŗL */
void CPU_Initialize(void)
{
  /*** PLLNbNU ***/

  /* łPLL쒆ꍇ͒~ */
  if ( *CLK_PLLSTAT & (1<<25) ) {
	/* PLLCON - PLL Enable & disconnected */
	*CLK_PLLCON   =0x00000001;
	/* PLL Feed operation */
	*CLK_PLLFEED  =0x000000AA;
	*CLK_PLLFEED  =0x00000055;
  }
  /* PLLCON - PLL Disable & disconnected(PLLS~) */
  *CLK_PLLCON   =0x00000000;
  /* PLL Feed operation */
  *CLK_PLLFEED  =0x000000AA;
  *CLK_PLLFEED  =0x00000055;

  *SYS_SCS = 0x21;	/* 12MHz OSC Enable & FGPIO Select */
  while((*SYS_SCS&0x40) == 0){}	/* OSCSTAT Wait */

  /* CLKSRCSEL - MASTER oscillator select */
  *CLK_CLKSRCSEL=0x00000001;

  /* PLLCFG - MCLK=12MHz use, FCC0 = 288MHz M=72,N=12 */
  *CLK_PLLCFG   =0x000C0090;
  /* PLL Feed operation. */
  *CLK_PLLFEED  =0x000000AA;
  *CLK_PLLFEED  =0x00000055;

  /* PLLCON - PLL Enable & disconnected */
  *CLK_PLLCON   =0x00000001;
  /* PLL Feed operation */
  *CLK_PLLFEED  =0x000000AA;
  *CLK_PLLFEED  =0x00000055;

  /* CPU Clock Divider 1/4 */
  *CLK_CCLKCFG  =0x00000003;
  /* USB Clock Divider 1/8 */
  *CLK_USBCLKCFG=0x00000006;

  while ( ((*CLK_PLLSTAT & (1<<26)) == 0) ); /* Check lock bit status */

  /* PLLCON - PLL Enable & Connected */
  *CLK_PLLCON   =0x00000003;
  /* PLL Feed operation. */
  *CLK_PLLFEED  =0x000000AA;
  *CLK_PLLFEED  =0x00000055;
  while ( ((*CLK_PLLSTAT & (1<<25)) == 0) ); /* Check connect bit status */

}

void init_pwm()
{
  *PCONP = *PCONP | (1 << 6); // set bit PCPWM1
                              // ̓Zbg1ɂȂĂ
  *PCLKSEL0 = *PCLKSEL0 | (1 << 12); // PCLK_PWM1[13:12] <= "01"
  *GPIO_PINSEL3 = *GPIO_PINSEL3 | (2 << 4); // PINSEL3[5:4] <= "10"
  //*GPIO_PINMODE3 = *GPIO_PINMODE3 | (2 << 4); // PINSEL3[5:4] <= "10"
  
  // the PWMTC will be reset if PWMMR0 matches it.
  *PWM1MCR = *PWM1MCR | (1 << 0) | (1 << 1);
  //*PWM1CCR = 0;
  *PWM1PCR = *PWM1PCR | (1 << 9); // PWMENA1
  *PWM1MR0 = 1000;
  *PWM1MR1 = 0;

  *VIC_IntEnable = (1 << 8); // PWMMatch0-6Ŋ݂𔭐
  __enable_interrupt();
  __enable_irq();

  // counter and prescaler are enabled/PWM mode is enabled
  *PWM1TCR = *PWM1TCR | (1 << 0) | (1 << 3);
}

void set_ratio(unsigned int value)
{
  *PWM1TCR = 0;
  *PWM1MR1 = (value < 1000) ? value : 1000;
  *PWM1TCR = *PWM1TCR | (1 << 0) | (1 << 3);
}

int main(void)
{

  CPU_Initialize();

  init_pwm();

  for(;;){
  }

}
