28 #include "DS3231RTC.h"
29 #include "../I2C/I2CMaster.h"
30 #if defined(ARDUINO) && ARDUINO >= 100
66 #define DS3231_I2C_ADDRESS 0x68
69 #define DS3231_SECOND 0x00
70 #define DS3231_MINUTE 0x01
71 #define DS3231_HOUR 0x02
72 #define DS3231_DAY_OF_WEEK 0x03
73 #define DS3231_DATE 0x04
74 #define DS3231_MONTH 0x05
75 #define DS3231_YEAR 0x06
76 #define DS3231_ALARM1_SEC 0x07
77 #define DS3231_ALARM1_MIN 0x08
78 #define DS3231_ALARM1_HOUR 0x09
79 #define DS3231_ALARM1_DAY 0x0A
80 #define DS3231_ALARM2_MIN 0x0B
81 #define DS3231_ALARM2_HOUR 0x0C
82 #define DS3231_ALARM2_DAY 0x0D
83 #define DS3231_CONTROL 0x0E
84 #define DS3231_STATUS 0x0F
85 #define DS3231_AGING_OFFSET 0x10
86 #define DS3231_TEMP_MSB 0x11
87 #define DS3231_TEMP_LSB 0x12
90 #define DS3231_EOSC 0x80
91 #define DS3231_BBSQW 0x40
92 #define DS3231_CONV 0x20
93 #define DS3231_RS_1HZ 0x00
94 #define DS3231_RS_1024HZ 0x08
95 #define DS3231_RS_4096HZ 0x10
96 #define DS3231_RS_8192HZ 0x18
97 #define DS3231_INTCN 0x04
98 #define DS3231_A2IE 0x02
99 #define DS3231_A1IE 0x01
102 #define DS3231_OSF 0x80
103 #define DS3231_BB32KHZ 0x40
104 #define DS3231_EN32KHZ 0x08
105 #define DS3231_BSY 0x04
106 #define DS3231_A2F 0x02
107 #define DS3231_A1F 0x01
110 #define DS3231_ALARM_0 0x07
111 #define DS3231_ALARM_1 0x0B
127 , _oneHzPin(oneHzPin)
130 , alarmInterrupts(false) {
133 _bus->
write(DS3231_CONTROL);
134 if ( _bus->
startRead(DS3231_I2C_ADDRESS, 1) ) {
135 uint8_t value = _bus->
read() & DS3231_CONV;
136 if ( oneHzPin != 255 ) {
137 value |= DS3231_BBSQW | DS3231_RS_1HZ;
140 _bus->
write(DS3231_CONTROL);
150 if ( ( oneHzPin != 255) && _isRealTime ) {
151 pinMode(oneHzPin, INPUT);
152 digitalWrite(oneHzPin, HIGH);
169 if ( ( _oneHzPin == 255) || !_isRealTime ) {
175 bool value = digitalRead(_oneHzPin);
176 if ( value && !prevOneHz ) {
186 inline uint8_t fromBCD(uint8_t value) {
187 return (value >> 4) * 10 + (value & 0x0F);
190 inline uint8_t fromHourBCD(uint8_t value) {
191 if ( (value & 0x40) != 0 ) {
193 uint8_t result = ( (value >> 4) & 0x01 ) * 10 + (value & 0x0F);
194 if ( (value & 0x20) != 0 ) {
195 return (result == 12) ? 12 : (result + 12);
198 return (result == 12) ? 0 : result;
203 return fromBCD(value);
210 _bus->
write(DS3231_SECOND);
211 if ( _bus->
startRead(DS3231_I2C_ADDRESS, 3) ) {
214 value->
hour = fromHourBCD( _bus->
read() );
229 if ( !_isRealTime ) {
234 _bus->
write(DS3231_DATE);
235 if ( _bus->
startRead(DS3231_I2C_ADDRESS, 3) ) {
236 value->
day = fromBCD( _bus->
read() );
237 value->
month = fromBCD(_bus->
read() & 0x7F);
238 value->
year = fromBCD( _bus->
read() ) + 2000;
248 inline uint8_t toBCD(uint8_t value) {
249 return ( (value / 10) << 4 ) + (value % 10);
255 _bus->
write(DS3231_SECOND);
269 _bus->
write(DS3231_DATE);
282 uint8_t reg_value = readRegister(DS3231_CONTROL);
284 if ( 0 == alarmNum ) {
285 _bus->
write(DS3231_ALARM_0);
286 if ( _bus->
startRead(DS3231_I2C_ADDRESS, 4) ) {
287 alarmSecondValues(_bus->
read(), value);
288 alarmMinuteValues(_bus->
read(), value);
289 alarmHourValues(_bus->
read(), value);
290 alarmDayValues(_bus->
read(), value);
291 value->
flags &= ~0x80;
292 value->
flags |= (reg_value & 0x01) << 6;
302 else if ( 1 == alarmNum ) {
303 _bus->
write(DS3231_ALARM_1);
304 if ( _bus->
startRead(DS3231_I2C_ADDRESS, 3) ) {
306 alarmMinuteValues(_bus->
read(), value);
307 alarmHourValues(_bus->
read(), value);
308 alarmDayValues(_bus->
read(), value);
309 value->
flags |= 0x80;
310 value->
flags |= (reg_value & 0x02) << 5;
326 void DS3231RTC::alarmSecondValues(uint8_t read_value,
RTCAlarm* value) {
327 uint8_t mask_bit = (read_value & 0x80) ? 0x01 : 0x00;
329 value->
second = fromBCD(read_value & 0x7F);
330 value->
flags |= mask_bit;
333 void DS3231RTC::alarmMinuteValues(uint8_t read_value,
RTCAlarm* value) {
334 uint8_t mask_bit = (read_value & 0x80) ? 0x02 : 0x00;
336 value->
minute = fromBCD(read_value & 0x7F);
337 value->
flags |= mask_bit;
340 void DS3231RTC::alarmHourValues(uint8_t read_value,
RTCAlarm* value) {
341 uint8_t mask_bit = (read_value & 0x80) ? 0x04 : 0x00;
342 uint8_t is_ampm = read_value & 0x40;
345 uint8_t hour = fromBCD(read_value & ~0xE0);
346 if ( read_value & 0x20 ) {
352 value->
hour = fromBCD(read_value & ~0xC0);
354 value->
flags |= mask_bit;
357 void DS3231RTC::alarmDayValues(uint8_t read_value,
RTCAlarm* value) {
358 uint8_t mask_bit = (read_value & 0x80) ? 0x08 : 0x00;
359 uint8_t is_dow = read_value & 0x40;
363 value->
dow = fromBCD(read_value & 0x0F);
364 value->
flags |= 0x20;
368 value->
day = fromBCD(read_value & 0x3F);
369 value->
flags &= ~0x20;
371 value->
flags |= mask_bit;
379 void DS3231RTC::clearAlarm(uint8_t alarmNum) {
380 if ( 0 == alarmNum ) {
382 _bus->
write(DS3231_ALARM_0);
389 else if ( 1 == alarmNum ) {
391 _bus->
write(DS3231_ALARM_1);
410 uint8_t alarm_mask_bits = value->
flags;
412 if ( 0 == alarmNum ) {
413 if ( alarm_mask_bits & 0x80 ) {
418 _bus->
write(DS3231_ALARM_0);
419 _bus->
write( toBCD(value->
second) | ( ( alarm_mask_bits & 0x01 ) << 7 ) );
420 _bus->
write( toBCD(value->
minute) | ( ( alarm_mask_bits & 0x02 ) << 6 ) );
422 _bus->
write( toBCD(value->
hour) | ( ( alarm_mask_bits & 0x04 ) << 5 ) );
423 _bus->
write( getAlarmDayValue(value) );
425 if ( value->
flags & 0x40 ) {
429 else if ( 1 == alarmNum ) {
430 if ( !(alarm_mask_bits & 0x80) ) {
435 _bus->
write(DS3231_ALARM_1);
436 _bus->
write( toBCD(value->
minute) | ( ( alarm_mask_bits & 0x02 ) << 6 ) );
438 _bus->
write( toBCD(value->
hour) | ( ( alarm_mask_bits & 0x04 ) << 5 ) );
439 _bus->
write( getAlarmDayValue(value) );
441 if ( value->
flags & 0x40 ) {
454 uint8_t DS3231RTC::getAlarmDayValue(
const RTCAlarm* value) {
455 uint8_t alarm_mask_bits = value->
flags;
456 uint8_t day_value_mask = ( alarm_mask_bits & 0x08 ) << 4;
458 if ( alarm_mask_bits & 0x20 ) {
460 day_value_mask |= 0x40;
461 return (toBCD(value->
dow) | day_value_mask);
465 day_value_mask &= ~0x40;
466 return (toBCD(value->
day) | day_value_mask);
472 return ( ( (
int)(
signed char)readRegister(DS3231_TEMP_MSB) ) << 2 ) |
473 (readRegister(DS3231_TEMP_LSB) >> 6);
495 if ( ( _oneHzPin == 255) && _isRealTime ) {
496 uint8_t value = readRegister(DS3231_CONTROL);
497 value |= DS3231_INTCN;
498 writeRegister(DS3231_CONTROL, value);
499 alarmInterrupts =
true;
509 if ( alarmInterrupts ) {
510 uint8_t value = readRegister(DS3231_CONTROL);
511 value &= ~(DS3231_INTCN | DS3231_A2IE | DS3231_A1IE);
512 writeRegister(DS3231_CONTROL, value);
513 alarmInterrupts =
false;
531 if ( !_isRealTime ) {
534 uint8_t value = readRegister(DS3231_STATUS);
536 if ( value & DS3231_A1F ) {
537 if ( value & DS3231_A2F ) {
544 else if ( value & DS3231_A2F ) {
551 value &= ~(DS3231_A1F | DS3231_A2F);
552 writeRegister(DS3231_STATUS, value);
564 uint8_t value = readRegister(DS3231_STATUS);
565 value |= DS3231_BB32KHZ | DS3231_EN32KHZ;
566 writeRegister(DS3231_STATUS, value);
577 uint8_t value = readRegister(DS3231_STATUS);
578 value &= ~(DS3231_BB32KHZ | DS3231_EN32KHZ);
579 writeRegister(DS3231_STATUS, value);
583 uint8_t DS3231RTC::readRegister(uint8_t reg) {
586 if ( !_bus->
startRead(DS3231_I2C_ADDRESS, 1) ) {
592 bool DS3231RTC::writeRegister(uint8_t reg, uint8_t value) {
607 uint8_t value = readRegister(DS3231_CONTROL);
609 if ( 0 == alarmNum ) {
610 value |= DS3231_A1IE;
612 else if ( 1 == alarmNum ) {
613 value |= DS3231_A2IE;
615 writeRegister(DS3231_CONTROL, value);
626 uint8_t value = readRegister(DS3231_CONTROL);
628 clearAlarm(alarmNum);
630 if ( 0 == alarmNum ) {
631 value &= ~DS3231_A1IE;
633 else if ( 1 == alarmNum ) {
634 value &= ~DS3231_A2IE;
636 writeRegister(DS3231_CONTROL, value);
uint8_t month
Month of the year (1-12)
virtual void writeTime(const RTCTime *value)
Updates the time in the realtime clock to match value.
void enable32kHzOutput()
Enables the 32 kHz output on the DS3231 chip.
void disableAlarmInterrupts()
Disables the generation of interrupts for alarms 0 and 1.
uint8_t minute
Minute within the hour (0-59)
virtual void readAlarm(uint8_t alarmNum, RTCAlarm *value)
Reads the details of the alarm with index alarmNum into value.
virtual void readDate(RTCDate *value)
Reads the current date from the realtime clock into value.
uint8_t day
Day of the month for the alarm if not zero.
void readDate(RTCDate *value)
Reads the current date from the realtime clock into value.
int readTemperature()
Reads the value of the temperature sensor and returns the temperature in quarters of a degree celcius...
virtual void write(uint8_t value)=0
Writes a single byte value on the I2C bus.
virtual void writeAlarm(uint8_t alarmNum, const RTCAlarm *value)
Updates the details of the alarm with index alarmNum from value.
void enableAlarmInterrupts()
Enables the generation of interrupts for alarms 0 and 1.
virtual void writeDate(const RTCDate *value)
Updates the date in the realtime clock to match value.
virtual bool startRead(unsigned int address, unsigned int count)=0
Starts a read operation for count bytes by sending the start condition and the I2C control byte...
uint8_t hour
Hour of the day for the alarm (0-23).
static const int NO_TEMPERATURE
Value that is returned from readTemperature() if the realtime clock chip cannot determine the tempera...
uint8_t flags
Additional flags for the alarm.
void enableAlarm(uint8_t alarmNum)
Enables a specific alarm.
uint8_t dow
Day of the week for the alarm if not zero.
Stores date information from a realtime clock chip.
void readAlarm(uint8_t alarmNum, RTCAlarm *value)
Reads the details of the alarm with index alarmNum into value.
DS3231RTC(I2CMaster &bus, uint8_t oneHzPin=255)
Attaches to a realtime clock slave device on bus.
virtual void startWrite(unsigned int address)
Starts a write operation by sending a start condition and the I2C control byte.
void disableAlarm(uint8_t alarmNum)
Disables a specific alarm.
bool setAlarm(uint8_t alarmNum, const RTCAlarm *value)
Sets the alarm with index alarmNum from value.
virtual bool endWrite()=0
Ends the current write operation.
unsigned int year
Year (4-digit)
void writeDate(const RTCDate *value)
Updates the date in the realtime clock to match value.
void writeAlarm(uint8_t alarmNum, const RTCAlarm *value)
Updates the details of the alarm with index alarmNum from value.
uint8_t minute
Minute of the hour for the alarm (0-59).
void disable32kHzOutput()
Disables the 32 kHz output on the DS3231 chip.
uint8_t second
Second of the minute for the alarm (0-59).
Stores time information from a realtime clock chip.
void writeTime(const RTCTime *value)
Updates the time in the realtime clock to match value.
Abstract base class for I2C master implementations.
Stores alarm information from a realtime clock chip.
bool hasUpdates()
Returns true if there are updates.
virtual uint8_t read()=0
Reads a single byte from the I2C bus.
uint8_t hour
Hour of the day (0-23)
void readTime(RTCTime *value)
Reads the current time from the realtime clock into value.
uint8_t day
Day of the month (1-31)
uint8_t second
Second within the minute (0-59)
int firedAlarm()
Determines which of alarms 0 or 1 have fired since the last call.
virtual void readTime(RTCTime *value)
Reads the current time from the realtime clock into value.