#include <p32xxxx.h>
#include <sys/attribs.h>

// 外部の8MHz水晶発振器から40MHzのクロックを生成するための設定
#pragma config FNOSC = PRIPLL // 発信源 = 主外部発振器
#pragma config POSCMOD = XT // 主発振の方法　= 外部高精度発振器を使う
#pragma config FPLLIDIV = DIV_2 // PLL入力分数 = x1/2
#pragma config FPLLMUL = MUL_20 // PLL逓倍比 = x20
#pragma config FPLLODIV = DIV_2 // PLL出力分数 = x1/2
#pragma config FPBDIV = DIV_2 //周辺モジュールクロック倍数 : x1/2

int count = 0, toggle = 0;
void __ISR(_TIMER_1_VECTOR, IPL4AUTO) OnTimer1(void) 
{
    IFS0bits.T1IF = 0; // 割り込みフラグをリセット

    count++;
    if(count >= 10){
        toggle = !toggle;
        LATBbits.LATB0 = toggle; // RB0のスイッチを切り替える      
        count = 0;
    }
}

void InitTimer1()
{
    T1CONbits.ON = 0;    // 設定のため、タイマー1を無効にする
    TMR1 = 0;            // タイマー1をリセット
     
    // 100ms周期で割り込み <- 500ns(1 / 20MHz) * 256 * 7812(0x1E84) = 100ms
    T1CONbits.TCKPS = 3; // プリスケーラ : x1/256
    PR1 = 0x1E84;        // カウンター
        
    IPC1bits.T1IS = 3;   // 副優先度(0-3)
    IPC1bits.T1IP = 4;   // 割り込み優先度(0-7)
    IFS0bits.T1IF = 0;   // 割り込みフラグをリセット
    IEC0bits.T1IE = 1;   // タイマー1の割り込みを許可
}

void __ISR(_CHANGE_NOTICE_VECTOR, IPL4AUTO) OnChanged(void) 
{
    IFS1bits.CNBIF = 0;
    T1CONbits.ON = 1;    // タイマー1有効
}

void InitB1Input()
{
    TRISBbits.TRISB1 = 1; // B1を入力にする
    CNCONBbits.ON = 1;    // ポートBの状態変化検出モジュールを使用
    CNENBbits.CNIEB1 = 1; // B1の検出を有効
    CNPUBbits.CNPUB1 = 1; // プルアップ抵抗を使用   
    
    IPC8bits.CNIP = 4;    // 割り込み優先度(0-7)
    IPC8bits.CNIS = 3;    // 副優先度(0-3)
    IFS1bits.CNBIF = 0;   // 割り込みフラグをリセット
    IEC1bits.CNBIE = 1;   // 状態変化Bの割り込みを許可
    
    PORTBbits.RB1 = 1;  // B1の初期状態を設定
}

int main(void)
{
    ANSELB = 0x00;          // ポートBをすべてデジタルモードにする  
    TRISB = 0;              // ポートBをすべて出力にする
    PORTB = 0;
    
    InitB1Input();
    InitTimer1();
        
    INTCONbits.MVEC = 1;            // マルチベクタ割り込みを有効にする      
    __builtin_enable_interrupts();  // マイコンにおける割り込みの有効  

    asm volatile ("wait");   // wait命令でアイドルモードに移行
        
    while(1) ;
}