DS3231 External RTC I2C
Fork of DS3231 by
DS3231.cpp@3:f599542b06ad, 2015-11-05 (annotated)
- Committer:
- vart
- Date:
- Thu Nov 05 16:44:45 2015 +0000
- Revision:
- 3:f599542b06ad
- Parent:
- 2:fc6317727d1d
- Child:
- 5:6fab75b89838
added status() function
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 | 1:1607610a4ee9 | 30 | #define SINCE 1900 |
techstep | 0:e4fbbd93299b | 31 | |
techstep | 0:e4fbbd93299b | 32 | // Constructor |
techstep | 0:e4fbbd93299b | 33 | DS3231::DS3231(PinName sda_pin, PinName scl_pin) : _i2c(sda_pin, scl_pin) { |
techstep | 0:e4fbbd93299b | 34 | _i2c.frequency(100000); |
techstep | 0:e4fbbd93299b | 35 | } |
techstep | 0:e4fbbd93299b | 36 | /***************************************** |
techstep | 0:e4fbbd93299b | 37 | Public Functions |
techstep | 0:e4fbbd93299b | 38 | *****************************************/ |
techstep | 0:e4fbbd93299b | 39 | |
techstep | 0:e4fbbd93299b | 40 | 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 | 41 | uint8_t tempBuffer; |
techstep | 0:e4fbbd93299b | 42 | bool PM; |
techstep | 0:e4fbbd93299b | 43 | bool h12; |
techstep | 0:e4fbbd93299b | 44 | |
techstep | 1:1607610a4ee9 | 45 | char data[7]; |
techstep | 1:1607610a4ee9 | 46 | char cmd; |
techstep | 1:1607610a4ee9 | 47 | cmd = 0x00; |
techstep | 1:1607610a4ee9 | 48 | _i2c.write(ADDR, &cmd, 1 ); |
techstep | 1:1607610a4ee9 | 49 | _i2c.read( ADDR, data, 7 ); |
techstep | 0:e4fbbd93299b | 50 | |
techstep | 1:1607610a4ee9 | 51 | second = bcdToDec(data[0]); |
techstep | 1:1607610a4ee9 | 52 | minute = bcdToDec(data[1]); |
techstep | 1:1607610a4ee9 | 53 | tempBuffer = bcdToDec(data[2]); |
techstep | 0:e4fbbd93299b | 54 | |
techstep | 0:e4fbbd93299b | 55 | h12 = tempBuffer & 0x40; |
techstep | 0:e4fbbd93299b | 56 | if (h12) { |
techstep | 0:e4fbbd93299b | 57 | PM = tempBuffer & 0x20; |
techstep | 0:e4fbbd93299b | 58 | hour = bcdToDec(tempBuffer & 0x1F); |
techstep | 0:e4fbbd93299b | 59 | } else { |
techstep | 0:e4fbbd93299b | 60 | hour = bcdToDec(tempBuffer & 0x3F); |
techstep | 0:e4fbbd93299b | 61 | } |
techstep | 1:1607610a4ee9 | 62 | DoW = bcdToDec(data[3]); |
techstep | 1:1607610a4ee9 | 63 | date = bcdToDec(data[4]); |
techstep | 1:1607610a4ee9 | 64 | month = bcdToDec(data[5] & 0x7F); |
techstep | 1:1607610a4ee9 | 65 | year = bcdToDec(data[6]); |
techstep | 0:e4fbbd93299b | 66 | } |
techstep | 0:e4fbbd93299b | 67 | |
techstep | 0:e4fbbd93299b | 68 | int8_t DS3231::getSecond(void) { |
techstep | 0:e4fbbd93299b | 69 | char data; |
techstep | 0:e4fbbd93299b | 70 | char cmd; |
techstep | 0:e4fbbd93299b | 71 | cmd = 0x00; |
techstep | 0:e4fbbd93299b | 72 | _i2c.write(ADDR, &cmd, 1 ); |
techstep | 0:e4fbbd93299b | 73 | _i2c.read( ADDR, &data, 1 ); |
techstep | 0:e4fbbd93299b | 74 | return(bcdToDec(data)); |
techstep | 0:e4fbbd93299b | 75 | } |
techstep | 0:e4fbbd93299b | 76 | |
techstep | 0:e4fbbd93299b | 77 | uint8_t DS3231::getMinute(void) { |
techstep | 0:e4fbbd93299b | 78 | char data; |
techstep | 0:e4fbbd93299b | 79 | char cmd; |
techstep | 0:e4fbbd93299b | 80 | cmd = 0x01; |
techstep | 0:e4fbbd93299b | 81 | _i2c.write(ADDR, &cmd, 1 ); |
techstep | 0:e4fbbd93299b | 82 | _i2c.read( ADDR, &data, 1 ); |
techstep | 0:e4fbbd93299b | 83 | return(bcdToDec(data)); |
techstep | 0:e4fbbd93299b | 84 | } |
techstep | 0:e4fbbd93299b | 85 | |
techstep | 0:e4fbbd93299b | 86 | uint8_t DS3231::getHour(bool& h12, bool& PM) { |
techstep | 0:e4fbbd93299b | 87 | char temp_buffer; |
techstep | 0:e4fbbd93299b | 88 | char hour; |
techstep | 0:e4fbbd93299b | 89 | char cmd; |
techstep | 0:e4fbbd93299b | 90 | cmd = 0x02; |
techstep | 0:e4fbbd93299b | 91 | _i2c.write(ADDR, &cmd, 1 ); |
techstep | 0:e4fbbd93299b | 92 | _i2c.read( ADDR, &temp_buffer, 1 ); |
techstep | 0:e4fbbd93299b | 93 | |
techstep | 0:e4fbbd93299b | 94 | h12 = temp_buffer & 0x40; |
techstep | 0:e4fbbd93299b | 95 | if (h12) { |
techstep | 0:e4fbbd93299b | 96 | PM = temp_buffer & 0x20; |
techstep | 0:e4fbbd93299b | 97 | hour = bcdToDec(temp_buffer & 0x1F); |
techstep | 0:e4fbbd93299b | 98 | } else { |
techstep | 0:e4fbbd93299b | 99 | hour = bcdToDec(temp_buffer & 0x3F); |
techstep | 0:e4fbbd93299b | 100 | } |
techstep | 0:e4fbbd93299b | 101 | return hour; |
techstep | 0:e4fbbd93299b | 102 | } |
techstep | 0:e4fbbd93299b | 103 | |
techstep | 0:e4fbbd93299b | 104 | uint8_t DS3231::getDoW(void) { |
techstep | 0:e4fbbd93299b | 105 | char data; |
techstep | 0:e4fbbd93299b | 106 | char cmd; |
techstep | 0:e4fbbd93299b | 107 | cmd = 0x03; |
techstep | 0:e4fbbd93299b | 108 | _i2c.write(ADDR, &cmd, 1 ); |
techstep | 0:e4fbbd93299b | 109 | _i2c.read( ADDR, &data, 1 ); |
techstep | 0:e4fbbd93299b | 110 | return(bcdToDec(data)); |
techstep | 0:e4fbbd93299b | 111 | } |
techstep | 0:e4fbbd93299b | 112 | |
techstep | 0:e4fbbd93299b | 113 | uint8_t DS3231::getDate(void) { |
techstep | 0:e4fbbd93299b | 114 | char data; |
techstep | 0:e4fbbd93299b | 115 | char cmd; |
techstep | 0:e4fbbd93299b | 116 | cmd = 0x04; |
techstep | 0:e4fbbd93299b | 117 | _i2c.write(ADDR, &cmd, 1 ); |
techstep | 0:e4fbbd93299b | 118 | _i2c.read( ADDR, &data, 1 ); |
techstep | 0:e4fbbd93299b | 119 | return(bcdToDec(data)); |
techstep | 0:e4fbbd93299b | 120 | } |
techstep | 0:e4fbbd93299b | 121 | |
techstep | 0:e4fbbd93299b | 122 | uint8_t DS3231::getMonth(bool& Century) { |
techstep | 0:e4fbbd93299b | 123 | char temp_buffer; |
techstep | 0:e4fbbd93299b | 124 | char cmd; |
techstep | 0:e4fbbd93299b | 125 | cmd = 0x05; |
techstep | 0:e4fbbd93299b | 126 | _i2c.write(ADDR, &cmd, 1 ); |
techstep | 0:e4fbbd93299b | 127 | _i2c.read( ADDR, &temp_buffer, 1 ); |
techstep | 0:e4fbbd93299b | 128 | |
techstep | 0:e4fbbd93299b | 129 | Century = temp_buffer & 0x80; |
techstep | 0:e4fbbd93299b | 130 | return (bcdToDec(temp_buffer & 0x7F)) ; |
techstep | 0:e4fbbd93299b | 131 | } |
techstep | 0:e4fbbd93299b | 132 | |
techstep | 0:e4fbbd93299b | 133 | uint8_t DS3231::getYear(void) { |
techstep | 0:e4fbbd93299b | 134 | char data; |
techstep | 0:e4fbbd93299b | 135 | char cmd; |
techstep | 0:e4fbbd93299b | 136 | cmd = 0x06; |
techstep | 0:e4fbbd93299b | 137 | _i2c.write(ADDR, &cmd, 1 ); |
techstep | 0:e4fbbd93299b | 138 | _i2c.read( ADDR, &data, 1 ); |
techstep | 0:e4fbbd93299b | 139 | return(bcdToDec(data)); |
techstep | 0:e4fbbd93299b | 140 | } |
techstep | 0:e4fbbd93299b | 141 | |
techstep | 0:e4fbbd93299b | 142 | void DS3231::setSecond(uint8_t Second) { |
techstep | 0:e4fbbd93299b | 143 | // Sets the seconds |
techstep | 0:e4fbbd93299b | 144 | // This function also resets the Oscillator Stop Flag, which is set |
techstep | 0:e4fbbd93299b | 145 | // whenever power is interrupted. |
techstep | 0:e4fbbd93299b | 146 | char cmd[2]; |
techstep | 0:e4fbbd93299b | 147 | cmd[0] = 0x00; |
techstep | 0:e4fbbd93299b | 148 | cmd[1] = decToBcd(Second); |
techstep | 0:e4fbbd93299b | 149 | _i2c.write(ADDR, cmd, 2); |
techstep | 0:e4fbbd93299b | 150 | |
techstep | 0:e4fbbd93299b | 151 | // Clear OSF flag |
techstep | 0:e4fbbd93299b | 152 | uint8_t temp_buffer = readControlByte(1); |
techstep | 0:e4fbbd93299b | 153 | writeControlByte((temp_buffer & 0x7F), 1); |
techstep | 0:e4fbbd93299b | 154 | } |
techstep | 0:e4fbbd93299b | 155 | |
techstep | 0:e4fbbd93299b | 156 | void DS3231::setMinute(uint8_t Minute) { |
techstep | 0:e4fbbd93299b | 157 | // Sets the minutes |
techstep | 0:e4fbbd93299b | 158 | char cmd[2]; |
techstep | 0:e4fbbd93299b | 159 | cmd[0] = 0x01; |
techstep | 0:e4fbbd93299b | 160 | cmd[1] = decToBcd(Minute); |
techstep | 0:e4fbbd93299b | 161 | _i2c.write(ADDR, cmd, 2); |
techstep | 0:e4fbbd93299b | 162 | } |
techstep | 0:e4fbbd93299b | 163 | |
techstep | 0:e4fbbd93299b | 164 | void DS3231::setHour(uint8_t Hour) { |
techstep | 0:e4fbbd93299b | 165 | // Sets the hour, without changing 12/24h mode. |
techstep | 0:e4fbbd93299b | 166 | // The hour must be in 24h format. |
techstep | 0:e4fbbd93299b | 167 | |
techstep | 0:e4fbbd93299b | 168 | bool h12; |
techstep | 0:e4fbbd93299b | 169 | |
techstep | 0:e4fbbd93299b | 170 | // Start by figuring out what the 12/24 mode is |
techstep | 0:e4fbbd93299b | 171 | char data; |
techstep | 0:e4fbbd93299b | 172 | char cmd; |
techstep | 0:e4fbbd93299b | 173 | cmd = 0x02; |
techstep | 0:e4fbbd93299b | 174 | _i2c.write(ADDR, &cmd, 1 ); |
techstep | 0:e4fbbd93299b | 175 | _i2c.read( ADDR, &data, 1 ); |
techstep | 0:e4fbbd93299b | 176 | |
techstep | 0:e4fbbd93299b | 177 | h12 = (data & 0x40); |
techstep | 0:e4fbbd93299b | 178 | // if h12 is true, it's 12h mode; false is 24h. |
techstep | 0:e4fbbd93299b | 179 | |
techstep | 0:e4fbbd93299b | 180 | if (h12) { |
techstep | 0:e4fbbd93299b | 181 | // 12 hour |
techstep | 0:e4fbbd93299b | 182 | if (Hour > 12) { |
techstep | 0:e4fbbd93299b | 183 | Hour = decToBcd(Hour-12) | 0x60; |
techstep | 0:e4fbbd93299b | 184 | } else { |
techstep | 0:e4fbbd93299b | 185 | Hour = decToBcd(Hour) & 0xDF; |
techstep | 0:e4fbbd93299b | 186 | } |
techstep | 0:e4fbbd93299b | 187 | } else { |
techstep | 0:e4fbbd93299b | 188 | // 24 hour |
techstep | 0:e4fbbd93299b | 189 | Hour = decToBcd(Hour) & 0xBF; |
techstep | 0:e4fbbd93299b | 190 | } |
techstep | 0:e4fbbd93299b | 191 | char cmdHour[2]; |
techstep | 0:e4fbbd93299b | 192 | cmdHour[0] = 0x02; |
techstep | 0:e4fbbd93299b | 193 | cmdHour[1] = Hour; |
techstep | 0:e4fbbd93299b | 194 | _i2c.write(ADDR, cmdHour, 2); |
techstep | 0:e4fbbd93299b | 195 | } |
techstep | 0:e4fbbd93299b | 196 | |
techstep | 0:e4fbbd93299b | 197 | void DS3231::setDoW(uint8_t DoW) { |
techstep | 0:e4fbbd93299b | 198 | // Sets the Day of Week |
techstep | 0:e4fbbd93299b | 199 | char cmd[2]; |
techstep | 0:e4fbbd93299b | 200 | cmd[0] = 0x03; |
techstep | 0:e4fbbd93299b | 201 | cmd[1] = decToBcd(DoW); |
techstep | 0:e4fbbd93299b | 202 | _i2c.write(ADDR, cmd, 2 ); |
techstep | 0:e4fbbd93299b | 203 | } |
techstep | 0:e4fbbd93299b | 204 | |
techstep | 0:e4fbbd93299b | 205 | void DS3231::setDate(uint8_t Date) { |
techstep | 0:e4fbbd93299b | 206 | // Sets the Date |
techstep | 0:e4fbbd93299b | 207 | char cmd[2]; |
techstep | 0:e4fbbd93299b | 208 | cmd[0] = 0x04; |
techstep | 0:e4fbbd93299b | 209 | cmd[1] = decToBcd(Date); |
techstep | 0:e4fbbd93299b | 210 | _i2c.write(ADDR, cmd, 2 ); |
techstep | 0:e4fbbd93299b | 211 | } |
techstep | 0:e4fbbd93299b | 212 | |
techstep | 0:e4fbbd93299b | 213 | void DS3231::setMonth(uint8_t Month) { |
techstep | 0:e4fbbd93299b | 214 | // Sets the month |
techstep | 0:e4fbbd93299b | 215 | char cmd[2]; |
techstep | 0:e4fbbd93299b | 216 | cmd[0] = 0x05; |
techstep | 0:e4fbbd93299b | 217 | cmd[1] = decToBcd(Month); |
techstep | 0:e4fbbd93299b | 218 | _i2c.write(ADDR, cmd, 2 ); |
techstep | 0:e4fbbd93299b | 219 | } |
techstep | 0:e4fbbd93299b | 220 | |
techstep | 0:e4fbbd93299b | 221 | void DS3231::setYear(uint8_t Year) { |
techstep | 0:e4fbbd93299b | 222 | // Sets the year |
techstep | 0:e4fbbd93299b | 223 | char cmd[2]; |
techstep | 0:e4fbbd93299b | 224 | cmd[0] = 0x06; |
techstep | 0:e4fbbd93299b | 225 | cmd[1] = decToBcd(Year); |
techstep | 0:e4fbbd93299b | 226 | _i2c.write(ADDR, cmd, 2 ); |
techstep | 0:e4fbbd93299b | 227 | } |
techstep | 0:e4fbbd93299b | 228 | |
techstep | 0:e4fbbd93299b | 229 | void DS3231::setClockMode(bool h12) { |
techstep | 0:e4fbbd93299b | 230 | // sets the mode to 12-hour (true) or 24-hour (false). |
techstep | 0:e4fbbd93299b | 231 | // One thing that bothers me about how I've written this is that |
techstep | 0:e4fbbd93299b | 232 | // if the read and right happen at the right hourly millisecnd, |
techstep | 0:e4fbbd93299b | 233 | // the clock will be set back an hour. Not sure how to do it better, |
techstep | 0:e4fbbd93299b | 234 | // though, and as long as one doesn't set the mode frequently it's |
techstep | 0:e4fbbd93299b | 235 | // a very minimal risk. |
techstep | 0:e4fbbd93299b | 236 | // It's zero risk if you call this BEFORE setting the hour, since |
techstep | 0:e4fbbd93299b | 237 | // the setHour() function doesn't change this mode. |
techstep | 0:e4fbbd93299b | 238 | |
techstep | 0:e4fbbd93299b | 239 | char temp_buffer; |
techstep | 0:e4fbbd93299b | 240 | char cmd; |
techstep | 0:e4fbbd93299b | 241 | cmd = 0x02; |
techstep | 0:e4fbbd93299b | 242 | |
techstep | 0:e4fbbd93299b | 243 | // Start by reading byte 0x02. |
techstep | 0:e4fbbd93299b | 244 | _i2c.write(ADDR, &cmd, 1 ); |
techstep | 0:e4fbbd93299b | 245 | _i2c.read( ADDR, &temp_buffer, 1 ); |
techstep | 0:e4fbbd93299b | 246 | |
techstep | 0:e4fbbd93299b | 247 | // Set the flag to the requested value: |
techstep | 0:e4fbbd93299b | 248 | if (h12) { |
techstep | 0:e4fbbd93299b | 249 | temp_buffer = temp_buffer | 0x40; |
techstep | 0:e4fbbd93299b | 250 | } else { |
techstep | 0:e4fbbd93299b | 251 | temp_buffer = temp_buffer & 0xBF; |
techstep | 0:e4fbbd93299b | 252 | } |
techstep | 0:e4fbbd93299b | 253 | |
techstep | 0:e4fbbd93299b | 254 | // Write the byte |
techstep | 0:e4fbbd93299b | 255 | _i2c.write(ADDR, &cmd, 1 ); |
techstep | 0:e4fbbd93299b | 256 | _i2c.write(temp_buffer); |
techstep | 0:e4fbbd93299b | 257 | } |
techstep | 0:e4fbbd93299b | 258 | |
techstep | 0:e4fbbd93299b | 259 | float DS3231::getTemperature(void) { |
techstep | 0:e4fbbd93299b | 260 | // Checks the internal thermometer on the DS3231 and returns the |
techstep | 0:e4fbbd93299b | 261 | // temperature as a floating-point value. |
techstep | 1:1607610a4ee9 | 262 | char temp[2]; |
techstep | 0:e4fbbd93299b | 263 | char cmd; |
techstep | 0:e4fbbd93299b | 264 | cmd = 0x11; |
techstep | 1:1607610a4ee9 | 265 | _i2c.write(ADDR, &cmd, 1); |
techstep | 1:1607610a4ee9 | 266 | _i2c.read( ADDR, temp, 2); |
techstep | 1:1607610a4ee9 | 267 | return float(temp[0]) + 0.25*(temp[1]>>6); |
techstep | 0:e4fbbd93299b | 268 | } |
vart | 3:f599542b06ad | 269 | bool DS3231::status(void) { |
vart | 3:f599542b06ad | 270 | // Checks DS3231 and returns the status. |
vart | 3:f599542b06ad | 271 | // returns true if DS3231 is present and on |
vart | 3:f599542b06ad | 272 | char temp[2]; |
vart | 3:f599542b06ad | 273 | char cmd; |
vart | 3:f599542b06ad | 274 | cmd = 0x11; |
vart | 3:f599542b06ad | 275 | int w= _i2c.write(ADDR, &cmd, 1); |
vart | 3:f599542b06ad | 276 | int r= _i2c.read( ADDR, temp, 2); |
vart | 3:f599542b06ad | 277 | bool error=((w!=0)||(r!=0)); |
vart | 3:f599542b06ad | 278 | return !error; |
vart | 3:f599542b06ad | 279 | } |
techstep | 0:e4fbbd93299b | 280 | |
techstep | 0:e4fbbd93299b | 281 | 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 | 282 | uint8_t temp_buffer; |
techstep | 1:1607610a4ee9 | 283 | char data[4]; |
techstep | 1:1607610a4ee9 | 284 | char cmd; |
techstep | 1:1607610a4ee9 | 285 | cmd = 0x07; |
techstep | 1:1607610a4ee9 | 286 | _i2c.write(ADDR, &cmd, 1); |
techstep | 1:1607610a4ee9 | 287 | _i2c.read( ADDR, data, 4); |
techstep | 0:e4fbbd93299b | 288 | |
techstep | 1:1607610a4ee9 | 289 | temp_buffer = data[0]; // 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 | 1:1607610a4ee9 | 294 | temp_buffer = data[1]; // 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 | 1:1607610a4ee9 | 299 | temp_buffer = data[2]; // 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 | 1:1607610a4ee9 | 311 | temp_buffer = data[3]; // 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 | 1:1607610a4ee9 | 327 | char data[3]; |
techstep | 1:1607610a4ee9 | 328 | char cmd; |
techstep | 1:1607610a4ee9 | 329 | cmd = 0x0B; |
techstep | 1:1607610a4ee9 | 330 | _i2c.write(ADDR, &cmd, 1); |
techstep | 1:1607610a4ee9 | 331 | _i2c.read( ADDR, data, 4); |
techstep | 0:e4fbbd93299b | 332 | |
techstep | 0:e4fbbd93299b | 333 | //I2C.requestFrom(CLOCK_ADDRESS, 3); |
techstep | 1:1607610a4ee9 | 334 | temp_buffer = data[0]; // Get A2M2 and A2 Minutes |
techstep | 0:e4fbbd93299b | 335 | A2Minute = bcdToDec(temp_buffer & 0x7F); |
techstep | 0:e4fbbd93299b | 336 | // put A2M2 bit in position 4 of DS3231_AlarmBits. |
techstep | 0:e4fbbd93299b | 337 | AlarmBits = AlarmBits | (temp_buffer & 0x80)>>3; |
techstep | 0:e4fbbd93299b | 338 | |
techstep | 1:1607610a4ee9 | 339 | temp_buffer = data[1]; // Get A2M3 and A2 Hour |
techstep | 0:e4fbbd93299b | 340 | // put A2M3 bit in position 5 of DS3231_AlarmBits. |
techstep | 0:e4fbbd93299b | 341 | AlarmBits = AlarmBits | (temp_buffer & 0x80)>>2; |
techstep | 0:e4fbbd93299b | 342 | // determine A2 12/24 mode |
techstep | 0:e4fbbd93299b | 343 | A2h12 = temp_buffer & 0x40; |
techstep | 0:e4fbbd93299b | 344 | if (A2h12) { |
techstep | 0:e4fbbd93299b | 345 | A2PM = temp_buffer & 0x20; // determine am/pm |
techstep | 0:e4fbbd93299b | 346 | A2Hour = bcdToDec(temp_buffer & 0x1F); // 12-hour |
techstep | 0:e4fbbd93299b | 347 | } else { |
techstep | 0:e4fbbd93299b | 348 | A2Hour = bcdToDec(temp_buffer & 0x3F); // 24-hour |
techstep | 0:e4fbbd93299b | 349 | } |
techstep | 0:e4fbbd93299b | 350 | |
techstep | 1:1607610a4ee9 | 351 | temp_buffer = data[2]; // Get A2M4 and A1 Day/Date |
techstep | 0:e4fbbd93299b | 352 | // put A2M4 bit in position 6 of DS3231_AlarmBits. |
techstep | 0:e4fbbd93299b | 353 | AlarmBits = AlarmBits | (temp_buffer & 0x80)>>1; |
techstep | 0:e4fbbd93299b | 354 | // determine A2 day or date flag |
techstep | 0:e4fbbd93299b | 355 | A2Dy = (temp_buffer & 0x40)>>6; |
techstep | 0:e4fbbd93299b | 356 | if (A2Dy) { |
techstep | 0:e4fbbd93299b | 357 | // alarm is by day of week, not date. |
techstep | 0:e4fbbd93299b | 358 | A2Day = bcdToDec(temp_buffer & 0x0F); |
techstep | 0:e4fbbd93299b | 359 | } else { |
techstep | 0:e4fbbd93299b | 360 | // alarm is by date, not day of week. |
techstep | 0:e4fbbd93299b | 361 | A2Day = bcdToDec(temp_buffer & 0x3F); |
techstep | 0:e4fbbd93299b | 362 | } |
techstep | 0:e4fbbd93299b | 363 | } |
techstep | 0:e4fbbd93299b | 364 | |
techstep | 0:e4fbbd93299b | 365 | 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 | 366 | // Sets the alarm-1 date and time on the DS3231, using A1* information |
techstep | 0:e4fbbd93299b | 367 | uint8_t temp_buffer; |
techstep | 0:e4fbbd93299b | 368 | |
techstep | 1:1607610a4ee9 | 369 | char data[4]; |
techstep | 1:1607610a4ee9 | 370 | data[0] = 0x07; // A1 starts at 07h |
techstep | 1:1607610a4ee9 | 371 | data[1] = decToBcd(A1Second) | ((AlarmBits & 0x01) << 7); // Send A1 second and A1M1 |
techstep | 1:1607610a4ee9 | 372 | data[2] = decToBcd(A1Minute) | ((AlarmBits & 0x02) << 6); // Send A1 Minute and A1M2 |
techstep | 1:1607610a4ee9 | 373 | |
techstep | 0:e4fbbd93299b | 374 | // Figure out A1 hour |
techstep | 0:e4fbbd93299b | 375 | if (A1h12) { |
techstep | 0:e4fbbd93299b | 376 | // Start by converting existing time to h12 if it was given in 24h. |
techstep | 0:e4fbbd93299b | 377 | if (A1Hour > 12) { |
techstep | 0:e4fbbd93299b | 378 | // well, then, this obviously isn't a h12 time, is it? |
techstep | 0:e4fbbd93299b | 379 | A1Hour = A1Hour - 12; |
techstep | 0:e4fbbd93299b | 380 | A1PM = true; |
techstep | 0:e4fbbd93299b | 381 | } |
techstep | 0:e4fbbd93299b | 382 | if (A1PM) { |
techstep | 0:e4fbbd93299b | 383 | // Afternoon |
techstep | 0:e4fbbd93299b | 384 | // Convert the hour to BCD and add appropriate flags. |
techstep | 0:e4fbbd93299b | 385 | temp_buffer = decToBcd(A1Hour) | 0x60; |
techstep | 0:e4fbbd93299b | 386 | } else { |
techstep | 0:e4fbbd93299b | 387 | // Morning |
techstep | 0:e4fbbd93299b | 388 | // Convert the hour to BCD and add appropriate flags. |
techstep | 0:e4fbbd93299b | 389 | temp_buffer = decToBcd(A1Hour) | 0x40; |
techstep | 0:e4fbbd93299b | 390 | } |
techstep | 0:e4fbbd93299b | 391 | } else { |
techstep | 0:e4fbbd93299b | 392 | // Now for 24h |
techstep | 0:e4fbbd93299b | 393 | temp_buffer = decToBcd(A1Hour); |
techstep | 0:e4fbbd93299b | 394 | } |
techstep | 0:e4fbbd93299b | 395 | temp_buffer = temp_buffer | ((AlarmBits & 0x04)<<5); |
techstep | 0:e4fbbd93299b | 396 | // A1 hour is figured out, send it |
techstep | 0:e4fbbd93299b | 397 | //I2C.write(temp_buffer); |
techstep | 0:e4fbbd93299b | 398 | _i2c.write(temp_buffer); |
techstep | 0:e4fbbd93299b | 399 | |
techstep | 0:e4fbbd93299b | 400 | // Figure out A1 day/date and A1M4 |
techstep | 0:e4fbbd93299b | 401 | temp_buffer = ((AlarmBits & 0x08)<<4) | decToBcd(A1Day); |
techstep | 0:e4fbbd93299b | 402 | if (A1Dy) { |
techstep | 0:e4fbbd93299b | 403 | // Set A1 Day/Date flag (Otherwise it's zero) |
techstep | 0:e4fbbd93299b | 404 | temp_buffer = temp_buffer | 0x40; |
techstep | 0:e4fbbd93299b | 405 | } |
techstep | 1:1607610a4ee9 | 406 | data[3] = temp_buffer; |
techstep | 1:1607610a4ee9 | 407 | _i2c.write(ADDR, data, 4); |
techstep | 1:1607610a4ee9 | 408 | |
techstep | 0:e4fbbd93299b | 409 | } |
techstep | 0:e4fbbd93299b | 410 | |
techstep | 0:e4fbbd93299b | 411 | void DS3231::setA2Time(uint8_t A2Day, uint8_t A2Hour, uint8_t A2Minute, uint8_t AlarmBits, bool A2Dy, bool A2h12, bool A2PM) { |
techstep | 0:e4fbbd93299b | 412 | // Sets the alarm-2 date and time on the DS3231, using A2* information |
techstep | 0:e4fbbd93299b | 413 | uint8_t temp_buffer; |
techstep | 0:e4fbbd93299b | 414 | |
techstep | 1:1607610a4ee9 | 415 | char data[4]; |
techstep | 1:1607610a4ee9 | 416 | data[0] = 0x0B; // A2 starts at 0Bh |
techstep | 1:1607610a4ee9 | 417 | data[1] = decToBcd(A2Minute) | ((AlarmBits & 0x10) << 3); // Send A2 Minute and A2M2 |
techstep | 0:e4fbbd93299b | 418 | |
techstep | 0:e4fbbd93299b | 419 | // Figure out A2 hour |
techstep | 0:e4fbbd93299b | 420 | if (A2h12) { |
techstep | 0:e4fbbd93299b | 421 | // Start by converting existing time to h12 if it was given in 24h. |
techstep | 0:e4fbbd93299b | 422 | if (A2Hour > 12) { |
techstep | 0:e4fbbd93299b | 423 | // well, then, this obviously isn't a h12 time, is it? |
techstep | 0:e4fbbd93299b | 424 | A2Hour = A2Hour - 12; |
techstep | 0:e4fbbd93299b | 425 | A2PM = true; |
techstep | 0:e4fbbd93299b | 426 | } |
techstep | 0:e4fbbd93299b | 427 | if (A2PM) { |
techstep | 0:e4fbbd93299b | 428 | // Afternoon |
techstep | 0:e4fbbd93299b | 429 | // Convert the hour to BCD and add appropriate flags. |
techstep | 0:e4fbbd93299b | 430 | temp_buffer = decToBcd(A2Hour) | 0x60; |
techstep | 0:e4fbbd93299b | 431 | } else { |
techstep | 0:e4fbbd93299b | 432 | // Morning |
techstep | 0:e4fbbd93299b | 433 | // Convert the hour to BCD and add appropriate flags. |
techstep | 0:e4fbbd93299b | 434 | temp_buffer = decToBcd(A2Hour) | 0x40; |
techstep | 0:e4fbbd93299b | 435 | } |
techstep | 0:e4fbbd93299b | 436 | } else { |
techstep | 0:e4fbbd93299b | 437 | // Now for 24h |
techstep | 0:e4fbbd93299b | 438 | temp_buffer = decToBcd(A2Hour); |
techstep | 0:e4fbbd93299b | 439 | } |
techstep | 0:e4fbbd93299b | 440 | // add in A2M3 bit |
techstep | 0:e4fbbd93299b | 441 | temp_buffer = temp_buffer | ((AlarmBits & 0x20)<<2); |
techstep | 0:e4fbbd93299b | 442 | // A2 hour is figured out, send it |
techstep | 1:1607610a4ee9 | 443 | data[2] = temp_buffer; |
techstep | 0:e4fbbd93299b | 444 | |
techstep | 0:e4fbbd93299b | 445 | // Figure out A2 day/date and A2M4 |
techstep | 0:e4fbbd93299b | 446 | temp_buffer = ((AlarmBits & 0x40)<<1) | decToBcd(A2Day); |
techstep | 0:e4fbbd93299b | 447 | if (A2Dy) { |
techstep | 0:e4fbbd93299b | 448 | // Set A2 Day/Date flag (Otherwise it's zero) |
techstep | 0:e4fbbd93299b | 449 | temp_buffer = temp_buffer | 0x40; |
techstep | 0:e4fbbd93299b | 450 | } |
techstep | 1:1607610a4ee9 | 451 | data[3] = temp_buffer; |
techstep | 1:1607610a4ee9 | 452 | _i2c.write(ADDR, data, 4); |
techstep | 1:1607610a4ee9 | 453 | |
techstep | 0:e4fbbd93299b | 454 | } |
techstep | 0:e4fbbd93299b | 455 | |
techstep | 0:e4fbbd93299b | 456 | void DS3231::turnOnAlarm(uint8_t Alarm) { |
techstep | 0:e4fbbd93299b | 457 | // turns on alarm number "Alarm". Defaults to 2 if Alarm is not 1. |
techstep | 0:e4fbbd93299b | 458 | uint8_t temp_buffer = readControlByte(0); |
techstep | 0:e4fbbd93299b | 459 | // modify control byte |
techstep | 0:e4fbbd93299b | 460 | if (Alarm == 1) { |
techstep | 0:e4fbbd93299b | 461 | temp_buffer = temp_buffer | 0x05; |
techstep | 0:e4fbbd93299b | 462 | } else { |
techstep | 0:e4fbbd93299b | 463 | temp_buffer = temp_buffer | 0x06; |
techstep | 0:e4fbbd93299b | 464 | } |
techstep | 0:e4fbbd93299b | 465 | writeControlByte(temp_buffer, 0); |
techstep | 0:e4fbbd93299b | 466 | } |
techstep | 0:e4fbbd93299b | 467 | |
techstep | 0:e4fbbd93299b | 468 | void DS3231::turnOffAlarm(uint8_t Alarm) { |
techstep | 0:e4fbbd93299b | 469 | // turns off alarm number "Alarm". Defaults to 2 if Alarm is not 1. |
techstep | 0:e4fbbd93299b | 470 | // Leaves interrupt pin alone. |
techstep | 0:e4fbbd93299b | 471 | uint8_t temp_buffer = readControlByte(0); |
techstep | 0:e4fbbd93299b | 472 | // modify control byte |
techstep | 0:e4fbbd93299b | 473 | if (Alarm == 1) { |
techstep | 0:e4fbbd93299b | 474 | temp_buffer = temp_buffer & 0xFE; |
techstep | 0:e4fbbd93299b | 475 | } else { |
techstep | 0:e4fbbd93299b | 476 | temp_buffer = temp_buffer & 0xFD; |
techstep | 0:e4fbbd93299b | 477 | } |
techstep | 0:e4fbbd93299b | 478 | writeControlByte(temp_buffer, 0); |
techstep | 0:e4fbbd93299b | 479 | } |
techstep | 0:e4fbbd93299b | 480 | |
techstep | 0:e4fbbd93299b | 481 | bool DS3231::checkAlarmEnabled(uint8_t Alarm) { |
techstep | 0:e4fbbd93299b | 482 | // Checks whether the given alarm is enabled. |
techstep | 0:e4fbbd93299b | 483 | uint8_t result = 0x0; |
techstep | 0:e4fbbd93299b | 484 | uint8_t temp_buffer = readControlByte(0); |
techstep | 0:e4fbbd93299b | 485 | if (Alarm == 1) { |
techstep | 0:e4fbbd93299b | 486 | result = temp_buffer & 0x01; |
techstep | 0:e4fbbd93299b | 487 | } else { |
techstep | 0:e4fbbd93299b | 488 | result = temp_buffer & 0x02; |
techstep | 0:e4fbbd93299b | 489 | } |
techstep | 0:e4fbbd93299b | 490 | return result; |
techstep | 0:e4fbbd93299b | 491 | } |
techstep | 0:e4fbbd93299b | 492 | |
techstep | 0:e4fbbd93299b | 493 | bool DS3231::checkIfAlarm(uint8_t Alarm) { |
techstep | 0:e4fbbd93299b | 494 | // Checks whether alarm 1 or alarm 2 flag is on, returns T/F accordingly. |
techstep | 0:e4fbbd93299b | 495 | // Turns flag off, also. |
techstep | 0:e4fbbd93299b | 496 | // defaults to checking alarm 2, unless Alarm == 1. |
techstep | 0:e4fbbd93299b | 497 | uint8_t result; |
techstep | 0:e4fbbd93299b | 498 | uint8_t temp_buffer = readControlByte(1); |
techstep | 0:e4fbbd93299b | 499 | if (Alarm == 1) { |
techstep | 0:e4fbbd93299b | 500 | // Did alarm 1 go off? |
techstep | 0:e4fbbd93299b | 501 | result = temp_buffer & 0x01; |
techstep | 0:e4fbbd93299b | 502 | // clear flag |
techstep | 0:e4fbbd93299b | 503 | temp_buffer = temp_buffer & 0xFE; |
techstep | 0:e4fbbd93299b | 504 | } else { |
techstep | 0:e4fbbd93299b | 505 | // Did alarm 2 go off? |
techstep | 0:e4fbbd93299b | 506 | result = temp_buffer & 0x02; |
techstep | 0:e4fbbd93299b | 507 | // clear flag |
techstep | 0:e4fbbd93299b | 508 | temp_buffer = temp_buffer & 0xFD; |
techstep | 0:e4fbbd93299b | 509 | } |
techstep | 0:e4fbbd93299b | 510 | writeControlByte(temp_buffer, 1); |
techstep | 0:e4fbbd93299b | 511 | return result; |
techstep | 0:e4fbbd93299b | 512 | } |
techstep | 0:e4fbbd93299b | 513 | |
vart | 2:fc6317727d1d | 514 | void DS3231::tikerOn (void){ |
vart | 2:fc6317727d1d | 515 | // turn 1 Hz oscillator on and reset Control Register (0Eh) |
vart | 2:fc6317727d1d | 516 | writeControlByte(0, 0); |
vart | 2:fc6317727d1d | 517 | } |
vart | 2:fc6317727d1d | 518 | |
techstep | 0:e4fbbd93299b | 519 | void DS3231::enableOscillator(bool TF, bool battery, uint8_t frequency) { |
techstep | 0:e4fbbd93299b | 520 | // turns oscillator on or off. True is on, false is off. |
techstep | 0:e4fbbd93299b | 521 | // if battery is true, turns on even for battery-only operation, |
techstep | 0:e4fbbd93299b | 522 | // otherwise turns off if Vcc is off. |
techstep | 0:e4fbbd93299b | 523 | // frequency must be 0, 1, 2, or 3. |
techstep | 0:e4fbbd93299b | 524 | // 0 = 1 Hz |
techstep | 0:e4fbbd93299b | 525 | // 1 = 1.024 kHz |
techstep | 0:e4fbbd93299b | 526 | // 2 = 4.096 kHz |
techstep | 0:e4fbbd93299b | 527 | // 3 = 8.192 kHz (Default if frequency byte is out of range) |
techstep | 0:e4fbbd93299b | 528 | if (frequency > 3) frequency = 3; |
techstep | 0:e4fbbd93299b | 529 | // read control byte in, but zero out current state of RS2 and RS1. |
techstep | 0:e4fbbd93299b | 530 | uint8_t temp_buffer = readControlByte(0) & 0xE7; |
techstep | 0:e4fbbd93299b | 531 | if (battery) { |
techstep | 0:e4fbbd93299b | 532 | // turn on BBSQW flag |
techstep | 0:e4fbbd93299b | 533 | temp_buffer = temp_buffer | 0x40; |
techstep | 0:e4fbbd93299b | 534 | } else { |
techstep | 0:e4fbbd93299b | 535 | // turn off BBSQW flag |
techstep | 0:e4fbbd93299b | 536 | temp_buffer = temp_buffer & 0xBF; |
techstep | 0:e4fbbd93299b | 537 | } |
techstep | 0:e4fbbd93299b | 538 | if (TF) { |
techstep | 0:e4fbbd93299b | 539 | // set ~EOSC to 0 and INTCN to zero. |
techstep | 0:e4fbbd93299b | 540 | temp_buffer = temp_buffer & 0x7B; |
techstep | 0:e4fbbd93299b | 541 | } else { |
techstep | 0:e4fbbd93299b | 542 | // set ~EOSC to 1, leave INTCN as is. |
techstep | 0:e4fbbd93299b | 543 | temp_buffer = temp_buffer | 0x80; |
techstep | 0:e4fbbd93299b | 544 | } |
techstep | 0:e4fbbd93299b | 545 | // shift frequency into bits 3 and 4 and set. |
techstep | 0:e4fbbd93299b | 546 | frequency = frequency << 3; |
techstep | 0:e4fbbd93299b | 547 | temp_buffer = temp_buffer | frequency; |
techstep | 0:e4fbbd93299b | 548 | // And write the control bits |
techstep | 0:e4fbbd93299b | 549 | writeControlByte(temp_buffer, 0); |
techstep | 0:e4fbbd93299b | 550 | } |
techstep | 0:e4fbbd93299b | 551 | |
techstep | 0:e4fbbd93299b | 552 | void DS3231::enable32kHz(bool TF) { |
techstep | 0:e4fbbd93299b | 553 | // turn 32kHz pin on or off |
techstep | 0:e4fbbd93299b | 554 | uint8_t temp_buffer = readControlByte(1); |
techstep | 0:e4fbbd93299b | 555 | if (TF) { |
techstep | 0:e4fbbd93299b | 556 | // turn on 32kHz pin |
techstep | 0:e4fbbd93299b | 557 | temp_buffer = temp_buffer | 0x08; |
techstep | 0:e4fbbd93299b | 558 | } else { |
techstep | 0:e4fbbd93299b | 559 | // turn off 32kHz pin |
techstep | 0:e4fbbd93299b | 560 | temp_buffer = temp_buffer & 0xF7; |
techstep | 0:e4fbbd93299b | 561 | } |
techstep | 0:e4fbbd93299b | 562 | writeControlByte(temp_buffer, 1); |
techstep | 0:e4fbbd93299b | 563 | } |
techstep | 0:e4fbbd93299b | 564 | |
techstep | 0:e4fbbd93299b | 565 | bool DS3231::oscillatorCheck() { |
techstep | 0:e4fbbd93299b | 566 | // Returns false if the oscillator has been off for some reason. |
techstep | 0:e4fbbd93299b | 567 | // If this is the case, the time is probably not correct. |
techstep | 0:e4fbbd93299b | 568 | uint8_t temp_buffer = readControlByte(1); |
techstep | 0:e4fbbd93299b | 569 | bool result = true; |
techstep | 0:e4fbbd93299b | 570 | if (temp_buffer & 0x80) { |
techstep | 0:e4fbbd93299b | 571 | // Oscillator Stop Flag (OSF) is set, so return false. |
techstep | 0:e4fbbd93299b | 572 | result = false; |
techstep | 0:e4fbbd93299b | 573 | } |
techstep | 0:e4fbbd93299b | 574 | return result; |
techstep | 0:e4fbbd93299b | 575 | } |
techstep | 0:e4fbbd93299b | 576 | |
techstep | 0:e4fbbd93299b | 577 | /***************************************** |
techstep | 0:e4fbbd93299b | 578 | Private Functions |
techstep | 0:e4fbbd93299b | 579 | *****************************************/ |
techstep | 0:e4fbbd93299b | 580 | uint8_t DS3231::decToBcd(uint8_t val) { |
techstep | 0:e4fbbd93299b | 581 | // Convert normal decimal numbers to binary coded decimal |
techstep | 0:e4fbbd93299b | 582 | return ( (val/10*16) + (val%10) ); |
techstep | 0:e4fbbd93299b | 583 | } |
techstep | 0:e4fbbd93299b | 584 | |
techstep | 0:e4fbbd93299b | 585 | uint8_t DS3231::bcdToDec(uint8_t val) { |
techstep | 0:e4fbbd93299b | 586 | // Convert binary coded decimal to normal decimal numbers |
techstep | 0:e4fbbd93299b | 587 | return ( (val/16*10) + (val%16) ); |
techstep | 0:e4fbbd93299b | 588 | } |
techstep | 0:e4fbbd93299b | 589 | |
techstep | 0:e4fbbd93299b | 590 | uint8_t DS3231::readControlByte(bool which) { |
techstep | 0:e4fbbd93299b | 591 | // Read selected control byte |
techstep | 0:e4fbbd93299b | 592 | // first byte (0) is 0x0e, second (1) is 0x0f |
techstep | 1:1607610a4ee9 | 593 | char data; |
techstep | 1:1607610a4ee9 | 594 | char cmd[2]; |
techstep | 1:1607610a4ee9 | 595 | cmd[0] = 0x0F; |
techstep | 1:1607610a4ee9 | 596 | cmd[1] = 0x0E; |
techstep | 1:1607610a4ee9 | 597 | |
techstep | 0:e4fbbd93299b | 598 | if (which) { |
techstep | 0:e4fbbd93299b | 599 | // second control byte |
techstep | 1:1607610a4ee9 | 600 | _i2c.write(ADDR, &cmd[0], 1 ); |
techstep | 0:e4fbbd93299b | 601 | } else { |
techstep | 0:e4fbbd93299b | 602 | // first control byte |
techstep | 1:1607610a4ee9 | 603 | _i2c.write(ADDR, &cmd[1], 1 ); |
techstep | 0:e4fbbd93299b | 604 | } |
techstep | 1:1607610a4ee9 | 605 | _i2c.read( ADDR, &data, 1 ); |
techstep | 1:1607610a4ee9 | 606 | return data; |
techstep | 0:e4fbbd93299b | 607 | } |
techstep | 0:e4fbbd93299b | 608 | |
techstep | 0:e4fbbd93299b | 609 | void DS3231::writeControlByte(uint8_t control, bool which) { |
techstep | 0:e4fbbd93299b | 610 | // Write the selected control byte. |
techstep | 0:e4fbbd93299b | 611 | // which=false -> 0x0e, true->0x0f. |
techstep | 1:1607610a4ee9 | 612 | char data1[2]; |
techstep | 1:1607610a4ee9 | 613 | char data2[2]; |
techstep | 1:1607610a4ee9 | 614 | data1[0] = 0x0F; |
techstep | 1:1607610a4ee9 | 615 | data1[1] = control; |
techstep | 1:1607610a4ee9 | 616 | data2[0] = 0x0E; |
techstep | 1:1607610a4ee9 | 617 | data2[1] = control; |
techstep | 0:e4fbbd93299b | 618 | |
techstep | 0:e4fbbd93299b | 619 | if (which) { |
vart | 2:fc6317727d1d | 620 | _i2c.write( ADDR, data1, 2); |
techstep | 0:e4fbbd93299b | 621 | } else { |
vart | 2:fc6317727d1d | 622 | _i2c.write( ADDR, data2, 2); |
techstep | 0:e4fbbd93299b | 623 | } |
techstep | 1:1607610a4ee9 | 624 | |
techstep | 0:e4fbbd93299b | 625 | } |
techstep | 0:e4fbbd93299b | 626 |