DS3231 External RTC I2C

Fork of DS3231 by Bird Techstep

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?

UserRevisionLine numberNew 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