#include <intrinsics.h>

/************************************
   JP2がショートされるたびに割り込みを発生し、
　　LEDを点滅させる
*************************************/

/* システムコントローラのレジスタ */
#define SYS_SCS		((volatile unsigned int *)(0xE01FC1A0))

/* ポートコントローラのレジスタ */
#define PINSEL4		((volatile unsigned int *)(0xE002C010))

/* FGPIOコントローラのレジスタ */
#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))

/* 割り込みコントローラ(VIC)のレジスタ */
#define VIC_IntEnable   ((volatile unsigned int *)(0xFFFFF010))
#define VIC_IntSelect   ((volatile unsigned int *)(0xFFFFF00C))
#define VIC_INT_EINT0   (1 << 14)   /* 14番 */

/* 外部割込み設定用のレジスタ */
#define SYS_EXTINT          ((volatile unsigned int *)(0xE01FC140))
#define SYS_EXTMODE         ((volatile unsigned int *)(0xE01FC148))
#define SYS_EXTPOLAR        ((volatile unsigned int *)(0xE01FC14C))

/* LEDを点灯する処理 */
void LED_ON() {
    *FGPIO_FIO1PIN=0x00000000; /* P1[18] を'0'に（LEDを点ける） */
}  

/* LEDを消灯する処理 */
void LED_OFF() {
    *FGPIO_FIO1PIN=0x00040000; /* P1[18] を'1'に（LEDを消す）　 */
}  

/* LEDの状態を覚えておく変数 */
volatile int led_status = 0;

/* LEDを点滅させる処理 */
void toggle_LED() {
    if( led_status == 0 ) {
        led_status = 1;
        LED_ON();
    } else {
        led_status = 0;
        LED_OFF();
    }
}

/* IRQ 割り込み処理 */
__irq __arm void IRQ_Handler()
{
    if( (*SYS_EXTINT & 1) == 1 ) {
        toggle_LED();
        *SYS_EXTINT = 1; /* EINT0割り込みをクリア */
    }
}

/* main関数 */
int main(void)
{
    *SYS_SCS = *SYS_SCS | 1;    /* FGPIO Select            */

    *FGPIO_FIO1DIR = 0x00040000; /* P1[18] を出力端子にする       */
    *FGPIO_FIO1MASK= 0x00000000; /* P1には一切マスクをかけない    */

    *PINSEL4       = 0x00100000; /* P2[10]の端子を EINT0として使う */
    
    /* EINT0割り込みを立ち下がりエッジ入力にする  */
    *SYS_EXTMODE   = 1;
    *SYS_EXTPOLAR  = 0;

    /* 割り込みがかかると初めて点灯するようにLEDを消しておく     */
    LED_OFF();

    /* 割り込み種類選択 (全ての割り込みをFIQではなくIRQにする)   */
    *VIC_IntSelect = 0;

    /* VICに割り込み許可を指示する        */
    *VIC_IntEnable = VIC_INT_EINT0;

    /* CPUに割り込み許可を指示する        */
    __enable_interrupt();

    /* 無限ループ(ここでは何もしない。JP2がショートされるとIRQ_Handler()関数が呼び出される  */
    for(;;){
    }
}
