DS3231 alarm-interrupt
/*H*******************************************************
AlarmInterrupt.ino
Jacob Nuernberg 08/22
Example on using interrupts with DS3231 alarms.
Hardware setup:
Connect DS3231 SQW pin to Arduino interrupt pin 2
Tested on: - Arduino UNO - Arduino nano
Added to this example:
1. Descriptively named variables to pass parameter values.
2. Modify AlarmBits for Alarm 1 to 0b00001111,
for clarity, because Alarm 1 uses only bits 3:0.
3. Add code to prevent Alarm 2 from interfering with the interrupt,
by setting A2Minute to a value that can never match the time
and setting AlarmBits to 0b01100000: alarm "when minutes match".
Also clear the A2 alarm flag.  David Sparks, September 2022
********************************************************/
#include <DS3231.h>
#include <Wire.h>

//************************* DEFINES ************************************
#define  CLINT 2                    // myRTC interrupt pin
#define  BAUD  9600

//************************* PROTOTYPES ************************************

//************************* VARIABLES ************************************
DS3231 myRTC; // Setup clock

byte   alarmDay, alarmHour, alarmMinute, alarmSecond, alarmBits;
bool   alarmDayIsDay, alarmH12, alarmPM;
volatile byte tick = 1;        // Interrupt signaling byte

/*F********************************************************************
*
**********************************************************************/
void 
setup() 
{
	Wire.begin();                                 // BEGIN I2C COMMUNICATION
	Serial.begin( 9600 );                      // BEGIN SERIAL COMMUNICATION
	while( !Serial );
	Serial.println();
	Serial.println( "Starting Serial");
	alarmDay = 0;                     // ASSIGN PARAMETER VALUES FOR ALARM 1
	alarmHour = 0;
	alarmMinute = 0;
	alarmSecond = 0;
	alarmBits = 0b00001111;                         // ALARM 1 EVERY SECOND
	alarmDayIsDay = false;
	alarmH12 = false;
	alarmPM = false;    
	myRTC.turnOffAlarm( 1 );  // SET ALARM 1 TO FIRE AT ONE-SECOND INTERVALS
	myRTC.setA1Time( alarmDay, alarmHour, alarmMinute, alarmSecond
		, alarmBits, alarmDayIsDay, alarmH12, alarmPM);
	myRTC.turnOnAlarm( 1 );                     // ENABLE ALARM 1 INTERRUPTS
	myRTC.checkIfAlarm( 1 );                           // CLEAR ALARM 1 FLAG
	// WHEN USING INTERRUPT WITH ONLY ONE OF THE DS3231 ALARMS, AS IN THIS EXAMPLE,
	// IT MAY BE ADVISABLE TO PREVENT THE OTHER ALARM ENTIRELY, SO IT WILL 
	// NOT COVERTLY BLOCK THE OUTGOING INTERRUPT SIGNAL. PREVENT ALARM 2
	// ALTOGETHER BY ASSIGNING A NONSENSICAL ALARM MINUTE VALUE THAT CANNOT
	// MATCH CLOCK TIME, AND AN alarmBits VALUE TO ACTIVATE 
	// "when minutes match".
	alarmMinute = 0xFF;                // A VALUE THAT WILL NEVER MATCH TIME
	alarmBits = 0b01100000;       // ALARM 2 WHEN MINUTES MATCH, I.E., NEVER
	                        // UPLOAD PARAMETERS TO PREVENT ALARM 2 ENTIRELY
	myRTC.setA2Time( alarmDay, alarmHour, alarmMinute, alarmBits
		, alarmDayIsDay, alarmH12, alarmPM );
	myRTC.turnOffAlarm( 2 );                    // DISABLE ALARM 2 INTERRUPT
	myRTC.checkIfAlarm( 2 );                           // CLEAR ALARM 2 FLAG
	// NOTE: BOTH ALARM FLAGS MUST BE CLEAR TO ENABLE OUTPUT OF A FALLING
	// INTERRUPT ATTACH CLOCK INTERRUPT
	pinMode( CLINT, INPUT_PULLUP );
	attachInterrupt( digitalPinToInterrupt( CLINT ), isr_TickTock, FALLING);
	pinMode( LED_BUILTIN, OUTPUT );              // USE BUILTIN LED TO BLINK
}
/*F********************************************************************
*
**********************************************************************/
void 
loop() 
{
	static byte state = false;             // KEEP TRACK OF LED ON/OFF STATE
	if( tick )                           // IF ALARM WENT OF, DO ALARM STUFF
	{
		tick = 0;
		state = ~state;
		digitalWrite( LED_BUILTIN, state);
		Serial.print( "Turning LED ");             // OPTIONAL SERIAL OUTPUT
		Serial.println( (state ? "ON" : "OFF"));
		myRTC.checkIfAlarm( 1 );                       // CLEAR ALARM 1 FLAG
	}
	delay( 10 );                 // LOOP DELAY TO EMULATE OTHER RUNNING CODE
}
/*F********************************************************************
*
**********************************************************************/
void 
isr_TickTock() 
{
	tick = 1;                                  // INTERRUPT SIGNALS TO LOOP
	return;
}