AVRのI2Cモジュール / リアルタイムクロックDS3231 / アラームを使う / 割り込み用の信号をポーリングで監視する

前回はアラームフラグをI2C経由でポーリングしたが、今度はINT/SQW端子から出る信号そのものをAVRのPD2端子でポーリングする。INT/SQW端子はどちらのアラームも共通なので、どちらのアラームが発動したのかを知るためには結局アラームフラグも見なければならない。
f:id:ti-nspire:20200206134905p:plain:w400
f:id:ti-nspire:20200206134940p:plain:w400

#include <avr/io.h>
#include <util/delay.h>
#include "USART.h"
#include "myI2Cv2.h"
#include "DS3231.h"

int main(){
    // DDRD &= ~(1 << PD2); // PD2のIOをINにする(0にする)(INが初期値なので省略できる)。L、Hを入力するので内部プルアップはしない。
    
    initUSART();

    DS3231 rtc;         // リアルタイムクロックDS3231 (I2Cスレーブ)を実体化する。
    myI2Cv2.enable(80); // システムクロックの80分周をI2CクロックとしてAVRのI2Cモジュールを有効化する。

    rtc.setDateTimeMan(); // USART経由で手動で時刻合わせをして、
    
    printString("***** Set the alarm 1 *****\n"); // USART経由で手動でアラーム1の発動タイミングを設定して、
    rtc.setAlarmMan(1);
    printString("***** Set the alarm 2 *****\n"); // USART経由で手動でアラーム2の発動タイミングを設定して、
    rtc.setAlarmMan(2);

    rtc.enableAlarm(1); // アラーム1を有効化して、
    rtc.enableAlarm(2); // アラーム2を有効化して、

    uint8_t whichAlarm;
    while(1){
      
        loop_until_bit_is_clear(PIND, PD2);     // 割り込み用の信号(L)がPD2に検知されたら、
        whichAlarm = rtc.whichAlarmActivated(); // どちらのアラームが発動したのかを調べて、
        rtc.getDateTimeBCD();                   // それに応じて何かをして、
        rtc.printDateTime();
        printString(" Alarm "); printNibble(whichAlarm); printString(" has been activated.\n");
        rtc.clearAlarmFlag(whichAlarm);         // そのアラーム発動フラグを解除して、

/*
        if(bit_is_clear(PIND, PD2) && rtc.alarmActivated(1)){ // 割り込み用の信号(L)がPD2に検知されて、かつそれがアラーム1であったなら、
                                                              // 何かをして、
            rtc.getDateTimeBCD(); rtc.printDateTime(); printString(" Alarm 1 has been activated.\n");
            rtc.clearAlarmFlag(1);                            // アラーム1発動フラグを解除して、
        }
        if(bit_is_clear(PIND, PD2) && rtc.alarmActivated(2)){ // 割り込み用の信号(L)がPD2に検知されて、かつそれがアラーム2であったなら、
                                                              // 何かをして、
            rtc.getDateTimeBCD(); rtc.printDateTime(); printString(" Alarm 2 has been activated.\n");
            rtc.clearAlarmFlag(2);                            // アラーム2発動フラグを解除して、
        }
*/

        _delay_ms(200); // またアラームの発動を待つ。を繰り返す。
    }

    // unreachable:
    rtc.disableAlarm(1);
    rtc.disableAlarm(2);
    myI2Cv2.disable();
    return 0;
}
    uint8_t whichAlarmActivated();              // どちらのアラームが出たのか
uint8_t DS3231::whichAlarmActivated(){
    myI2Cv2.start();                   // スタートコンディションを生成して、
    myI2Cv2.writeByte(ADDRESS_W);      // スレーブに呼びかけて、writeであることを示して、
    myI2Cv2.writeByte(CONTROL_STATUS); // スレーブ側のレジスタポインタをセットして、

    myI2Cv2.start();                      // スタートコンディションを生成して、
    myI2Cv2.writeByte(ADDRESS_R);         // スレーブに呼びかけて、readであることを示して、
    uint8_t cs = myI2Cv2.readByteNACK();  // 目的のCONTROL_STATUSレジスタの内容を読み出して、

    myI2Cv2.stop(); // ストップコンディションを生成して、

    return (cs & 0x03); // どちらのアラームが出たのか(下2ビット)を返す。
}