1
0
mirror of https://github.com/taigrr/arduinolibs synced 2025-01-18 04:33:12 -08:00

Refactor the I2C library API

This commit is contained in:
Rhys Weatherley
2012-05-18 09:37:42 +10:00
parent 5819690b42
commit 8a601d3a80
6 changed files with 277 additions and 157 deletions

View File

@@ -21,7 +21,7 @@
*/
#include "DS1307RTC.h"
#include "../I2C/BitBangI2C.h"
#include "../I2C/I2CMaster.h"
#include <WProgram.h>
/**
@@ -76,38 +76,29 @@
*
* \sa hasUpdates()
*/
DS1307RTC::DS1307RTC(BitBangI2C &bus, uint8_t oneHzPin)
DS1307RTC::DS1307RTC(I2CMaster &bus, uint8_t oneHzPin)
: _bus(&bus)
, _oneHzPin(oneHzPin)
, prevOneHz(false)
, _isRealTime(true)
{
// Make sure the CH bit in register 0 is off or the clock won't update.
if (_bus->startWrite(DS1307_I2C_ADDRESS) == BitBangI2C::ACK) {
_bus->write(DS1307_SECOND);
_bus->startRead(DS1307_I2C_ADDRESS);
uint8_t value = _bus->read(BitBangI2C::NACK);
_bus->stop();
if ((value & 0x80) != 0) {
_bus->startWrite(DS1307_I2C_ADDRESS);
_bus->write(DS1307_SECOND);
_bus->write(value & 0x7F);
_bus->stop();
}
_bus->startWrite(DS1307_I2C_ADDRESS);
_bus->write(DS1307_SECOND);
if (_bus->startRead(DS1307_I2C_ADDRESS, 1)) {
uint8_t value = _bus->read();
if ((value & 0x80) != 0)
writeRegister(DS1307_SECOND, value & 0x7F);
} else {
// Did not get an acknowledgement from the RTC chip.
_isRealTime = false;
_bus->stop();
}
// Turn on the 1 Hz square wave signal if required.
if (oneHzPin != 255 && _isRealTime) {
pinMode(oneHzPin, INPUT);
digitalWrite(oneHzPin, HIGH);
_bus->startWrite(DS1307_I2C_ADDRESS);
_bus->write(DS1307_CONTROL);
_bus->write(0x10);
_bus->stop();
writeRegister(DS1307_CONTROL, 0x10);
}
// Initialize the alarms in the RTC chip's NVRAM.
@@ -168,11 +159,16 @@ void DS1307RTC::readTime(RTCTime *value)
if (_isRealTime) {
_bus->startWrite(DS1307_I2C_ADDRESS);
_bus->write(DS1307_SECOND);
_bus->startRead(DS1307_I2C_ADDRESS);
value->second = fromBCD(_bus->read() & 0x7F);
value->minute = fromBCD(_bus->read());
value->hour = fromHourBCD(_bus->read(BitBangI2C::NACK));
_bus->stop();
if (_bus->startRead(DS1307_I2C_ADDRESS, 3)) {
value->second = fromBCD(_bus->read() & 0x7F);
value->minute = fromBCD(_bus->read());
value->hour = fromHourBCD(_bus->read());
} else {
// RTC chip is not responding.
value->second = 0;
value->minute = 0;
value->hour = 0;
}
} else {
RTC::readTime(value);
}
@@ -186,11 +182,16 @@ void DS1307RTC::readDate(RTCDate *value)
}
_bus->startWrite(DS1307_I2C_ADDRESS);
_bus->write(DS1307_DATE);
_bus->startRead(DS1307_I2C_ADDRESS);
value->day = fromBCD(_bus->read());
value->month = fromBCD(_bus->read());
value->year = fromBCD(_bus->read(BitBangI2C::NACK)) + 2000;
_bus->stop();
if (_bus->startRead(DS1307_I2C_ADDRESS, 3)) {
value->day = fromBCD(_bus->read());
value->month = fromBCD(_bus->read());
value->year = fromBCD(_bus->read()) + 2000;
} else {
// RTC chip is not responding.
value->day = 1;
value->month = 1;
value->year = 2012;
}
}
inline uint8_t toBCD(uint8_t value)
@@ -206,7 +207,7 @@ void DS1307RTC::writeTime(const RTCTime *value)
_bus->write(toBCD(value->second));
_bus->write(toBCD(value->minute));
_bus->write(toBCD(value->hour)); // Changes mode to 24-hour clock.
_bus->stop();
_bus->endWrite();
} else {
RTC::writeTime(value);
}
@@ -220,7 +221,7 @@ void DS1307RTC::writeDate(const RTCDate *value)
_bus->write(toBCD(value->day));
_bus->write(toBCD(value->month));
_bus->write(toBCD(value->year % 100));
_bus->stop();
_bus->endWrite();
} else {
RTC::writeDate(value);
}
@@ -231,11 +232,16 @@ void DS1307RTC::readAlarm(uint8_t alarmNum, RTCAlarm *value)
if (_isRealTime) {
_bus->startWrite(DS1307_I2C_ADDRESS);
_bus->write(DS1307_ALARMS + alarmNum * DS1307_ALARM_SIZE);
_bus->startRead(DS1307_I2C_ADDRESS);
value->hour = fromBCD(_bus->read());
value->minute = fromBCD(_bus->read());
value->flags = _bus->read(BitBangI2C::NACK);
_bus->stop();
if (_bus->startRead(DS1307_I2C_ADDRESS, 3)) {
value->hour = fromBCD(_bus->read());
value->minute = fromBCD(_bus->read());
value->flags = _bus->read();
} else {
// RTC chip is not responding.
value->hour = 0;
value->minute = 0;
value->flags = 0;
}
} else {
RTC::readAlarm(alarmNum, value);
}
@@ -249,7 +255,7 @@ void DS1307RTC::writeAlarm(uint8_t alarmNum, const RTCAlarm *value)
_bus->write(toBCD(value->hour));
_bus->write(toBCD(value->minute));
_bus->write(value->flags);
_bus->stop();
_bus->endWrite();
} else {
RTC::writeAlarm(alarmNum, value);
}
@@ -257,37 +263,23 @@ void DS1307RTC::writeAlarm(uint8_t alarmNum, const RTCAlarm *value)
uint8_t DS1307RTC::readByte(uint8_t offset)
{
if (_isRealTime) {
_bus->startWrite(DS1307_I2C_ADDRESS);
_bus->write(DS1307_NVRAM + offset);
_bus->startRead(DS1307_I2C_ADDRESS);
uint8_t value = _bus->read(BitBangI2C::NACK);
_bus->stop();
return value;
} else {
if (_isRealTime)
return readRegister(DS1307_NVRAM + offset);
else
return RTC::readByte(offset);
}
}
void DS1307RTC::writeByte(uint8_t offset, uint8_t value)
{
if (_isRealTime) {
_bus->startWrite(DS1307_I2C_ADDRESS);
_bus->write(DS1307_NVRAM + offset);
_bus->write(value);
_bus->stop();
} else {
if (_isRealTime)
writeRegister(DS1307_NVRAM + offset, value);
else
RTC::writeByte(offset, value);
}
}
void DS1307RTC::initAlarms()
{
_bus->startWrite(DS1307_I2C_ADDRESS);
_bus->write(DS1307_ALARM_MAGIC);
_bus->startRead(DS1307_I2C_ADDRESS);
uint8_t value = _bus->read(BitBangI2C::NACK);
_bus->stop();
uint8_t value = readRegister(DS1307_ALARM_MAGIC);
if (value != (0xB0 + ALARM_COUNT)) {
// This is the first time we have used this clock chip,
// so initialize all alarms to their default state.
@@ -297,10 +289,7 @@ void DS1307RTC::initAlarms()
alarm.flags = 0;
for (uint8_t index = 0; index < ALARM_COUNT; ++index)
writeAlarm(index, &alarm);
_bus->startWrite(DS1307_I2C_ADDRESS);
_bus->write(DS1307_ALARM_MAGIC);
_bus->write(0xB0 + ALARM_COUNT);
_bus->stop();
writeRegister(DS1307_I2C_ADDRESS, 0xB0 + ALARM_COUNT);
// Also clear the rest of NVRAM so that it is in a known state.
// Otherwise we'll have whatever garbage was present at power-on.
@@ -308,6 +297,23 @@ void DS1307RTC::initAlarms()
_bus->write(DS1307_NVRAM);
for (uint8_t index = DS1307_NVRAM; index < DS1307_ALARMS; ++index)
_bus->write(0);
_bus->stop();
_bus->endWrite();
}
}
uint8_t DS1307RTC::readRegister(uint8_t reg)
{
_bus->startWrite(DS1307_I2C_ADDRESS);
_bus->write(reg);
if (!_bus->startRead(DS1307_I2C_ADDRESS, 1))
return 0; // RTC chip is not responding.
return _bus->read();
}
bool DS1307RTC::writeRegister(uint8_t reg, uint8_t value)
{
_bus->startWrite(DS1307_I2C_ADDRESS);
_bus->write(reg);
_bus->write(value);
return _bus->endWrite();
}

View File

@@ -25,11 +25,11 @@
#include "RTC.h"
class BitBangI2C;
class I2CMaster;
class DS1307RTC : public RTC {
public:
DS1307RTC(BitBangI2C &bus, uint8_t oneHzPin = 255);
DS1307RTC(I2CMaster &bus, uint8_t oneHzPin = 255);
~DS1307RTC();
bool isRealTime() const { return _isRealTime; }
@@ -49,12 +49,15 @@ public:
void writeByte(uint8_t offset, uint8_t value);
private:
BitBangI2C *_bus;
I2CMaster *_bus;
uint8_t _oneHzPin;
bool prevOneHz;
bool _isRealTime;
void initAlarms();
uint8_t readRegister(uint8_t reg);
bool writeRegister(uint8_t reg, uint8_t value);
};
#endif