From e452d6aefd79d8bfb2bbf2fce32725a8d61ac009 Mon Sep 17 00:00:00 2001 From: Manjunath CV Date: Sat, 5 Jun 2021 20:28:26 +0530 Subject: [PATCH] Fixes and Examples * Epoch Bug fixes * Added Examples --- examples/DS3231/DS3231_Auto/DS3231_Auto.ino | 64 +++ examples/DS3231/DS3231_Epoch/DS3231_Epoch.ino | 47 +++ examples/DS3231/DS3231_Info/DS3231_Info.ino | 2 +- .../DS3231_Manual.ino} | 37 +- .../PCF8563_Auto/PCF8563_Auto.ino} | 18 +- .../PCF8563/PCF8563_Epoch/PCF8563_Epoch.ino | 35 ++ .../PCF8563/PCF8563_Info/PCF8563_Info.ino | 2 +- .../PCF8563/PCF8563_Manual/PCF8563_Manual.ino | 71 ++++ library.properties | 2 +- src/DS3231.cpp | 241 +++++++++-- src/PCF8563.cpp | 397 ++++++++++++------ src/RTC.h | 7 +- 12 files changed, 709 insertions(+), 214 deletions(-) create mode 100644 examples/DS3231/DS3231_Auto/DS3231_Auto.ino create mode 100644 examples/DS3231/DS3231_Epoch/DS3231_Epoch.ino rename examples/DS3231/{DS3231_M_Adjust/DS3231_M_Adjust.ino => DS3231_Manual/DS3231_Manual.ino} (75%) rename examples/{DS3231/DS3231_Adjust/DS3231_Adjust.ino => PCF8563/PCF8563_Auto/PCF8563_Auto.ino} (73%) create mode 100644 examples/PCF8563/PCF8563_Epoch/PCF8563_Epoch.ino create mode 100644 examples/PCF8563/PCF8563_Manual/PCF8563_Manual.ino diff --git a/examples/DS3231/DS3231_Auto/DS3231_Auto.ino b/examples/DS3231/DS3231_Auto/DS3231_Auto.ino new file mode 100644 index 0000000..dea7582 --- /dev/null +++ b/examples/DS3231/DS3231_Auto/DS3231_Auto.ino @@ -0,0 +1,64 @@ + +#include +#include + +static DS3231 RTC; + +void setup() +{ + Serial.begin(9600); + RTC.begin(); + + //RTC.stopClock(); + + Serial.print("Is Clock Running: "); + if (RTC.isRunning()) + { + Serial.println("Yes"); + Serial.print(RTC.getDay()); + Serial.print("-"); + Serial.print(RTC.getMonth()); + Serial.print("-"); + Serial.print(RTC.getYear()); + Serial.print(" "); + Serial.print(RTC.getHours()); + Serial.print(":"); + Serial.print(RTC.getMinutes()); + Serial.print(":"); + Serial.print(RTC.getSeconds()); + Serial.print(""); + if (RTC.getHourMode() == CLOCK_H12) + { + switch (RTC.getMeridiem()) { + case HOUR_AM: + Serial.print(" AM"); + break; + case HOUR_PM: + Serial.print(" PM"); + break; + } + } + Serial.println(""); + delay(1000); + } + else + { + delay(200); + + Serial.println("No"); + Serial.println("Setting Time"); + RTC.setHourMode(CLOCK_H12); + //RTC.setHourMode(CLOCK_H24); + RTC.setDateTime(__DATE__, __TIME__); + Serial.println("New Time Set"); + Serial.print(__DATE__); + Serial.print(" "); + Serial.println(__TIME__); + RTC.startClock(); + } +} + +void loop() +{ + +} diff --git a/examples/DS3231/DS3231_Epoch/DS3231_Epoch.ino b/examples/DS3231/DS3231_Epoch/DS3231_Epoch.ino new file mode 100644 index 0000000..f0ff430 --- /dev/null +++ b/examples/DS3231/DS3231_Epoch/DS3231_Epoch.ino @@ -0,0 +1,47 @@ +#include +#include + +static DS3231 RTC; + +void setup() +{ + Serial.begin(9600); + RTC.begin(); + + //RTC.setHourMode(CLOCK_H24); + RTC.setHourMode(CLOCK_H12); + + //RTC.setEpoch(1622904335); +} + +void loop() +{ + Serial.println(); + Serial.print("UnixTime : "); + Serial.println(RTC.getEpoch()); + + Serial.print(RTC.getDay()); + Serial.print("-"); + Serial.print(RTC.getMonth()); + Serial.print("-"); + Serial.print(RTC.getYear()); + + Serial.print(" "); + + Serial.print(RTC.getHours()); + Serial.print(":"); + Serial.print(RTC.getMinutes()); + Serial.print(":"); + Serial.print(RTC.getSeconds()); + Serial.print(" "); + + if (RTC.getHourMode() == CLOCK_H12) + { + if(RTC.getMeridiem() == HOUR_AM) + Serial.println(" AM"); + if (RTC.getMeridiem() == HOUR_PM) + Serial.println(" PM"); + } + + delay(1000); +} diff --git a/examples/DS3231/DS3231_Info/DS3231_Info.ino b/examples/DS3231/DS3231_Info/DS3231_Info.ino index 17154c8..4edbd97 100644 --- a/examples/DS3231/DS3231_Info/DS3231_Info.ino +++ b/examples/DS3231/DS3231_Info/DS3231_Info.ino @@ -11,7 +11,7 @@ void setup() DateTime A1, A2; Serial.println(); - Serial.println("*** RTC 3231 ***"); + Serial.println("*** RTC DS3231 ***"); Serial.print("Is Clock Running : "); if (RTC.isRunning()) Serial.println("Yes"); diff --git a/examples/DS3231/DS3231_M_Adjust/DS3231_M_Adjust.ino b/examples/DS3231/DS3231_Manual/DS3231_Manual.ino similarity index 75% rename from examples/DS3231/DS3231_M_Adjust/DS3231_M_Adjust.ino rename to examples/DS3231/DS3231_Manual/DS3231_Manual.ino index 0637092..b2f2211 100644 --- a/examples/DS3231/DS3231_M_Adjust/DS3231_M_Adjust.ino +++ b/examples/DS3231/DS3231_Manual/DS3231_Manual.ino @@ -8,37 +8,33 @@ void setup() Serial.begin(9600); RTC.begin(); - + RTC.setHourMode(CLOCK_H12); + //RTC.setHourMode(CLOCK_H24); if (RTC.getHourMode() == CLOCK_H12) { - // RTC.setMeridiem(HOUR_AM); + //RTC.setMeridiem(HOUR_PM); } -/* - RTC.setDay(13); - RTC.setMonth(05); + + RTC.setDay(22); + RTC.setMonth(5); RTC.setYear(2020); - RTC.setHours(9); + RTC.setHours(23); RTC.setMinutes(47); RTC.setSeconds(56); -*/ - RTC.setWeek(1); - RTC.setHourMode(CLOCK_H12); - //RTC.setHourMode(CLOCK_H24); + RTC.setWeek(1); - RTC.setDate(22,07,29); + //RTC.setDate(22,07,29); //RTC.setTime(22,10,20); - RTC.setHours(22); - - } void loop() { + switch (RTC.getWeek()) { case 1: @@ -81,15 +77,10 @@ void loop() if (RTC.getHourMode() == CLOCK_H12) { - switch (RTC.getMeridiem()) { - case HOUR_AM : - Serial.print(" AM"); - break; - case HOUR_PM : - Serial.print(" PM"); - break; - } + if(RTC.getMeridiem() == HOUR_AM) + Serial.println(" AM"); + if (RTC.getMeridiem() == HOUR_PM) + Serial.println(" PM"); } - Serial.println(""); delay(1000); } diff --git a/examples/DS3231/DS3231_Adjust/DS3231_Adjust.ino b/examples/PCF8563/PCF8563_Auto/PCF8563_Auto.ino similarity index 73% rename from examples/DS3231/DS3231_Adjust/DS3231_Adjust.ino rename to examples/PCF8563/PCF8563_Auto/PCF8563_Auto.ino index 40a3726..c2b9cf1 100644 --- a/examples/DS3231/DS3231_Adjust/DS3231_Adjust.ino +++ b/examples/PCF8563/PCF8563_Auto/PCF8563_Auto.ino @@ -2,13 +2,15 @@ #include #include -static DS3231 RTC; +static PCF8563 RTC; void setup() { Serial.begin(9600); RTC.begin(); + //RTC.stopClock(); + Serial.print("Is Clock Running: "); if (RTC.isRunning()) { @@ -25,17 +27,7 @@ void setup() Serial.print(":"); Serial.print(RTC.getSeconds()); Serial.print(""); - if (RTC.getHourMode() == CLOCK_H12) - { - switch (RTC.getMeridiem()) { - case HOUR_AM: - Serial.print(" AM"); - break; - case HOUR_PM: - Serial.print(" PM"); - break; - } - } + Serial.println(""); delay(1000); } @@ -45,8 +37,6 @@ void setup() Serial.println("No"); Serial.println("Setting Time"); - //RTC.setHourMode(CLOCK_H12); - RTC.setHourMode(CLOCK_H24); RTC.setDateTime(__DATE__, __TIME__); Serial.println("New Time Set"); Serial.print(__DATE__); diff --git a/examples/PCF8563/PCF8563_Epoch/PCF8563_Epoch.ino b/examples/PCF8563/PCF8563_Epoch/PCF8563_Epoch.ino new file mode 100644 index 0000000..b1a0327 --- /dev/null +++ b/examples/PCF8563/PCF8563_Epoch/PCF8563_Epoch.ino @@ -0,0 +1,35 @@ +#include +#include + +static PCF8563 RTC; + +void setup() +{ + Serial.begin(9600); + RTC.begin(); + + //RTC.setEpoch(0); +} + +void loop() +{ + Serial.print("UnixTime : "); + Serial.println(RTC.getEpoch()); + + Serial.print(RTC.getDay()); + Serial.print("-"); + Serial.print(RTC.getMonth()); + Serial.print("-"); + Serial.print(RTC.getYear()); + + Serial.print(" "); + + Serial.print(RTC.getHours()); + Serial.print(":"); + Serial.print(RTC.getMinutes()); + Serial.print(":"); + Serial.print(RTC.getSeconds()); + Serial.println(" "); + + delay(1000); +} diff --git a/examples/PCF8563/PCF8563_Info/PCF8563_Info.ino b/examples/PCF8563/PCF8563_Info/PCF8563_Info.ino index 56a071d..28edc4e 100644 --- a/examples/PCF8563/PCF8563_Info/PCF8563_Info.ino +++ b/examples/PCF8563/PCF8563_Info/PCF8563_Info.ino @@ -9,7 +9,7 @@ void setup() RTC.begin(); Serial.println(); - + Serial.println("*** RTC PCF8563 ***"); Serial.print("Is Clock Running : "); if (RTC.isRunning()) Serial.println("Yes"); diff --git a/examples/PCF8563/PCF8563_Manual/PCF8563_Manual.ino b/examples/PCF8563/PCF8563_Manual/PCF8563_Manual.ino new file mode 100644 index 0000000..1e61b87 --- /dev/null +++ b/examples/PCF8563/PCF8563_Manual/PCF8563_Manual.ino @@ -0,0 +1,71 @@ +#include +#include + +static PCF8563 RTC; + +void setup() { + + Serial.begin(9600); + RTC.begin(); + + /* + RTC.setDay(13); + RTC.setMonth(05); + RTC.setYear(2020); + RTC.setWeek(7); // Always Set weekday after setting Date + + RTC.setHours(9); + RTC.setMinutes(47); + RTC.setSeconds(56); + */ + + RTC.setDate(05, 06, 25); //SetDate(Day,Month,Year) + RTC.setTime(12, 14, 00); //SetTime(Hours,Minutes,Seconds) + RTC.setWeek(7); // Always Set weekday after setting Date + + //RTC.setEpoch(0); +} + +void loop() { + switch (RTC.getWeek()) { + case 1: + Serial.print("SUN"); + break; + case 2: + Serial.print("MON"); + break; + case 3: + Serial.print("TUE"); + break; + case 4: + Serial.print("WED"); + break; + case 5: + Serial.print("THU"); + break; + case 6: + Serial.print("FRI"); + break; + case 7: + Serial.print("SAT"); + break; + } + Serial.print(" "); + Serial.print(RTC.getDay()); + Serial.print("-"); + Serial.print(RTC.getMonth()); + Serial.print("-"); + Serial.print(RTC.getYear()); + + Serial.print(" "); + + Serial.print(RTC.getHours()); + Serial.print(":"); + Serial.print(RTC.getMinutes()); + Serial.print(":"); + Serial.print(RTC.getSeconds()); + Serial.print(" "); + + Serial.println(""); + delay(1000); +} diff --git a/library.properties b/library.properties index 7fdebb2..ec1326a 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=RTC -version=1.0.1 +version=1.0.2 author=Manjunath CV maintainer=Manjunath CV sentence=Library for I2C based RTCs (DS1307, DS3231, PCF8563). diff --git a/src/DS3231.cpp b/src/DS3231.cpp index 3c97eff..36a4935 100644 --- a/src/DS3231.cpp +++ b/src/DS3231.cpp @@ -356,7 +356,8 @@ void DS3231::setDay(uint8_t day) } /*----------------------------------------------------------- -getMonth (Perfect) +getMonth () + * Take Care of Century Bit -----------------------------------------------------------*/ uint8_t DS3231::getMonth() { @@ -368,19 +369,32 @@ uint8_t DS3231::getMonth() Wire.requestFrom(DS3231_ADDR, 1); month = Wire.read(); - + bitClear(month,7); //Clear Century; return (bcd2bin(month)); } /*----------------------------------------------------------- setMonth (Perfect) + * Take Care of Century Bit -----------------------------------------------------------*/ void DS3231::setMonth(uint8_t month) { + uint8_t data, century_bit; if (month >= 1 && month <= 12) { Wire.beginTransmission(DS3231_ADDR); Wire.write(0x05); // Month Register + Wire.endTransmission(); + Wire.requestFrom(DS3231_ADDR, 1); + data = Wire.read(); + + //Read Century bit and return it safe + century_bit = bitRead(data, 7); + month = bin2bcd(month); + bitWrite(month,7,century_bit); + + Wire.beginTransmission(PCF8563_ADDR); + Wire.write(0x05); // Month Register Wire.write(month); Wire.endTransmission(); } @@ -391,26 +405,70 @@ getYear (Completed) -----------------------------------------------------------*/ uint16_t DS3231::getYear() { - uint8_t data; - uint16_t year; + uint8_t century_bit,data; + uint16_t century,year; + Wire.beginTransmission(DS3231_ADDR); + Wire.write(0x05); // Read Month register for Century + Wire.endTransmission(); + Wire.requestFrom(DS3231_ADDR,1); + data = Wire.read(); + century_bit = bitRead(data, 7); + if(century_bit == 0) + { + century = 1900; + } + else + { + century = 2000; + } + + //Read Year Register and add Century Wire.beginTransmission(DS3231_ADDR); Wire.write(0x06); // Year Register Wire.endTransmission(); - Wire.requestFrom(DS3231_ADDR, 1); - data = Wire.read(); - year = bcd2bin(data) + 2000; + year = Wire.read(); + year = bcd2bin(year) + century; return (year); } void DS3231::setYear(uint16_t year) { - year = year % 100; //Converting to 2 Digit - Wire.beginTransmission(DS3231_ADDR); /* Writing 2 Digit year to Year Register(0x06) */ - Wire.write(0x06); // Year Register to write year + uint8_t century,data; + + // If year is 2 digits. + if(year < 100) + year = year + 2000; + + century = year / 100; // Find Century + year = year % 100; //Converting to 2 Digit + + Wire.beginTransmission(DS3231_ADDR); + Wire.write(0x05); // Century and month Register + Wire.endTransmission(); + + Wire.requestFrom(DS3231_ADDR, 1); + data = Wire.read(); + + // Set century bit to 1 for year > 2000; + if(century == 20) + bitSet(data,7); + else + bitClear(data,7); + + // Write Century bit to Month Register(0x05) + Wire.beginTransmission(DS3231_ADDR); + Wire.write(0x05); // Seconds Register + Wire.write(data); + Wire.endTransmission(); + + // Write 2 Digit year to Year Register(0x06) + Wire.beginTransmission(DS3231_ADDR); + Wire.write(0x06); // Year Register to write year Wire.write(bin2bcd(year)); Wire.endTransmission(); + } /*----------------------------------------------------------- @@ -470,6 +528,7 @@ void DS3231::setTime(uint8_t hours, uint8_t minutes, uint8_t seconds) /*----------------------------------------------------------- setDate + *Take Care Century Bit -----------------------------------------------------------*/ void DS3231::setDate(uint8_t day, uint8_t month, uint16_t year) { @@ -496,15 +555,15 @@ void DS3231::setDateTime(char* date, char* time) setYear(year); // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec switch (date[0]) { - case 'J': month = (date[1] == 'a') ? 1 : ((date[2] == 'n') ? 6 : 7); break; - case 'F': month = 2; break; - case 'A': month = date[2] == 'r' ? 4 : 8; break; - case 'M': month = date[2] == 'r' ? 3 : 5; break; - case 'S': month = 9; break; - case 'O': month = 10; break; - case 'N': month = 11; break; - case 'D': month = 12; break; - } + case 'J': month = (date[1] == 'a') ? 1 : ((date[2] == 'n') ? 6 : 7); break; + case 'F': month = 2; break; + case 'A': month = date[2] == 'r' ? 4 : 8; break; + case 'M': month = date[2] == 'r' ? 3 : 5; break; + case 'S': month = 9; break; + case 'O': month = 10; break; + case 'N': month = 11; break; + case 'D': month = 12; break; + } setMonth(month); day = atoi(date + 4); setDay(day); @@ -518,27 +577,109 @@ void DS3231::setDateTime(char* date, char* time) /*----------------------------------------------------------- setEpoch() + +https://en.wikipedia.org/wiki/Epoch_(computing) -----------------------------------------------------------*/ -void DS3231::setEpoch(time_t epoch, time_t e_year, int16_t offset) +void DS3231::setEpoch(time_t epoch) { - time_t rawtime; - struct tm epoch_tm, * ptr_epoch_tm; - - epoch = epoch - e_year; + uint8_t h_mode, data, century; + uint16_t year; + struct tm epoch_tm, *ptr_epoch_tm; - rawtime = epoch; - ptr_epoch_tm = gmtime(&rawtime); + ptr_epoch_tm = gmtime(&epoch); epoch_tm = *ptr_epoch_tm; - setSeconds(epoch_tm.tm_sec); //0x00 - Seconds - setMinutes(epoch_tm.tm_min); - setHours(epoch_tm.tm_hour); - setWeek(epoch_tm.tm_wday + 1); - setDay(epoch_tm.tm_mday); - setMonth(epoch_tm.tm_mon + 1); - setYear(epoch_tm.tm_year + 1900); + century = (epoch_tm.tm_year + 1870) / 100; // Find Century + year = (epoch_tm.tm_year + 1870) % 100; //Converting to 2 Digit + + + Wire.beginTransmission(DS3231_ADDR); + Wire.write(0x00); // Seconds Register + Wire.write(bin2bcd(epoch_tm.tm_sec)); //0x00 Seconds + Wire.write(bin2bcd(epoch_tm.tm_min)); //0x01 Minutes + Wire.endTransmission(); + + Wire.beginTransmission(DS3231_ADDR); + Wire.write(0x02); + Wire.endTransmission(); + + Wire.requestFrom(DS3231_ADDR, 1); + data = Wire.read(); + + h_mode = bitRead(data, 6); + + Wire.beginTransmission(DS3231_ADDR); + Wire.write(0x02); + Wire.write(bin2bcd(epoch_tm.tm_hour)); //0x02 Hours + Wire.write(bin2bcd(epoch_tm.tm_wday)); //0x03 Week Day + Wire.write(bin2bcd(epoch_tm.tm_mday)); //0x04 Date + Wire.write(bin2bcd(epoch_tm.tm_mon+1)); //0x05 Month + Wire.write(bin2bcd(year)); //0x06 Year + Wire.endTransmission(); + + /* Convert time to 24Hour if it is in 12 Hour */ + + + + + if (h_mode == CLOCK_H12) + { + Serial.println("I'm here!"); + Wire.beginTransmission(DS3231_ADDR); + Wire.write(0x02); // Hour Register + + if (epoch_tm.tm_hour == 0) + { + epoch_tm.tm_hour = bin2bcd(12); + bitSet(epoch_tm.tm_hour, 6); + bitClear(epoch_tm.tm_hour, 5); + Wire.write(epoch_tm.tm_hour); + } + else if (epoch_tm.tm_hour <= 11) + { + epoch_tm.tm_hour = bin2bcd(epoch_tm.tm_hour); + bitSet(epoch_tm.tm_hour, 6); + bitClear(epoch_tm.tm_hour, 5); + Wire.write(epoch_tm.tm_hour); + } + else if (epoch_tm.tm_hour == 12) + { + epoch_tm.tm_hour = bin2bcd(epoch_tm.tm_hour); + bitSet(epoch_tm.tm_hour, 6); + bitSet(epoch_tm.tm_hour, 5); + Wire.write(epoch_tm.tm_hour); + } + else + { + epoch_tm.tm_hour -= 12; + epoch_tm.tm_hour = bin2bcd(epoch_tm.tm_hour); + bitSet(epoch_tm.tm_hour, 6); + bitSet(epoch_tm.tm_hour, 5); + Wire.write(epoch_tm.tm_hour); + } + Wire.endTransmission(); + } + /* Write Century Bit to Century Month Register (0x05) */ + + Wire.beginTransmission(DS3231_ADDR); + Wire.write(0x05); // Century and month Register + Wire.endTransmission(); + + Wire.requestFrom(DS3231_ADDR, 1); + data = Wire.read(); + + // Set century bit to 1 for year > 2000; + if(century == 20) + bitSet(data,7); + else + bitClear(data,7); + + // Write Century bit to Month Register(0x05) + Wire.beginTransmission(DS3231_ADDR); + Wire.write(0x05); // + Wire.write(data); Wire.endTransmission(); } @@ -547,19 +688,37 @@ getEpoch() -----------------------------------------------------------*/ time_t DS3231::getEpoch() { + uint8_t century_bit; + uint16_t century; time_t epoch; struct tm epoch_tm; - epoch_tm.tm_sec = getSeconds(); - epoch_tm.tm_min = getMinutes(); - epoch_tm.tm_hour = getHours(); - epoch_tm.tm_wday = getWeek() - 1; - epoch_tm.tm_mday = getDay(); - epoch_tm.tm_mon = getMonth() - 1; - epoch_tm.tm_year = getYear() - 1900; + Wire.beginTransmission(DS3231_ADDR); + Wire.write(0x00); // Seconds Register + Wire.endTransmission(); + Wire.requestFrom(DS3231_ADDR,7); + + epoch_tm.tm_sec = bcd2bin(Wire.read()); //0x00 Seconds + epoch_tm.tm_min = bcd2bin(Wire.read()); //0x01 Minutes + epoch_tm.tm_hour = bcd2bin(Wire.read()); //0x02 Hours + epoch_tm.tm_wday = bcd2bin(Wire.read()); //0x03 Week Day + epoch_tm.tm_mday = bcd2bin(Wire.read()); //0x04 Date + epoch_tm.tm_mon = Wire.read(); //0x05 Months + epoch_tm.tm_year = bcd2bin(Wire.read()); //0x06 Years + + // Read Century Bit from Month Register + century_bit = bitRead(epoch_tm.tm_mon, 7); + bitClear(epoch_tm.tm_mon,7); + epoch_tm.tm_mon = bcd2bin(epoch_tm.tm_mon)-1; + + if(century_bit == 0) + century = 1900; + else + century = 2000; - epoch = mktime(&epoch_tm); + epoch_tm.tm_year = epoch_tm.tm_year + century - 1870; + epoch = mktime(&epoch_tm); return (epoch); } diff --git a/src/PCF8563.cpp b/src/PCF8563.cpp index 19ab6e8..e9cee50 100644 --- a/src/PCF8563.cpp +++ b/src/PCF8563.cpp @@ -55,21 +55,21 @@ void PCF8563::startClock(void) //Not Updated void PCF8563::stopClock(void) //Not Updated { - uint8_t data; + uint8_t data; - Wire.beginTransmission(PCF8563_ADDR); - Wire.write(0x00); - Wire.endTransmission(); + Wire.beginTransmission(PCF8563_ADDR); + Wire.write(0x00); + Wire.endTransmission(); - Wire.requestFrom(PCF8563_ADDR, 1); - data = Wire.read(); + Wire.requestFrom(PCF8563_ADDR, 1); + data = Wire.read(); - bitSet(data, 5); + bitSet(data, 5); - Wire.beginTransmission(PCF8563_ADDR); - Wire.write(0x00); // Seconds Register - Wire.write(data); - Wire.endTransmission(); + Wire.beginTransmission(PCF8563_ADDR); + Wire.write(0x00); // Seconds Register + Wire.write(data); + Wire.endTransmission(); } /*----------------------------------------------------------- @@ -148,21 +148,21 @@ getWeek -----------------------------------------------------------*/ uint8_t PCF8563::getWeek() { - uint8_t week; - Wire.beginTransmission(PCF8563_ADDR); - Wire.write(0x06); // Week Register - Wire.endTransmission(); - Wire.requestFrom(PCF8563_ADDR, 1); - week = Wire.read(); - return week; + uint8_t week; + Wire.beginTransmission(PCF8563_ADDR); + Wire.write(0x06); // Week Register + Wire.endTransmission(); + Wire.requestFrom(PCF8563_ADDR, 1); + week = Wire.read(); + return week+1; } void PCF8563::setWeek(uint8_t week) { - Wire.beginTransmission(PCF8563_ADDR); - Wire.write(0x06); // Minute Register - Wire.write(week); - Wire.endTransmission(); + Wire.beginTransmission(PCF8563_ADDR); + Wire.write(0x06); // Week Register + Wire.write(week-1); + Wire.endTransmission(); } /*----------------------------------------------------------- @@ -192,51 +192,122 @@ getMonth() -----------------------------------------------------------*/ uint8_t PCF8563::getMonth() { - uint8_t month; - Wire.beginTransmission(PCF8563_ADDR); - Wire.write(0x07); // Month Register - Wire.endTransmission(); - Wire.requestFrom(PCF8563_ADDR, 1); - month = Wire.read(); - return (bcd2bin(month)); + uint8_t month; + Wire.beginTransmission(PCF8563_ADDR); + Wire.write(0x07); // Month Register + Wire.endTransmission(); + Wire.requestFrom(PCF8563_ADDR, 1); + month = Wire.read(); + bitClear(month,7); //Clear Century; + return (bcd2bin(month)); } /*----------------------------------------------------------- -setMonth() +setMonth() -----------------------------------------------------------*/ void PCF8563::setMonth(uint8_t month) { - Wire.beginTransmission(PCF8563_ADDR); - Wire.write(0x07); // Month Register - Wire.write(bin2bcd(month)); - Wire.endTransmission(); + uint8_t data, century_bit; + if (month >= 1 && month <= 12) + { + + Wire.beginTransmission(PCF8563_ADDR); + Wire.write(0x07); // Month Register + Wire.endTransmission(); + Wire.requestFrom(PCF8563_ADDR, 1); + data = Wire.read(); + + //Read Century bit and return it safe + century_bit = bitRead(data, 7); + month = bin2bcd(month); + bitWrite(month,7,century_bit); + + Wire.beginTransmission(PCF8563_ADDR); + Wire.write(0x07); // Month Register + Wire.write(month); + Wire.endTransmission(); + } } /*----------------------------------------------------------- getYear (Completed) + * Always return 4 Digit year + * Takes Care of Century. -----------------------------------------------------------*/ uint16_t PCF8563::getYear() { - uint16_t year; - - Wire.beginTransmission(PCF8563_ADDR); - Wire.write(0x08); // Year Register - Wire.endTransmission(); - - Wire.requestFrom(PCF8563_ADDR, 1); - year = Wire.read(); - return (bcd2bin(year)+2000); + uint8_t century_bit,data; + uint16_t century,year; + + Wire.beginTransmission(PCF8563_ADDR); + Wire.write(0x07); // Read Month register for Century + Wire.endTransmission(); + Wire.requestFrom(PCF8563_ADDR,1); + data = Wire.read(); + century_bit = bitRead(data, 7); + if(century_bit == 0) + { + century = 1900; + } + else + { + century = 2000; + } + + //Read Year Register and add Century + Wire.beginTransmission(PCF8563_ADDR); + Wire.write(0x08); // Year Register + Wire.endTransmission(); + Wire.requestFrom(PCF8563_ADDR, 1); + year = Wire.read(); + year = bcd2bin(year) + century; + return (year); } +/*----------------------------------------------------------- +setYear (Completed) + * Takes Care of Century. + * Accepts both 2 and 4 Digit Years. +-----------------------------------------------------------*/ void PCF8563::setYear(uint16_t year) { - year = year % 100; //Converting to 2 Digit + uint8_t century,data; + + // If year is 2 digits. + if(year < 100) + year = year + 2000; - /*Writing 2 Digit year to Year Register(0x06)*/ - Wire.beginTransmission(PCF8563_ADDR); - Wire.write(0x08); // Year Register to write year - Wire.write(bin2bcd(year)); - Wire.endTransmission(); + century = year / 100; // Find Century + year = year % 100; //Converting to 2 Digit + + Wire.beginTransmission(PCF8563_ADDR); + Wire.write(0x07); // Century and month Register + Wire.endTransmission(); + + Wire.requestFrom(PCF8563_ADDR, 1); + data = Wire.read(); + + // Set century bit to 1 for year > 2000; + if(century == 20) + { + bitSet(data,7); + } + else + { + bitClear(data,7); + } + + // Write Century bit to Month Register(0x07) + Wire.beginTransmission(PCF8563_ADDR); + Wire.write(0x07); // Month Register + Wire.write(data); + Wire.endTransmission(); + + // Write 2 Digit year to Year Register(0x08) + Wire.beginTransmission(PCF8563_ADDR); + Wire.write(0x08); // Year Register to write year + Wire.write(bin2bcd(year)); + Wire.endTransmission(); } /*----------------------------------------------------------- @@ -247,26 +318,52 @@ void PCF8563::setTime(uint8_t hour, uint8_t minute, uint8_t second) { Wire.beginTransmission(PCF8563_ADDR); Wire.write(0x02); // Year Register - Wire.write(bin2bcd(second)); - Wire.write(bin2bcd(minute)); - Wire.write(bin2bcd(hour)); + Wire.write(bin2bcd(second)); //0x02 Seconds + Wire.write(bin2bcd(minute)); //0x03 Minutes + Wire.write(bin2bcd(hour)); //0x04 Hours Wire.endTransmission(); } /*----------------------------------------------------------- -setDate (Should be Optimised) +setDate (Should be Optimised and add Century) -----------------------------------------------------------*/ void PCF8563::setDate(uint8_t day, uint8_t month, uint16_t year) { - year = year % 100; //Converting to 2 Digit + uint8_t century, data; + + // If year is 2 digits. + if(year < 100) + year = year + 2000; + + century = year / 100; // Find Century + year = year % 100; //Converting to 2 Digit - Wire.beginTransmission(PCF8563_ADDR); - Wire.write(0x05); - Wire.write(bin2bcd(day)); - Wire.write(0); //Weekday Resets to Zero! - Wire.write(bin2bcd(month)); - Wire.write(bin2bcd(year)); - Wire.endTransmission(); + Wire.beginTransmission(PCF8563_ADDR); + Wire.write(0x05); + Wire.write(bin2bcd(day)); //0x05 Day + Wire.write(0); //0x06 Weekday + Wire.write(bin2bcd(month)); //0x07 Months + Wire.write(bin2bcd(year)); //0x08 Years + Wire.endTransmission(); + + Wire.beginTransmission(PCF8563_ADDR); + Wire.write(0x07); // Century and month Register + Wire.endTransmission(); + + Wire.requestFrom(PCF8563_ADDR, 1); + data = Wire.read(); + + // Set century bit to 1 for year > 2000; + if(century == 20) + bitSet(data,7); + else + bitClear(data,7); + + // Write Century bit to Month Register(0x07) + Wire.beginTransmission(PCF8563_ADDR); + Wire.write(0x07); // + Wire.write(data); + Wire.endTransmission(); } /*----------------------------------------------------------- @@ -276,76 +373,118 @@ Taken from https://github.com/adafruit/RTClib/ void PCF8563::setDateTime(char* date, char* time) { - uint8_t day, month, hour, minute, second; - uint16_t year; -// sample input: date = "Dec 26 2009", time = "12:34:56" - year = atoi(date + 9); - setYear(year); - // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec - switch (date[0]) { - case 'J': month = (date[1] == 'a') ? 1 : ((date[2] == 'n') ? 6 : 7); break; - case 'F': month = 2; break; - case 'A': month = date[2] == 'r' ? 4 : 8; break; - case 'M': month = date[2] == 'r' ? 3 : 5; break; - case 'S': month = 9; break; - case 'O': month = 10; break; - case 'N': month = 11; break; - case 'D': month = 12; break; - } - setMonth(month); - day = atoi(date + 4); - setDay(day); - hour = atoi(time); - setHours(hour); - minute = atoi(time + 3); - setMinutes(minute); - second = atoi(time + 6); - setSeconds(second); + uint8_t day, month, hour, minute, second; + uint16_t year; + // sample input: date = "Dec 26 2009", time = "12:34:56" + year = atoi(date + 9); + setYear(year); + // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec + switch (date[0]) { + case 'J': month = (date[1] == 'a') ? 1 : ((date[2] == 'n') ? 6 : 7); break; + case 'F': month = 2; break; + case 'A': month = date[2] == 'r' ? 4 : 8; break; + case 'M': month = date[2] == 'r' ? 3 : 5; break; + case 'S': month = 9; break; + case 'O': month = 10; break; + case 'N': month = 11; break; + case 'D': month = 12; break; + } + setMonth(month); + day = atoi(date + 4); + setDay(day); + hour = atoi(time); + setHours(hour); + minute = atoi(time + 3); + setMinutes(minute); + second = atoi(time + 6); + setSeconds(second); } /*----------------------------------------------------------- setEpoch() + * Weekday Might not work properly -----------------------------------------------------------*/ void PCF8563::setEpoch(time_t epoch) { - time_t rawtime; - struct tm epoch_tm , *ptr_epoch_tm; - uint16_t year; - - rawtime = epoch; - ptr_epoch_tm = gmtime(&rawtime); - epoch_tm = *ptr_epoch_tm; - - setSeconds(epoch_tm.tm_sec); //0x00 - Seconds - setMinutes(epoch_tm.tm_min); - setHours(epoch_tm.tm_hour); - setWeek(epoch_tm.tm_wday+1); - setDay(epoch_tm.tm_mday); - setMonth(epoch_tm.tm_mon+1); - setYear(epoch_tm.tm_year+1900); - - Wire.endTransmission(); + uint8_t data, century; + uint16_t year; + struct tm epoch_tm, *ptr_epoch_tm; + + ptr_epoch_tm = gmtime(&epoch); + epoch_tm = *ptr_epoch_tm; + + century = (epoch_tm.tm_year + 1870) / 100; // Find Century + year = (epoch_tm.tm_year + 1870) % 100; //Converting to 2 Digit + + Wire.beginTransmission(PCF8563_ADDR); + Wire.write(0x02); // Seconds Register + Wire.write(bin2bcd(epoch_tm.tm_sec)); //0x02 + Wire.write(bin2bcd(epoch_tm.tm_min)); //0x03 + Wire.write(bin2bcd(epoch_tm.tm_hour)); //0x04 + Wire.write(bin2bcd(epoch_tm.tm_mday)); //0x05 + Wire.write(bin2bcd(epoch_tm.tm_wday)); //0x06 + Wire.write(bin2bcd(epoch_tm.tm_mon+1)); //0x07 + Wire.write(bin2bcd(year)); //0x08 + Wire.endTransmission(); + + Wire.beginTransmission(PCF8563_ADDR); + Wire.write(0x07); // Century and month Register + Wire.endTransmission(); + + Wire.requestFrom(PCF8563_ADDR, 1); + data = Wire.read(); + + // Set century bit to 1 for year > 2000; + if(century == 20) + bitSet(data,7); + else + bitClear(data,7); + + // Write Century bit to Month Register(0x07) + Wire.beginTransmission(PCF8563_ADDR); + Wire.write(0x07); // + Wire.write(data); + Wire.endTransmission(); } /*----------------------------------------------------------- getEpoch() + * Weekday Might not work properly -----------------------------------------------------------*/ time_t PCF8563::getEpoch() { - time_t epoch; - struct tm epoch_tm; - - epoch_tm.tm_sec = getSeconds(); - epoch_tm.tm_min = getMinutes(); - epoch_tm.tm_hour = getHours(); - epoch_tm.tm_wday = getWeek() - 1; - epoch_tm.tm_mday = getDay(); - epoch_tm.tm_mon = getMonth() - 1; - epoch_tm.tm_year = getYear() - 1900; - - epoch = mktime (&epoch_tm); + uint8_t century_bit; + uint16_t century; + time_t epoch; + struct tm epoch_tm; + + Wire.beginTransmission(PCF8563_ADDR); + Wire.write(0x02); // Seconds Register + Wire.endTransmission(); + Wire.requestFrom(PCF8563_ADDR,7); + + epoch_tm.tm_sec = bcd2bin(Wire.read()); //0x02 Seconds + epoch_tm.tm_min = bcd2bin(Wire.read()); //0x03 Minutes + epoch_tm.tm_hour = bcd2bin(Wire.read()); //0x04 Hours + epoch_tm.tm_mday = bcd2bin(Wire.read()); //0x05 Day + epoch_tm.tm_wday = bcd2bin(Wire.read()); //0x06 Weekday + epoch_tm.tm_mon = Wire.read(); //0x07 Months + epoch_tm.tm_year = bcd2bin(Wire.read()); //0x08 Years + + // Read Century Bit from Month Register + century_bit = bitRead(epoch_tm.tm_mon, 7); + bitClear(epoch_tm.tm_mon,7); + epoch_tm.tm_mon = bcd2bin(epoch_tm.tm_mon)-1; + + if(century_bit == 0) + century = 1900; + else + century = 2000; + + epoch_tm.tm_year = epoch_tm.tm_year + century - 1870; + epoch = mktime(&epoch_tm); return (epoch); } @@ -386,24 +525,24 @@ void PCF8563::disableAlarm() void PCF8563::setAlarm(uint8_t hours, uint8_t minutes) { - Wire.beginTransmission(PCF8563_ADDR); - Wire.write(0x09); - Wire.write(bin2bcd(minutes)); - Wire.write(bin2bcd(hours)); - Wire.write(0x80); - Wire.write(0x80); - Wire.endTransmission(); + Wire.beginTransmission(PCF8563_ADDR); + Wire.write(0x09); + Wire.write(bin2bcd(minutes)); + Wire.write(bin2bcd(hours)); + Wire.write(0x80); + Wire.write(0x80); + Wire.endTransmission(); } void PCF8563::setAlarm(uint8_t week,uint8_t day, uint8_t hours, uint8_t minutes) { - Wire.beginTransmission(PCF8563_ADDR); - Wire.write(0x09); - Wire.write(bin2bcd(minutes)); - Wire.write(bin2bcd(hours)); - Wire.write(bin2bcd(day)); - Wire.write(bin2bcd(week)); - Wire.endTransmission(); + Wire.beginTransmission(PCF8563_ADDR); + Wire.write(0x09); + Wire.write(bin2bcd(minutes)); + Wire.write(bin2bcd(hours)); + Wire.write(bin2bcd(day)); + Wire.write(bin2bcd(week)); + Wire.endTransmission(); } diff --git a/src/RTC.h b/src/RTC.h index 88cb1f4..e9b6f45 100644 --- a/src/RTC.h +++ b/src/RTC.h @@ -50,7 +50,7 @@ class DateTime { uint8_t day; uint8_t week; uint8_t month; - uint16_t year; + uint16_t year; }; @@ -151,7 +151,8 @@ class DS3231 { void setDate(uint8_t day, uint8_t month, uint16_t year); void setTime(uint8_t hour, uint8_t minute, uint8_t second); - void setEpoch(time_t epoch, time_t e_year, int16_t offset); + void setEpoch(time_t epoch); + time_t getEpoch(); void setDateTime(char* date, char* time); @@ -164,8 +165,6 @@ class DS3231 { uint8_t getWeek(); - time_t getEpoch(); - void enableAlarmPin(); void enableAlarm1();