High Level Requirements
I need to be able to set an alarm and trigger a hardware interrupt via the alarm from a PCF8523 RTC PCF8523 RTC.
Details
It turns out there's already a forked version of the RTCLib that has alarm capability for the PCF8523; however, the hardware interrupt is not triggered. I've also included a test sketch that demonstrates the capability that I'm trying to achieve; however, I can't seem to get the sketch to trigger the interrupt.
Assumptions
I also still need to maintain the RTC set/get time functions.
Deliverables
A "fixed" version of the RTCLib for the PCF8523 coupled with the test sketch code that demonstrates a working version of the hardware interrupt for the PCF8523 and date/time functionality.
Any questions let me know.
/**
Sets a timer for 10 seconds, and watches a pin (MONITOR_PIN) for
its interrupt signal.
The RTC's INT line is pulled down when the timer goes off and the
interrupt is active.
*/
#include <Wire.h>
#include "RTClib.h"
#define MONITOR_PIN A1
RTC_PCF8523 rtc;
Pcf8523TimerState state;
volatile uint32_t counter = 0; // this counter should only be incremented one time
void onAlarm() {
noInterrupts();
digitalWrite(LED_BUILTIN, HIGH);
++counter;
interrupts();
}
void setup () {
Serial.begin(115200);
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
if (! rtc.initialized()) {
Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// This line sets the RTC with an explicit date & time, for example to set
// January 21, 2014 at 3am you would call:
// rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
}
pinMode(LED_BUILTIN, OUTPUT);
pinMode(MONITOR_PIN, INPUT_PULLUP);
attachInterrupt(MONITOR_PIN, onAlarm, CHANGE);
/*
struct type signatures:
typedef struct {
bool irupt_flag; // whether the timer has gone off
bool irupt_enabled; // whether the flag state is tied to the interrupt pin state
} Pcf8523IruptState;
typedef struct {
bool enabled; // whether the timer is running
uint8_t value; // the current value of the timer
Pcf8523FrequencyDivision freq; // the clock divider used
Pcf8523IruptState irupt_state; // the timer's interrupt state
} Pcf8523TimerState;
*/
// should trigger an interrupt in 10s
state.enabled = true;
state.value = 10;
state.freq = PCF8523_Freq_second;
state.irupt_state.irupt_flag = false;
state.irupt_state.irupt_enabled = true;
//rtc.writeSqwPinMode(PCF8523_OFF);
rtc.write_timer(PCF8523_Timer_Countdown_A, &state);
}
void loop () {
rtc.read_timer(PCF8523_Timer_Countdown_A, &state);
Serial.print("timer value: ");
Serial.print(state.value, DEC);
Serial.print(", enabled: ");
Serial.print(state.enabled ? "yes" : "no");
Serial.print(", freq: ");
Serial.print(state.freq, DEC);
Serial.println();
Serial.print("irupt flag: ");
Serial.print(state.irupt_state.irupt_flag, DEC);
Serial.print(", enabled: ");
Serial.print(state.irupt_state.irupt_enabled, DEC);
Serial.println();
Serial.print("Interrupt pin: ");
Serial.println(digitalRead(MONITOR_PIN) ? "HIGH" : "LOW");
Serial.print("Interrupt ctr: " );
Serial.println(counter);
Pcf8523SqwPinMode sqw = rtc.readSqwPinMode();
Serial.print("readSqwPinMode: " );
Serial.println(sqw);
Serial.println();
DateTime now = rtc.now();
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(' ');
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
// reset the alarm
if (counter > 0) {
Serial.println("Alarm has been triggered. Clearing the alarm");
state.enabled = false;
state.value = 0;
state.freq = PCF8523_Freq_second;
state.irupt_state.irupt_flag = false;
state.irupt_state.irupt_enabled = false;
//rtc.writeSqwPinMode(PCF8523_OFF);
rtc.write_timer(PCF8523_Timer_Countdown_A, &state);
counter = 0;
// once this happens, the output of the register state should be interrupt disabled and never triggered
}
delay(1000);
}