Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: DipCortex-EEprom RTC flw mbed
RTC/ds3231m.cpp@0:f6e68b4ce169, 2015-02-09 (annotated)
- Committer:
- Backstrom
- Date:
- Mon Feb 09 13:40:46 2015 +0000
- Revision:
- 0:f6e68b4ce169
Initial commit
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| Backstrom | 0:f6e68b4ce169 | 1 | /* |
| Backstrom | 0:f6e68b4ce169 | 2 | * VFD Modular Clock - mbed |
| Backstrom | 0:f6e68b4ce169 | 3 | * (C) 2011-14 Akafugu Corporation |
| Backstrom | 0:f6e68b4ce169 | 4 | * |
| Backstrom | 0:f6e68b4ce169 | 5 | * This program is free software; you can redistribute it and/or modify it under the |
| Backstrom | 0:f6e68b4ce169 | 6 | * terms of the GNU General Public License as published by the Free Software |
| Backstrom | 0:f6e68b4ce169 | 7 | * Foundation; either version 2 of the License, or (at your option) any later |
| Backstrom | 0:f6e68b4ce169 | 8 | * version. |
| Backstrom | 0:f6e68b4ce169 | 9 | * |
| Backstrom | 0:f6e68b4ce169 | 10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY |
| Backstrom | 0:f6e68b4ce169 | 11 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A |
| Backstrom | 0:f6e68b4ce169 | 12 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. |
| Backstrom | 0:f6e68b4ce169 | 13 | * |
| Backstrom | 0:f6e68b4ce169 | 14 | */ |
| Backstrom | 0:f6e68b4ce169 | 15 | |
| Backstrom | 0:f6e68b4ce169 | 16 | #include "global.h" |
| Backstrom | 0:f6e68b4ce169 | 17 | #include "ds3231m.h" |
| Backstrom | 0:f6e68b4ce169 | 18 | |
| Backstrom | 0:f6e68b4ce169 | 19 | #define DS3231M_SLAVE_ADDR 0xD0 |
| Backstrom | 0:f6e68b4ce169 | 20 | |
| Backstrom | 0:f6e68b4ce169 | 21 | DS3231M::DS3231M(I2C& i2c) |
| Backstrom | 0:f6e68b4ce169 | 22 | : RTC() |
| Backstrom | 0:f6e68b4ce169 | 23 | , m_i2c(i2c) |
| Backstrom | 0:f6e68b4ce169 | 24 | { |
| Backstrom | 0:f6e68b4ce169 | 25 | m_i2c.frequency(100000); |
| Backstrom | 0:f6e68b4ce169 | 26 | } |
| Backstrom | 0:f6e68b4ce169 | 27 | |
| Backstrom | 0:f6e68b4ce169 | 28 | void DS3231M::begin() |
| Backstrom | 0:f6e68b4ce169 | 29 | { |
| Backstrom | 0:f6e68b4ce169 | 30 | } |
| Backstrom | 0:f6e68b4ce169 | 31 | |
| Backstrom | 0:f6e68b4ce169 | 32 | time_t DS3231M::time() |
| Backstrom | 0:f6e68b4ce169 | 33 | { |
| Backstrom | 0:f6e68b4ce169 | 34 | return m_time; |
| Backstrom | 0:f6e68b4ce169 | 35 | } |
| Backstrom | 0:f6e68b4ce169 | 36 | |
| Backstrom | 0:f6e68b4ce169 | 37 | struct tm* DS3231M::getTime() |
| Backstrom | 0:f6e68b4ce169 | 38 | { |
| Backstrom | 0:f6e68b4ce169 | 39 | char rtc[7]; |
| Backstrom | 0:f6e68b4ce169 | 40 | |
| Backstrom | 0:f6e68b4ce169 | 41 | rtc[0] = 0; // second register, 0 |
| Backstrom | 0:f6e68b4ce169 | 42 | int w = m_i2c.write(DS3231M_SLAVE_ADDR, rtc, 1); |
| Backstrom | 0:f6e68b4ce169 | 43 | int r = m_i2c.read(DS3231M_SLAVE_ADDR, rtc, 7); |
| Backstrom | 0:f6e68b4ce169 | 44 | |
| Backstrom | 0:f6e68b4ce169 | 45 | // Clear clock halt bit from read data |
| Backstrom | 0:f6e68b4ce169 | 46 | //rtc[0] &= ~(_BV(CH_BIT)); |
| Backstrom | 0:f6e68b4ce169 | 47 | |
| Backstrom | 0:f6e68b4ce169 | 48 | m_tm.tm_sec = bcd2dec(rtc[0]); |
| Backstrom | 0:f6e68b4ce169 | 49 | m_tm.tm_min = bcd2dec(rtc[1]); |
| Backstrom | 0:f6e68b4ce169 | 50 | m_tm.tm_hour = bcd2dec(rtc[2]); |
| Backstrom | 0:f6e68b4ce169 | 51 | m_tm.tm_wday = bcd2dec(rtc[3])-1; |
| Backstrom | 0:f6e68b4ce169 | 52 | m_tm.tm_mday = bcd2dec(rtc[4]); |
| Backstrom | 0:f6e68b4ce169 | 53 | m_tm.tm_mon = bcd2dec(rtc[5])-1; // tm_mon is 0-11 |
| Backstrom | 0:f6e68b4ce169 | 54 | m_tm.tm_year = bcd2dec(rtc[6]); |
| Backstrom | 0:f6e68b4ce169 | 55 | |
| Backstrom | 0:f6e68b4ce169 | 56 | return &m_tm; |
| Backstrom | 0:f6e68b4ce169 | 57 | } |
| Backstrom | 0:f6e68b4ce169 | 58 | |
| Backstrom | 0:f6e68b4ce169 | 59 | void DS3231M::getTime(uint8_t* hour, uint8_t* min, uint8_t* sec) |
| Backstrom | 0:f6e68b4ce169 | 60 | { |
| Backstrom | 0:f6e68b4ce169 | 61 | char rtc[3]; |
| Backstrom | 0:f6e68b4ce169 | 62 | |
| Backstrom | 0:f6e68b4ce169 | 63 | rtc[0] = 0; // second register, 0 |
| Backstrom | 0:f6e68b4ce169 | 64 | int w = m_i2c.write(DS3231M_SLAVE_ADDR, rtc, 1); |
| Backstrom | 0:f6e68b4ce169 | 65 | int r = m_i2c.read(DS3231M_SLAVE_ADDR, rtc, 3); |
| Backstrom | 0:f6e68b4ce169 | 66 | |
| Backstrom | 0:f6e68b4ce169 | 67 | // Clear clock halt bit from read data |
| Backstrom | 0:f6e68b4ce169 | 68 | //rtc[0] &= ~(_BV(CH_BIT)); |
| Backstrom | 0:f6e68b4ce169 | 69 | |
| Backstrom | 0:f6e68b4ce169 | 70 | if (sec) *sec = bcd2dec(rtc[0]); |
| Backstrom | 0:f6e68b4ce169 | 71 | if (min) *min = bcd2dec(rtc[1]); |
| Backstrom | 0:f6e68b4ce169 | 72 | if (hour) *hour = bcd2dec(rtc[2]); |
| Backstrom | 0:f6e68b4ce169 | 73 | } |
| Backstrom | 0:f6e68b4ce169 | 74 | |
| Backstrom | 0:f6e68b4ce169 | 75 | void DS3231M::setTime(time_t t) |
| Backstrom | 0:f6e68b4ce169 | 76 | { |
| Backstrom | 0:f6e68b4ce169 | 77 | struct tm * timeinfo; |
| Backstrom | 0:f6e68b4ce169 | 78 | timeinfo = localtime (&t); |
| Backstrom | 0:f6e68b4ce169 | 79 | setTime(timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); |
| Backstrom | 0:f6e68b4ce169 | 80 | } |
| Backstrom | 0:f6e68b4ce169 | 81 | |
| Backstrom | 0:f6e68b4ce169 | 82 | void DS3231M::setTime(uint8_t hour, uint8_t min, uint8_t sec) |
| Backstrom | 0:f6e68b4ce169 | 83 | { |
| Backstrom | 0:f6e68b4ce169 | 84 | write_byte(dec2bcd(sec), 0); |
| Backstrom | 0:f6e68b4ce169 | 85 | write_byte(dec2bcd(min), 1); |
| Backstrom | 0:f6e68b4ce169 | 86 | write_byte(dec2bcd(hour), 2); |
| Backstrom | 0:f6e68b4ce169 | 87 | } |
| Backstrom | 0:f6e68b4ce169 | 88 | |
| Backstrom | 0:f6e68b4ce169 | 89 | void DS3231M::setTime(struct tm* tm) |
| Backstrom | 0:f6e68b4ce169 | 90 | { |
| Backstrom | 0:f6e68b4ce169 | 91 | write_byte(dec2bcd(tm->tm_sec), 0); |
| Backstrom | 0:f6e68b4ce169 | 92 | write_byte(dec2bcd(tm->tm_min), 1); |
| Backstrom | 0:f6e68b4ce169 | 93 | write_byte(dec2bcd(tm->tm_hour), 2); |
| Backstrom | 0:f6e68b4ce169 | 94 | write_byte(dec2bcd(tm->tm_wday+1), 3); |
| Backstrom | 0:f6e68b4ce169 | 95 | write_byte(dec2bcd(tm->tm_mday), 4); |
| Backstrom | 0:f6e68b4ce169 | 96 | write_byte(dec2bcd(tm->tm_mon+1), 5); |
| Backstrom | 0:f6e68b4ce169 | 97 | write_byte(dec2bcd(tm->tm_year), 6); |
| Backstrom | 0:f6e68b4ce169 | 98 | } |
| Backstrom | 0:f6e68b4ce169 | 99 | |
| Backstrom | 0:f6e68b4ce169 | 100 | void DS3231M::setAlarm(time_t t) |
| Backstrom | 0:f6e68b4ce169 | 101 | { |
| Backstrom | 0:f6e68b4ce169 | 102 | struct tm * timeinfo; |
| Backstrom | 0:f6e68b4ce169 | 103 | timeinfo = localtime (&t); |
| Backstrom | 0:f6e68b4ce169 | 104 | setAlarm(timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); |
| Backstrom | 0:f6e68b4ce169 | 105 | } |
| Backstrom | 0:f6e68b4ce169 | 106 | |
| Backstrom | 0:f6e68b4ce169 | 107 | void DS3231M::setAlarm(uint8_t hour, uint8_t min, uint8_t sec) |
| Backstrom | 0:f6e68b4ce169 | 108 | { |
| Backstrom | 0:f6e68b4ce169 | 109 | /* |
| Backstrom | 0:f6e68b4ce169 | 110 | * 07h: A1M1:0 Alarm 1 seconds |
| Backstrom | 0:f6e68b4ce169 | 111 | * 08h: A1M2:0 Alarm 1 minutes |
| Backstrom | 0:f6e68b4ce169 | 112 | * 09h: A1M3:0 Alarm 1 hour (bit6 is am/pm flag in 12h mode) |
| Backstrom | 0:f6e68b4ce169 | 113 | * 0ah: A1M4:1 Alarm 1 day/date (bit6: 1 for day, 0 for date) |
| Backstrom | 0:f6e68b4ce169 | 114 | * Sets alarm to fire when hour, minute and second matches |
| Backstrom | 0:f6e68b4ce169 | 115 | */ |
| Backstrom | 0:f6e68b4ce169 | 116 | write_byte(dec2bcd(sec), 0x07); // second |
| Backstrom | 0:f6e68b4ce169 | 117 | write_byte(dec2bcd(min), 0x08); // minute |
| Backstrom | 0:f6e68b4ce169 | 118 | write_byte(dec2bcd(hour), 0x09); // hour |
| Backstrom | 0:f6e68b4ce169 | 119 | write_byte(0x81, 0x0a); // day (upper bit must be set) |
| Backstrom | 0:f6e68b4ce169 | 120 | |
| Backstrom | 0:f6e68b4ce169 | 121 | // clear alarm flag |
| Backstrom | 0:f6e68b4ce169 | 122 | uint8_t val = read_byte(0x0f); |
| Backstrom | 0:f6e68b4ce169 | 123 | write_byte(val & ~0x01, 0x0f); |
| Backstrom | 0:f6e68b4ce169 | 124 | } |
| Backstrom | 0:f6e68b4ce169 | 125 | |
| Backstrom | 0:f6e68b4ce169 | 126 | |
| Backstrom | 0:f6e68b4ce169 | 127 | struct tm* DS3231M::getAlarm(void) |
| Backstrom | 0:f6e68b4ce169 | 128 | { |
| Backstrom | 0:f6e68b4ce169 | 129 | struct tm * timeinfo = getTime(); |
| Backstrom | 0:f6e68b4ce169 | 130 | uint8_t hour, min, sec; |
| Backstrom | 0:f6e68b4ce169 | 131 | |
| Backstrom | 0:f6e68b4ce169 | 132 | getAlarm(&hour, &min, &sec); |
| Backstrom | 0:f6e68b4ce169 | 133 | timeinfo->tm_hour = hour; |
| Backstrom | 0:f6e68b4ce169 | 134 | timeinfo->tm_min = min; |
| Backstrom | 0:f6e68b4ce169 | 135 | timeinfo->tm_sec = sec; |
| Backstrom | 0:f6e68b4ce169 | 136 | return timeinfo; |
| Backstrom | 0:f6e68b4ce169 | 137 | } |
| Backstrom | 0:f6e68b4ce169 | 138 | |
| Backstrom | 0:f6e68b4ce169 | 139 | void DS3231M::getAlarm(uint8_t* hour, uint8_t* min, uint8_t* sec) |
| Backstrom | 0:f6e68b4ce169 | 140 | { |
| Backstrom | 0:f6e68b4ce169 | 141 | *sec = bcd2dec(read_byte(0x07) & ~0x80); |
| Backstrom | 0:f6e68b4ce169 | 142 | *min = bcd2dec(read_byte(0x08) & ~0x80); |
| Backstrom | 0:f6e68b4ce169 | 143 | *hour = bcd2dec(read_byte(0x09) & ~0x80); |
| Backstrom | 0:f6e68b4ce169 | 144 | } |
| Backstrom | 0:f6e68b4ce169 | 145 | |
| Backstrom | 0:f6e68b4ce169 | 146 | bool DS3231M::checkAlarm(void) |
| Backstrom | 0:f6e68b4ce169 | 147 | { |
| Backstrom | 0:f6e68b4ce169 | 148 | // Alarm 1 flag (A1F) in bit 0 |
| Backstrom | 0:f6e68b4ce169 | 149 | uint8_t val = read_byte(0x0f); |
| Backstrom | 0:f6e68b4ce169 | 150 | |
| Backstrom | 0:f6e68b4ce169 | 151 | // clear flag when set |
| Backstrom | 0:f6e68b4ce169 | 152 | if (val & 1) |
| Backstrom | 0:f6e68b4ce169 | 153 | write_byte(val & ~0x01, 0x0f); |
| Backstrom | 0:f6e68b4ce169 | 154 | |
| Backstrom | 0:f6e68b4ce169 | 155 | return val & 1 ? 1 : 0; |
| Backstrom | 0:f6e68b4ce169 | 156 | } |
| Backstrom | 0:f6e68b4ce169 | 157 | |
| Backstrom | 0:f6e68b4ce169 | 158 | void DS3231M::SQWEnable(bool enable) |
| Backstrom | 0:f6e68b4ce169 | 159 | { |
| Backstrom | 0:f6e68b4ce169 | 160 | uint8_t control = read_byte(0x0E); // read control register |
| Backstrom | 0:f6e68b4ce169 | 161 | if (enable) { |
| Backstrom | 0:f6e68b4ce169 | 162 | control |= 0x40; // set BBSQW to 1 |
| Backstrom | 0:f6e68b4ce169 | 163 | control &= ~0x04; // set INTCN to 0 |
| Backstrom | 0:f6e68b4ce169 | 164 | } |
| Backstrom | 0:f6e68b4ce169 | 165 | else { |
| Backstrom | 0:f6e68b4ce169 | 166 | control &= ~0x40; // set BBSQW to 0 |
| Backstrom | 0:f6e68b4ce169 | 167 | } |
| Backstrom | 0:f6e68b4ce169 | 168 | // write control back |
| Backstrom | 0:f6e68b4ce169 | 169 | write_byte(control, 0x0E); |
| Backstrom | 0:f6e68b4ce169 | 170 | } |
| Backstrom | 0:f6e68b4ce169 | 171 | |
| Backstrom | 0:f6e68b4ce169 | 172 | void DS3231M::SQWSetFreq(enum RTC_SQW_FREQ freq) |
| Backstrom | 0:f6e68b4ce169 | 173 | { |
| Backstrom | 0:f6e68b4ce169 | 174 | uint8_t control = read_byte(0x0E); // read control register |
| Backstrom | 0:f6e68b4ce169 | 175 | control &= ~0x18; // Set to 0 |
| Backstrom | 0:f6e68b4ce169 | 176 | control |= (freq << 4); // Set freq bitmask |
| Backstrom | 0:f6e68b4ce169 | 177 | |
| Backstrom | 0:f6e68b4ce169 | 178 | // write control back |
| Backstrom | 0:f6e68b4ce169 | 179 | write_byte(control, 0x0E); |
| Backstrom | 0:f6e68b4ce169 | 180 | } |
| Backstrom | 0:f6e68b4ce169 | 181 | |
| Backstrom | 0:f6e68b4ce169 | 182 | void DS3231M::Osc32kHzEnable(bool enable) |
| Backstrom | 0:f6e68b4ce169 | 183 | { |
| Backstrom | 0:f6e68b4ce169 | 184 | uint8_t status = read_byte(0x0F); // read status |
| Backstrom | 0:f6e68b4ce169 | 185 | |
| Backstrom | 0:f6e68b4ce169 | 186 | if (enable) |
| Backstrom | 0:f6e68b4ce169 | 187 | status |= 0x08; // set to 1 |
| Backstrom | 0:f6e68b4ce169 | 188 | else |
| Backstrom | 0:f6e68b4ce169 | 189 | status &= ~0x08; // Set to 0 |
| Backstrom | 0:f6e68b4ce169 | 190 | |
| Backstrom | 0:f6e68b4ce169 | 191 | // write status back |
| Backstrom | 0:f6e68b4ce169 | 192 | write_byte(status, 0x0F); |
| Backstrom | 0:f6e68b4ce169 | 193 | } |
| Backstrom | 0:f6e68b4ce169 | 194 | |
| Backstrom | 0:f6e68b4ce169 | 195 | uint8_t DS3231M::read_byte(uint8_t offset) |
| Backstrom | 0:f6e68b4ce169 | 196 | { |
| Backstrom | 0:f6e68b4ce169 | 197 | char buf[1]; |
| Backstrom | 0:f6e68b4ce169 | 198 | buf[0] = offset; |
| Backstrom | 0:f6e68b4ce169 | 199 | |
| Backstrom | 0:f6e68b4ce169 | 200 | int w = m_i2c.write(DS3231M_SLAVE_ADDR, buf, 1); |
| Backstrom | 0:f6e68b4ce169 | 201 | int r = m_i2c.read(DS3231M_SLAVE_ADDR, buf, 1); |
| Backstrom | 0:f6e68b4ce169 | 202 | //error = ((w!=0) || (r!=0)); |
| Backstrom | 0:f6e68b4ce169 | 203 | |
| Backstrom | 0:f6e68b4ce169 | 204 | return buf[0]; |
| Backstrom | 0:f6e68b4ce169 | 205 | } |
| Backstrom | 0:f6e68b4ce169 | 206 | |
| Backstrom | 0:f6e68b4ce169 | 207 | void DS3231M::write_byte(uint8_t b, uint8_t offset) |
| Backstrom | 0:f6e68b4ce169 | 208 | { |
| Backstrom | 0:f6e68b4ce169 | 209 | char buf[2]; |
| Backstrom | 0:f6e68b4ce169 | 210 | buf[0] = offset; |
| Backstrom | 0:f6e68b4ce169 | 211 | buf[1] = b; |
| Backstrom | 0:f6e68b4ce169 | 212 | |
| Backstrom | 0:f6e68b4ce169 | 213 | int w = m_i2c.write(DS3231M_SLAVE_ADDR, buf, 2); |
| Backstrom | 0:f6e68b4ce169 | 214 | //error=(w!=0); |
| Backstrom | 0:f6e68b4ce169 | 215 | } |
| Backstrom | 0:f6e68b4ce169 | 216 | |
| Backstrom | 0:f6e68b4ce169 | 217 | void DS3231M::write_addr(uint8_t addr) |
| Backstrom | 0:f6e68b4ce169 | 218 | { |
| Backstrom | 0:f6e68b4ce169 | 219 | /* |
| Backstrom | 0:f6e68b4ce169 | 220 | Wire.beginTransmission(RTC_ADDR); |
| Backstrom | 0:f6e68b4ce169 | 221 | Wire.write(addr); |
| Backstrom | 0:f6e68b4ce169 | 222 | Wire.endTransmission(); |
| Backstrom | 0:f6e68b4ce169 | 223 | */ |
| Backstrom | 0:f6e68b4ce169 | 224 | } |
| Backstrom | 0:f6e68b4ce169 | 225 |