Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DS3231: Add support for fetching alarm values #257

Merged
merged 2 commits into from
Aug 4, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 26 additions & 5 deletions examples/DS3231_alarm/DS3231_alarm.ino
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,32 @@ void loop() {
char date[10] = "hh:mm:ss";
rtc.now().toString(date);
Serial.print(date);

// the stored alarm value + mode
DateTime alarm1 = rtc.getAlarm1();
Ds3231Alarm1Mode alarm1mode = rtc.getAlarm1Mode();
char alarm1Date[12] = "DD hh:mm:ss";
rtc.getAlarm1().toString(alarm1Date);
Serial.print(" [Alarm1: ");
Serial.print(alarm1Date);
Serial.print(", Mode: ");
switch (rtc.getAlarm1Mode()) {
case DS3231_A1_PerSecond: Serial.print("PerSecond"); break;
case DS3231_A1_Second: Serial.print("Second"); break;
case DS3231_A1_Minute: Serial.print("Minute"); break;
case DS3231_A1_Hour: Serial.print("Hour"); break;
case DS3231_A1_Date: Serial.print("Date"); break;
case DS3231_A1_Day: Serial.print("Day"); break;
}

// the value at SQW-Pin (because of pullup 1 means no alarm)
Serial.print(" SQW: ");
Serial.print("] SQW: ");
Serial.print(digitalRead(CLOCK_INTERRUPT_PIN));
// whether a alarm happened happened
Serial.print(" Alarm1: ");

// whether a alarm fired
Serial.print(" Fired: ");
Serial.print(rtc.alarmFired(1));

// Serial.print(" Alarm2: ");
// Serial.println(rtc.alarmFired(2));
// control register values (see https://datasheets.maximintegrated.com/en/ds/DS3231.pdf page 13)
Expand All @@ -79,10 +99,11 @@ void loop() {

// resetting SQW and alarm 1 flag
// using setAlarm1, the next alarm could now be configurated
if(rtc.alarmFired(1)) {
if (rtc.alarmFired(1)) {
rtc.clearAlarm(1);
Serial.println("Alarm cleared");
Serial.print(" - Alarm cleared");
}
Serial.println();

delay(2000);
}
Expand Down
129 changes: 129 additions & 0 deletions src/RTC_DS3231.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,135 @@ bool RTC_DS3231::setAlarm2(const DateTime &dt, Ds3231Alarm2Mode alarm_mode) {
return true;
}

/**************************************************************************/
/*!
@brief Get the date/time value of Alarm1
@return DateTime object with the Alarm1 data set in the
day, hour, minutes, and seconds fields
*/
/**************************************************************************/
DateTime RTC_DS3231::getAlarm1() {
uint8_t buffer[5] = {DS3231_ALARM1, 0, 0, 0, 0};
i2c_dev->write_then_read(buffer, 1, buffer, 5);

uint8_t seconds = bcd2bin(buffer[0] & 0x7F);
uint8_t minutes = bcd2bin(buffer[1] & 0x7F);
// Fetching the hour assumes 24 hour time (never 12)
// because this library exclusively stores the time
// in 24 hour format. Note that the DS3231 supports
// 12 hour storage, and sets bits to indicate the type
// that is stored.
uint8_t hour = bcd2bin(buffer[2] & 0x3F);

// Determine if the alarm is set to fire based on the
// day of the week, or an explicit date match.
bool isDayOfWeek = (buffer[3] & 0x40) >> 6;
uint8_t day;
if (isDayOfWeek) {
// Alarm set to match on day of the week
day = bcd2bin(buffer[3] & 0x0F);
} else {
// Alarm set to match on day of the month
day = bcd2bin(buffer[3] & 0x3F);
}

return DateTime(2000U, 1, day, hour, minutes, seconds);
justinnewitter marked this conversation as resolved.
Show resolved Hide resolved
}

/**************************************************************************/
/*!
@brief Get the date/time value of Alarm2
@return DateTime object with the Alarm2 data set in the
day, hour, and minutes fields
*/
/**************************************************************************/
DateTime RTC_DS3231::getAlarm2() {
uint8_t buffer[4] = {DS3231_ALARM2, 0, 0, 0};
i2c_dev->write_then_read(buffer, 1, buffer, 4);

uint8_t minutes = bcd2bin(buffer[0] & 0x7F);
// Fetching the hour assumes 24 hour time (never 12)
// because this library exclusively stores the time
// in 24 hour format. Note that the DS3231 supports
// 12 hour storage, and sets bits to indicate the type
// that is stored.
uint8_t hour = bcd2bin(buffer[1] & 0x3F);

// Determine if the alarm is set to fire based on the
// day of the week, or an explicit date match.
bool isDayOfWeek = (buffer[2] & 0x40) >> 6;
uint8_t day;
if (isDayOfWeek) {
// Alarm set to match on day of the week
day = bcd2bin(buffer[2] & 0x0F);
} else {
// Alarm set to match on day of the month
day = bcd2bin(buffer[2] & 0x3F);
}

return DateTime(2000U, 1, day, hour, minutes, 0);
justinnewitter marked this conversation as resolved.
Show resolved Hide resolved
}

/**************************************************************************/
/*!
@brief Get the mode for Alarm1
@return Ds3231Alarm1Mode enum value for the current Alarm1 mode
*/
/**************************************************************************/
Ds3231Alarm1Mode RTC_DS3231::getAlarm1Mode() {
uint8_t buffer[5] = {DS3231_ALARM1, 0, 0, 0, 0};
i2c_dev->write_then_read(buffer, 1, buffer, 5);

uint8_t alarm_mode = (buffer[0] & 0x80) >> 7 // A1M1 - Seconds bit
| (buffer[1] & 0x80) >> 6 // A1M2 - Minutes bit
| (buffer[2] & 0x80) >> 5 // A1M3 - Hour bit
| (buffer[3] & 0x80) >> 4 // A1M4 - Day/Date bit
| (buffer[3] & 0x40) >> 2; // DY_DT

// Determine which mode the fetched alarm bits map to
switch (alarm_mode) {
case DS3231_A1_PerSecond:
case DS3231_A1_Second:
case DS3231_A1_Minute:
case DS3231_A1_Hour:
case DS3231_A1_Date:
case DS3231_A1_Day:
return (Ds3231Alarm1Mode)alarm_mode;
default:
// Default if the alarm mode cannot be read
return DS3231_A1_Date;
}
}

/**************************************************************************/
/*!
@brief Get the mode for Alarm2
@return Ds3231Alarm2Mode enum value for the current Alarm2 mode
*/
/**************************************************************************/
Ds3231Alarm2Mode RTC_DS3231::getAlarm2Mode() {
uint8_t buffer[4] = {DS3231_ALARM2, 0, 0, 0};
i2c_dev->write_then_read(buffer, 1, buffer, 4);

uint8_t alarm_mode = (buffer[0] & 0x80) >> 7 // A2M2 - Minutes bit
| (buffer[1] & 0x80) >> 6 // A2M3 - Hour bit
| (buffer[2] & 0x80) >> 5 // A2M4 - Day/Date bit
| (buffer[2] & 0x40) >> 3; // DY_DT

// Determine which mode the fetched alarm bits map to
switch (alarm_mode) {
case DS3231_A2_PerMinute:
case DS3231_A2_Minute:
case DS3231_A2_Hour:
case DS3231_A2_Date:
case DS3231_A2_Day:
return (Ds3231Alarm2Mode)alarm_mode;
default:
// Default if the alarm mode cannot be read
return DS3231_A2_Date;
}
}

/**************************************************************************/
/*!
@brief Disable alarm
Expand Down
4 changes: 4 additions & 0 deletions src/RTClib.h
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,10 @@ class RTC_DS3231 : RTC_I2C {
void writeSqwPinMode(Ds3231SqwPinMode mode);
bool setAlarm1(const DateTime &dt, Ds3231Alarm1Mode alarm_mode);
bool setAlarm2(const DateTime &dt, Ds3231Alarm2Mode alarm_mode);
DateTime getAlarm1();
DateTime getAlarm2();
Ds3231Alarm1Mode getAlarm1Mode();
Ds3231Alarm2Mode getAlarm2Mode();
void disableAlarm(uint8_t alarm_num);
void clearAlarm(uint8_t alarm_num);
bool alarmFired(uint8_t alarm_num);
Expand Down