DS3231 External RTC I2C
Fork of DS3231 by
DS3231.cpp@0:e4fbbd93299b, 2014-08-05 (annotated)
- Committer:
- techstep
- Date:
- Tue Aug 05 16:43:01 2014 +0000
- Revision:
- 0:e4fbbd93299b
- Child:
- 1:1607610a4ee9
DS3231; I2C Library
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
techstep | 0:e4fbbd93299b | 1 | /***************************************************************************** |
techstep | 0:e4fbbd93299b | 2 | * Type : C++ |
techstep | 0:e4fbbd93299b | 3 | * File : DS3231.cpp |
techstep | 0:e4fbbd93299b | 4 | * Dec. : DS3231 + AT24C32 IIC Module Precision RTC Module Memory Module |
techstep | 0:e4fbbd93299b | 5 | * Copyright (c) 2013-2014, Bird Techstep, tbird_th@hotmail.com |
techstep | 0:e4fbbd93299b | 6 | * |
techstep | 0:e4fbbd93299b | 7 | * Remark Original codr from DS3231 Library [Arduino] |
techstep | 0:e4fbbd93299b | 8 | * |
techstep | 0:e4fbbd93299b | 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
techstep | 0:e4fbbd93299b | 10 | * of this software and associated documentation files (the "Software"), to deal |
techstep | 0:e4fbbd93299b | 11 | * in the Software without restriction, including without limitation the rights |
techstep | 0:e4fbbd93299b | 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
techstep | 0:e4fbbd93299b | 13 | * copies of the Software, and to permit persons to whom the Software is |
techstep | 0:e4fbbd93299b | 14 | * furnished to do so, subject to the following conditions: |
techstep | 0:e4fbbd93299b | 15 | * |
techstep | 0:e4fbbd93299b | 16 | * The above copyright notice and this permission notice shall be included in |
techstep | 0:e4fbbd93299b | 17 | * all copies or substantial portions of the Software. |
techstep | 0:e4fbbd93299b | 18 | * |
techstep | 0:e4fbbd93299b | 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
techstep | 0:e4fbbd93299b | 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
techstep | 0:e4fbbd93299b | 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
techstep | 0:e4fbbd93299b | 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
techstep | 0:e4fbbd93299b | 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
techstep | 0:e4fbbd93299b | 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
techstep | 0:e4fbbd93299b | 25 | * THE SOFTWARE. |
techstep | 0:e4fbbd93299b | 26 | *****************************************************************************/ |
techstep | 0:e4fbbd93299b | 27 | #include "DS3231.h" |
techstep | 0:e4fbbd93299b | 28 | #define CLOCK_ADDRESS 0x68 |
techstep | 0:e4fbbd93299b | 29 | #define ADDR char(CLOCK_ADDRESS<<1) |
techstep | 0:e4fbbd93299b | 30 | |
techstep | 0:e4fbbd93299b | 31 | // Constructor |
techstep | 0:e4fbbd93299b | 32 | DS3231::DS3231(PinName sda_pin, PinName scl_pin) : _i2c(sda_pin, scl_pin) { |
techstep | 0:e4fbbd93299b | 33 | _i2c.frequency(100000); |
techstep | 0:e4fbbd93299b | 34 | } |
techstep | 0:e4fbbd93299b | 35 | /***************************************** |
techstep | 0:e4fbbd93299b | 36 | Public Functions |
techstep | 0:e4fbbd93299b | 37 | *****************************************/ |
techstep | 0:e4fbbd93299b | 38 | |
techstep | 0:e4fbbd93299b | 39 | void DS3231::getTime(uint8_t& year, uint8_t& month, uint8_t& date, uint8_t& DoW, uint8_t& hour, uint8_t& minute, uint8_t& second) { |
techstep | 0:e4fbbd93299b | 40 | uint8_t tempBuffer; |
techstep | 0:e4fbbd93299b | 41 | bool PM; |
techstep | 0:e4fbbd93299b | 42 | bool h12; |
techstep | 0:e4fbbd93299b | 43 | |
techstep | 0:e4fbbd93299b | 44 | //I2C.beginTransmission(CLOCK_ADDRESS); |
techstep | 0:e4fbbd93299b | 45 | //I2C.write(uint8_t(0x00)); |
techstep | 0:e4fbbd93299b | 46 | //I2C.endTransmission(); |
techstep | 0:e4fbbd93299b | 47 | _i2c.start(); |
techstep | 0:e4fbbd93299b | 48 | _i2c.write(uint8_t(CLOCK_ADDRESS)); |
techstep | 0:e4fbbd93299b | 49 | _i2c.write(uint8_t(0x00)); |
techstep | 0:e4fbbd93299b | 50 | _i2c.stop(); |
techstep | 0:e4fbbd93299b | 51 | |
techstep | 0:e4fbbd93299b | 52 | //I2C.requestFrom(CLOCK_ADDRESS, 7); |
techstep | 0:e4fbbd93299b | 53 | second = bcdToDec(_i2c.read(uint8_t(CLOCK_ADDRESS))); |
techstep | 0:e4fbbd93299b | 54 | minute = bcdToDec(_i2c.read(uint8_t(CLOCK_ADDRESS))); |
techstep | 0:e4fbbd93299b | 55 | tempBuffer = bcdToDec(_i2c.read(uint8_t(CLOCK_ADDRESS))); |
techstep | 0:e4fbbd93299b | 56 | |
techstep | 0:e4fbbd93299b | 57 | h12 = tempBuffer & 0x40; |
techstep | 0:e4fbbd93299b | 58 | if (h12) { |
techstep | 0:e4fbbd93299b | 59 | PM = tempBuffer & 0x20; |
techstep | 0:e4fbbd93299b | 60 | hour = bcdToDec(tempBuffer & 0x1F); |
techstep | 0:e4fbbd93299b | 61 | } else { |
techstep | 0:e4fbbd93299b | 62 | hour = bcdToDec(tempBuffer & 0x3F); |
techstep | 0:e4fbbd93299b | 63 | } |
techstep | 0:e4fbbd93299b | 64 | DoW = bcdToDec(_i2c.read(uint8_t(CLOCK_ADDRESS))); |
techstep | 0:e4fbbd93299b | 65 | date = bcdToDec(_i2c.read(uint8_t(CLOCK_ADDRESS))); |
techstep | 0:e4fbbd93299b | 66 | month = bcdToDec(_i2c.read(uint8_t(CLOCK_ADDRESS)) & 0x7F); |
techstep | 0:e4fbbd93299b | 67 | year = bcdToDec(_i2c.read(uint8_t(CLOCK_ADDRESS))); |
techstep | 0:e4fbbd93299b | 68 | } |
techstep | 0:e4fbbd93299b | 69 | |
techstep | 0:e4fbbd93299b | 70 | int8_t DS3231::getSecond(void) { |
techstep | 0:e4fbbd93299b | 71 | char data; |
techstep | 0:e4fbbd93299b | 72 | char cmd; |
techstep | 0:e4fbbd93299b | 73 | cmd = 0x00; |
techstep | 0:e4fbbd93299b | 74 | _i2c.write(ADDR, &cmd, 1 ); |
techstep | 0:e4fbbd93299b | 75 | _i2c.read( ADDR, &data, 1 ); |
techstep | 0:e4fbbd93299b | 76 | return(bcdToDec(data)); |
techstep | 0:e4fbbd93299b | 77 | } |
techstep | 0:e4fbbd93299b | 78 | |
techstep | 0:e4fbbd93299b | 79 | uint8_t DS3231::getMinute(void) { |
techstep | 0:e4fbbd93299b | 80 | char data; |
techstep | 0:e4fbbd93299b | 81 | char cmd; |
techstep | 0:e4fbbd93299b | 82 | cmd = 0x01; |
techstep | 0:e4fbbd93299b | 83 | _i2c.write(ADDR, &cmd, 1 ); |
techstep | 0:e4fbbd93299b | 84 | _i2c.read( ADDR, &data, 1 ); |
techstep | 0:e4fbbd93299b | 85 | return(bcdToDec(data)); |
techstep | 0:e4fbbd93299b | 86 | } |
techstep | 0:e4fbbd93299b | 87 | |
techstep | 0:e4fbbd93299b | 88 | uint8_t DS3231::getHour(bool& h12, bool& PM) { |
techstep | 0:e4fbbd93299b | 89 | char temp_buffer; |
techstep | 0:e4fbbd93299b | 90 | char hour; |
techstep | 0:e4fbbd93299b | 91 | char cmd; |
techstep | 0:e4fbbd93299b | 92 | cmd = 0x02; |
techstep | 0:e4fbbd93299b | 93 | _i2c.write(ADDR, &cmd, 1 ); |
techstep | 0:e4fbbd93299b | 94 | _i2c.read( ADDR, &temp_buffer, 1 ); |
techstep | 0:e4fbbd93299b | 95 | |
techstep | 0:e4fbbd93299b | 96 | h12 = temp_buffer & 0x40; |
techstep | 0:e4fbbd93299b | 97 | if (h12) { |
techstep | 0:e4fbbd93299b | 98 | PM = temp_buffer & 0x20; |
techstep | 0:e4fbbd93299b | 99 | hour = bcdToDec(temp_buffer & 0x1F); |
techstep | 0:e4fbbd93299b | 100 | } else { |
techstep | 0:e4fbbd93299b | 101 | hour = bcdToDec(temp_buffer & 0x3F); |
techstep | 0:e4fbbd93299b | 102 | } |
techstep | 0:e4fbbd93299b | 103 | return hour; |
techstep | 0:e4fbbd93299b | 104 | } |
techstep | 0:e4fbbd93299b | 105 | |
techstep | 0:e4fbbd93299b | 106 | uint8_t DS3231::getDoW(void) { |
techstep | 0:e4fbbd93299b | 107 | char data; |
techstep | 0:e4fbbd93299b | 108 | char cmd; |
techstep | 0:e4fbbd93299b | 109 | cmd = 0x03; |
techstep | 0:e4fbbd93299b | 110 | _i2c.write(ADDR, &cmd, 1 ); |
techstep | 0:e4fbbd93299b | 111 | _i2c.read( ADDR, &data, 1 ); |
techstep | 0:e4fbbd93299b | 112 | return(bcdToDec(data)); |
techstep | 0:e4fbbd93299b | 113 | } |
techstep | 0:e4fbbd93299b | 114 | |
techstep | 0:e4fbbd93299b | 115 | uint8_t DS3231::getDate(void) { |
techstep | 0:e4fbbd93299b | 116 | char data; |
techstep | 0:e4fbbd93299b | 117 | char cmd; |
techstep | 0:e4fbbd93299b | 118 | cmd = 0x04; |
techstep | 0:e4fbbd93299b | 119 | _i2c.write(ADDR, &cmd, 1 ); |
techstep | 0:e4fbbd93299b | 120 | _i2c.read( ADDR, &data, 1 ); |
techstep | 0:e4fbbd93299b | 121 | return(bcdToDec(data)); |
techstep | 0:e4fbbd93299b | 122 | } |
techstep | 0:e4fbbd93299b | 123 | |
techstep | 0:e4fbbd93299b | 124 | uint8_t DS3231::getMonth(bool& Century) { |
techstep | 0:e4fbbd93299b | 125 | char temp_buffer; |
techstep | 0:e4fbbd93299b | 126 | char cmd; |
techstep | 0:e4fbbd93299b | 127 | cmd = 0x05; |
techstep | 0:e4fbbd93299b | 128 | _i2c.write(ADDR, &cmd, 1 ); |
techstep | 0:e4fbbd93299b | 129 | _i2c.read( ADDR, &temp_buffer, 1 ); |
techstep | 0:e4fbbd93299b | 130 | |
techstep | 0:e4fbbd93299b | 131 | Century = temp_buffer & 0x80; |
techstep | 0:e4fbbd93299b | 132 | return (bcdToDec(temp_buffer & 0x7F)) ; |
techstep | 0:e4fbbd93299b | 133 | } |
techstep | 0:e4fbbd93299b | 134 | |
techstep | 0:e4fbbd93299b | 135 | uint8_t DS3231::getYear(void) { |
techstep | 0:e4fbbd93299b | 136 | char data; |
techstep | 0:e4fbbd93299b | 137 | char cmd; |
techstep | 0:e4fbbd93299b | 138 | cmd = 0x06; |
techstep | 0:e4fbbd93299b | 139 | _i2c.write(ADDR, &cmd, 1 ); |
techstep | 0:e4fbbd93299b | 140 | _i2c.read( ADDR, &data, 1 ); |
techstep | 0:e4fbbd93299b | 141 | return(bcdToDec(data)); |
techstep | 0:e4fbbd93299b | 142 | } |
techstep | 0:e4fbbd93299b | 143 | |
techstep | 0:e4fbbd93299b | 144 | void DS3231::setSecond(uint8_t Second) { |
techstep | 0:e4fbbd93299b | 145 | // Sets the seconds |
techstep | 0:e4fbbd93299b | 146 | // This function also resets the Oscillator Stop Flag, which is set |
techstep | 0:e4fbbd93299b | 147 | // whenever power is interrupted. |
techstep | 0:e4fbbd93299b | 148 | char cmd[2]; |
techstep | 0:e4fbbd93299b | 149 | cmd[0] = 0x00; |
techstep | 0:e4fbbd93299b | 150 | cmd[1] = decToBcd(Second); |
techstep | 0:e4fbbd93299b | 151 | _i2c.write(ADDR, cmd, 2); |
techstep | 0:e4fbbd93299b | 152 | |
techstep | 0:e4fbbd93299b | 153 | // Clear OSF flag |
techstep | 0:e4fbbd93299b | 154 | uint8_t temp_buffer = readControlByte(1); |
techstep | 0:e4fbbd93299b | 155 | writeControlByte((temp_buffer & 0x7F), 1); |
techstep | 0:e4fbbd93299b | 156 | } |
techstep | 0:e4fbbd93299b | 157 | |
techstep | 0:e4fbbd93299b | 158 | void DS3231::setMinute(uint8_t Minute) { |
techstep | 0:e4fbbd93299b | 159 | // Sets the minutes |
techstep | 0:e4fbbd93299b | 160 | char cmd[2]; |
techstep | 0:e4fbbd93299b | 161 | cmd[0] = 0x01; |
techstep | 0:e4fbbd93299b | 162 | cmd[1] = decToBcd(Minute); |
techstep | 0:e4fbbd93299b | 163 | _i2c.write(ADDR, cmd, 2); |
techstep | 0:e4fbbd93299b | 164 | } |
techstep | 0:e4fbbd93299b | 165 | |
techstep | 0:e4fbbd93299b | 166 | void DS3231::setHour(uint8_t Hour) { |
techstep | 0:e4fbbd93299b | 167 | // Sets the hour, without changing 12/24h mode. |
techstep | 0:e4fbbd93299b | 168 | // The hour must be in 24h format. |
techstep | 0:e4fbbd93299b | 169 | |
techstep | 0:e4fbbd93299b | 170 | bool h12; |
techstep | 0:e4fbbd93299b | 171 | |
techstep | 0:e4fbbd93299b | 172 | // Start by figuring out what the 12/24 mode is |
techstep | 0:e4fbbd93299b | 173 | char data; |
techstep | 0:e4fbbd93299b | 174 | char cmd; |
techstep | 0:e4fbbd93299b | 175 | cmd = 0x02; |
techstep | 0:e4fbbd93299b | 176 | _i2c.write(ADDR, &cmd, 1 ); |
techstep | 0:e4fbbd93299b | 177 | _i2c.read( ADDR, &data, 1 ); |
techstep | 0:e4fbbd93299b | 178 | |
techstep | 0:e4fbbd93299b | 179 | h12 = (data & 0x40); |
techstep | 0:e4fbbd93299b | 180 | // if h12 is true, it's 12h mode; false is 24h. |
techstep | 0:e4fbbd93299b | 181 | |
techstep | 0:e4fbbd93299b | 182 | if (h12) { |
techstep | 0:e4fbbd93299b | 183 | // 12 hour |
techstep | 0:e4fbbd93299b | 184 | if (Hour > 12) { |
techstep | 0:e4fbbd93299b | 185 | Hour = decToBcd(Hour-12) | 0x60; |
techstep | 0:e4fbbd93299b | 186 | } else { |
techstep | 0:e4fbbd93299b | 187 | Hour = decToBcd(Hour) & 0xDF; |
techstep | 0:e4fbbd93299b | 188 | } |
techstep | 0:e4fbbd93299b | 189 | } else { |
techstep | 0:e4fbbd93299b | 190 | // 24 hour |
techstep | 0:e4fbbd93299b | 191 | Hour = decToBcd(Hour) & 0xBF; |
techstep | 0:e4fbbd93299b | 192 | } |
techstep | 0:e4fbbd93299b | 193 | char cmdHour[2]; |
techstep | 0:e4fbbd93299b | 194 | cmdHour[0] = 0x02; |
techstep | 0:e4fbbd93299b | 195 | cmdHour[1] = Hour; |
techstep | 0:e4fbbd93299b | 196 | _i2c.write(ADDR, cmdHour, 2); |
techstep | 0:e4fbbd93299b | 197 | } |
techstep | 0:e4fbbd93299b | 198 | |
techstep | 0:e4fbbd93299b | 199 | void DS3231::setDoW(uint8_t DoW) { |
techstep | 0:e4fbbd93299b | 200 | // Sets the Day of Week |
techstep | 0:e4fbbd93299b | 201 | char cmd[2]; |
techstep | 0:e4fbbd93299b | 202 | cmd[0] = 0x03; |
techstep | 0:e4fbbd93299b | 203 | cmd[1] = decToBcd(DoW); |
techstep | 0:e4fbbd93299b | 204 | _i2c.write(ADDR, cmd, 2 ); |
techstep | 0:e4fbbd93299b | 205 | } |
techstep | 0:e4fbbd93299b | 206 | |
techstep | 0:e4fbbd93299b | 207 | void DS3231::setDate(uint8_t Date) { |
techstep | 0:e4fbbd93299b | 208 | // Sets the Date |
techstep | 0:e4fbbd93299b | 209 | char cmd[2]; |
techstep | 0:e4fbbd93299b | 210 | cmd[0] = 0x04; |
techstep | 0:e4fbbd93299b | 211 | cmd[1] = decToBcd(Date); |
techstep | 0:e4fbbd93299b | 212 | _i2c.write(ADDR, cmd, 2 ); |
techstep | 0:e4fbbd93299b | 213 | } |
techstep | 0:e4fbbd93299b | 214 | |
techstep | 0:e4fbbd93299b | 215 | void DS3231::setMonth(uint8_t Month) { |
techstep | 0:e4fbbd93299b | 216 | // Sets the month |
techstep | 0:e4fbbd93299b | 217 | char cmd[2]; |
techstep | 0:e4fbbd93299b | 218 | cmd[0] = 0x05; |
techstep | 0:e4fbbd93299b | 219 | cmd[1] = decToBcd(Month); |
techstep | 0:e4fbbd93299b | 220 | _i2c.write(ADDR, cmd, 2 ); |
techstep | 0:e4fbbd93299b | 221 | } |
techstep | 0:e4fbbd93299b | 222 | |
techstep | 0:e4fbbd93299b | 223 | void DS3231::setYear(uint8_t Year) { |
techstep | 0:e4fbbd93299b | 224 | // Sets the year |
techstep | 0:e4fbbd93299b | 225 | char cmd[2]; |
techstep | 0:e4fbbd93299b | 226 | cmd[0] = 0x06; |
techstep | 0:e4fbbd93299b | 227 | cmd[1] = decToBcd(Year); |
techstep | 0:e4fbbd93299b | 228 | _i2c.write(ADDR, cmd, 2 ); |
techstep | 0:e4fbbd93299b | 229 | } |
techstep | 0:e4fbbd93299b | 230 | |
techstep | 0:e4fbbd93299b | 231 | void DS3231::setClockMode(bool h12) { |
techstep | 0:e4fbbd93299b | 232 | // sets the mode to 12-hour (true) or 24-hour (false). |
techstep | 0:e4fbbd93299b | 233 | // One thing that bothers me about how I've written this is that |
techstep | 0:e4fbbd93299b | 234 | // if the read and right happen at the right hourly millisecnd, |
techstep | 0:e4fbbd93299b | 235 | // the clock will be set back an hour. Not sure how to do it better, |
techstep | 0:e4fbbd93299b | 236 | // though, and as long as one doesn't set the mode frequently it's |
techstep | 0:e4fbbd93299b | 237 | // a very minimal risk. |
techstep | 0:e4fbbd93299b | 238 | // It's zero risk if you call this BEFORE setting the hour, since |
techstep | 0:e4fbbd93299b | 239 | // the setHour() function doesn't change this mode. |
techstep | 0:e4fbbd93299b | 240 | |
techstep | 0:e4fbbd93299b | 241 | char temp_buffer; |
techstep | 0:e4fbbd93299b | 242 | char cmd; |
techstep | 0:e4fbbd93299b | 243 | cmd = 0x02; |
techstep | 0:e4fbbd93299b | 244 | |
techstep | 0:e4fbbd93299b | 245 | // Start by reading byte 0x02. |
techstep | 0:e4fbbd93299b | 246 | //I2C.beginTransmission(CLOCK_ADDRESS); |
techstep | 0:e4fbbd93299b | 247 | //I2C.write(uint8_t(0x02)); |
techstep | 0:e4fbbd93299b | 248 | //I2C.endTransmission(); |
techstep | 0:e4fbbd93299b | 249 | _i2c.write(ADDR, &cmd, 1 ); |
techstep | 0:e4fbbd93299b | 250 | _i2c.read( ADDR, &temp_buffer, 1 ); |
techstep | 0:e4fbbd93299b | 251 | |
techstep | 0:e4fbbd93299b | 252 | // Set the flag to the requested value: |
techstep | 0:e4fbbd93299b | 253 | if (h12) { |
techstep | 0:e4fbbd93299b | 254 | temp_buffer = temp_buffer | 0x40; |
techstep | 0:e4fbbd93299b | 255 | } else { |
techstep | 0:e4fbbd93299b | 256 | temp_buffer = temp_buffer & 0xBF; |
techstep | 0:e4fbbd93299b | 257 | } |
techstep | 0:e4fbbd93299b | 258 | |
techstep | 0:e4fbbd93299b | 259 | // Write the byte |
techstep | 0:e4fbbd93299b | 260 | _i2c.write(ADDR, &cmd, 1 ); |
techstep | 0:e4fbbd93299b | 261 | _i2c.write(temp_buffer); |
techstep | 0:e4fbbd93299b | 262 | } |
techstep | 0:e4fbbd93299b | 263 | |
techstep | 0:e4fbbd93299b | 264 | float DS3231::getTemperature(void) { |
techstep | 0:e4fbbd93299b | 265 | // Checks the internal thermometer on the DS3231 and returns the |
techstep | 0:e4fbbd93299b | 266 | // temperature as a floating-point value. |
techstep | 0:e4fbbd93299b | 267 | char tempMSB; |
techstep | 0:e4fbbd93299b | 268 | char tempLSB; |
techstep | 0:e4fbbd93299b | 269 | char cmd; |
techstep | 0:e4fbbd93299b | 270 | cmd = 0x11; |
techstep | 0:e4fbbd93299b | 271 | _i2c.write(ADDR, &cmd, 1 ); |
techstep | 0:e4fbbd93299b | 272 | _i2c.read( ADDR, &tempMSB, 1); // Here's the MSB |
techstep | 0:e4fbbd93299b | 273 | _i2c.read( ADDR, &tempLSB, 1); // Here's the LSB |
techstep | 0:e4fbbd93299b | 274 | return float(tempMSB) + 0.25*(tempLSB>>6); |
techstep | 0:e4fbbd93299b | 275 | } |
techstep | 0:e4fbbd93299b | 276 | |
techstep | 0:e4fbbd93299b | 277 | void DS3231::getA1Time(uint8_t& A1Day, uint8_t& A1Hour, uint8_t& A1Minute, uint8_t& A1Second, uint8_t& AlarmBits, bool& A1Dy, bool& A1h12, bool& A1PM) { |
techstep | 0:e4fbbd93299b | 278 | uint8_t temp_buffer; |
techstep | 0:e4fbbd93299b | 279 | //I2C.beginTransmission(CLOCK_ADDRESS); |
techstep | 0:e4fbbd93299b | 280 | //I2C.write(uint8_t(0x07)); |
techstep | 0:e4fbbd93299b | 281 | //I2C.endTransmission(); |
techstep | 0:e4fbbd93299b | 282 | _i2c.start(); |
techstep | 0:e4fbbd93299b | 283 | _i2c.write(uint8_t(CLOCK_ADDRESS)); |
techstep | 0:e4fbbd93299b | 284 | _i2c.write(uint8_t(0x07)); |
techstep | 0:e4fbbd93299b | 285 | _i2c.stop(); |
techstep | 0:e4fbbd93299b | 286 | |
techstep | 0:e4fbbd93299b | 287 | //I2C.requestFrom(CLOCK_ADDRESS, 4); |
techstep | 0:e4fbbd93299b | 288 | |
techstep | 0:e4fbbd93299b | 289 | temp_buffer = _i2c.read(uint8_t(CLOCK_ADDRESS)); // Get A1M1 and A1 Seconds |
techstep | 0:e4fbbd93299b | 290 | A1Second = bcdToDec(temp_buffer & 0x7F); |
techstep | 0:e4fbbd93299b | 291 | // put A1M1 bit in position 0 of DS3231_AlarmBits. |
techstep | 0:e4fbbd93299b | 292 | AlarmBits = AlarmBits | (temp_buffer & 0x80)>>7; |
techstep | 0:e4fbbd93299b | 293 | |
techstep | 0:e4fbbd93299b | 294 | temp_buffer = _i2c.read(uint8_t(CLOCK_ADDRESS)); // Get A1M2 and A1 minutes |
techstep | 0:e4fbbd93299b | 295 | A1Minute = bcdToDec(temp_buffer & 0x7F); |
techstep | 0:e4fbbd93299b | 296 | // put A1M2 bit in position 1 of DS3231_AlarmBits. |
techstep | 0:e4fbbd93299b | 297 | AlarmBits = AlarmBits | (temp_buffer & 0x80)>>6; |
techstep | 0:e4fbbd93299b | 298 | |
techstep | 0:e4fbbd93299b | 299 | temp_buffer = _i2c.read(uint8_t(CLOCK_ADDRESS)); // Get A1M3 and A1 Hour |
techstep | 0:e4fbbd93299b | 300 | // put A1M3 bit in position 2 of DS3231_AlarmBits. |
techstep | 0:e4fbbd93299b | 301 | AlarmBits = AlarmBits | (temp_buffer & 0x80)>>5; |
techstep | 0:e4fbbd93299b | 302 | // determine A1 12/24 mode |
techstep | 0:e4fbbd93299b | 303 | A1h12 = temp_buffer & 0x40; |
techstep | 0:e4fbbd93299b | 304 | if (A1h12) { |
techstep | 0:e4fbbd93299b | 305 | A1PM = temp_buffer & 0x20; // determine am/pm |
techstep | 0:e4fbbd93299b | 306 | A1Hour = bcdToDec(temp_buffer & 0x1F); // 12-hour |
techstep | 0:e4fbbd93299b | 307 | } else { |
techstep | 0:e4fbbd93299b | 308 | A1Hour = bcdToDec(temp_buffer & 0x3F); // 24-hour |
techstep | 0:e4fbbd93299b | 309 | } |
techstep | 0:e4fbbd93299b | 310 | |
techstep | 0:e4fbbd93299b | 311 | temp_buffer = _i2c.read(uint8_t(CLOCK_ADDRESS)); // Get A1M4 and A1 Day/Date |
techstep | 0:e4fbbd93299b | 312 | // put A1M3 bit in position 3 of DS3231_AlarmBits. |
techstep | 0:e4fbbd93299b | 313 | AlarmBits = AlarmBits | (temp_buffer & 0x80)>>4; |
techstep | 0:e4fbbd93299b | 314 | // determine A1 day or date flag |
techstep | 0:e4fbbd93299b | 315 | A1Dy = (temp_buffer & 0x40)>>6; |
techstep | 0:e4fbbd93299b | 316 | if (A1Dy) { |
techstep | 0:e4fbbd93299b | 317 | // alarm is by day of week, not date. |
techstep | 0:e4fbbd93299b | 318 | A1Day = bcdToDec(temp_buffer & 0x0F); |
techstep | 0:e4fbbd93299b | 319 | } else { |
techstep | 0:e4fbbd93299b | 320 | // alarm is by date, not day of week. |
techstep | 0:e4fbbd93299b | 321 | A1Day = bcdToDec(temp_buffer & 0x3F); |
techstep | 0:e4fbbd93299b | 322 | } |
techstep | 0:e4fbbd93299b | 323 | } |
techstep | 0:e4fbbd93299b | 324 | |
techstep | 0:e4fbbd93299b | 325 | void DS3231::getA2Time(uint8_t& A2Day, uint8_t& A2Hour, uint8_t& A2Minute, uint8_t& AlarmBits, bool& A2Dy, bool& A2h12, bool& A2PM) { |
techstep | 0:e4fbbd93299b | 326 | uint8_t temp_buffer; |
techstep | 0:e4fbbd93299b | 327 | //I2C.beginTransmission(CLOCK_ADDRESS); |
techstep | 0:e4fbbd93299b | 328 | //I2C.write(uint8_t(0x0b)); |
techstep | 0:e4fbbd93299b | 329 | //I2C.endTransmission(); |
techstep | 0:e4fbbd93299b | 330 | _i2c.start(); |
techstep | 0:e4fbbd93299b | 331 | _i2c.write(uint8_t(CLOCK_ADDRESS)); |
techstep | 0:e4fbbd93299b | 332 | _i2c.write(uint8_t(0x0b)); |
techstep | 0:e4fbbd93299b | 333 | _i2c.stop(); |
techstep | 0:e4fbbd93299b | 334 | |
techstep | 0:e4fbbd93299b | 335 | //I2C.requestFrom(CLOCK_ADDRESS, 3); |
techstep | 0:e4fbbd93299b | 336 | temp_buffer = _i2c.read(uint8_t(CLOCK_ADDRESS)); // Get A2M2 and A2 Minutes |
techstep | 0:e4fbbd93299b | 337 | A2Minute = bcdToDec(temp_buffer & 0x7F); |
techstep | 0:e4fbbd93299b | 338 | // put A2M2 bit in position 4 of DS3231_AlarmBits. |
techstep | 0:e4fbbd93299b | 339 | AlarmBits = AlarmBits | (temp_buffer & 0x80)>>3; |
techstep | 0:e4fbbd93299b | 340 | |
techstep | 0:e4fbbd93299b | 341 | temp_buffer = _i2c.read(uint8_t(CLOCK_ADDRESS)); // Get A2M3 and A2 Hour |
techstep | 0:e4fbbd93299b | 342 | // put A2M3 bit in position 5 of DS3231_AlarmBits. |
techstep | 0:e4fbbd93299b | 343 | AlarmBits = AlarmBits | (temp_buffer & 0x80)>>2; |
techstep | 0:e4fbbd93299b | 344 | // determine A2 12/24 mode |
techstep | 0:e4fbbd93299b | 345 | A2h12 = temp_buffer & 0x40; |
techstep | 0:e4fbbd93299b | 346 | if (A2h12) { |
techstep | 0:e4fbbd93299b | 347 | A2PM = temp_buffer & 0x20; // determine am/pm |
techstep | 0:e4fbbd93299b | 348 | A2Hour = bcdToDec(temp_buffer & 0x1F); // 12-hour |
techstep | 0:e4fbbd93299b | 349 | } else { |
techstep | 0:e4fbbd93299b | 350 | A2Hour = bcdToDec(temp_buffer & 0x3F); // 24-hour |
techstep | 0:e4fbbd93299b | 351 | } |
techstep | 0:e4fbbd93299b | 352 | |
techstep | 0:e4fbbd93299b | 353 | temp_buffer = _i2c.read(uint8_t(CLOCK_ADDRESS)); // Get A2M4 and A1 Day/Date |
techstep | 0:e4fbbd93299b | 354 | // put A2M4 bit in position 6 of DS3231_AlarmBits. |
techstep | 0:e4fbbd93299b | 355 | AlarmBits = AlarmBits | (temp_buffer & 0x80)>>1; |
techstep | 0:e4fbbd93299b | 356 | // determine A2 day or date flag |
techstep | 0:e4fbbd93299b | 357 | A2Dy = (temp_buffer & 0x40)>>6; |
techstep | 0:e4fbbd93299b | 358 | if (A2Dy) { |
techstep | 0:e4fbbd93299b | 359 | // alarm is by day of week, not date. |
techstep | 0:e4fbbd93299b | 360 | A2Day = bcdToDec(temp_buffer & 0x0F); |
techstep | 0:e4fbbd93299b | 361 | } else { |
techstep | 0:e4fbbd93299b | 362 | // alarm is by date, not day of week. |
techstep | 0:e4fbbd93299b | 363 | A2Day = bcdToDec(temp_buffer & 0x3F); |
techstep | 0:e4fbbd93299b | 364 | } |
techstep | 0:e4fbbd93299b | 365 | } |
techstep | 0:e4fbbd93299b | 366 | |
techstep | 0:e4fbbd93299b | 367 | void DS3231::setA1Time(uint8_t A1Day, uint8_t A1Hour, uint8_t A1Minute, uint8_t A1Second, uint8_t AlarmBits, bool A1Dy, bool A1h12, bool A1PM) { |
techstep | 0:e4fbbd93299b | 368 | // Sets the alarm-1 date and time on the DS3231, using A1* information |
techstep | 0:e4fbbd93299b | 369 | uint8_t temp_buffer; |
techstep | 0:e4fbbd93299b | 370 | //I2C.beginTransmission(CLOCK_ADDRESS); |
techstep | 0:e4fbbd93299b | 371 | //I2C.write(uint8_t(0x07)); // A1 starts at 07h |
techstep | 0:e4fbbd93299b | 372 | _i2c.start(); |
techstep | 0:e4fbbd93299b | 373 | _i2c.write(uint8_t(CLOCK_ADDRESS)); |
techstep | 0:e4fbbd93299b | 374 | _i2c.write(uint8_t(0x07)); |
techstep | 0:e4fbbd93299b | 375 | |
techstep | 0:e4fbbd93299b | 376 | // Send A1 second and A1M1 |
techstep | 0:e4fbbd93299b | 377 | //I2C.write(decToBcd(A1Second) | ((AlarmBits & 0x01) << 7)); |
techstep | 0:e4fbbd93299b | 378 | _i2c.write(decToBcd(A1Second) | ((AlarmBits & 0x01) << 7)); |
techstep | 0:e4fbbd93299b | 379 | |
techstep | 0:e4fbbd93299b | 380 | // Send A1 Minute and A1M2 |
techstep | 0:e4fbbd93299b | 381 | //I2C.write(decToBcd(A1Minute) | ((AlarmBits & 0x02) << 6)); |
techstep | 0:e4fbbd93299b | 382 | _i2c.write(decToBcd(A1Minute) | ((AlarmBits & 0x02) << 6)); |
techstep | 0:e4fbbd93299b | 383 | |
techstep | 0:e4fbbd93299b | 384 | // Figure out A1 hour |
techstep | 0:e4fbbd93299b | 385 | if (A1h12) { |
techstep | 0:e4fbbd93299b | 386 | // Start by converting existing time to h12 if it was given in 24h. |
techstep | 0:e4fbbd93299b | 387 | if (A1Hour > 12) { |
techstep | 0:e4fbbd93299b | 388 | // well, then, this obviously isn't a h12 time, is it? |
techstep | 0:e4fbbd93299b | 389 | A1Hour = A1Hour - 12; |
techstep | 0:e4fbbd93299b | 390 | A1PM = true; |
techstep | 0:e4fbbd93299b | 391 | } |
techstep | 0:e4fbbd93299b | 392 | if (A1PM) { |
techstep | 0:e4fbbd93299b | 393 | // Afternoon |
techstep | 0:e4fbbd93299b | 394 | // Convert the hour to BCD and add appropriate flags. |
techstep | 0:e4fbbd93299b | 395 | temp_buffer = decToBcd(A1Hour) | 0x60; |
techstep | 0:e4fbbd93299b | 396 | } else { |
techstep | 0:e4fbbd93299b | 397 | // Morning |
techstep | 0:e4fbbd93299b | 398 | // Convert the hour to BCD and add appropriate flags. |
techstep | 0:e4fbbd93299b | 399 | temp_buffer = decToBcd(A1Hour) | 0x40; |
techstep | 0:e4fbbd93299b | 400 | } |
techstep | 0:e4fbbd93299b | 401 | } else { |
techstep | 0:e4fbbd93299b | 402 | // Now for 24h |
techstep | 0:e4fbbd93299b | 403 | temp_buffer = decToBcd(A1Hour); |
techstep | 0:e4fbbd93299b | 404 | } |
techstep | 0:e4fbbd93299b | 405 | temp_buffer = temp_buffer | ((AlarmBits & 0x04)<<5); |
techstep | 0:e4fbbd93299b | 406 | // A1 hour is figured out, send it |
techstep | 0:e4fbbd93299b | 407 | //I2C.write(temp_buffer); |
techstep | 0:e4fbbd93299b | 408 | _i2c.write(temp_buffer); |
techstep | 0:e4fbbd93299b | 409 | |
techstep | 0:e4fbbd93299b | 410 | // Figure out A1 day/date and A1M4 |
techstep | 0:e4fbbd93299b | 411 | temp_buffer = ((AlarmBits & 0x08)<<4) | decToBcd(A1Day); |
techstep | 0:e4fbbd93299b | 412 | if (A1Dy) { |
techstep | 0:e4fbbd93299b | 413 | // Set A1 Day/Date flag (Otherwise it's zero) |
techstep | 0:e4fbbd93299b | 414 | temp_buffer = temp_buffer | 0x40; |
techstep | 0:e4fbbd93299b | 415 | } |
techstep | 0:e4fbbd93299b | 416 | //I2C.write(temp_buffer); |
techstep | 0:e4fbbd93299b | 417 | _i2c.write(temp_buffer); |
techstep | 0:e4fbbd93299b | 418 | |
techstep | 0:e4fbbd93299b | 419 | // All done! |
techstep | 0:e4fbbd93299b | 420 | //I2C.endTransmission(); |
techstep | 0:e4fbbd93299b | 421 | _i2c.stop(); |
techstep | 0:e4fbbd93299b | 422 | } |
techstep | 0:e4fbbd93299b | 423 | |
techstep | 0:e4fbbd93299b | 424 | void DS3231::setA2Time(uint8_t A2Day, uint8_t A2Hour, uint8_t A2Minute, uint8_t AlarmBits, bool A2Dy, bool A2h12, bool A2PM) { |
techstep | 0:e4fbbd93299b | 425 | // Sets the alarm-2 date and time on the DS3231, using A2* information |
techstep | 0:e4fbbd93299b | 426 | uint8_t temp_buffer; |
techstep | 0:e4fbbd93299b | 427 | //I2C.beginTransmission(CLOCK_ADDRESS); |
techstep | 0:e4fbbd93299b | 428 | //I2C.write(uint8_t(0x0b)); // A1 starts at 0bh |
techstep | 0:e4fbbd93299b | 429 | _i2c.start(); |
techstep | 0:e4fbbd93299b | 430 | _i2c.write(uint8_t(CLOCK_ADDRESS)); |
techstep | 0:e4fbbd93299b | 431 | _i2c.write(uint8_t(0x0b)); |
techstep | 0:e4fbbd93299b | 432 | |
techstep | 0:e4fbbd93299b | 433 | // Send A2 Minute and A2M2 |
techstep | 0:e4fbbd93299b | 434 | //I2C.write(decToBcd(A2Minute) | ((AlarmBits & 0x10) << 3)); |
techstep | 0:e4fbbd93299b | 435 | _i2c.write(decToBcd(A2Minute) | ((AlarmBits & 0x10) << 3)); |
techstep | 0:e4fbbd93299b | 436 | |
techstep | 0:e4fbbd93299b | 437 | // Figure out A2 hour |
techstep | 0:e4fbbd93299b | 438 | if (A2h12) { |
techstep | 0:e4fbbd93299b | 439 | // Start by converting existing time to h12 if it was given in 24h. |
techstep | 0:e4fbbd93299b | 440 | if (A2Hour > 12) { |
techstep | 0:e4fbbd93299b | 441 | // well, then, this obviously isn't a h12 time, is it? |
techstep | 0:e4fbbd93299b | 442 | A2Hour = A2Hour - 12; |
techstep | 0:e4fbbd93299b | 443 | A2PM = true; |
techstep | 0:e4fbbd93299b | 444 | } |
techstep | 0:e4fbbd93299b | 445 | if (A2PM) { |
techstep | 0:e4fbbd93299b | 446 | // Afternoon |
techstep | 0:e4fbbd93299b | 447 | // Convert the hour to BCD and add appropriate flags. |
techstep | 0:e4fbbd93299b | 448 | temp_buffer = decToBcd(A2Hour) | 0x60; |
techstep | 0:e4fbbd93299b | 449 | } else { |
techstep | 0:e4fbbd93299b | 450 | // Morning |
techstep | 0:e4fbbd93299b | 451 | // Convert the hour to BCD and add appropriate flags. |
techstep | 0:e4fbbd93299b | 452 | temp_buffer = decToBcd(A2Hour) | 0x40; |
techstep | 0:e4fbbd93299b | 453 | } |
techstep | 0:e4fbbd93299b | 454 | } else { |
techstep | 0:e4fbbd93299b | 455 | // Now for 24h |
techstep | 0:e4fbbd93299b | 456 | temp_buffer = decToBcd(A2Hour); |
techstep | 0:e4fbbd93299b | 457 | } |
techstep | 0:e4fbbd93299b | 458 | // add in A2M3 bit |
techstep | 0:e4fbbd93299b | 459 | temp_buffer = temp_buffer | ((AlarmBits & 0x20)<<2); |
techstep | 0:e4fbbd93299b | 460 | // A2 hour is figured out, send it |
techstep | 0:e4fbbd93299b | 461 | //I2C.write(temp_buffer); |
techstep | 0:e4fbbd93299b | 462 | _i2c.write(temp_buffer); |
techstep | 0:e4fbbd93299b | 463 | |
techstep | 0:e4fbbd93299b | 464 | // Figure out A2 day/date and A2M4 |
techstep | 0:e4fbbd93299b | 465 | temp_buffer = ((AlarmBits & 0x40)<<1) | decToBcd(A2Day); |
techstep | 0:e4fbbd93299b | 466 | if (A2Dy) { |
techstep | 0:e4fbbd93299b | 467 | // Set A2 Day/Date flag (Otherwise it's zero) |
techstep | 0:e4fbbd93299b | 468 | temp_buffer = temp_buffer | 0x40; |
techstep | 0:e4fbbd93299b | 469 | } |
techstep | 0:e4fbbd93299b | 470 | //I2C.write(temp_buffer); |
techstep | 0:e4fbbd93299b | 471 | _i2c.write(temp_buffer); |
techstep | 0:e4fbbd93299b | 472 | |
techstep | 0:e4fbbd93299b | 473 | // All done! |
techstep | 0:e4fbbd93299b | 474 | //I2C.endTransmission(); |
techstep | 0:e4fbbd93299b | 475 | _i2c.stop(); |
techstep | 0:e4fbbd93299b | 476 | } |
techstep | 0:e4fbbd93299b | 477 | |
techstep | 0:e4fbbd93299b | 478 | void DS3231::turnOnAlarm(uint8_t Alarm) { |
techstep | 0:e4fbbd93299b | 479 | // turns on alarm number "Alarm". Defaults to 2 if Alarm is not 1. |
techstep | 0:e4fbbd93299b | 480 | uint8_t temp_buffer = readControlByte(0); |
techstep | 0:e4fbbd93299b | 481 | // modify control byte |
techstep | 0:e4fbbd93299b | 482 | if (Alarm == 1) { |
techstep | 0:e4fbbd93299b | 483 | temp_buffer = temp_buffer | 0x05; |
techstep | 0:e4fbbd93299b | 484 | } else { |
techstep | 0:e4fbbd93299b | 485 | temp_buffer = temp_buffer | 0x06; |
techstep | 0:e4fbbd93299b | 486 | } |
techstep | 0:e4fbbd93299b | 487 | writeControlByte(temp_buffer, 0); |
techstep | 0:e4fbbd93299b | 488 | } |
techstep | 0:e4fbbd93299b | 489 | |
techstep | 0:e4fbbd93299b | 490 | void DS3231::turnOffAlarm(uint8_t Alarm) { |
techstep | 0:e4fbbd93299b | 491 | // turns off alarm number "Alarm". Defaults to 2 if Alarm is not 1. |
techstep | 0:e4fbbd93299b | 492 | // Leaves interrupt pin alone. |
techstep | 0:e4fbbd93299b | 493 | uint8_t temp_buffer = readControlByte(0); |
techstep | 0:e4fbbd93299b | 494 | // modify control byte |
techstep | 0:e4fbbd93299b | 495 | if (Alarm == 1) { |
techstep | 0:e4fbbd93299b | 496 | temp_buffer = temp_buffer & 0xFE; |
techstep | 0:e4fbbd93299b | 497 | } else { |
techstep | 0:e4fbbd93299b | 498 | temp_buffer = temp_buffer & 0xFD; |
techstep | 0:e4fbbd93299b | 499 | } |
techstep | 0:e4fbbd93299b | 500 | writeControlByte(temp_buffer, 0); |
techstep | 0:e4fbbd93299b | 501 | } |
techstep | 0:e4fbbd93299b | 502 | |
techstep | 0:e4fbbd93299b | 503 | bool DS3231::checkAlarmEnabled(uint8_t Alarm) { |
techstep | 0:e4fbbd93299b | 504 | // Checks whether the given alarm is enabled. |
techstep | 0:e4fbbd93299b | 505 | uint8_t result = 0x0; |
techstep | 0:e4fbbd93299b | 506 | uint8_t temp_buffer = readControlByte(0); |
techstep | 0:e4fbbd93299b | 507 | if (Alarm == 1) { |
techstep | 0:e4fbbd93299b | 508 | result = temp_buffer & 0x01; |
techstep | 0:e4fbbd93299b | 509 | } else { |
techstep | 0:e4fbbd93299b | 510 | result = temp_buffer & 0x02; |
techstep | 0:e4fbbd93299b | 511 | } |
techstep | 0:e4fbbd93299b | 512 | return result; |
techstep | 0:e4fbbd93299b | 513 | } |
techstep | 0:e4fbbd93299b | 514 | |
techstep | 0:e4fbbd93299b | 515 | bool DS3231::checkIfAlarm(uint8_t Alarm) { |
techstep | 0:e4fbbd93299b | 516 | // Checks whether alarm 1 or alarm 2 flag is on, returns T/F accordingly. |
techstep | 0:e4fbbd93299b | 517 | // Turns flag off, also. |
techstep | 0:e4fbbd93299b | 518 | // defaults to checking alarm 2, unless Alarm == 1. |
techstep | 0:e4fbbd93299b | 519 | uint8_t result; |
techstep | 0:e4fbbd93299b | 520 | uint8_t temp_buffer = readControlByte(1); |
techstep | 0:e4fbbd93299b | 521 | if (Alarm == 1) { |
techstep | 0:e4fbbd93299b | 522 | // Did alarm 1 go off? |
techstep | 0:e4fbbd93299b | 523 | result = temp_buffer & 0x01; |
techstep | 0:e4fbbd93299b | 524 | // clear flag |
techstep | 0:e4fbbd93299b | 525 | temp_buffer = temp_buffer & 0xFE; |
techstep | 0:e4fbbd93299b | 526 | } else { |
techstep | 0:e4fbbd93299b | 527 | // Did alarm 2 go off? |
techstep | 0:e4fbbd93299b | 528 | result = temp_buffer & 0x02; |
techstep | 0:e4fbbd93299b | 529 | // clear flag |
techstep | 0:e4fbbd93299b | 530 | temp_buffer = temp_buffer & 0xFD; |
techstep | 0:e4fbbd93299b | 531 | } |
techstep | 0:e4fbbd93299b | 532 | writeControlByte(temp_buffer, 1); |
techstep | 0:e4fbbd93299b | 533 | return result; |
techstep | 0:e4fbbd93299b | 534 | } |
techstep | 0:e4fbbd93299b | 535 | |
techstep | 0:e4fbbd93299b | 536 | void DS3231::enableOscillator(bool TF, bool battery, uint8_t frequency) { |
techstep | 0:e4fbbd93299b | 537 | // turns oscillator on or off. True is on, false is off. |
techstep | 0:e4fbbd93299b | 538 | // if battery is true, turns on even for battery-only operation, |
techstep | 0:e4fbbd93299b | 539 | // otherwise turns off if Vcc is off. |
techstep | 0:e4fbbd93299b | 540 | // frequency must be 0, 1, 2, or 3. |
techstep | 0:e4fbbd93299b | 541 | // 0 = 1 Hz |
techstep | 0:e4fbbd93299b | 542 | // 1 = 1.024 kHz |
techstep | 0:e4fbbd93299b | 543 | // 2 = 4.096 kHz |
techstep | 0:e4fbbd93299b | 544 | // 3 = 8.192 kHz (Default if frequency byte is out of range) |
techstep | 0:e4fbbd93299b | 545 | if (frequency > 3) frequency = 3; |
techstep | 0:e4fbbd93299b | 546 | // read control byte in, but zero out current state of RS2 and RS1. |
techstep | 0:e4fbbd93299b | 547 | uint8_t temp_buffer = readControlByte(0) & 0xE7; |
techstep | 0:e4fbbd93299b | 548 | if (battery) { |
techstep | 0:e4fbbd93299b | 549 | // turn on BBSQW flag |
techstep | 0:e4fbbd93299b | 550 | temp_buffer = temp_buffer | 0x40; |
techstep | 0:e4fbbd93299b | 551 | } else { |
techstep | 0:e4fbbd93299b | 552 | // turn off BBSQW flag |
techstep | 0:e4fbbd93299b | 553 | temp_buffer = temp_buffer & 0xBF; |
techstep | 0:e4fbbd93299b | 554 | } |
techstep | 0:e4fbbd93299b | 555 | if (TF) { |
techstep | 0:e4fbbd93299b | 556 | // set ~EOSC to 0 and INTCN to zero. |
techstep | 0:e4fbbd93299b | 557 | temp_buffer = temp_buffer & 0x7B; |
techstep | 0:e4fbbd93299b | 558 | } else { |
techstep | 0:e4fbbd93299b | 559 | // set ~EOSC to 1, leave INTCN as is. |
techstep | 0:e4fbbd93299b | 560 | temp_buffer = temp_buffer | 0x80; |
techstep | 0:e4fbbd93299b | 561 | } |
techstep | 0:e4fbbd93299b | 562 | // shift frequency into bits 3 and 4 and set. |
techstep | 0:e4fbbd93299b | 563 | frequency = frequency << 3; |
techstep | 0:e4fbbd93299b | 564 | temp_buffer = temp_buffer | frequency; |
techstep | 0:e4fbbd93299b | 565 | // And write the control bits |
techstep | 0:e4fbbd93299b | 566 | writeControlByte(temp_buffer, 0); |
techstep | 0:e4fbbd93299b | 567 | } |
techstep | 0:e4fbbd93299b | 568 | |
techstep | 0:e4fbbd93299b | 569 | void DS3231::enable32kHz(bool TF) { |
techstep | 0:e4fbbd93299b | 570 | // turn 32kHz pin on or off |
techstep | 0:e4fbbd93299b | 571 | uint8_t temp_buffer = readControlByte(1); |
techstep | 0:e4fbbd93299b | 572 | if (TF) { |
techstep | 0:e4fbbd93299b | 573 | // turn on 32kHz pin |
techstep | 0:e4fbbd93299b | 574 | temp_buffer = temp_buffer | 0x08; |
techstep | 0:e4fbbd93299b | 575 | } else { |
techstep | 0:e4fbbd93299b | 576 | // turn off 32kHz pin |
techstep | 0:e4fbbd93299b | 577 | temp_buffer = temp_buffer & 0xF7; |
techstep | 0:e4fbbd93299b | 578 | } |
techstep | 0:e4fbbd93299b | 579 | writeControlByte(temp_buffer, 1); |
techstep | 0:e4fbbd93299b | 580 | } |
techstep | 0:e4fbbd93299b | 581 | |
techstep | 0:e4fbbd93299b | 582 | bool DS3231::oscillatorCheck() { |
techstep | 0:e4fbbd93299b | 583 | // Returns false if the oscillator has been off for some reason. |
techstep | 0:e4fbbd93299b | 584 | // If this is the case, the time is probably not correct. |
techstep | 0:e4fbbd93299b | 585 | uint8_t temp_buffer = readControlByte(1); |
techstep | 0:e4fbbd93299b | 586 | bool result = true; |
techstep | 0:e4fbbd93299b | 587 | if (temp_buffer & 0x80) { |
techstep | 0:e4fbbd93299b | 588 | // Oscillator Stop Flag (OSF) is set, so return false. |
techstep | 0:e4fbbd93299b | 589 | result = false; |
techstep | 0:e4fbbd93299b | 590 | } |
techstep | 0:e4fbbd93299b | 591 | return result; |
techstep | 0:e4fbbd93299b | 592 | } |
techstep | 0:e4fbbd93299b | 593 | |
techstep | 0:e4fbbd93299b | 594 | /***************************************** |
techstep | 0:e4fbbd93299b | 595 | Private Functions |
techstep | 0:e4fbbd93299b | 596 | *****************************************/ |
techstep | 0:e4fbbd93299b | 597 | uint8_t DS3231::decToBcd(uint8_t val) { |
techstep | 0:e4fbbd93299b | 598 | // Convert normal decimal numbers to binary coded decimal |
techstep | 0:e4fbbd93299b | 599 | return ( (val/10*16) + (val%10) ); |
techstep | 0:e4fbbd93299b | 600 | } |
techstep | 0:e4fbbd93299b | 601 | |
techstep | 0:e4fbbd93299b | 602 | uint8_t DS3231::bcdToDec(uint8_t val) { |
techstep | 0:e4fbbd93299b | 603 | // Convert binary coded decimal to normal decimal numbers |
techstep | 0:e4fbbd93299b | 604 | return ( (val/16*10) + (val%16) ); |
techstep | 0:e4fbbd93299b | 605 | } |
techstep | 0:e4fbbd93299b | 606 | |
techstep | 0:e4fbbd93299b | 607 | uint8_t DS3231::readControlByte(bool which) { |
techstep | 0:e4fbbd93299b | 608 | // Read selected control byte |
techstep | 0:e4fbbd93299b | 609 | // first byte (0) is 0x0e, second (1) is 0x0f |
techstep | 0:e4fbbd93299b | 610 | //I2C.beginTransmission(CLOCK_ADDRESS); |
techstep | 0:e4fbbd93299b | 611 | _i2c.start(); |
techstep | 0:e4fbbd93299b | 612 | _i2c.write(uint8_t(CLOCK_ADDRESS)); |
techstep | 0:e4fbbd93299b | 613 | |
techstep | 0:e4fbbd93299b | 614 | if (which) { |
techstep | 0:e4fbbd93299b | 615 | // second control byte |
techstep | 0:e4fbbd93299b | 616 | //I2C.write(uint8_t(0x0f)); |
techstep | 0:e4fbbd93299b | 617 | _i2c.write(uint8_t(0x0f)); |
techstep | 0:e4fbbd93299b | 618 | |
techstep | 0:e4fbbd93299b | 619 | } else { |
techstep | 0:e4fbbd93299b | 620 | // first control byte |
techstep | 0:e4fbbd93299b | 621 | //I2C.write(uint8_t(0x0e)); |
techstep | 0:e4fbbd93299b | 622 | _i2c.write(uint8_t(0x0e)); |
techstep | 0:e4fbbd93299b | 623 | |
techstep | 0:e4fbbd93299b | 624 | } |
techstep | 0:e4fbbd93299b | 625 | //I2C.endTransmission(); |
techstep | 0:e4fbbd93299b | 626 | _i2c.stop(); |
techstep | 0:e4fbbd93299b | 627 | |
techstep | 0:e4fbbd93299b | 628 | //I2C.requestFrom(CLOCK_ADDRESS, 1); |
techstep | 0:e4fbbd93299b | 629 | return _i2c.read(uint8_t(CLOCK_ADDRESS)); |
techstep | 0:e4fbbd93299b | 630 | } |
techstep | 0:e4fbbd93299b | 631 | |
techstep | 0:e4fbbd93299b | 632 | void DS3231::writeControlByte(uint8_t control, bool which) { |
techstep | 0:e4fbbd93299b | 633 | // Write the selected control byte. |
techstep | 0:e4fbbd93299b | 634 | // which=false -> 0x0e, true->0x0f. |
techstep | 0:e4fbbd93299b | 635 | //I2C.beginTransmission(CLOCK_ADDRESS); |
techstep | 0:e4fbbd93299b | 636 | _i2c.start(); |
techstep | 0:e4fbbd93299b | 637 | _i2c.write(uint8_t(CLOCK_ADDRESS)); |
techstep | 0:e4fbbd93299b | 638 | |
techstep | 0:e4fbbd93299b | 639 | if (which) { |
techstep | 0:e4fbbd93299b | 640 | //I2C.write(uint8_t(0x0f)); |
techstep | 0:e4fbbd93299b | 641 | _i2c.write(uint8_t(0x0f)); |
techstep | 0:e4fbbd93299b | 642 | |
techstep | 0:e4fbbd93299b | 643 | } else { |
techstep | 0:e4fbbd93299b | 644 | //I2C.write(uint8_t(0x0e)); |
techstep | 0:e4fbbd93299b | 645 | _i2c.write(uint8_t(0x0e)); |
techstep | 0:e4fbbd93299b | 646 | |
techstep | 0:e4fbbd93299b | 647 | } |
techstep | 0:e4fbbd93299b | 648 | //I2C.write(control); |
techstep | 0:e4fbbd93299b | 649 | //I2C.endTransmission(); |
techstep | 0:e4fbbd93299b | 650 | _i2c.write(control); |
techstep | 0:e4fbbd93299b | 651 | _i2c.stop(); |
techstep | 0:e4fbbd93299b | 652 | } |
techstep | 0:e4fbbd93299b | 653 |