#define MAIN_C

#include "common.h"
#include <stdio.h>
#include <string.h>

#include "util.h"
#include "uart0.h"

volatile u8 global_ms_update_before_n_seconds;
volatile u32 global_ms = 0;
volatile u32 tickcount = 0;
volatile u8 state = 0;

// Initialization Routines
void sys_clk_init(void){
  // Configure internal oscillator for its maximum frequency
  OSCICN |= 0x07;
  
  //CLKSEL = 0x00;
}

void port_init(void){
  // Default values on reset:
  // P0MDIN=0xFF;   P1MDIN=0xFF; 
  // P0MDOUT=0x00;  P1MDOUT=0x00;
  // P0SKIP=0x00;   P1SKIP=0x00;
  // P0=0xFF;       P1=0xFF;
  // XBR0=0x00;     XBR1=0x00;
  XBR0 = 0x01;   // UART0 enabled
  XBR1 = (0x40 | 0x80 | 0x01); // Enable crossbar, CEX0, disable weak pull-up
  
  P0SKIP = 0xE7;
  P1SKIP = 0x1F;
  
  // P0 -- 0-2,5,7 => GPIO, 3 => TX0, 4=> RX0, 6 => -INT0
  P0MDOUT = 0x08; // enable TX0 as a push-pull
  P0 &= ~(0x04);
  IT01CF = 0x06;   // -INT0 => 6 negative
  //IE |= 0x01;      // Enable INT0 interrupt (EX0)
  
  // P1 -- => GPIO, 4(OUT), 5(IN => PCA0.0)  
  P1MDOUT = 0x10;
  P1 = (~0x10);
  EIE1 |= 0x04;    // Enable PCA0 interrupt (EPCA0)
  
  // PCA0
  PCA0MD = 0x00;   // SYSCLK/12
  PCA0CPM0 = 0x31; // PCA0.0 => capture
  PCA0CN |= 0x40;  // enable PCA0
}

/**
 * Timer initialization
 * - Timer 3 reload, used to check if switch pressed on overflow and
 * used for ADC continuous conversion
 * 
 */
void timer_init(){
  TMR2CN = 0x00;    // Stop Timer2; Clear TF2;

  CKCON &= ~0x30;   // Timer2 clocked based on SYSCLK(24.5MHz)/12
  TMR2RL = 0xB03F;  // Re-initialize reload value (100Hz, 10ms), 0x10000-(24.5M/12/100)
  TMR2 = 0xFFFF;    // Set to reload immediately

  IE |= 0x20;     // Enable Timer2 interrupts(ET2)
  TMR2CN |= 0x04;   // Start Timer2(TR2)
}

void main(){

  sys_clk_init();                        // Initialize oscillator
  port_init();                           // Initialize crossbar and GPIO

  //uart0_init();
  timer_init();                          // Initialize timer2
  
  wait_ms(1);
  
#ifdef ALWAY_AUTO
  P1 |= 0x10;                            // デバックで常に自動にしたいとき
#else
  EA = 1;                                // Global Interrupt enable
#endif
  
  while(1){
  }
}

/**
 * interrupt_timer2()
 * 
 */
void interrupt_timer2() interrupt 5 { 
  TMR2CN &= ~0x80; // Clear interrupt
	global_ms += 10;
  tickcount++;
}

/**
 * interrupt_CPA0
 * 
 */
void interrupt_cpa0 () interrupt 9 {
  u8 flag = PCA0CN; 
  PCA0CN = 0x40;
  
  if(flag & 0x01){
    static volatile u16 pca0_cp0;
    if(P1 & 0x20){
      pca0_cp0 = PCA0CPH0;
      pca0_cp0 <<= 8;
      pca0_cp0 |= PCA0CPL0;
    }else{
      {
        u32 pca0 = PCA0CPH0;
        pca0 <<= 8;
        pca0 |= PCA0CPL0;
        pca0 |= (u32)0x10000;
        pca0_cp0 = (pca0 - pca0_cp0);
      }
      if(pca0_cp0 >= 0x0BF6){ // 0x0BF6 = 24.5E6 / 12 * 1500E-6
        P1 |= 0x10;
      }else{
        P1 &= ~0x10;
      }
    }
  }
}

unsigned char _sdcc_external_startup(){
  // Disable Watchdog timer
	PCA0MD &= ~0x40;
  return 0;
}
