ArduinoLibs
|
00001 /* 00002 * Copyright (C) 2012 Southern Storm Software, Pty Ltd. 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a 00005 * copy of this software and associated documentation files (the "Software"), 00006 * to deal in the Software without restriction, including without limitation 00007 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00008 * and/or sell copies of the Software, and to permit persons to whom the 00009 * Software is furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included 00012 * in all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00015 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 00019 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 00020 * DEALINGS IN THE SOFTWARE. 00021 */ 00022 00023 #include "DS1307RTC.h" 00024 #include "../I2C/I2CMaster.h" 00025 #if defined(ARDUINO) && ARDUINO >= 100 00026 #include <Arduino.h> 00027 #else 00028 #include <WProgram.h> 00029 #endif 00030 00054 // I2C address of the RTC chip (7-bit). 00055 #define DS1307_I2C_ADDRESS 0x68 00056 00057 // Registers. 00058 #define DS1307_SECOND 0x00 00059 #define DS1307_MINUTE 0x01 00060 #define DS1307_HOUR 0x02 00061 #define DS1307_DAY_OF_WEEK 0x03 00062 #define DS1307_DATE 0x04 00063 #define DS1307_MONTH 0x05 00064 #define DS1307_YEAR 0x06 00065 #define DS1307_CONTROL 0x07 00066 #define DS1307_NVRAM 0x08 00067 00068 // Alarm storage at the end of the RTC's NVRAM. 00069 #define DS1307_ALARM_SIZE 3 00070 #define DS1307_ALARMS (64 - RTC::ALARM_COUNT * DS1307_ALARM_SIZE - 1) 00071 #define DS1307_ALARM_MAGIC 63 00072 00083 DS1307RTC::DS1307RTC(I2CMaster &bus, uint8_t oneHzPin) 00084 : _bus(&bus) 00085 , _oneHzPin(oneHzPin) 00086 , prevOneHz(false) 00087 , _isRealTime(true) 00088 { 00089 // Make sure the CH bit in register 0 is off or the clock won't update. 00090 _bus->startWrite(DS1307_I2C_ADDRESS); 00091 _bus->write(DS1307_SECOND); 00092 if (_bus->startRead(DS1307_I2C_ADDRESS, 1)) { 00093 uint8_t value = _bus->read(); 00094 if ((value & 0x80) != 0) 00095 writeRegister(DS1307_SECOND, value & 0x7F); 00096 } else { 00097 // Did not get an acknowledgement from the RTC chip. 00098 _isRealTime = false; 00099 } 00100 00101 // Turn on the 1 Hz square wave signal if required. 00102 if (oneHzPin != 255 && _isRealTime) { 00103 pinMode(oneHzPin, INPUT); 00104 digitalWrite(oneHzPin, HIGH); 00105 writeRegister(DS1307_CONTROL, 0x10); 00106 } 00107 00108 // Initialize the alarms in the RTC chip's NVRAM. 00109 if (_isRealTime) 00110 initAlarms(); 00111 } 00112 00118 bool DS1307RTC::hasUpdates() 00119 { 00120 // If not using a 1 Hz pin or there is no RTC chip available, 00121 // then assume that there is an update available. 00122 if (_oneHzPin == 255 || !_isRealTime) 00123 return true; 00124 00125 // The DS1307 updates the internal registers on the falling edge of the 00126 // 1 Hz clock. The values should be ready to read on the rising edge. 00127 bool value = digitalRead(_oneHzPin); 00128 if (value && !prevOneHz) { 00129 prevOneHz = value; 00130 return true; 00131 } else { 00132 prevOneHz = value; 00133 return false; 00134 } 00135 } 00136 00137 inline uint8_t fromBCD(uint8_t value) 00138 { 00139 return (value >> 4) * 10 + (value & 0x0F); 00140 } 00141 00142 inline uint8_t fromHourBCD(uint8_t value) 00143 { 00144 if ((value & 0x40) != 0) { 00145 // 12-hour mode. 00146 uint8_t result = ((value >> 4) & 0x01) * 10 + (value & 0x0F); 00147 if ((value & 0x20) != 0) 00148 return (result == 12) ? 12 : (result + 12); // PM 00149 else 00150 return (result == 12) ? 0 : result; // AM 00151 } else { 00152 // 24-hour mode. 00153 return fromBCD(value); 00154 } 00155 } 00156 00157 void DS1307RTC::readTime(RTCTime *value) 00158 { 00159 if (_isRealTime) { 00160 _bus->startWrite(DS1307_I2C_ADDRESS); 00161 _bus->write(DS1307_SECOND); 00162 if (_bus->startRead(DS1307_I2C_ADDRESS, 3)) { 00163 value->second = fromBCD(_bus->read() & 0x7F); 00164 value->minute = fromBCD(_bus->read()); 00165 value->hour = fromHourBCD(_bus->read()); 00166 } else { 00167 // RTC chip is not responding. 00168 value->second = 0; 00169 value->minute = 0; 00170 value->hour = 0; 00171 } 00172 } else { 00173 RTC::readTime(value); 00174 } 00175 } 00176 00177 void DS1307RTC::readDate(RTCDate *value) 00178 { 00179 if (!_isRealTime) { 00180 RTC::readDate(value); 00181 return; 00182 } 00183 _bus->startWrite(DS1307_I2C_ADDRESS); 00184 _bus->write(DS1307_DATE); 00185 if (_bus->startRead(DS1307_I2C_ADDRESS, 3)) { 00186 value->day = fromBCD(_bus->read()); 00187 value->month = fromBCD(_bus->read()); 00188 value->year = fromBCD(_bus->read()) + 2000; 00189 } else { 00190 // RTC chip is not responding. 00191 value->day = 1; 00192 value->month = 1; 00193 value->year = 2000; 00194 } 00195 } 00196 00197 inline uint8_t toBCD(uint8_t value) 00198 { 00199 return ((value / 10) << 4) + (value % 10); 00200 } 00201 00202 void DS1307RTC::writeTime(const RTCTime *value) 00203 { 00204 if (_isRealTime) { 00205 _bus->startWrite(DS1307_I2C_ADDRESS); 00206 _bus->write(DS1307_SECOND); 00207 _bus->write(toBCD(value->second)); 00208 _bus->write(toBCD(value->minute)); 00209 _bus->write(toBCD(value->hour)); // Changes mode to 24-hour clock. 00210 _bus->endWrite(); 00211 } else { 00212 RTC::writeTime(value); 00213 } 00214 } 00215 00216 void DS1307RTC::writeDate(const RTCDate *value) 00217 { 00218 if (_isRealTime) { 00219 _bus->startWrite(DS1307_I2C_ADDRESS); 00220 _bus->write(DS1307_DATE); 00221 _bus->write(toBCD(value->day)); 00222 _bus->write(toBCD(value->month)); 00223 _bus->write(toBCD(value->year % 100)); 00224 _bus->endWrite(); 00225 } else { 00226 RTC::writeDate(value); 00227 } 00228 } 00229 00230 void DS1307RTC::readAlarm(uint8_t alarmNum, RTCAlarm *value) 00231 { 00232 if (_isRealTime) { 00233 _bus->startWrite(DS1307_I2C_ADDRESS); 00234 _bus->write(DS1307_ALARMS + alarmNum * DS1307_ALARM_SIZE); 00235 if (_bus->startRead(DS1307_I2C_ADDRESS, 3)) { 00236 value->hour = fromBCD(_bus->read()); 00237 value->minute = fromBCD(_bus->read()); 00238 value->flags = _bus->read(); 00239 } else { 00240 // RTC chip is not responding. 00241 value->hour = 0; 00242 value->minute = 0; 00243 value->flags = 0; 00244 } 00245 } else { 00246 RTC::readAlarm(alarmNum, value); 00247 } 00248 } 00249 00250 void DS1307RTC::writeAlarm(uint8_t alarmNum, const RTCAlarm *value) 00251 { 00252 if (_isRealTime) { 00253 _bus->startWrite(DS1307_I2C_ADDRESS); 00254 _bus->write(DS1307_ALARMS + alarmNum * DS1307_ALARM_SIZE); 00255 _bus->write(toBCD(value->hour)); 00256 _bus->write(toBCD(value->minute)); 00257 _bus->write(value->flags); 00258 _bus->endWrite(); 00259 } else { 00260 RTC::writeAlarm(alarmNum, value); 00261 } 00262 } 00263 00264 int DS1307RTC::byteCount() const 00265 { 00266 return DS1307_ALARMS - DS1307_NVRAM; 00267 } 00268 00269 uint8_t DS1307RTC::readByte(uint8_t offset) 00270 { 00271 if (_isRealTime) 00272 return readRegister(DS1307_NVRAM + offset); 00273 else 00274 return RTC::readByte(offset); 00275 } 00276 00277 void DS1307RTC::writeByte(uint8_t offset, uint8_t value) 00278 { 00279 if (_isRealTime) 00280 writeRegister(DS1307_NVRAM + offset, value); 00281 else 00282 RTC::writeByte(offset, value); 00283 } 00284 00285 void DS1307RTC::initAlarms() 00286 { 00287 uint8_t value = readRegister(DS1307_ALARM_MAGIC); 00288 if (value != (0xB0 + ALARM_COUNT)) { 00289 // This is the first time we have used this clock chip, 00290 // so initialize all alarms to their default state. 00291 RTCAlarm alarm; 00292 alarm.hour = 6; // Default to 6am for alarms. 00293 alarm.minute = 0; 00294 alarm.flags = 0; 00295 for (uint8_t index = 0; index < ALARM_COUNT; ++index) 00296 writeAlarm(index, &alarm); 00297 writeRegister(DS1307_ALARM_MAGIC, 0xB0 + ALARM_COUNT); 00298 00299 // Also clear the rest of NVRAM so that it is in a known state. 00300 // Otherwise we'll have whatever garbage was present at power-on. 00301 _bus->startWrite(DS1307_I2C_ADDRESS); 00302 _bus->write(DS1307_NVRAM); 00303 for (uint8_t index = DS1307_NVRAM; index < DS1307_ALARMS; ++index) 00304 _bus->write(0); 00305 _bus->endWrite(); 00306 } 00307 } 00308 00309 uint8_t DS1307RTC::readRegister(uint8_t reg) 00310 { 00311 _bus->startWrite(DS1307_I2C_ADDRESS); 00312 _bus->write(reg); 00313 if (!_bus->startRead(DS1307_I2C_ADDRESS, 1)) 00314 return 0; // RTC chip is not responding. 00315 return _bus->read(); 00316 } 00317 00318 bool DS1307RTC::writeRegister(uint8_t reg, uint8_t value) 00319 { 00320 _bus->startWrite(DS1307_I2C_ADDRESS); 00321 _bus->write(reg); 00322 _bus->write(value); 00323 return _bus->endWrite(); 00324 }