first commit
This commit is contained in:
165
libraries/Rtc_by_Makuna/COPYING
Normal file
165
libraries/Rtc_by_Makuna/COPYING
Normal file
@@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
24
libraries/Rtc_by_Makuna/README.md
Normal file
24
libraries/Rtc_by_Makuna/README.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Rtc
|
||||
|
||||
Arduino Real Time Clock library.
|
||||
An RTC library with deep device support.
|
||||
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6AA97KE54UJR4)
|
||||
|
||||
For quick questions and support:
|
||||
* [Try the new Github Discussions](https://github.com/Makuna/Rtc/discussions)
|
||||
* Or, jump on Gitter
|
||||
[](https://gitter.im/Makuna/Rtc?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
|
||||
For bugs, make sure there isn't an active issue and then create one.
|
||||
|
||||
## Documentation
|
||||
[See Wiki](https://github.com/Makuna/Rtc/wiki)
|
||||
|
||||
## Installing This Library (prefered, you just want to use it)
|
||||
Open the Library Manager and search for "Rtc by Makuna" and install
|
||||
|
||||
## Installing This Library From GitHub (advanced, you want to contribute)
|
||||
Create a directory in your Arduino\Library folder named "Rtc"
|
||||
Clone (Git) this project into that folder.
|
||||
It should now show up in the import list when you restart Arduino IDE.
|
||||
8
libraries/Rtc_by_Makuna/SUPPORT.md
Normal file
8
libraries/Rtc_by_Makuna/SUPPORT.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Support
|
||||
|
||||
For questions and help, jump on Gitter and ask away.
|
||||
[](https://gitter.im/Makuna/Rtc?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
|
||||
For documentation [See the Wiki](https://github.com/Makuna/Rtc/wiki)
|
||||
|
||||
For bugs, make sure there isn't an active issue and then create one. Understand that issues are for bugs found in the library and not issues you are having with the library.
|
||||
@@ -0,0 +1,175 @@
|
||||
|
||||
// CONNECTIONS:
|
||||
// At24c32 SDA --> SDA
|
||||
// At24c32 SCL --> SCL
|
||||
// At24c32 VCC --> 5v
|
||||
// At24c32 GND --> GND
|
||||
|
||||
/* for software wire use below
|
||||
#include <SoftwareWire.h> // must be included here so that Arduino library object file references work
|
||||
#include <EepromAT24C32.h>
|
||||
|
||||
SoftwareWire myWire(SDA, SCL);
|
||||
EepromAt24c32<SoftwareWire> Rtc(myWire);
|
||||
/* for software wire use above */
|
||||
|
||||
/* for normal hardware wire use below */
|
||||
#include <Wire.h> // must be included here so that Arduino library object file references work
|
||||
#include <EepromAT24C32.h>
|
||||
|
||||
EepromAt24c32<TwoWire> RtcEeprom(Wire);
|
||||
|
||||
// if the above doesn't work, and you don't have "address" pads or switches on
|
||||
// the board to set the address, then try the common address of 7
|
||||
// EepromAt24c32<TwoWire> RtcEeprom(Wire, 0b111);
|
||||
//
|
||||
// If you have any of the address pads on the board soldered together
|
||||
// then you need to provide the state of those pads, normally they
|
||||
// are connected to vcc with a reading of 1, if soldered they are
|
||||
// grounded with a reading of 0. The bits are in the order A2 A1 A0
|
||||
// thus the following would have the A2 soldered together
|
||||
// EepromAt24c32<TwoWire> RtcEeprom(Wire, 0b011);
|
||||
|
||||
/* for normal hardware wire use above */
|
||||
|
||||
// nothing longer than 32 bytes
|
||||
// rtc eeprom memory is 32 byte pages
|
||||
// writing is limited to each page, so it will wrap at page
|
||||
// boundaries.
|
||||
// But reading is only limited by the buffer in Wire class which
|
||||
// by default is 32
|
||||
|
||||
// example settings objec that will be serialized into and out of EEPROM
|
||||
struct Settings
|
||||
{
|
||||
uint8_t size; // size of this structure for versioning/validation
|
||||
uint8_t value1 : 6; // only 6 bits (0-63)
|
||||
uint8_t value2 : 6; // only 6 bits (0-63)
|
||||
uint8_t value3 : 6; // only 6 bits (0-63)
|
||||
uint32_t value4;
|
||||
};
|
||||
|
||||
// where in EEPROM we will store the settings
|
||||
const uint8_t SettingsAddress = 0;
|
||||
|
||||
// handy routine to return true if there was an error
|
||||
// but it will also print out an error message with the given topic
|
||||
bool wasError(const char* errorTopic = "")
|
||||
{
|
||||
uint8_t error = RtcEeprom.LastError();
|
||||
if (error != 0)
|
||||
{
|
||||
// we have a communications error
|
||||
// see https://www.arduino.cc/reference/en/language/functions/communication/wire/endtransmission/
|
||||
// for what the number means
|
||||
Serial.print("[");
|
||||
Serial.print(errorTopic);
|
||||
Serial.print("] WIRE communications error (");
|
||||
Serial.print(error);
|
||||
Serial.print(") : ");
|
||||
|
||||
switch (error)
|
||||
{
|
||||
case Rtc_Wire_Error_None:
|
||||
Serial.println("(none?!)");
|
||||
break;
|
||||
case Rtc_Wire_Error_TxBufferOverflow:
|
||||
Serial.println("transmit buffer overflow");
|
||||
break;
|
||||
case Rtc_Wire_Error_NoAddressableDevice:
|
||||
Serial.println("no device responded");
|
||||
break;
|
||||
case Rtc_Wire_Error_UnsupportedRequest:
|
||||
Serial.println("device doesn't support request");
|
||||
break;
|
||||
case Rtc_Wire_Error_Unspecific:
|
||||
Serial.println("unspecified error");
|
||||
break;
|
||||
case Rtc_Wire_Error_CommunicationTimeout:
|
||||
Serial.println("communications timed out");
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
//--------RTC EEPROM SETUP ------------
|
||||
// if you are using ESP-01 then uncomment the line below to define pins for
|
||||
// those available for SDA, SCL
|
||||
// RtcEeprom.Begin(0, 2); // due to limited pins, use pin 0 and 2 for SDA, SCL
|
||||
|
||||
RtcEeprom.Begin();
|
||||
#if defined(WIRE_HAS_TIMEOUT)
|
||||
Wire.setWireTimeout(3000 /* us */, true /* reset_on_timeout */);
|
||||
#endif
|
||||
|
||||
/* comment out on a second run to see that the info is stored long term */
|
||||
// Store something in memory on the Eeprom
|
||||
{
|
||||
Settings mySettings =
|
||||
{
|
||||
sizeof(Settings), // size
|
||||
42, // value1
|
||||
21, // value2
|
||||
7, // value3
|
||||
18875, // value4
|
||||
};
|
||||
|
||||
// store the settings, nothing longer than 32 bytes due to paging
|
||||
uint8_t written = RtcEeprom.SetMemory(SettingsAddress,
|
||||
reinterpret_cast<const uint8_t*>(&mySettings),
|
||||
sizeof(mySettings));
|
||||
wasError("setup setMemory settings");
|
||||
}
|
||||
/* end of comment out section */
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
delay(5000);
|
||||
|
||||
// read data
|
||||
{
|
||||
Settings retrievedSettings = { 0, 0, 0, 0, 0 }; // init to zero
|
||||
|
||||
// get our data from the address with the given size
|
||||
uint8_t gotten = RtcEeprom.GetMemory(SettingsAddress,
|
||||
reinterpret_cast<uint8_t*>(&retrievedSettings),
|
||||
sizeof(Settings));
|
||||
if (!wasError("loop getMemory settings"))
|
||||
{
|
||||
if (gotten != sizeof(Settings) ||
|
||||
retrievedSettings.size != sizeof(Settings))
|
||||
{
|
||||
Serial.print("something didn't match, requested = ");
|
||||
Serial.print(sizeof(Settings));
|
||||
Serial.print(", gotten = ");
|
||||
Serial.print(gotten);
|
||||
Serial.print(", size = ");
|
||||
Serial.print(retrievedSettings.size);
|
||||
Serial.println();
|
||||
}
|
||||
Serial.print("data read (");
|
||||
Serial.print(gotten);
|
||||
Serial.println(")");
|
||||
Serial.print(" size = ");
|
||||
Serial.println(retrievedSettings.size);
|
||||
Serial.print(" value1 = ");
|
||||
Serial.println(retrievedSettings.value1);
|
||||
Serial.print(" value2 = ");
|
||||
Serial.println(retrievedSettings.value2);
|
||||
Serial.print(" value3 = ");
|
||||
Serial.println(retrievedSettings.value3);
|
||||
Serial.print(" value4 = ");
|
||||
Serial.println(retrievedSettings.value4);
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
102
libraries/Rtc_by_Makuna/examples/AlarmManager/AlarmManager.ino
Normal file
102
libraries/Rtc_by_Makuna/examples/AlarmManager/AlarmManager.ino
Normal file
@@ -0,0 +1,102 @@
|
||||
#include "RtcAlarmManager.h"
|
||||
#include <Wire.h>
|
||||
#include <RtcDS1307.h> // Replace with the RTC you have
|
||||
|
||||
// foreward declare our alarm manager callback
|
||||
void alarmCallback(uint8_t id, const RtcDateTime& alarm);
|
||||
// global instance of the manager with three possible alarms
|
||||
RtcAlarmManager<alarmCallback> Alarms(3);
|
||||
|
||||
// Replace with the RTC you have
|
||||
RtcDS1307<TwoWire> Rtc(Wire);
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
Serial.println("Initializing...");
|
||||
|
||||
//--------RTC SETUP ------------
|
||||
Rtc.Begin();
|
||||
#if defined(WIRE_HAS_TIMEOUT)
|
||||
Wire.setWireTimeout(3000 /* us */, true /* reset_on_timeout */);
|
||||
#endif
|
||||
|
||||
// get the real date and time from a source like an already
|
||||
// configured RTC module
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
// Sync the Alarms to current time
|
||||
Alarms.Sync(now);
|
||||
|
||||
// NOTE: Due to this sketch not deleting alarms, the returned ids from
|
||||
// AddAlarm can be assumed to start at zero and increment from there.
|
||||
// Otherwise the ids would need to be captured and used in the callback
|
||||
//
|
||||
int8_t result;
|
||||
// add an alarm to sync time from rtc at a regular interval,
|
||||
// due to CPU timing variance, the Alarms time can get off over
|
||||
// time, so this alarm will trigger a resync every 20 minutes
|
||||
result = Alarms.AddAlarm(now, 20 * c_MinuteAsSeconds); // every 20 minutes
|
||||
if (result < 0)
|
||||
{
|
||||
// an error happened
|
||||
Serial.print("AddAlarm Sync failed : ");
|
||||
Serial.print(result);
|
||||
}
|
||||
|
||||
// add a daily alarm at 5:30am
|
||||
RtcDateTime working(now.Year(), now.Month(), now.Day(), 5, 30, 0);
|
||||
result = Alarms.AddAlarm(working, AlarmPeriod_Daily);
|
||||
if (result < 0)
|
||||
{
|
||||
// an error happened
|
||||
Serial.print("AddAlarm Daily failed : ");
|
||||
Serial.print(result);
|
||||
}
|
||||
|
||||
// add a weekly alarm for Saturday at 7:30am
|
||||
working = RtcDateTime(now.Year(), now.Month(), now.Day(), 7, 30, 0);
|
||||
working = working.NextDayOfWeek(DayOfWeek_Saturday);
|
||||
result = Alarms.AddAlarm(working, AlarmPeriod_Weekly);
|
||||
if (result < 0)
|
||||
{
|
||||
// an error happened
|
||||
Serial.print("AddAlarm Weekly failed : ");
|
||||
Serial.print(result);
|
||||
}
|
||||
|
||||
Serial.println("Running...");
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
delay(1000); // simulating other work your sketch will do
|
||||
Alarms.ProcessAlarms();
|
||||
}
|
||||
|
||||
void alarmCallback(uint8_t id, [[maybe_unused]] const RtcDateTime& alarm)
|
||||
{
|
||||
// NOTE: Due to this sketch not deleting alarms, the returned ids from
|
||||
// AddAlarm can be assumed to start at zero and increment from there.
|
||||
// Otherwise the ids would need to be captured and used here
|
||||
//
|
||||
switch (id)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
// periodic sync from trusted source to minimize
|
||||
// drift due to inaccurate CPU timing
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
Alarms.Sync(now);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
Serial.println("DAILY ALARM: Its 5:30am!");
|
||||
break;
|
||||
|
||||
case 2:
|
||||
Serial.println("WEEKLY ALARM: Its Saturday at 7:30am!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
134
libraries/Rtc_by_Makuna/examples/DS1302_Memory/DS1302_Memory.ino
Normal file
134
libraries/Rtc_by_Makuna/examples/DS1302_Memory/DS1302_Memory.ino
Normal file
@@ -0,0 +1,134 @@
|
||||
|
||||
// CONNECTIONS:
|
||||
// DS1302 CLK/SCLK --> 5
|
||||
// DS1302 DAT/IO --> 4
|
||||
// DS1302 RST/CE --> 2
|
||||
// DS1302 VCC --> 3.3v - 5v
|
||||
// DS1302 GND --> GND
|
||||
|
||||
#include <RtcDS1302.h>
|
||||
|
||||
ThreeWire myWire(4,5,2); // IO, SCLK, CE
|
||||
RtcDS1302<ThreeWire> Rtc(myWire);
|
||||
|
||||
#define countof(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
const char data[] = "what time is it";
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(57600);
|
||||
|
||||
Serial.print("compiled: ");
|
||||
Serial.print(__DATE__);
|
||||
Serial.println(__TIME__);
|
||||
|
||||
Rtc.Begin();
|
||||
|
||||
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
|
||||
printDateTime(compiled);
|
||||
Serial.println();
|
||||
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
|
||||
if (Rtc.GetIsWriteProtected())
|
||||
{
|
||||
Serial.println("RTC was write protected, enabling writing now");
|
||||
Rtc.SetIsWriteProtected(false);
|
||||
}
|
||||
|
||||
if (!Rtc.GetIsRunning())
|
||||
{
|
||||
Serial.println("RTC was not actively running, starting now");
|
||||
Rtc.SetIsRunning(true);
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (now < compiled)
|
||||
{
|
||||
Serial.println("RTC is older than compile time! (Updating DateTime)");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
|
||||
|
||||
/* comment out on a second run to see that the info is stored long term */
|
||||
// Store something in memory on the RTC
|
||||
uint8_t count = sizeof(data);
|
||||
uint8_t written = Rtc.SetMemory((const uint8_t*)data, count); // this includes a null terminator for the string
|
||||
if (written != count)
|
||||
{
|
||||
Serial.print("something didn't match, count = ");
|
||||
Serial.print(count, DEC);
|
||||
Serial.print(", written = ");
|
||||
Serial.print(written, DEC);
|
||||
Serial.println();
|
||||
}
|
||||
/* end of comment out section */
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
|
||||
printDateTime(now);
|
||||
Serial.println(" +");
|
||||
|
||||
if (!now.IsValid())
|
||||
{
|
||||
// Common Causes:
|
||||
// 1) the battery on the device is low or even missing and the power line was disconnected
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
}
|
||||
|
||||
delay(5000);
|
||||
|
||||
// read data
|
||||
uint8_t buff[20];
|
||||
const uint8_t count = sizeof(buff);
|
||||
// get our data
|
||||
uint8_t gotten = Rtc.GetMemory(buff, count);
|
||||
|
||||
if (gotten != count)
|
||||
{
|
||||
Serial.print("something didn't match, count = ");
|
||||
Serial.print(count, DEC);
|
||||
Serial.print(", gotten = ");
|
||||
Serial.print(gotten, DEC);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
Serial.print("data read (");
|
||||
Serial.print(gotten);
|
||||
Serial.print(") = \"");
|
||||
// print the string, but terminate if we get a null
|
||||
for (uint8_t ch = 0; ch < gotten && buff[ch]; ch++)
|
||||
{
|
||||
Serial.print((char)buff[ch]);
|
||||
}
|
||||
Serial.println("\"");
|
||||
|
||||
delay(5000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void printDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
char datestring[26];
|
||||
|
||||
snprintf_P(datestring,
|
||||
countof(datestring),
|
||||
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
|
||||
dt.Month(),
|
||||
dt.Day(),
|
||||
dt.Year(),
|
||||
dt.Hour(),
|
||||
dt.Minute(),
|
||||
dt.Second() );
|
||||
Serial.print(datestring);
|
||||
}
|
||||
|
||||
100
libraries/Rtc_by_Makuna/examples/DS1302_Simple/DS1302_Simple.ino
Normal file
100
libraries/Rtc_by_Makuna/examples/DS1302_Simple/DS1302_Simple.ino
Normal file
@@ -0,0 +1,100 @@
|
||||
|
||||
// CONNECTIONS:
|
||||
// DS1302 CLK/SCLK --> 5
|
||||
// DS1302 DAT/IO --> 4
|
||||
// DS1302 RST/CE --> 2
|
||||
// DS1302 VCC --> 3.3v - 5v
|
||||
// DS1302 GND --> GND
|
||||
|
||||
#include <RtcDS1302.h>
|
||||
|
||||
ThreeWire myWire(4,5,2); // IO, SCLK, CE
|
||||
RtcDS1302<ThreeWire> Rtc(myWire);
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(57600);
|
||||
|
||||
Serial.print("compiled: ");
|
||||
Serial.print(__DATE__);
|
||||
Serial.println(__TIME__);
|
||||
|
||||
Rtc.Begin();
|
||||
|
||||
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
|
||||
printDateTime(compiled);
|
||||
Serial.println();
|
||||
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
// Common Causes:
|
||||
// 1) first time you ran and the device wasn't running yet
|
||||
// 2) the battery on the device is low or even missing
|
||||
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
|
||||
if (Rtc.GetIsWriteProtected())
|
||||
{
|
||||
Serial.println("RTC was write protected, enabling writing now");
|
||||
Rtc.SetIsWriteProtected(false);
|
||||
}
|
||||
|
||||
if (!Rtc.GetIsRunning())
|
||||
{
|
||||
Serial.println("RTC was not actively running, starting now");
|
||||
Rtc.SetIsRunning(true);
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (now < compiled)
|
||||
{
|
||||
Serial.println("RTC is older than compile time! (Updating DateTime)");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
else if (now > compiled)
|
||||
{
|
||||
Serial.println("RTC is newer than compile time. (this is expected)");
|
||||
}
|
||||
else if (now == compiled)
|
||||
{
|
||||
Serial.println("RTC is the same as compile time! (not expected but all is fine)");
|
||||
}
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
|
||||
printDateTime(now);
|
||||
Serial.println();
|
||||
|
||||
if (!now.IsValid())
|
||||
{
|
||||
// Common Causes:
|
||||
// 1) the battery on the device is low or even missing and the power line was disconnected
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
}
|
||||
|
||||
delay(10000); // ten seconds
|
||||
}
|
||||
|
||||
#define countof(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
void printDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
char datestring[26];
|
||||
|
||||
snprintf_P(datestring,
|
||||
countof(datestring),
|
||||
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
|
||||
dt.Month(),
|
||||
dt.Day(),
|
||||
dt.Year(),
|
||||
dt.Hour(),
|
||||
dt.Minute(),
|
||||
dt.Second() );
|
||||
Serial.print(datestring);
|
||||
}
|
||||
|
||||
241
libraries/Rtc_by_Makuna/examples/DS1307_Memory/DS1307_Memory.ino
Normal file
241
libraries/Rtc_by_Makuna/examples/DS1307_Memory/DS1307_Memory.ino
Normal file
@@ -0,0 +1,241 @@
|
||||
|
||||
// CONNECTIONS:
|
||||
// DS1307 SDA --> SDA
|
||||
// DS1307 SCL --> SCL
|
||||
// DS1307 VCC --> 5v
|
||||
// DS1307 GND --> GND
|
||||
|
||||
#define countof(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
/* for software wire use below
|
||||
#include <SoftwareWire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS1307.h>
|
||||
|
||||
SoftwareWire myWire(SDA, SCL);
|
||||
RtcDS1307<SoftwareWire> Rtc(myWire);
|
||||
for software wire use above */
|
||||
|
||||
/* for normal hardware wire use below */
|
||||
#include <Wire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS1307.h>
|
||||
RtcDS1307<TwoWire> Rtc(Wire);
|
||||
/* for normal hardware wire use above */
|
||||
|
||||
|
||||
// nothing longer than 32 bytes
|
||||
// rtc eeprom memory is 32 byte pages
|
||||
// writing is limited to each page, so it will wrap at page
|
||||
// boundaries.
|
||||
// But reading is only limited by the buffer in Wire class which
|
||||
// by default is 32
|
||||
|
||||
// example settings objec that will be serialized into and out of EEPROM
|
||||
struct Settings
|
||||
{
|
||||
uint8_t size; // size of this structure for versioning/validation
|
||||
uint8_t value1;
|
||||
uint16_t value2;
|
||||
uint32_t value3;
|
||||
float value4;
|
||||
};
|
||||
|
||||
// where in EEPROM we will store the settings
|
||||
const uint8_t SettingsAddress = 0;
|
||||
|
||||
// handy routine to return true if there was an error
|
||||
// but it will also print out an error message with the given topic
|
||||
bool wasError(const char* errorTopic = "")
|
||||
{
|
||||
uint8_t error = Rtc.LastError();
|
||||
if (error != 0)
|
||||
{
|
||||
// we have a communications error
|
||||
// see https://www.arduino.cc/reference/en/language/functions/communication/wire/endtransmission/
|
||||
// for what the number means
|
||||
Serial.print("[");
|
||||
Serial.print(errorTopic);
|
||||
Serial.print("] WIRE communications error (");
|
||||
Serial.print(error);
|
||||
Serial.print(") : ");
|
||||
|
||||
switch (error)
|
||||
{
|
||||
case Rtc_Wire_Error_None:
|
||||
Serial.println("(none?!)");
|
||||
break;
|
||||
case Rtc_Wire_Error_TxBufferOverflow:
|
||||
Serial.println("transmit buffer overflow");
|
||||
break;
|
||||
case Rtc_Wire_Error_NoAddressableDevice:
|
||||
Serial.println("no device responded");
|
||||
break;
|
||||
case Rtc_Wire_Error_UnsupportedRequest:
|
||||
Serial.println("device doesn't support request");
|
||||
break;
|
||||
case Rtc_Wire_Error_Unspecific:
|
||||
Serial.println("unspecified error");
|
||||
break;
|
||||
case Rtc_Wire_Error_CommunicationTimeout:
|
||||
Serial.println("communications timed out");
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
Serial.print("compiled: ");
|
||||
Serial.print(__DATE__);
|
||||
Serial.println(__TIME__);
|
||||
|
||||
//--------RTC SETUP ------------
|
||||
// if you are using ESP-01 then uncomment the line below to reset the pins to
|
||||
// the available pins for SDA, SCL
|
||||
// Rtc.Begin(0, 2); // due to limited pins, use pin 0 and 2 for SDA, SCL
|
||||
|
||||
Rtc.Begin();
|
||||
#if defined(WIRE_HAS_TIMEOUT)
|
||||
Wire.setWireTimeout(3000 /* us */, true /* reset_on_timeout */);
|
||||
#endif
|
||||
|
||||
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
|
||||
printDateTime(compiled);
|
||||
Serial.println();
|
||||
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (!wasError("setup IsDateTimeValid"))
|
||||
{
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Rtc.GetIsRunning())
|
||||
{
|
||||
if (!wasError("setup GetIsRunning"))
|
||||
{
|
||||
Serial.println("RTC was not actively running, starting now");
|
||||
Rtc.SetIsRunning(true);
|
||||
}
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (!wasError("setup GetDateTime"))
|
||||
{
|
||||
if (now < compiled)
|
||||
{
|
||||
Serial.println("RTC is older than compile time, updating DateTime");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
}
|
||||
|
||||
// never assume the Rtc was last configured by you, so
|
||||
// just clear them to your needed state
|
||||
Rtc.SetSquareWavePin(DS1307SquareWaveOut_Low);
|
||||
wasError("setup SetSquareWavePin");
|
||||
|
||||
/* comment out on a second run to see that the info is stored long term */
|
||||
// Store something in memory on the RTC
|
||||
{
|
||||
Settings mySettings =
|
||||
{
|
||||
sizeof(Settings), // size
|
||||
42, // value1
|
||||
420, // value2
|
||||
18875, // value3
|
||||
3.14159f, // value4
|
||||
};
|
||||
|
||||
// store the settings, nothing longer than 32 bytes due to paging
|
||||
uint8_t written = Rtc.SetMemory(SettingsAddress,
|
||||
reinterpret_cast<const uint8_t*>(&mySettings),
|
||||
sizeof(mySettings));
|
||||
wasError("setup setMemory settings");
|
||||
}
|
||||
/* end of comment out section */
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (!wasError("loop IsDateTimeValid"))
|
||||
{
|
||||
// Common Causes:
|
||||
// 1) the battery on the device is low or even missing and the power line was disconnected
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
}
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (!wasError("loop GetDateTime"))
|
||||
{
|
||||
printDateTime(now);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
delay(5000);
|
||||
|
||||
// read data
|
||||
{
|
||||
Settings retrievedSettings = { 0, 0, 0, 0, 0 }; // init to zero
|
||||
|
||||
// get our data from the address with the given size
|
||||
uint8_t gotten = Rtc.GetMemory(SettingsAddress,
|
||||
reinterpret_cast<uint8_t*>(&retrievedSettings),
|
||||
sizeof(Settings));
|
||||
if (!wasError("loop getMemory settings"))
|
||||
{
|
||||
if (gotten != sizeof(Settings) ||
|
||||
retrievedSettings.size != sizeof(Settings))
|
||||
{
|
||||
Serial.print("something didn't match, requested = ");
|
||||
Serial.print(sizeof(Settings));
|
||||
Serial.print(", gotten = ");
|
||||
Serial.print(gotten);
|
||||
Serial.print(", size = ");
|
||||
Serial.print(retrievedSettings.size);
|
||||
Serial.println();
|
||||
}
|
||||
Serial.print("data read (");
|
||||
Serial.print(gotten);
|
||||
Serial.println(")");
|
||||
Serial.print(" size = ");
|
||||
Serial.println(retrievedSettings.size);
|
||||
Serial.print(" value1 = ");
|
||||
Serial.println(retrievedSettings.value1);
|
||||
Serial.print(" value2 = ");
|
||||
Serial.println(retrievedSettings.value2);
|
||||
Serial.print(" value3 = ");
|
||||
Serial.println(retrievedSettings.value3);
|
||||
Serial.print(" value4 = ");
|
||||
Serial.println(retrievedSettings.value4);
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
delay(5000);
|
||||
}
|
||||
|
||||
void printDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
char datestring[26];
|
||||
|
||||
snprintf_P(datestring,
|
||||
countof(datestring),
|
||||
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
|
||||
dt.Month(),
|
||||
dt.Day(),
|
||||
dt.Year(),
|
||||
dt.Hour(),
|
||||
dt.Minute(),
|
||||
dt.Second() );
|
||||
Serial.print(datestring);
|
||||
}
|
||||
|
||||
176
libraries/Rtc_by_Makuna/examples/DS1307_Simple/DS1307_Simple.ino
Normal file
176
libraries/Rtc_by_Makuna/examples/DS1307_Simple/DS1307_Simple.ino
Normal file
@@ -0,0 +1,176 @@
|
||||
|
||||
// CONNECTIONS:
|
||||
// DS1307 SDA --> SDA
|
||||
// DS1307 SCL --> SCL
|
||||
// DS1307 VCC --> 5v
|
||||
// DS1307 GND --> GND
|
||||
|
||||
/* for software wire use below
|
||||
#include <SoftwareWire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS1307.h>
|
||||
|
||||
SoftwareWire myWire(SDA, SCL);
|
||||
RtcDS1307<SoftwareWire> Rtc(myWire);
|
||||
for software wire use above */
|
||||
|
||||
/* for normal hardware wire use below */
|
||||
#include <Wire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS1307.h>
|
||||
RtcDS1307<TwoWire> Rtc(Wire);
|
||||
/* for normal hardware wire use above */
|
||||
|
||||
// handy routine to return true if there was an error
|
||||
// but it will also print out an error message with the given topic
|
||||
bool wasError(const char* errorTopic = "")
|
||||
{
|
||||
uint8_t error = Rtc.LastError();
|
||||
if (error != 0)
|
||||
{
|
||||
// we have a communications error
|
||||
// see https://www.arduino.cc/reference/en/language/functions/communication/wire/endtransmission/
|
||||
// for what the number means
|
||||
Serial.print("[");
|
||||
Serial.print(errorTopic);
|
||||
Serial.print("] WIRE communications error (");
|
||||
Serial.print(error);
|
||||
Serial.print(") : ");
|
||||
|
||||
switch (error)
|
||||
{
|
||||
case Rtc_Wire_Error_None:
|
||||
Serial.println("(none?!)");
|
||||
break;
|
||||
case Rtc_Wire_Error_TxBufferOverflow:
|
||||
Serial.println("transmit buffer overflow");
|
||||
break;
|
||||
case Rtc_Wire_Error_NoAddressableDevice:
|
||||
Serial.println("no device responded");
|
||||
break;
|
||||
case Rtc_Wire_Error_UnsupportedRequest:
|
||||
Serial.println("device doesn't support request");
|
||||
break;
|
||||
case Rtc_Wire_Error_Unspecific:
|
||||
Serial.println("unspecified error");
|
||||
break;
|
||||
case Rtc_Wire_Error_CommunicationTimeout:
|
||||
Serial.println("communications timed out");
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
Serial.print("compiled: ");
|
||||
Serial.print(__DATE__);
|
||||
Serial.println(__TIME__);
|
||||
|
||||
//--------RTC SETUP ------------
|
||||
// if you are using ESP-01 then uncomment the line below to reset the pins to
|
||||
// the available pins for SDA, SCL
|
||||
// Rtc.Begin(0, 2); // due to limited pins, use pin 0 and 2 for SDA, SCL
|
||||
|
||||
Rtc.Begin();
|
||||
#if defined(WIRE_HAS_TIMEOUT)
|
||||
Wire.setWireTimeout(3000 /* us */, true /* reset_on_timeout */);
|
||||
#endif
|
||||
|
||||
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
|
||||
printDateTime(compiled);
|
||||
Serial.println();
|
||||
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (!wasError("setup IsDateTimeValid"))
|
||||
{
|
||||
// Common Causes:
|
||||
// 1) first time you ran and the device wasn't running yet
|
||||
// 2) the battery on the device is low or even missing
|
||||
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
// following line sets the RTC to the date & time this sketch was compiled
|
||||
// it will also reset the valid flag internally unless the Rtc device is
|
||||
// having an issue
|
||||
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Rtc.GetIsRunning())
|
||||
{
|
||||
if (!wasError("setup GetIsRunning"))
|
||||
{
|
||||
Serial.println("RTC was not actively running, starting now");
|
||||
Rtc.SetIsRunning(true);
|
||||
}
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (!wasError("setup GetDateTime"))
|
||||
{
|
||||
if (now < compiled)
|
||||
{
|
||||
Serial.println("RTC is older than compile time, updating DateTime");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
else if (now > compiled)
|
||||
{
|
||||
Serial.println("RTC is newer than compile time, this is expected");
|
||||
}
|
||||
else if (now == compiled)
|
||||
{
|
||||
Serial.println("RTC is the same as compile time, while not expected all is still fine");
|
||||
}
|
||||
}
|
||||
|
||||
// never assume the Rtc was last configured by you, so
|
||||
// just clear them to your needed state
|
||||
Rtc.SetSquareWavePin(DS1307SquareWaveOut_Low);
|
||||
wasError("setup SetSquareWavePin");
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (!wasError("loop IsDateTimeValid"))
|
||||
{
|
||||
// Common Causes:
|
||||
// 1) the battery on the device is low or even missing and the power line was disconnected
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
}
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (!wasError("loop GetDateTime"))
|
||||
{
|
||||
printDateTime(now);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
delay(10000); // ten seconds
|
||||
}
|
||||
|
||||
#define countof(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
void printDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
char datestring[26];
|
||||
|
||||
snprintf_P(datestring,
|
||||
countof(datestring),
|
||||
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
|
||||
dt.Month(),
|
||||
dt.Day(),
|
||||
dt.Year(),
|
||||
dt.Hour(),
|
||||
dt.Minute(),
|
||||
dt.Second() );
|
||||
Serial.print(datestring);
|
||||
}
|
||||
|
||||
257
libraries/Rtc_by_Makuna/examples/DS3231_Alarms/DS3231_Alarms.ino
Normal file
257
libraries/Rtc_by_Makuna/examples/DS3231_Alarms/DS3231_Alarms.ino
Normal file
@@ -0,0 +1,257 @@
|
||||
|
||||
// CONNECTIONS:
|
||||
// DS3231 SDA --> SDA
|
||||
// DS3231 SCL --> SCL
|
||||
// DS3231 VCC --> 3.3v or 5v
|
||||
// DS3231 GND --> GND
|
||||
// SQW ---> (Pin19) Don't forget to pullup (4.7k to 10k to VCC)
|
||||
|
||||
/* for software wire use below
|
||||
#include <SoftwareWire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS3231.h>
|
||||
|
||||
SoftwareWire myWire(SDA, SCL);
|
||||
RtcDS3231<SoftwareWire> Rtc(myWire);
|
||||
for software wire use above */
|
||||
|
||||
/* for normal hardware wire use below */
|
||||
#include <Wire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS3231.h>
|
||||
RtcDS3231<TwoWire> Rtc(Wire);
|
||||
/* for normal hardware wire use above */
|
||||
|
||||
|
||||
// Interrupt Pin Lookup Table
|
||||
// (copied from Arduino Docs)
|
||||
//
|
||||
// CAUTION: The interrupts are Arduino numbers NOT Atmel numbers
|
||||
// and may not match (example, Mega2560 int.4 is actually Atmel Int2)
|
||||
// this is only an issue if you plan to use the lower level interupt features
|
||||
//
|
||||
// Board int.0 int.1 int.2 int.3 int.4 int.5
|
||||
// ---------------------------------------------------------------
|
||||
// Uno, Ethernet 2 3
|
||||
// Mega2560 2 3 21 20 [19] 18
|
||||
// Leonardo 3 2 0 1 7
|
||||
|
||||
#define RtcSquareWavePin 19 // Mega2560
|
||||
#define RtcSquareWaveInterrupt 4 // Mega2560
|
||||
|
||||
// marked volatile so interrupt can safely modify them and
|
||||
// other code can safely read and modify them
|
||||
volatile uint16_t interuptCount = 0;
|
||||
volatile bool interuptFlag = false;
|
||||
|
||||
void ISR_ATTR InteruptServiceRoutine()
|
||||
{
|
||||
// since this interupted any other running code,
|
||||
// don't do anything that takes long and especially avoid
|
||||
// any communications calls within this routine
|
||||
interuptCount++;
|
||||
interuptFlag = true;
|
||||
}
|
||||
|
||||
// handy routine to return true if there was an error
|
||||
// but it will also print out an error message with the given topic
|
||||
bool wasError(const char* errorTopic = "")
|
||||
{
|
||||
uint8_t error = Rtc.LastError();
|
||||
if (error != 0)
|
||||
{
|
||||
// we have a communications error
|
||||
// see https://www.arduino.cc/reference/en/language/functions/communication/wire/endtransmission/
|
||||
// for what the number means
|
||||
Serial.print("[");
|
||||
Serial.print(errorTopic);
|
||||
Serial.print("] WIRE communications error (");
|
||||
Serial.print(error);
|
||||
Serial.print(") : ");
|
||||
|
||||
switch (error)
|
||||
{
|
||||
case Rtc_Wire_Error_None:
|
||||
Serial.println("(none?!)");
|
||||
break;
|
||||
case Rtc_Wire_Error_TxBufferOverflow:
|
||||
Serial.println("transmit buffer overflow");
|
||||
break;
|
||||
case Rtc_Wire_Error_NoAddressableDevice:
|
||||
Serial.println("no device responded");
|
||||
break;
|
||||
case Rtc_Wire_Error_UnsupportedRequest:
|
||||
Serial.println("device doesn't support request");
|
||||
break;
|
||||
case Rtc_Wire_Error_Unspecific:
|
||||
Serial.println("unspecified error");
|
||||
break;
|
||||
case Rtc_Wire_Error_CommunicationTimeout:
|
||||
Serial.println("communications timed out");
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
// set the interupt pin to input mode
|
||||
pinMode(RtcSquareWavePin, INPUT);
|
||||
|
||||
//--------RTC SETUP ------------
|
||||
// if you are using ESP-01 then uncomment the line below to reset the pins to
|
||||
// the available pins for SDA, SCL
|
||||
// Wire.begin(0, 2); // due to limited pins, use pin 0 and 2 for SDA, SCL
|
||||
|
||||
Rtc.Begin();
|
||||
#if defined(WIRE_HAS_TIMEOUT)
|
||||
Wire.setWireTimeout(3000 /* us */, true /* reset_on_timeout */);
|
||||
#endif
|
||||
|
||||
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
|
||||
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (!wasError("setup IsDateTimeValid"))
|
||||
{
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Rtc.GetIsRunning())
|
||||
{
|
||||
if (!wasError("setup GetIsRunning"))
|
||||
{
|
||||
Serial.println("RTC was not actively running, starting now");
|
||||
Rtc.SetIsRunning(true);
|
||||
}
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (!wasError("setup GetDateTime"))
|
||||
{
|
||||
if (now < compiled)
|
||||
{
|
||||
Serial.println("RTC is older than compile time, updating DateTime");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
}
|
||||
|
||||
Rtc.Enable32kHzPin(false);
|
||||
wasError("setup Enable32kHzPin");
|
||||
Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeAlarmBoth);
|
||||
wasError("setup SetSquareWavePin");
|
||||
|
||||
// Alarm 1 set to trigger every day when
|
||||
// the hours, minutes, and seconds match
|
||||
RtcDateTime alarmTime = now + 88; // into the future
|
||||
DS3231AlarmOne alarm1(
|
||||
alarmTime.Day(),
|
||||
alarmTime.Hour(),
|
||||
alarmTime.Minute(),
|
||||
alarmTime.Second(),
|
||||
DS3231AlarmOneControl_HoursMinutesSecondsMatch);
|
||||
Rtc.SetAlarmOne(alarm1);
|
||||
wasError("setup SetAlarmOne");
|
||||
|
||||
// Alarm 2 set to trigger at the top of the minute
|
||||
DS3231AlarmTwo alarm2(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
DS3231AlarmTwoControl_OncePerMinute);
|
||||
Rtc.SetAlarmTwo(alarm2);
|
||||
wasError("setup SetAlarmTwo");
|
||||
|
||||
// throw away any old alarm state before we ran
|
||||
Rtc.LatchAlarmsTriggeredFlags();
|
||||
wasError("setup LatchAlarmsTriggeredFlags");
|
||||
|
||||
#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR)
|
||||
// setup external interupt
|
||||
// for some Arduino hardware they use interrupt number for the first param
|
||||
attachInterrupt(RtcSquareWaveInterrupt, InteruptServiceRoutine, FALLING);
|
||||
#else
|
||||
// for some Arduino hardware they use interrupt pin for the first param
|
||||
attachInterrupt(RtcSquareWavePin, InteruptServiceRoutine, FALLING);
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (!wasError("loop IsDateTimeValid"))
|
||||
{
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
}
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (!wasError("loop GetDateTime"))
|
||||
{
|
||||
printDateTime(now);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// we only want to show time every 10 seconds
|
||||
// but we want to show responce to the interupt firing
|
||||
for (int timeCount = 0; timeCount < 20; timeCount++)
|
||||
{
|
||||
if (Alarmed())
|
||||
{
|
||||
Serial.print(">>Interupt Count: ");
|
||||
Serial.print(interuptCount);
|
||||
Serial.println("<<");
|
||||
}
|
||||
delay(500);
|
||||
}
|
||||
}
|
||||
|
||||
bool Alarmed()
|
||||
{
|
||||
bool wasAlarmed = false;
|
||||
if (interuptFlag) // check our flag that gets sets in the interupt
|
||||
{
|
||||
wasAlarmed = true;
|
||||
interuptFlag = false; // reset the flag
|
||||
|
||||
// this gives us which alarms triggered and
|
||||
// then allows for others to trigger again
|
||||
DS3231AlarmFlag flag = Rtc.LatchAlarmsTriggeredFlags();
|
||||
if (!wasError("alarmed LatchAlarmsTriggeredFlags"))
|
||||
{
|
||||
if (flag & DS3231AlarmFlag_Alarm1)
|
||||
{
|
||||
Serial.println("alarm one triggered");
|
||||
}
|
||||
if (flag & DS3231AlarmFlag_Alarm2)
|
||||
{
|
||||
Serial.println("alarm two triggered");
|
||||
}
|
||||
}
|
||||
}
|
||||
return wasAlarmed;
|
||||
}
|
||||
|
||||
#define countof(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
void printDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
char datestring[26];
|
||||
|
||||
snprintf_P(datestring,
|
||||
countof(datestring),
|
||||
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
|
||||
dt.Month(),
|
||||
dt.Day(),
|
||||
dt.Year(),
|
||||
dt.Hour(),
|
||||
dt.Minute(),
|
||||
dt.Second() );
|
||||
Serial.print(datestring);
|
||||
}
|
||||
|
||||
188
libraries/Rtc_by_Makuna/examples/DS3231_Simple/DS3231_Simple.ino
Normal file
188
libraries/Rtc_by_Makuna/examples/DS3231_Simple/DS3231_Simple.ino
Normal file
@@ -0,0 +1,188 @@
|
||||
|
||||
// CONNECTIONS:
|
||||
// DS3231 SDA --> SDA
|
||||
// DS3231 SCL --> SCL
|
||||
// DS3231 VCC --> 3.3v or 5v
|
||||
// DS3231 GND --> GND
|
||||
|
||||
/* for software wire use below
|
||||
#include <SoftwareWire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS3231.h>
|
||||
|
||||
SoftwareWire myWire(SDA, SCL);
|
||||
RtcDS3231<SoftwareWire> Rtc(myWire);
|
||||
for software wire use above */
|
||||
|
||||
/* for normal hardware wire use below */
|
||||
#include <Wire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS3231.h>
|
||||
RtcDS3231<TwoWire> Rtc(Wire);
|
||||
/* for normal hardware wire use above */
|
||||
|
||||
|
||||
// handy routine to return true if there was an error
|
||||
// but it will also print out an error message with the given topic
|
||||
bool wasError(const char* errorTopic = "")
|
||||
{
|
||||
uint8_t error = Rtc.LastError();
|
||||
if (error != 0)
|
||||
{
|
||||
// we have a communications error
|
||||
// see https://www.arduino.cc/reference/en/language/functions/communication/wire/endtransmission/
|
||||
// for what the number means
|
||||
Serial.print("[");
|
||||
Serial.print(errorTopic);
|
||||
Serial.print("] WIRE communications error (");
|
||||
Serial.print(error);
|
||||
Serial.print(") : ");
|
||||
|
||||
switch (error)
|
||||
{
|
||||
case Rtc_Wire_Error_None:
|
||||
Serial.println("(none?!)");
|
||||
break;
|
||||
case Rtc_Wire_Error_TxBufferOverflow:
|
||||
Serial.println("transmit buffer overflow");
|
||||
break;
|
||||
case Rtc_Wire_Error_NoAddressableDevice:
|
||||
Serial.println("no device responded");
|
||||
break;
|
||||
case Rtc_Wire_Error_UnsupportedRequest:
|
||||
Serial.println("device doesn't support request");
|
||||
break;
|
||||
case Rtc_Wire_Error_Unspecific:
|
||||
Serial.println("unspecified error");
|
||||
break;
|
||||
case Rtc_Wire_Error_CommunicationTimeout:
|
||||
Serial.println("communications timed out");
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
Serial.print("compiled: ");
|
||||
Serial.print(__DATE__);
|
||||
Serial.println(__TIME__);
|
||||
|
||||
//--------RTC SETUP ------------
|
||||
// if you are using ESP-01 then uncomment the line below to reset the pins to
|
||||
// the available pins for SDA, SCL
|
||||
// Wire.begin(0, 2); // due to limited pins, use pin 0 and 2 for SDA, SCL
|
||||
|
||||
Rtc.Begin();
|
||||
#if defined(WIRE_HAS_TIMEOUT)
|
||||
Wire.setWireTimeout(3000 /* us */, true /* reset_on_timeout */);
|
||||
#endif
|
||||
|
||||
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
|
||||
printDateTime(compiled);
|
||||
Serial.println();
|
||||
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (!wasError("setup IsDateTimeValid"))
|
||||
{
|
||||
// Common Causes:
|
||||
// 1) first time you ran and the device wasn't running yet
|
||||
// 2) the battery on the device is low or even missing
|
||||
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
|
||||
// following line sets the RTC to the date & time this sketch was compiled
|
||||
// it will also reset the valid flag internally unless the Rtc device is
|
||||
// having an issue
|
||||
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Rtc.GetIsRunning())
|
||||
{
|
||||
if (!wasError("setup GetIsRunning"))
|
||||
{
|
||||
Serial.println("RTC was not actively running, starting now");
|
||||
Rtc.SetIsRunning(true);
|
||||
}
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (!wasError("setup GetDateTime"))
|
||||
{
|
||||
if (now < compiled)
|
||||
{
|
||||
Serial.println("RTC is older than compile time, updating DateTime");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
else if (now > compiled)
|
||||
{
|
||||
Serial.println("RTC is newer than compile time, this is expected");
|
||||
}
|
||||
else if (now == compiled)
|
||||
{
|
||||
Serial.println("RTC is the same as compile time, while not expected all is still fine");
|
||||
}
|
||||
}
|
||||
|
||||
// never assume the Rtc was last configured by you, so
|
||||
// just clear them to your needed state
|
||||
Rtc.Enable32kHzPin(false);
|
||||
wasError("setup Enable32kHzPin");
|
||||
Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone);
|
||||
wasError("setup SetSquareWavePin");
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (!wasError("loop IsDateTimeValid"))
|
||||
{
|
||||
// Common Causes:
|
||||
// 1) the battery on the device is low or even missing and the power line was disconnected
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
}
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (!wasError("loop GetDateTime"))
|
||||
{
|
||||
printDateTime(now);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
RtcTemperature temp = Rtc.GetTemperature();
|
||||
if (!wasError("loop GetTemperature"))
|
||||
{
|
||||
temp.Print(Serial);
|
||||
// you may also get the temperature as a float and print it
|
||||
// Serial.print(temp.AsFloatDegC());
|
||||
Serial.println("C");
|
||||
}
|
||||
|
||||
delay(10000); // ten seconds
|
||||
}
|
||||
|
||||
#define countof(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
void printDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
char datestring[26];
|
||||
|
||||
snprintf_P(datestring,
|
||||
countof(datestring),
|
||||
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
|
||||
dt.Month(),
|
||||
dt.Day(),
|
||||
dt.Year(),
|
||||
dt.Hour(),
|
||||
dt.Minute(),
|
||||
dt.Second() );
|
||||
Serial.print(datestring);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
|
||||
// CONNECTIONS:
|
||||
// DS3231 SDA --> SDA
|
||||
// DS3231 SCL --> SCL
|
||||
// DS3231 VCC --> 3.3v or 5v
|
||||
// DS3231 GND --> GND
|
||||
|
||||
/* for software wire use below
|
||||
#include <SoftwareWire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS3231.h>
|
||||
|
||||
SoftwareWire myWire(SDA, SCL);
|
||||
RtcDS3231<SoftwareWire> Rtc(myWire);
|
||||
for software wire use above */
|
||||
|
||||
/* for normal hardware wire use below */
|
||||
#include <Wire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS3231.h>
|
||||
RtcDS3231<TwoWire> Rtc(Wire);
|
||||
/* for normal hardware wire use above */
|
||||
|
||||
// handy routine to return true if there was an error
|
||||
// but it will also print out an error message with the given topic
|
||||
bool wasError(const char* errorTopic = "")
|
||||
{
|
||||
uint8_t error = Rtc.LastError();
|
||||
if (error != 0)
|
||||
{
|
||||
// we have a communications error
|
||||
// see https://www.arduino.cc/reference/en/language/functions/communication/wire/endtransmission/
|
||||
// for what the number means
|
||||
Serial.print("[");
|
||||
Serial.print(errorTopic);
|
||||
Serial.print("] WIRE communications error (");
|
||||
Serial.print(error);
|
||||
Serial.print(") : ");
|
||||
|
||||
switch (error)
|
||||
{
|
||||
case Rtc_Wire_Error_None:
|
||||
Serial.println("(none?!)");
|
||||
break;
|
||||
case Rtc_Wire_Error_TxBufferOverflow:
|
||||
Serial.println("transmit buffer overflow");
|
||||
break;
|
||||
case Rtc_Wire_Error_NoAddressableDevice:
|
||||
Serial.println("no device responded");
|
||||
break;
|
||||
case Rtc_Wire_Error_UnsupportedRequest:
|
||||
Serial.println("device doesn't support request");
|
||||
break;
|
||||
case Rtc_Wire_Error_Unspecific:
|
||||
Serial.println("unspecified error");
|
||||
break;
|
||||
case Rtc_Wire_Error_CommunicationTimeout:
|
||||
Serial.println("communications timed out");
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
Serial.print("compiled: ");
|
||||
Serial.print(__DATE__);
|
||||
Serial.println(__TIME__);
|
||||
|
||||
//--------RTC SETUP ------------
|
||||
// if you are using ESP-01 then uncomment the line below to reset the pins to
|
||||
// the available pins for SDA, SCL
|
||||
// Wire.begin(0, 2); // due to limited pins, use pin 0 and 2 for SDA, SCL
|
||||
|
||||
Rtc.Begin();
|
||||
#if defined(WIRE_HAS_TIMEOUT)
|
||||
Wire.setWireTimeout(3000 /* us */, true /* reset_on_timeout */);
|
||||
#endif
|
||||
|
||||
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
|
||||
printDateTime(compiled);
|
||||
Serial.println();
|
||||
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (!wasError("setup IsDateTimeValid"))
|
||||
{
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Rtc.GetIsRunning())
|
||||
{
|
||||
if (!wasError("setup GetIsRunning"))
|
||||
{
|
||||
Serial.println("RTC was not actively running");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("RTC is actively running");
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (!wasError("setup GetDateTime"))
|
||||
{
|
||||
if (now < compiled)
|
||||
{
|
||||
Serial.println("RTC is older than compile time, updating DateTime");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
}
|
||||
|
||||
// never assume the Rtc was last configured by you, so
|
||||
// just clear them to your needed state
|
||||
Rtc.Enable32kHzPin(false);
|
||||
wasError("setup Enable32kHzPin");
|
||||
Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone);
|
||||
wasError("setup SetSquareWavePin");
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (!wasError("loop GetDateTime"))
|
||||
{
|
||||
printDateTime(now);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
for(;;)
|
||||
{
|
||||
Rtc.SetIsRunning(false);
|
||||
if (!wasError("loop SetIsRunning"))
|
||||
{
|
||||
Serial.println(">>> Rtc ready for storage <<<");
|
||||
}
|
||||
|
||||
delay(10000); // ten seconds
|
||||
}
|
||||
}
|
||||
|
||||
#define countof(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
void printDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
char datestring[26];
|
||||
|
||||
snprintf_P(datestring,
|
||||
countof(datestring),
|
||||
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
|
||||
dt.Month(),
|
||||
dt.Day(),
|
||||
dt.Year(),
|
||||
dt.Hour(),
|
||||
dt.Minute(),
|
||||
dt.Second() );
|
||||
Serial.print(datestring);
|
||||
}
|
||||
|
||||
247
libraries/Rtc_by_Makuna/examples/DS3232_Memory/DS3232_Memory.ino
Normal file
247
libraries/Rtc_by_Makuna/examples/DS3232_Memory/DS3232_Memory.ino
Normal file
@@ -0,0 +1,247 @@
|
||||
|
||||
// CONNECTIONS:
|
||||
// DS3232 SDA --> SDA
|
||||
// DS3232 SCL --> SCL
|
||||
// DS3232 VCC --> 5v
|
||||
// DS3232 GND --> GND
|
||||
|
||||
#define countof(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
/* for software wire use below
|
||||
#include <SoftwareWire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS3232.h>
|
||||
|
||||
SoftwareWire myWire(SDA, SCL);
|
||||
RtcDS3232<SoftwareWire> Rtc(myWire);
|
||||
for software wire use above */
|
||||
|
||||
/* for normal hardware wire use below */
|
||||
#include <Wire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS3232.h>
|
||||
RtcDS3232<TwoWire> Rtc(Wire);
|
||||
/* for normal hardware wire use above */
|
||||
|
||||
|
||||
// nothing longer than 32 bytes
|
||||
// rtc eeprom memory is 32 byte pages
|
||||
// writing is limited to each page, so it will wrap at page
|
||||
// boundaries.
|
||||
// But reading is only limited by the buffer in Wire class which
|
||||
// by default is 32
|
||||
|
||||
// example settings objec that will be serialized into and out of EEPROM
|
||||
struct Settings
|
||||
{
|
||||
uint8_t size; // size of this structure for versioning/validation
|
||||
uint8_t value1;
|
||||
uint16_t value2;
|
||||
uint32_t value3;
|
||||
float value4;
|
||||
};
|
||||
|
||||
// where in EEPROM we will store the settings
|
||||
const uint8_t SettingsAddress = 0;
|
||||
|
||||
// handy routine to return true if there was an error
|
||||
// but it will also print out an error message with the given topic
|
||||
bool wasError(const char* errorTopic = "")
|
||||
{
|
||||
uint8_t error = Rtc.LastError();
|
||||
if (error != 0)
|
||||
{
|
||||
// we have a communications error
|
||||
// see https://www.arduino.cc/reference/en/language/functions/communication/wire/endtransmission/
|
||||
// for what the number means
|
||||
Serial.print("[");
|
||||
Serial.print(errorTopic);
|
||||
Serial.print("] WIRE communications error (");
|
||||
Serial.print(error);
|
||||
Serial.print(") : ");
|
||||
|
||||
switch (error)
|
||||
{
|
||||
case Rtc_Wire_Error_None:
|
||||
Serial.println("(none?!)");
|
||||
break;
|
||||
case Rtc_Wire_Error_TxBufferOverflow:
|
||||
Serial.println("transmit buffer overflow");
|
||||
break;
|
||||
case Rtc_Wire_Error_NoAddressableDevice:
|
||||
Serial.println("no device responded");
|
||||
break;
|
||||
case Rtc_Wire_Error_UnsupportedRequest:
|
||||
Serial.println("device doesn't support request");
|
||||
break;
|
||||
case Rtc_Wire_Error_Unspecific:
|
||||
Serial.println("unspecified error");
|
||||
break;
|
||||
case Rtc_Wire_Error_CommunicationTimeout:
|
||||
Serial.println("communications timed out");
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
Serial.print("compiled: ");
|
||||
Serial.print(__DATE__);
|
||||
Serial.println(__TIME__);
|
||||
|
||||
//--------RTC SETUP ------------
|
||||
// if you are using ESP-01 then uncomment the line below to reset the pins to
|
||||
// the available pins for SDA, SCL
|
||||
// Rtc.Begin(0, 2); // due to limited pins, use pin 0 and 2 for SDA, SCL
|
||||
|
||||
Rtc.Begin();
|
||||
#if defined(WIRE_HAS_TIMEOUT)
|
||||
Wire.setWireTimeout(3000 /* us */, true /* reset_on_timeout */);
|
||||
#endif
|
||||
|
||||
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
|
||||
printDateTime(compiled);
|
||||
Serial.println();
|
||||
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (!wasError("setup IsDateTimeValid"))
|
||||
{
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Rtc.GetIsRunning())
|
||||
{
|
||||
if (!wasError("setup GetIsRunning"))
|
||||
{
|
||||
Serial.println("RTC was not actively running, starting now");
|
||||
Rtc.SetIsRunning(true);
|
||||
}
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (!wasError("setup GetDateTime"))
|
||||
{
|
||||
if (now < compiled)
|
||||
{
|
||||
Serial.println("RTC is older than compile time, updating DateTime");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
}
|
||||
|
||||
// never assume the Rtc was last configured by you, so
|
||||
// just clear them to your needed state
|
||||
Rtc.Enable32kHzPin(false);
|
||||
wasError("setup Enable32kHzPin");
|
||||
Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone);
|
||||
wasError("setup SetSquareWavePin");
|
||||
|
||||
/* comment out on a second run to see that the info is stored long term */
|
||||
// Store something in memory on the RTC
|
||||
{
|
||||
Settings mySettings =
|
||||
{
|
||||
sizeof(Settings), // size
|
||||
42, // value1
|
||||
420, // value2
|
||||
18875, // value3
|
||||
3.14159f, // value4
|
||||
};
|
||||
|
||||
// store the settings, nothing longer than 32 bytes due to I2C buffer
|
||||
uint8_t written = Rtc.SetMemory(SettingsAddress,
|
||||
reinterpret_cast<const uint8_t*>(&mySettings),
|
||||
sizeof(mySettings));
|
||||
wasError("setup setMemory settings");
|
||||
if (written != sizeof(mySettings))
|
||||
{
|
||||
Serial.println("setup setMemory failed to write complete settings");
|
||||
}
|
||||
}
|
||||
/* end of comment out section */
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (!wasError("loop IsDateTimeValid"))
|
||||
{
|
||||
// Common Causes:
|
||||
// 1) the battery on the device is low or even missing and the power line was disconnected
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
}
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (!wasError("loop GetDateTime"))
|
||||
{
|
||||
printDateTime(now);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
delay(5000);
|
||||
|
||||
// read data
|
||||
{
|
||||
Settings retrievedSettings = { 0,0,0,0,0 }; // init size to zero
|
||||
|
||||
// get our data from the address with the given size
|
||||
uint8_t gotten = Rtc.GetMemory(SettingsAddress,
|
||||
reinterpret_cast<uint8_t*>(&retrievedSettings),
|
||||
sizeof(Settings));
|
||||
if (!wasError("loop getMemory settings"))
|
||||
{
|
||||
if (gotten != sizeof(Settings) ||
|
||||
retrievedSettings.size != sizeof(Settings))
|
||||
{
|
||||
Serial.print("something didn't match, requested = ");
|
||||
Serial.print(sizeof(Settings));
|
||||
Serial.print(", gotten = ");
|
||||
Serial.print(gotten);
|
||||
Serial.print(", size = ");
|
||||
Serial.print(retrievedSettings.size);
|
||||
Serial.println();
|
||||
}
|
||||
Serial.print("data read (");
|
||||
Serial.print(gotten);
|
||||
Serial.println(")");
|
||||
Serial.print(" size = ");
|
||||
Serial.println(retrievedSettings.size);
|
||||
Serial.print(" value1 = ");
|
||||
Serial.println(retrievedSettings.value1);
|
||||
Serial.print(" value2 = ");
|
||||
Serial.println(retrievedSettings.value2);
|
||||
Serial.print(" value3 = ");
|
||||
Serial.println(retrievedSettings.value3);
|
||||
Serial.print(" value4 = ");
|
||||
Serial.println(retrievedSettings.value4);
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
delay(5000);
|
||||
}
|
||||
|
||||
void printDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
char datestring[26];
|
||||
|
||||
snprintf_P(datestring,
|
||||
countof(datestring),
|
||||
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
|
||||
dt.Month(),
|
||||
dt.Day(),
|
||||
dt.Year(),
|
||||
dt.Hour(),
|
||||
dt.Minute(),
|
||||
dt.Second() );
|
||||
Serial.print(datestring);
|
||||
}
|
||||
|
||||
179
libraries/Rtc_by_Makuna/examples/DS3234_Alarms/DS3234_Alarms.ino
Normal file
179
libraries/Rtc_by_Makuna/examples/DS3234_Alarms/DS3234_Alarms.ino
Normal file
@@ -0,0 +1,179 @@
|
||||
|
||||
// Reference for connecting SPI see https://www.arduino.cc/en/Reference/SPI
|
||||
// CONNECTIONS:
|
||||
// DS3234 MISO --> MISO
|
||||
// DS3234 MOSI --> MOSI
|
||||
// DS3234 CLK --> CLK (SCK)
|
||||
// DS3234 CS (SS) --> 5 (pin used to select the DS3234 on the SPI)
|
||||
// DS3234 VCC --> 3.3v or 5v
|
||||
// DS3234 GND --> GND
|
||||
// SQW ---> (Pin19) Don't forget to pullup (4.7k to 10k to VCC)
|
||||
|
||||
const uint8_t DS3234_CS_PIN = 5;
|
||||
|
||||
#include <SPI.h>
|
||||
#include <RtcDS3234.h>
|
||||
|
||||
RtcDS3234<SPIClass> Rtc(SPI, DS3234_CS_PIN);
|
||||
|
||||
// Interrupt Pin Lookup Table
|
||||
// (copied from Arduino Docs)
|
||||
//
|
||||
// CAUTION: The interrupts are Arduino numbers NOT Atmel numbers
|
||||
// and may not match (example, Mega2560 int.4 is actually Atmel Int2)
|
||||
// this is only an issue if you plan to use the lower level interupt features
|
||||
//
|
||||
// Board int.0 int.1 int.2 int.3 int.4 int.5
|
||||
// ---------------------------------------------------------------
|
||||
// Uno, Ethernet 2 3
|
||||
// Mega2560 2 3 21 20 [19] 18
|
||||
// Leonardo 3 2 0 1 7
|
||||
// esp8266 (pin and interrupt should be the same thing)
|
||||
// esp32 (pin and interrupt should be the same thing)
|
||||
|
||||
#define RtcSquareWavePin 19 // Mega2560
|
||||
#define RtcSquareWaveInterrupt 4 // Mega2560
|
||||
|
||||
// marked volatile so interrupt can safely modify them and
|
||||
// other code can safely read and modify them
|
||||
volatile uint16_t interuptCount = 0;
|
||||
volatile bool interuptFlag = false;
|
||||
|
||||
void ISR_ATTR InteruptServiceRoutine()
|
||||
{
|
||||
// since this interupted any other running code,
|
||||
// don't do anything that takes long and especially avoid
|
||||
// any communications calls within this routine
|
||||
interuptCount++;
|
||||
interuptFlag = true;
|
||||
}
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
|
||||
// set the interupt pin to input mode
|
||||
pinMode(RtcSquareWavePin, INPUT_PULLUP); // external pullup maybe required still
|
||||
|
||||
SPI.begin();
|
||||
Rtc.Begin();
|
||||
|
||||
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
|
||||
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
|
||||
if (!Rtc.GetIsRunning())
|
||||
{
|
||||
Serial.println("RTC was not actively running, starting now");
|
||||
Rtc.SetIsRunning(true);
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (now < compiled)
|
||||
{
|
||||
Serial.println("RTC is older than compile time! (Updating DateTime)");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
|
||||
Rtc.Enable32kHzPin(false);
|
||||
Rtc.SetSquareWavePin(DS3234SquareWavePin_ModeAlarmBoth);
|
||||
|
||||
// Alarm 1 set to trigger every day when
|
||||
// the hours, minutes, and seconds match
|
||||
RtcDateTime alarmTime = now + 88; // into the future
|
||||
DS3234AlarmOne alarm1(
|
||||
alarmTime.Day(),
|
||||
alarmTime.Hour(),
|
||||
alarmTime.Minute(),
|
||||
alarmTime.Second(),
|
||||
DS3234AlarmOneControl_HoursMinutesSecondsMatch);
|
||||
Rtc.SetAlarmOne(alarm1);
|
||||
|
||||
// Alarm 2 set to trigger at the top of the minute
|
||||
DS3234AlarmTwo alarm2(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
DS3234AlarmTwoControl_OncePerMinute);
|
||||
Rtc.SetAlarmTwo(alarm2);
|
||||
|
||||
// throw away any old alarm state before we ran
|
||||
Rtc.LatchAlarmsTriggeredFlags();
|
||||
|
||||
// setup external interupt
|
||||
attachInterrupt(RtcSquareWaveInterrupt, InteruptServiceRoutine, FALLING);
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
|
||||
printDateTime(now);
|
||||
Serial.println();
|
||||
|
||||
// we only want to show time every 10 seconds
|
||||
// but we want to show responce to the interupt firing
|
||||
for (int timeCount = 0; timeCount < 20; timeCount++)
|
||||
{
|
||||
if (Alarmed())
|
||||
{
|
||||
Serial.print(">>Interupt Count: ");
|
||||
Serial.print(interuptCount);
|
||||
Serial.println("<<");
|
||||
}
|
||||
delay(500);
|
||||
}
|
||||
}
|
||||
|
||||
bool Alarmed()
|
||||
{
|
||||
bool wasAlarmed = false;
|
||||
if (interuptFlag) // check our flag that gets sets in the interupt
|
||||
{
|
||||
wasAlarmed = true;
|
||||
interuptFlag = false; // reset the flag
|
||||
|
||||
// this gives us which alarms triggered and
|
||||
// then allows for others to trigger again
|
||||
DS3234AlarmFlag flag = Rtc.LatchAlarmsTriggeredFlags();
|
||||
|
||||
if (flag & DS3234AlarmFlag_Alarm1)
|
||||
{
|
||||
Serial.println("alarm one triggered");
|
||||
}
|
||||
if (flag & DS3234AlarmFlag_Alarm2)
|
||||
{
|
||||
Serial.println("alarm two triggered");
|
||||
}
|
||||
}
|
||||
return wasAlarmed;
|
||||
}
|
||||
|
||||
#define countof(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
void printDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
char datestring[26];
|
||||
|
||||
snprintf_P(datestring,
|
||||
countof(datestring),
|
||||
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
|
||||
dt.Month(),
|
||||
dt.Day(),
|
||||
dt.Year(),
|
||||
dt.Hour(),
|
||||
dt.Minute(),
|
||||
dt.Second() );
|
||||
Serial.print(datestring);
|
||||
}
|
||||
|
||||
139
libraries/Rtc_by_Makuna/examples/DS3234_Memory/DS3234_Memory.ino
Normal file
139
libraries/Rtc_by_Makuna/examples/DS3234_Memory/DS3234_Memory.ino
Normal file
@@ -0,0 +1,139 @@
|
||||
|
||||
// Reference for connecting SPI see https://www.arduino.cc/en/Reference/SPI
|
||||
// CONNECTIONS:
|
||||
// DS3234 MISO --> MISO
|
||||
// DS3234 MOSI --> MOSI
|
||||
// DS3234 CLK --> CLK (SCK)
|
||||
// DS3234 CS (SS) --> 5 (pin used to select the DS3234 on the SPI)
|
||||
// DS3234 VCC --> 3.3v or 5v
|
||||
// DS3234 GND --> GND
|
||||
|
||||
const uint8_t DS3234_CS_PIN = 5;
|
||||
|
||||
#include <SPI.h>
|
||||
#include <RtcDS3234.h>
|
||||
|
||||
RtcDS3234<SPIClass> Rtc(SPI, DS3234_CS_PIN);
|
||||
|
||||
const char data[] = "what time is it";
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
|
||||
Serial.print("compiled: ");
|
||||
Serial.print(__DATE__);
|
||||
Serial.println(__TIME__);
|
||||
|
||||
SPI.begin();
|
||||
Rtc.Begin();
|
||||
|
||||
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
|
||||
printDateTime(compiled);
|
||||
Serial.println();
|
||||
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
|
||||
if (!Rtc.GetIsRunning())
|
||||
{
|
||||
Serial.println("RTC was not actively running, starting now");
|
||||
Rtc.SetIsRunning(true);
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (now < compiled)
|
||||
{
|
||||
Serial.println("RTC is older than compile time! (Updating DateTime)");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
|
||||
// never assume the Rtc was last configured by you, so
|
||||
// just clear them to your needed state
|
||||
Rtc.SetSquareWavePin(DS3234SquareWavePin_ModeNone);
|
||||
|
||||
/* comment out on a second run to see that the info is stored long term */
|
||||
// Store something in memory on the RTC
|
||||
Rtc.SetMemory(0, 13); // address of a data item
|
||||
uint8_t written = Rtc.SetMemory(13, (const uint8_t*)data, sizeof(data) - 1); // remove the null terminator strings add
|
||||
Rtc.SetMemory(1, written); // size of data time
|
||||
/* end of comment out section */
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
// Common Causes:
|
||||
// 1) the battery on the device is low or even missing and the power line was disconnected
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
|
||||
printDateTime(now);
|
||||
Serial.println();
|
||||
|
||||
delay(5000);
|
||||
|
||||
// read data
|
||||
|
||||
// get the offset we stored our data from address zero
|
||||
uint8_t address = Rtc.GetMemory(0);
|
||||
if (address != 13)
|
||||
{
|
||||
Serial.println("address didn't match");
|
||||
}
|
||||
else
|
||||
{
|
||||
// get the size of the data from address 1
|
||||
uint8_t count = Rtc.GetMemory(1);
|
||||
uint8_t buff[20];
|
||||
|
||||
// get our data from the address with the given size
|
||||
uint8_t gotten = Rtc.GetMemory(address, buff, count);
|
||||
|
||||
if (gotten != count ||
|
||||
count != sizeof(data) - 1) // remove the extra null terminator strings add
|
||||
{
|
||||
Serial.print("something didn't match, count = ");
|
||||
Serial.print(count, DEC);
|
||||
Serial.print(", gotten = ");
|
||||
Serial.print(gotten, DEC);
|
||||
Serial.println();
|
||||
}
|
||||
Serial.print("data read (");
|
||||
Serial.print(gotten);
|
||||
Serial.print(") = \"");
|
||||
for (uint8_t ch = 0; ch < gotten; ch++)
|
||||
{
|
||||
Serial.print((char)buff[ch]);
|
||||
}
|
||||
Serial.println("\"");
|
||||
}
|
||||
|
||||
delay(5000);
|
||||
}
|
||||
|
||||
#define countof(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
void printDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
char datestring[26];
|
||||
|
||||
snprintf_P(datestring,
|
||||
countof(datestring),
|
||||
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
|
||||
dt.Month(),
|
||||
dt.Day(),
|
||||
dt.Year(),
|
||||
dt.Hour(),
|
||||
dt.Minute(),
|
||||
dt.Second() );
|
||||
Serial.print(datestring);
|
||||
}
|
||||
|
||||
115
libraries/Rtc_by_Makuna/examples/DS3234_Simple/DS3234_Simple.ino
Normal file
115
libraries/Rtc_by_Makuna/examples/DS3234_Simple/DS3234_Simple.ino
Normal file
@@ -0,0 +1,115 @@
|
||||
|
||||
// Reference for connecting SPI see https://www.arduino.cc/en/Reference/SPI
|
||||
// CONNECTIONS:
|
||||
// DS3234 MISO --> MISO
|
||||
// DS3234 MOSI --> MOSI
|
||||
// DS3234 CLK --> CLK (SCK)
|
||||
// DS3234 CS (SS) --> 5 (pin used to select the DS3234 on the SPI)
|
||||
// DS3234 VCC --> 3.3v or 5v
|
||||
// DS3234 GND --> GND
|
||||
|
||||
const uint8_t DS3234_CS_PIN = 5;
|
||||
|
||||
#include <SPI.h>
|
||||
#include <RtcDS3234.h>
|
||||
|
||||
RtcDS3234<SPIClass> Rtc(SPI, DS3234_CS_PIN);
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
|
||||
Serial.print("compiled: ");
|
||||
Serial.print(__DATE__);
|
||||
Serial.println(__TIME__);
|
||||
|
||||
SPI.begin();
|
||||
Rtc.Begin();
|
||||
|
||||
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
|
||||
printDateTime(compiled);
|
||||
Serial.println();
|
||||
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
// Common Causes:
|
||||
// 1) first time you ran and the device wasn't running yet
|
||||
// 2) the battery on the device is low or even missing
|
||||
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
|
||||
// following line sets the RTC to the date & time this sketch was compiled
|
||||
// it will also reset the valid flag internally unless the Rtc device is
|
||||
// having an issue
|
||||
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
|
||||
if (!Rtc.GetIsRunning())
|
||||
{
|
||||
Serial.println("RTC was not actively running, starting now");
|
||||
Rtc.SetIsRunning(true);
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (now < compiled)
|
||||
{
|
||||
Serial.println("RTC is older than compile time! (Updating DateTime)");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
else if (now > compiled)
|
||||
{
|
||||
Serial.println("RTC is newer than compile time. (this is expected)");
|
||||
}
|
||||
else if (now == compiled)
|
||||
{
|
||||
Serial.println("RTC is the same as compile time! (not expected but all is fine)");
|
||||
}
|
||||
|
||||
// never assume the Rtc was last configured by you, so
|
||||
// just clear them to your needed state
|
||||
Rtc.Enable32kHzPin(false);
|
||||
Rtc.SetSquareWavePin(DS3234SquareWavePin_ModeNone);
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
// Common Causes:
|
||||
// 1) the battery on the device is low or even missing and the power line was disconnected
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
printDateTime(now);
|
||||
Serial.println();
|
||||
|
||||
RtcTemperature temp = Rtc.GetTemperature();
|
||||
temp.Print(Serial);
|
||||
// you may also get the temperature as a float and print it
|
||||
// Serial.print(temp.AsFloatDegC());
|
||||
Serial.println("C");
|
||||
|
||||
delay(10000); // ten seconds
|
||||
}
|
||||
|
||||
#define countof(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
void printDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
char datestring[26];
|
||||
|
||||
snprintf_P(datestring,
|
||||
countof(datestring),
|
||||
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
|
||||
dt.Month(),
|
||||
dt.Day(),
|
||||
dt.Year(),
|
||||
dt.Hour(),
|
||||
dt.Minute(),
|
||||
dt.Second() );
|
||||
Serial.print(datestring);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,269 @@
|
||||
|
||||
// CONNECTIONS:
|
||||
// PCF8563 SDA --> SDA
|
||||
// PCF8563 SCL --> SCL
|
||||
// PCF8563 VCC --> 3.3v or 5v
|
||||
// PCF8563 GND --> GND
|
||||
// PCF8563 INT ---> (Pin19) Don't forget to pullup (4.7k to 10k to VCC)
|
||||
|
||||
/* for software wire use below
|
||||
#include <SoftwareWire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcPCF8563.h>
|
||||
|
||||
SoftwareWire myWire(SDA, SCL);
|
||||
RtcPCF8563<SoftwareWire> Rtc(myWire);
|
||||
for software wire use above */
|
||||
|
||||
/* for normal hardware wire use below */
|
||||
#include <Wire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcPCF8563.h>
|
||||
RtcPCF8563<TwoWire> Rtc(Wire);
|
||||
/* for normal hardware wire use above */
|
||||
|
||||
|
||||
// Interrupt Pin Lookup Table
|
||||
// (copied from Arduino Docs)
|
||||
//
|
||||
// CAUTION: The interrupts are Arduino numbers NOT Atmel numbers
|
||||
// and may not match (example, Mega2560 int.4 is actually Atmel Int2)
|
||||
// this is only an issue if you plan to use the lower level interupt features
|
||||
//
|
||||
// Board int.0 int.1 int.2 int.3 int.4 int.5
|
||||
// ---------------------------------------------------------------
|
||||
// Uno, Ethernet 2 3
|
||||
// Mega2560 2 3 21 20 [19] 18
|
||||
// Leonardo 3 2 0 1 7
|
||||
|
||||
#define RtcInterruptPin 19 // Mega2560
|
||||
#define RtcInterruptInterrupt 4 // Mega2560
|
||||
|
||||
// marked volatile so interrupt can safely modify them and
|
||||
// other code can safely read and modify them
|
||||
volatile uint16_t interuptCount = 0;
|
||||
volatile bool interuptFlag = false;
|
||||
|
||||
void ISR_ATTR InteruptServiceRoutine()
|
||||
{
|
||||
// since this interupted any other running code,
|
||||
// don't do anything that takes long and especially avoid
|
||||
// any communications calls within this routine
|
||||
interuptCount++;
|
||||
interuptFlag = true;
|
||||
}
|
||||
|
||||
// handy routine to return true if there was an error
|
||||
// but it will also print out an error message with the given topic
|
||||
bool wasError(const char* errorTopic = "")
|
||||
{
|
||||
uint8_t error = Rtc.LastError();
|
||||
if (error != 0)
|
||||
{
|
||||
// we have a communications error
|
||||
// see https://www.arduino.cc/reference/en/language/functions/communication/wire/endtransmission/
|
||||
// for what the number means
|
||||
Serial.print("[");
|
||||
Serial.print(errorTopic);
|
||||
Serial.print("] WIRE communications error (");
|
||||
Serial.print(error);
|
||||
Serial.print(") : ");
|
||||
|
||||
switch (error)
|
||||
{
|
||||
case Rtc_Wire_Error_None:
|
||||
Serial.println("(none?!)");
|
||||
break;
|
||||
case Rtc_Wire_Error_TxBufferOverflow:
|
||||
Serial.println("transmit buffer overflow");
|
||||
break;
|
||||
case Rtc_Wire_Error_NoAddressableDevice:
|
||||
Serial.println("no device responded");
|
||||
break;
|
||||
case Rtc_Wire_Error_UnsupportedRequest:
|
||||
Serial.println("device doesn't support request");
|
||||
break;
|
||||
case Rtc_Wire_Error_Unspecific:
|
||||
Serial.println("unspecified error");
|
||||
break;
|
||||
case Rtc_Wire_Error_CommunicationTimeout:
|
||||
Serial.println("communications timed out");
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
// set the interupt pin to input mode
|
||||
pinMode(RtcInterruptPin, INPUT);
|
||||
|
||||
//--------RTC SETUP ------------
|
||||
// if you are using ESP-01 then uncomment the line below to reset the pins to
|
||||
// the available pins for SDA, SCL
|
||||
// Wire.begin(0, 2); // due to limited pins, use pin 0 and 2 for SDA, SCL
|
||||
|
||||
Rtc.Begin();
|
||||
#if defined(WIRE_HAS_TIMEOUT)
|
||||
Wire.setWireTimeout(3000 /* us */, true /* reset_on_timeout */);
|
||||
#endif
|
||||
|
||||
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
|
||||
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (!wasError("setup IsDateTimeValid"))
|
||||
{
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Rtc.GetIsRunning())
|
||||
{
|
||||
if (!wasError("setup GetIsRunning"))
|
||||
{
|
||||
Serial.println("RTC was not actively running, starting now");
|
||||
Rtc.SetIsRunning(true);
|
||||
}
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (!wasError("setup GetDateTime"))
|
||||
{
|
||||
if (now < compiled)
|
||||
{
|
||||
Serial.println("RTC is older than compile time, updating DateTime");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
}
|
||||
|
||||
// never assume the Rtc was last configured by you, so
|
||||
// just clear them to your needed state
|
||||
Rtc.StopAlarm();
|
||||
wasError("setup StopAlarm");
|
||||
Rtc.StopTimer();
|
||||
wasError("setup StopTimer");
|
||||
Rtc.SetSquareWavePin(PCF8563SquareWavePinMode_None);
|
||||
wasError("setup SetSquareWavePin");
|
||||
|
||||
// Alarm set to trigger every day when
|
||||
// the hours and minutes match
|
||||
RtcDateTime alarmTime = now + 88; // into the future
|
||||
PCF8563Alarm alarm(
|
||||
alarmTime.Day(), // will be ignored in this example
|
||||
alarmTime.Hour(),
|
||||
alarmTime.Minute(),
|
||||
alarmTime.DayOfWeek(), // will be ignored in this example
|
||||
PCF8563AlarmControl_MinuteMatch | PCF8563AlarmControl_HourMatch
|
||||
);
|
||||
Rtc.SetAlarm(alarm);
|
||||
wasError("setup SetAlarm");
|
||||
|
||||
// Timer set to trigger in 100 seconds
|
||||
//
|
||||
Rtc.SetTimer(PCF8563TimerMode_Seconds, 100);
|
||||
|
||||
#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR)
|
||||
// setup external interupt
|
||||
// for some Arduino hardware they use interrupt number for the first param
|
||||
attachInterrupt(RtcInterruptInterrupt, InteruptServiceRoutine, FALLING);
|
||||
#else
|
||||
// for some Arduino hardware they use interrupt pin for the first param
|
||||
attachInterrupt(RtcInterruptPin, InteruptServiceRoutine, FALLING);
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (!wasError("loop IsDateTimeValid"))
|
||||
{
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
}
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (!wasError("loop GetDateTime"))
|
||||
{
|
||||
printDateTime(now);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// we only want to show time every 10 seconds
|
||||
// but we want to show responce to the interupt firing
|
||||
for (int timeCount = 0; timeCount < 20; timeCount++)
|
||||
{
|
||||
if (Alarmed())
|
||||
{
|
||||
Serial.print(">>Interupt Count: ");
|
||||
Serial.print(interuptCount);
|
||||
Serial.println("<<");
|
||||
}
|
||||
delay(500);
|
||||
}
|
||||
}
|
||||
|
||||
bool Alarmed()
|
||||
{
|
||||
bool result = false;
|
||||
if (interuptFlag) // check our flag that gets sets in the interupt
|
||||
{
|
||||
interuptFlag = false; // reset the flag
|
||||
|
||||
// calling LatchAlarmTriggeredFlag() will return if
|
||||
// the alarm was what triggered the interrupt and also
|
||||
// resets the alarm flag inside the rtc which then allows
|
||||
// for alarms to trigger again.
|
||||
// note that the same int pin is also used for
|
||||
// the timer trigger if also used
|
||||
bool wasAlarmed = Rtc.LatchAlarmTriggeredFlag();
|
||||
if (!wasError("alarmed LatchAlarmTriggeredFlag"))
|
||||
{
|
||||
if (wasAlarmed)
|
||||
{
|
||||
result = true;
|
||||
Serial.println("alarm triggered");
|
||||
}
|
||||
}
|
||||
|
||||
// calling LatchTimerTriggeredFlag() will return if
|
||||
// the timer was what triggered the interrupt and also
|
||||
// resets the timer flag inside the rtc which then allows
|
||||
// for timers to trigger again.
|
||||
// note that the same int pin is also used for
|
||||
// the alarm trigger if also used
|
||||
bool wasTimerExpired = Rtc.LatchTimerTriggeredFlag();
|
||||
if (!wasError("alarmed LatchTimerTriggeredFlag"))
|
||||
{
|
||||
if (wasTimerExpired)
|
||||
{
|
||||
result = true;
|
||||
Serial.println("timer triggered");
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#define countof(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
void printDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
char datestring[26];
|
||||
|
||||
snprintf_P(datestring,
|
||||
countof(datestring),
|
||||
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
|
||||
dt.Month(),
|
||||
dt.Day(),
|
||||
dt.Year(),
|
||||
dt.Hour(),
|
||||
dt.Minute(),
|
||||
dt.Second() );
|
||||
Serial.print(datestring);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
|
||||
// CONNECTIONS:
|
||||
// PCF8563 SDA --> SDA
|
||||
// PCF8563 SCL --> SCL
|
||||
// PCF8563 VCC --> 3.3v or 5v
|
||||
// PCF8563 GND --> GND
|
||||
|
||||
/* for software wire use below
|
||||
#include <SoftwareWire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcPCF8563.h>
|
||||
|
||||
SoftwareWire myWire(SDA, SCL);
|
||||
RtcPCF8563<SoftwareWire> Rtc(myWire);
|
||||
for software wire use above */
|
||||
|
||||
/* for normal hardware wire use below */
|
||||
#include <Wire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcPCF8563.h>
|
||||
RtcPCF8563<TwoWire> Rtc(Wire);
|
||||
/* for normal hardware wire use above */
|
||||
|
||||
|
||||
// handy routine to return true if there was an error
|
||||
// but it will also print out an error message with the given topic
|
||||
bool wasError(const char* errorTopic = "")
|
||||
{
|
||||
uint8_t error = Rtc.LastError();
|
||||
if (error != 0)
|
||||
{
|
||||
// we have a communications error
|
||||
// see https://www.arduino.cc/reference/en/language/functions/communication/wire/endtransmission/
|
||||
// for what the number means
|
||||
Serial.print("[");
|
||||
Serial.print(errorTopic);
|
||||
Serial.print("] WIRE communications error (");
|
||||
Serial.print(error);
|
||||
Serial.print(") : ");
|
||||
|
||||
switch (error)
|
||||
{
|
||||
case Rtc_Wire_Error_None:
|
||||
Serial.println("(none?!)");
|
||||
break;
|
||||
case Rtc_Wire_Error_TxBufferOverflow:
|
||||
Serial.println("transmit buffer overflow");
|
||||
break;
|
||||
case Rtc_Wire_Error_NoAddressableDevice:
|
||||
Serial.println("no device responded");
|
||||
break;
|
||||
case Rtc_Wire_Error_UnsupportedRequest:
|
||||
Serial.println("device doesn't support request");
|
||||
break;
|
||||
case Rtc_Wire_Error_Unspecific:
|
||||
Serial.println("unspecified error");
|
||||
break;
|
||||
case Rtc_Wire_Error_CommunicationTimeout:
|
||||
Serial.println("communications timed out");
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
Serial.print("compiled: ");
|
||||
Serial.print(__DATE__);
|
||||
Serial.println(__TIME__);
|
||||
|
||||
//--------RTC SETUP ------------
|
||||
// if you are using ESP-01 then uncomment the line below to reset the pins to
|
||||
// the available pins for SDA, SCL
|
||||
// Wire.begin(0, 2); // due to limited pins, use pin 0 and 2 for SDA, SCL
|
||||
|
||||
Rtc.Begin();
|
||||
#if defined(WIRE_HAS_TIMEOUT)
|
||||
Wire.setWireTimeout(3000 /* us */, true /* reset_on_timeout */);
|
||||
#endif
|
||||
|
||||
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
|
||||
printDateTime(compiled);
|
||||
Serial.println();
|
||||
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (!wasError("setup IsDateTimeValid"))
|
||||
{
|
||||
// Common Causes:
|
||||
// 1) first time you ran and the device wasn't running yet
|
||||
// 2) the battery on the device is low or even missing
|
||||
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
|
||||
// following line sets the RTC to the date & time this sketch was compiled
|
||||
// it will also reset the valid flag internally unless the Rtc device is
|
||||
// having an issue
|
||||
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Rtc.GetIsRunning())
|
||||
{
|
||||
if (!wasError("setup GetIsRunning"))
|
||||
{
|
||||
Serial.println("RTC was not actively running, starting now");
|
||||
Rtc.SetIsRunning(true);
|
||||
}
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (!wasError("setup GetDateTime"))
|
||||
{
|
||||
if (now < compiled)
|
||||
{
|
||||
Serial.println("RTC is older than compile time, updating DateTime");
|
||||
Rtc.SetDateTime(compiled);
|
||||
}
|
||||
else if (now > compiled)
|
||||
{
|
||||
Serial.println("RTC is newer than compile time, this is expected");
|
||||
}
|
||||
else if (now == compiled)
|
||||
{
|
||||
Serial.println("RTC is the same as compile time, while not expected all is still fine");
|
||||
}
|
||||
}
|
||||
|
||||
// never assume the Rtc was last configured by you, so
|
||||
// just clear them to your needed state
|
||||
Rtc.StopAlarm();
|
||||
wasError("setup StopAlarm");
|
||||
Rtc.StopTimer();
|
||||
wasError("setup StopTimer");
|
||||
Rtc.SetSquareWavePin(PCF8563SquareWavePinMode_None);
|
||||
wasError("setup SetSquareWavePin");
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (!wasError("loop IsDateTimeValid"))
|
||||
{
|
||||
// Common Causes:
|
||||
// 1) the battery on the device is low or even missing and the power line was disconnected
|
||||
Serial.println("RTC lost confidence in the DateTime!");
|
||||
}
|
||||
}
|
||||
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
if (!wasError("loop GetDateTime"))
|
||||
{
|
||||
printDateTime(now);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
delay(10000); // ten seconds
|
||||
}
|
||||
|
||||
#define countof(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
void printDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
char datestring[26];
|
||||
|
||||
snprintf_P(datestring,
|
||||
countof(datestring),
|
||||
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
|
||||
dt.Month(),
|
||||
dt.Day(),
|
||||
dt.Year(),
|
||||
dt.Hour(),
|
||||
dt.Minute(),
|
||||
dt.Second() );
|
||||
Serial.print(datestring);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
// These tests do not rely on RTC hardware at all
|
||||
|
||||
//#include <Wire.h> // must be included here so that Arduino library object file references work
|
||||
#include <RtcDS3231.h>
|
||||
|
||||
void PrintPassFail(bool passed)
|
||||
{
|
||||
if (passed)
|
||||
{
|
||||
Serial.print("passed");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print("failed");
|
||||
}
|
||||
}
|
||||
|
||||
void ComparePrintlnPassFail(RtcTemperature& rtcTemp, float compare)
|
||||
{
|
||||
Serial.print(rtcTemp.AsFloatDegC());
|
||||
Serial.print("C ");
|
||||
PrintPassFail(rtcTemp.AsFloatDegC() == compare);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void ConstructorTests()
|
||||
{
|
||||
// RTC constructors
|
||||
Serial.println("Constructors:");
|
||||
{
|
||||
RtcTemperature temp075Below(0b11111111, 0b01000000); // -0.75
|
||||
ComparePrintlnPassFail(temp075Below, -0.75f);
|
||||
|
||||
RtcTemperature temp050Below(0b11111111, 0b10000000); // -0.5
|
||||
ComparePrintlnPassFail(temp050Below, -0.50f);
|
||||
|
||||
RtcTemperature temp025Below(0b11111111, 0b11000000); // -0.25
|
||||
ComparePrintlnPassFail(temp025Below, -0.25f);
|
||||
|
||||
RtcTemperature tempZero(0b00000000, 0b00000000); // 0.0
|
||||
ComparePrintlnPassFail(tempZero, -0.0f);
|
||||
|
||||
RtcTemperature temp025Above(0b00000000, 0b01000000); // 0.25
|
||||
ComparePrintlnPassFail(temp025Above, 0.25f);
|
||||
|
||||
RtcTemperature temp050Above(0b00000000, 0b10000000); // 0.5
|
||||
ComparePrintlnPassFail(temp050Above, 0.5f);
|
||||
|
||||
RtcTemperature temp075Above(0b00000000, 0b11000000); // 0.75
|
||||
ComparePrintlnPassFail(temp075Above, 0.75f);
|
||||
|
||||
RtcTemperature temp25Above(0b00011001, 0b00000000); // 25.0
|
||||
ComparePrintlnPassFail(temp25Above, 25.0f);
|
||||
|
||||
RtcTemperature temp25Below(0b11100111, 0b00000000); // -25.0
|
||||
ComparePrintlnPassFail(temp25Below, -25.0f);
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
// SameType
|
||||
{
|
||||
Serial.print("same type ");
|
||||
RtcTemperature temp25Below(0b11100111, 0b00000000); // -25.0
|
||||
RtcTemperature test = temp25Below;
|
||||
ComparePrintlnPassFail(test, -25.0f);
|
||||
}
|
||||
|
||||
// CentiDegrees
|
||||
{
|
||||
Serial.print("centi degrees ");
|
||||
RtcTemperature temp025Below(-25); // -0.25
|
||||
ComparePrintlnPassFail(temp025Below, -0.25f);
|
||||
|
||||
Serial.print("centi degrees ");
|
||||
RtcTemperature temp025Above(25); // 0.25
|
||||
ComparePrintlnPassFail(temp025Above, 0.25f);
|
||||
|
||||
Serial.print("centi degrees ");
|
||||
RtcTemperature temp25Below(-2500); // -25.0
|
||||
ComparePrintlnPassFail(temp25Below, -25.0f);
|
||||
|
||||
Serial.print("centi degrees ");
|
||||
RtcTemperature temp25Above(2500); // 25.0
|
||||
ComparePrintlnPassFail(temp25Above, 25.0f);
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void PrintlnExpected(RtcTemperature& temp, uint16_t digits)
|
||||
{
|
||||
Serial.print(" = ");
|
||||
Serial.print(temp.AsFloatDegC(), digits);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void PrintTests()
|
||||
{
|
||||
Serial.println("Prints:");
|
||||
|
||||
RtcTemperature temp25Above(2500);
|
||||
temp25Above.Print(Serial);
|
||||
PrintlnExpected(temp25Above, 2);
|
||||
|
||||
RtcTemperature temp25Below(-2500);
|
||||
temp25Below.Print(Serial);
|
||||
PrintlnExpected(temp25Below, 2);
|
||||
|
||||
RtcTemperature temp025Above(25);
|
||||
temp025Above.Print(Serial);
|
||||
PrintlnExpected(temp025Above, 2);
|
||||
temp025Above.Print(Serial, 1);
|
||||
PrintlnExpected(temp025Above, 1);
|
||||
|
||||
RtcTemperature temp025Below(-25);
|
||||
temp025Below.Print(Serial);
|
||||
PrintlnExpected(temp025Below, 2);
|
||||
temp025Below.Print(Serial, 1);
|
||||
PrintlnExpected(temp025Below, 1);
|
||||
|
||||
RtcTemperature temp050Above(50);
|
||||
temp050Above.Print(Serial);
|
||||
PrintlnExpected(temp050Above, 2);
|
||||
temp050Above.Print(Serial, 0);
|
||||
PrintlnExpected(temp050Above, 0);
|
||||
|
||||
RtcTemperature temp050Below(-50);
|
||||
temp050Below.Print(Serial);
|
||||
PrintlnExpected(temp050Below, 2);
|
||||
temp050Below.Print(Serial, 0);
|
||||
PrintlnExpected(temp050Below, 0);
|
||||
temp050Below.Print(Serial, 2, ',');
|
||||
Serial.println(" == -0,50");
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void MathmaticalOperatorTests()
|
||||
{
|
||||
Serial.println("Mathmaticals:");
|
||||
|
||||
RtcTemperature temp050Below(-50);
|
||||
RtcTemperature temp050Above(50);
|
||||
RtcTemperature temp050Diff(100);
|
||||
RtcTemperature temp050Same(-50);
|
||||
RtcTemperature tempResult;
|
||||
|
||||
Serial.print("equality ");
|
||||
PrintPassFail(temp050Below == temp050Same);
|
||||
Serial.println();
|
||||
|
||||
Serial.print("inequality ");
|
||||
PrintPassFail(temp050Below != temp050Above);
|
||||
Serial.println();
|
||||
|
||||
Serial.print("less than ");
|
||||
PrintPassFail(temp050Below < temp050Above);
|
||||
Serial.println();
|
||||
|
||||
Serial.print("greater than ");
|
||||
PrintPassFail(temp050Above > temp050Below);
|
||||
Serial.println();
|
||||
|
||||
Serial.print("less than ");
|
||||
PrintPassFail(temp050Below <= temp050Above);
|
||||
Serial.print(" or equal ");
|
||||
PrintPassFail(temp050Below <= temp050Same);
|
||||
Serial.println();
|
||||
|
||||
Serial.print("greater than ");
|
||||
PrintPassFail(temp050Above >= temp050Below);
|
||||
Serial.print(" or equal ");
|
||||
PrintPassFail(temp050Below >= temp050Same);
|
||||
Serial.println();
|
||||
|
||||
tempResult = temp050Above - temp050Below;
|
||||
Serial.print("subtraction ");
|
||||
PrintPassFail(tempResult == temp050Diff);
|
||||
Serial.println();
|
||||
|
||||
tempResult = temp050Above + temp050Above;
|
||||
Serial.print("addition ");
|
||||
PrintPassFail(tempResult == temp050Diff);
|
||||
Serial.println();
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
Serial.println();
|
||||
|
||||
ConstructorTests();
|
||||
PrintTests();
|
||||
MathmaticalOperatorTests();
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
delay(500);
|
||||
}
|
||||
|
||||
209
libraries/Rtc_by_Makuna/keywords.txt
Normal file
209
libraries/Rtc_by_Makuna/keywords.txt
Normal file
@@ -0,0 +1,209 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map RTC
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
ThreeWire KEYWORD1
|
||||
RtcDS1302 KEYWORD1
|
||||
RtcDS1307 KEYWORD1
|
||||
DS3234AlarmOne KEYWORD1
|
||||
DS3234AlarmTwo KEYWORD1
|
||||
RtcDS3234 KEYWORD1
|
||||
DS3231AlarmOne KEYWORD1
|
||||
DS3231AlarmTwo KEYWORD1
|
||||
RtcDS3231 KEYWORD1
|
||||
EepromAt24c32 KEYWORD1
|
||||
RtcPCF8563 KEYWORD1
|
||||
PCF8563Alarm KEYWORD1
|
||||
RtcAlarmManager KEYWORD1
|
||||
RtcTemperature KEYWORD1
|
||||
RtcDateTime KEYWORD1
|
||||
DayOfWeek KEYWORD1
|
||||
AlarmPeriod KEYWORD1
|
||||
AlarmAddError KEYWORD1
|
||||
RtcAlarmCallback KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
Begin KEYWORD2
|
||||
LastError KEYWORD2
|
||||
IsDateTimeValid KEYWORD2
|
||||
GetIsRunning KEYWORD2
|
||||
SetIsRunning KEYWORD2
|
||||
GetIsWriteProtected KEYWORD2
|
||||
SetIsWriteProtected KEYWORD2
|
||||
SetDateTime KEYWORD2
|
||||
GetDateTime KEYWORD2
|
||||
GetTemperature KEYWORD2
|
||||
Enable32kHzPin KEYWORD2
|
||||
SetSquareWavePin KEYWORD2
|
||||
SetSquareWavePinClockFrequency KEYWORD2
|
||||
SetAlarmOne KEYWORD2
|
||||
SetAlarmTwo KEYWORD2
|
||||
GetAlarmOne KEYWORD2
|
||||
GetAlarmTwo KEYWORD2
|
||||
LatchAlarmsTriggeredFlags KEYWORD2
|
||||
ForceTemperatureCompensationUpdate KEYWORD2
|
||||
SetTemperatureCompensationRate KEYWORD2
|
||||
GetTemperatureCompensationRate KEYWORD2
|
||||
GetAgingOffset KEYWORD2
|
||||
SetAgingOffset KEYWORD2
|
||||
GetMemory KEYWORD2
|
||||
SetMemory KEYWORD2
|
||||
GetTrickleChargeSettings KEYWORD2
|
||||
SetTrickleChargeSettings KEYWORD2
|
||||
SetAlarm KEYWORD2
|
||||
StopAlarm KEYWORD2
|
||||
SetTimer KEYWORD2
|
||||
StopTimer KEYWORD2
|
||||
LatchAlarmTriggeredFlag KEYWORD2
|
||||
LatchTimerTriggeredFlag KEYWORD2
|
||||
GetAlarmTriggered KEYWORD2
|
||||
GetTimerTriggered KEYWORD2
|
||||
AsFloatDegC KEYWORD2
|
||||
AsFloatDegF KEYWORD2
|
||||
AsCentiDegC KEYWORD2
|
||||
Print KEYWORD2
|
||||
Year KEYWORD2
|
||||
Month KEYWORD2
|
||||
Day KEYWORD2
|
||||
Hour KEYWORD2
|
||||
Minute KEYWORD2
|
||||
Second KEYWORD2
|
||||
DayOfWeek KEYWORD2
|
||||
TotalSeconds KEYWORD2
|
||||
TotalSeconds64 KEYWORD2
|
||||
TotalDays KEYWORD2
|
||||
DayOf KEYWORD2
|
||||
IsValid KEYWORD2
|
||||
Unix32Time KEYWORD2
|
||||
InitWithUnix32Time KEYWORD2
|
||||
Unix64Time KEYWORD2
|
||||
InitWithUnix64Time KEYWORD2
|
||||
Ntp32Time KEYWORD2
|
||||
InitWithNtp32Time KEYWORD2
|
||||
Ntp64Time KEYWORD2
|
||||
InitWithNtp64Time KEYWORD2
|
||||
InitWithDateTimeFormatString KEYWORD2
|
||||
ConvertDowToRtc KEYWORD2
|
||||
ConvertRtcToDow KEYWORD2
|
||||
ControlFlags KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
||||
DS3231SquareWaveClock_1Hz LITERAL1
|
||||
DS3231SquareWaveClock_1kHz LITERAL1
|
||||
DS3231SquareWaveClock_4kHz LITERAL1
|
||||
DS3231SquareWaveClock_8kHz LITERAL1
|
||||
DS3231SquareWavePin_ModeNone LITERAL1
|
||||
DS3231SquareWavePin_ModeClock LITERAL1
|
||||
DS3231SquareWavePin_ModeAlarmOne LITERAL1
|
||||
DS3231SquareWavePin_ModeAlarmTwo LITERAL1
|
||||
DS3231SquareWavePin_ModeAlarmBoth LITERAL1
|
||||
DS3231AlarmOneControl_HoursMinutesSecondsDayOfMonthMatch LITERAL1
|
||||
DS3231AlarmOneControl_OncePerSecond LITERAL1
|
||||
DS3231AlarmOneControl_SecondsMatch LITERAL1
|
||||
DS3231AlarmOneControl_MinutesSecondsMatch LITERAL1
|
||||
DS3231AlarmOneControl_HoursMinutesSecondsMatch LITERAL1
|
||||
DS3231AlarmOneControl_HoursMinutesSecondsDayOfWeekMatch LITERAL1
|
||||
DS3231AlarmTwoControl_HoursMinutesDayOfMonthMatch LITERAL1
|
||||
DS3231AlarmTwoControl_OncePerMinute LITERAL1
|
||||
DS3231AlarmTwoControl_MinutesMatch LITERAL1
|
||||
DS3231AlarmTwoControl_HoursMinutesMatch LITERAL1
|
||||
DS3231AlarmTwoControl_HoursMinutesDayOfWeekMatch LITERAL1
|
||||
DS3231AlarmFlag_Alarm1 LITERAL1
|
||||
DS3231AlarmFlag_Alarm2 LITERAL1
|
||||
DS3231AlarmFlag_AlarmBoth LITERAL1
|
||||
DS1302RamSize LITERAL1
|
||||
DS1302Tcr_Disabled LITERAL1
|
||||
DS1302TcrResistor_2KOhm LITERAL1
|
||||
DS1302TcrResistor_4KOhm LITERAL1
|
||||
DS1302TcrResistor_8KOhm LITERAL1
|
||||
DS1302TcrDiodes_One LITERAL1
|
||||
DS1302TcrDiodes_Two LITERAL1
|
||||
DS1302TcrStatus_Enabled LITERAL1
|
||||
DS1302TcrStatus_Disabled LITERAL1
|
||||
DS1307SquareWaveOut_1Hz LITERAL1
|
||||
DS1307SquareWaveOut_4kHz LITERAL1
|
||||
DS1307SquareWaveOut_8kHz LITERAL1
|
||||
DS1307SquareWaveOut_32kHz LITERAL1
|
||||
DS1307SquareWaveOut_High LITERAL1
|
||||
DS1307SquareWaveOut_Low LITERAL1
|
||||
DS3234SquareWaveClock_1Hz LITERAL1
|
||||
DS3234SquareWaveClock_1kHz LITERAL1
|
||||
DS3234SquareWaveClock_4kHz LITERAL1
|
||||
DS3234SquareWaveClock_8kHz LITERAL1
|
||||
DS3234SquareWavePin_ModeNone LITERAL1
|
||||
DS3234SquareWavePin_ModeBatteryBackup LITERAL1
|
||||
DS3234SquareWavePin_ModeClock LITERAL1
|
||||
DS3234SquareWavePin_ModeAlarmOne LITERAL1
|
||||
DS3234SquareWavePin_ModeAlarmTwo LITERAL1
|
||||
DS3234SquareWavePin_ModeAlarmBoth LITERAL1
|
||||
DS3234AlarmOneControl_HoursMinutesSecondsDayOfMonthMatch LITERAL1
|
||||
DS3234AlarmOneControl_OncePerSecond LITERAL1
|
||||
DS3234AlarmOneControl_SecondsMatch LITERAL1
|
||||
DS3234AlarmOneControl_MinutesSecondsMatch LITERAL1
|
||||
DS3234AlarmOneControl_HoursMinutesSecondsMatch LITERAL1
|
||||
DS3234AlarmOneControl_HoursMinutesSecondsDayOfWeekMatch LITERAL1
|
||||
DS3234AlarmTwoControl_HoursMinutesDayOfMonthMatch LITERAL1
|
||||
DS3234AlarmTwoControl_OncePerMinute LITERAL1
|
||||
DS3234AlarmTwoControl_MinutesMatch LITERAL1
|
||||
DS3234AlarmTwoControl_HoursMinutesMatch LITERAL1
|
||||
DS3234AlarmTwoControl_HoursMinutesDayOfWeekMatch LITERAL1
|
||||
DS3234AlarmFlag_Alarm1 LITERAL1
|
||||
DS3234AlarmFlag_Alarm2 LITERAL1
|
||||
DS3234AlarmFlag_AlarmBoth LITERAL1
|
||||
DS3234TempCompensationRate_64Seconds LITERAL1
|
||||
DS3234TempCompensationRate_128Seconds LITERAL1
|
||||
DS3234TempCompensationRate_256Seconds LITERAL1
|
||||
DS3234TempCompensationRate_512Seconds LITERAL1
|
||||
PCF8563SquareWavePinMode_None LITERAL1
|
||||
PCF8563SquareWavePinMode_32kHz LITERAL1
|
||||
PCF8563SquareWavePinMode_1kHz LITERAL1
|
||||
PCF8563SquareWavePinMode_32Hz LITERAL1
|
||||
PCF8563SquareWavePinMode_1Hz LITERAL1
|
||||
PCF8563TimerMode_None LITERAL1
|
||||
PCF8563TimerMode_4096thOfASecond LITERAL1
|
||||
PCF8563TimerMode_64thOfASecond LITERAL1
|
||||
PCF8563TimerMode_Seconds LITERAL1
|
||||
PCF8563TimerMode_Minutes LITERAL1
|
||||
PCF8563AlarmControl_MinuteMatch LITERAL1
|
||||
PCF8563AlarmControl_HourMatch LITERAL1
|
||||
PCF8563AlarmControl_DayOfMonthMatch LITERAL1
|
||||
PCF8563AlarmControl_DayOfWeekMatch LITERAL1
|
||||
DayOfWeek_Sunday LITERAL1
|
||||
DayOfWeek_Monday LITERAL1
|
||||
DayOfWeek_Tuesday LITERAL1
|
||||
DayOfWeek_Wednesday LITERAL1
|
||||
DayOfWeek_Thursday LITERAL1
|
||||
DayOfWeek_Friday LITERAL1
|
||||
DayOfWeek_Saturday LITERAL1
|
||||
Rtc_Wire_Error LITERAL1
|
||||
Rtc_Wire_Error_None LITERAL1
|
||||
Rtc_Wire_Error_TxBufferOverflow LITERAL1
|
||||
Rtc_Wire_Error_NoAddressableDevice LITERAL1
|
||||
Rtc_Wire_Error_UnsupportedRequest LITERAL1
|
||||
Rtc_Wire_Error_Unspecific LITERAL1
|
||||
Rtc_Wire_Error_CommunicationTimeout LITERAL1
|
||||
RtcLocaleEnUs LITERAL1
|
||||
RtcLocaleEn LITERAL1
|
||||
AlarmPeriod_Expired LITERAL1
|
||||
AlarmPeriod_SingleFire LITERAL1
|
||||
AlarmPeriod_Yearly LITERAL1
|
||||
AlarmPeriod_Monthly LITERAL1
|
||||
AlarmPeriod_Monthly_LastDay LITERAL1
|
||||
AlarmPeriod_Weekly LITERAL1
|
||||
AlarmPeriod_Daily LITERAL1
|
||||
AlarmPeriod_Hourly LITERAL1
|
||||
AlarmAddError_PeriodInvalid LITERAL1
|
||||
AlarmAddError_TimePast LITERAL1
|
||||
AlarmAddError_TimeInvalid LITERAL1
|
||||
AlarmAddError_CountExceeded LITERAL1
|
||||
|
||||
13
libraries/Rtc_by_Makuna/library.json
Normal file
13
libraries/Rtc_by_Makuna/library.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "RTC",
|
||||
"keywords": "RTC, DS1302, DS1307, DS3231, DS3234, AT24C32, PCF8563, BM8563, clock",
|
||||
"description": "A library that makes interfacing DS1302, DS1307, DS3231, DS3234, and PCF8563/BM8563 Real Time Clock modules easy.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Makuna/Rtc.git"
|
||||
},
|
||||
"version": "2.4.2",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*"
|
||||
}
|
||||
|
||||
9
libraries/Rtc_by_Makuna/library.properties
Normal file
9
libraries/Rtc_by_Makuna/library.properties
Normal file
@@ -0,0 +1,9 @@
|
||||
name=Rtc by Makuna
|
||||
version=2.4.2
|
||||
author=Michael C. Miller (makuna@live.com)
|
||||
maintainer=Michael C. Miller (makuna@live.com)
|
||||
sentence=A library that makes interfacing DS1302, DS1307, DS3231, DS3234, and PCF8563/BM8563 Real Time Clock modules easy.
|
||||
paragraph=Includes deep support of module features, including temperature, alarms and memory storage if present. Tested on esp8266.
|
||||
category=Device Control
|
||||
url=https://github.com/Makuna/Rtc/wiki
|
||||
architectures=*
|
||||
145
libraries/Rtc_by_Makuna/src/EepromAT24C32.h
Normal file
145
libraries/Rtc_by_Makuna/src/EepromAT24C32.h
Normal file
@@ -0,0 +1,145 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
RTC library
|
||||
|
||||
Written by Michael C. Miller.
|
||||
|
||||
I invest time and resources providing this open source code,
|
||||
please support me by dontating (see https://github.com/Makuna/Rtc)
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the Makuna/Rtc library.
|
||||
|
||||
Rtc is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Rtc is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with Rtc. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
//I2C Slave Address
|
||||
const uint8_t AT24C32_ADDRESS = 0x50; // 0b0 1010 A2 A1 A0
|
||||
|
||||
template<class T_WIRE_METHOD> class EepromAt24c32
|
||||
{
|
||||
public:
|
||||
EepromAt24c32(T_WIRE_METHOD& wire, uint8_t addressBits = 0b000) :
|
||||
_address(AT24C32_ADDRESS | (addressBits & 0b00000111)),
|
||||
_wire(wire),
|
||||
_lastError(Rtc_Wire_Error_None)
|
||||
{
|
||||
}
|
||||
|
||||
void Begin()
|
||||
{
|
||||
_wire.begin();
|
||||
}
|
||||
|
||||
void Begin(int sda, int scl)
|
||||
{
|
||||
_wire.begin(sda, scl);
|
||||
}
|
||||
|
||||
uint8_t LastError()
|
||||
{
|
||||
return _lastError;
|
||||
}
|
||||
|
||||
void SetMemory(uint16_t memoryAddress, uint8_t value)
|
||||
{
|
||||
SetMemory(memoryAddress, &value, 1);
|
||||
}
|
||||
|
||||
uint8_t GetMemory(uint16_t memoryAddress)
|
||||
{
|
||||
uint8_t value;
|
||||
|
||||
GetMemory(memoryAddress, &value, 1);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// note: this method will write within a single page of eeprom.
|
||||
// Pages are 32 bytes (5 bits), so writing past a page boundary will
|
||||
// just wrap within the page of the starting memory address.
|
||||
//
|
||||
// xxxppppp pppaaaaa => p = page #, a = address within the page
|
||||
//
|
||||
// NOTE: hardware WIRE libraries often have a limit of a 32 byte send buffer. The
|
||||
// effect of this is that only 30 bytes can be sent, 2 bytes for the address to write to,
|
||||
// and then 30 bytes of the actual data.
|
||||
uint8_t SetMemory(uint16_t memoryAddress, const uint8_t* pValue, uint8_t countBytes)
|
||||
{
|
||||
uint8_t countWritten = 0;
|
||||
|
||||
beginTransmission(memoryAddress);
|
||||
|
||||
while (countBytes > 0)
|
||||
{
|
||||
_wire.write(*pValue++);
|
||||
delay(10); // per spec, memory writes
|
||||
|
||||
countBytes--;
|
||||
countWritten++;
|
||||
}
|
||||
|
||||
_lastError = _wire.endTransmission();
|
||||
|
||||
return countWritten;
|
||||
}
|
||||
|
||||
// reading data does not wrap within pages, but due to only using
|
||||
// 12 (32K) or 13 (64K) bits are used, they will wrap within the memory limits
|
||||
// of the installed EEPROM
|
||||
//
|
||||
// NOTE: hardware WIRE libraries may have a limit of a 32 byte recieve buffer. The
|
||||
// effect of this is that only 32 bytes can be read at one time.
|
||||
uint8_t GetMemory(uint16_t memoryAddress, uint8_t* pValue, uint8_t countBytes)
|
||||
{
|
||||
// set address to read from
|
||||
beginTransmission(memoryAddress);
|
||||
_lastError = _wire.endTransmission();
|
||||
|
||||
if (_lastError != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// read the data
|
||||
uint8_t countRead = 0;
|
||||
|
||||
countRead = _wire.requestFrom(_address, countBytes);
|
||||
countBytes = countRead;
|
||||
|
||||
while (countBytes-- > 0)
|
||||
{
|
||||
*pValue++ = _wire.read();
|
||||
}
|
||||
|
||||
return countRead;
|
||||
}
|
||||
|
||||
private:
|
||||
const uint8_t _address;
|
||||
|
||||
T_WIRE_METHOD& _wire;
|
||||
uint8_t _lastError;
|
||||
|
||||
void beginTransmission(uint16_t memoryAddress)
|
||||
{
|
||||
_wire.beginTransmission(_address);
|
||||
_wire.write(memoryAddress >> 8);
|
||||
_wire.write(memoryAddress & 0xFf);
|
||||
}
|
||||
};
|
||||
400
libraries/Rtc_by_Makuna/src/RtcAlarmManager.h
Normal file
400
libraries/Rtc_by_Makuna/src/RtcAlarmManager.h
Normal file
@@ -0,0 +1,400 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
RTC library
|
||||
|
||||
Written by Michael C. Miller.
|
||||
|
||||
I invest time and resources providing this open source code,
|
||||
please support me by dontating (see https://github.com/Makuna/Rtc)
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the Makuna/Rtc library.
|
||||
|
||||
Rtc is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Rtc is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with Rtc. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "RtcUtility.h"
|
||||
#include "RtcDateTime.h"
|
||||
|
||||
enum AlarmPeriod
|
||||
{
|
||||
AlarmPeriod_Expired,
|
||||
AlarmPeriod_SingleFire,
|
||||
AlarmPeriod_Yearly,
|
||||
AlarmPeriod_Monthly,
|
||||
AlarmPeriod_Monthly_LastDay,
|
||||
AlarmPeriod_Weekly,
|
||||
AlarmPeriod_Daily,
|
||||
AlarmPeriod_Hourly,
|
||||
// the below values are for internal use only
|
||||
AlarmPeriod_Yearly_Feb29th, // last of month in Feb if days less than and not a leap year,
|
||||
AlarmPeriod_Monthly_29th, // last of month if days less than,
|
||||
AlarmPeriod_Monthly_30th, // otherwise the day of month matching,
|
||||
AlarmPeriod_Monthly_31st, // this will be set internally, just use monthly
|
||||
AlarmPeriod_StartOfSpecifics = 60 // anything over this is considered a specific time in seconds
|
||||
};
|
||||
|
||||
enum AlarmAddError
|
||||
{
|
||||
AlarmAddError_PeriodInvalid = -4,
|
||||
AlarmAddError_TimePast,
|
||||
AlarmAddError_TimeInvalid,
|
||||
AlarmAddError_CountExceeded,
|
||||
};
|
||||
|
||||
typedef void(*RtcAlarmCallback)(uint8_t id, const RtcDateTime& alarm);
|
||||
|
||||
template <RtcAlarmCallback V_CALLBACK> class RtcAlarmManager
|
||||
{
|
||||
public:
|
||||
// construct
|
||||
// count - the max number of active alarms
|
||||
RtcAlarmManager(uint8_t count) :
|
||||
_alarmsCount(count)
|
||||
{
|
||||
_alarms = new Alarm[_alarmsCount];
|
||||
}
|
||||
|
||||
~RtcAlarmManager()
|
||||
{
|
||||
delete[] _alarms;
|
||||
}
|
||||
|
||||
// Sync the time to the external trusted source, like
|
||||
// a RTC module
|
||||
// Do this at regular intervals as the internal CPU timing
|
||||
// is not very accurate
|
||||
int32_t Sync(const RtcDateTime& now)
|
||||
{
|
||||
uint32_t msNow = millis();
|
||||
uint32_t secondsNow = now.TotalSeconds();
|
||||
// calc an updated seconds for old information
|
||||
uint32_t secondsOld = _seconds + (msNow - _msLast) / 1000;
|
||||
// set new seconds and start tracking the millis
|
||||
_msLast = msNow;
|
||||
_seconds = secondsNow;
|
||||
// return the delta from new seconds from old seconds
|
||||
return (secondsNow - secondsOld);
|
||||
}
|
||||
|
||||
// retrieve what the current time the AlarmManager thinks it is
|
||||
// due to inacurrancy of the CPU timing this may not be exact,
|
||||
// but it is good enough for most timing needs
|
||||
// regular use of Sync() will improve this
|
||||
RtcDateTime Now() const
|
||||
{
|
||||
uint32_t msNow = millis();
|
||||
uint32_t secondsNow = _seconds + (msNow - _msLast) / 1000;
|
||||
return RtcDateTime(secondsNow);
|
||||
}
|
||||
|
||||
// add an alarm
|
||||
// when - the date and time to start triggering alarms
|
||||
// period - the type of alarm, does it repeat and how often, see AlarmPeriod enum
|
||||
// return - if postive, the id of the Alarm, otherwise see AlarmAddError
|
||||
int8_t AddAlarm(const RtcDateTime& when,
|
||||
uint32_t period)
|
||||
{
|
||||
if (!when.IsValid())
|
||||
{
|
||||
return AlarmAddError_TimeInvalid;
|
||||
}
|
||||
if (period > AlarmPeriod_Monthly_31st &&
|
||||
period < AlarmPeriod_StartOfSpecifics)
|
||||
{
|
||||
return AlarmAddError_PeriodInvalid;
|
||||
}
|
||||
|
||||
int8_t result = AlarmAddError_TimeInvalid;
|
||||
uint32_t seconds = when.TotalSeconds();
|
||||
|
||||
if (period == AlarmPeriod_Monthly_LastDay)
|
||||
{
|
||||
period = AlarmPeriod_Monthly_31st;
|
||||
// adjust given when to last day of its set month
|
||||
uint8_t daysInMonth = RtcDateTime::DaysInMonth(when.Year(), when.Month());
|
||||
if (when.Day() < daysInMonth)
|
||||
{
|
||||
RtcDateTime temp(when.Year(),
|
||||
when.Month(),
|
||||
daysInMonth,
|
||||
when.Hour(),
|
||||
when.Minute(),
|
||||
when.Second());
|
||||
seconds = temp.TotalSeconds();
|
||||
}
|
||||
}
|
||||
else if (period == AlarmPeriod_Monthly ||
|
||||
(period >= AlarmPeriod_Monthly_29th && period <= AlarmPeriod_Monthly_31st))
|
||||
{
|
||||
period = AlarmPeriod_Monthly;
|
||||
// adjust alarm period to store target day of month
|
||||
// for when months have less days than the target
|
||||
// it will trigger on the last day of the month but
|
||||
// retain and trigger on specific day of month when
|
||||
// available
|
||||
if (when.Day() == 29)
|
||||
{
|
||||
period = AlarmPeriod_Monthly_29th;
|
||||
}
|
||||
else if (when.Day() == 30)
|
||||
{
|
||||
period = AlarmPeriod_Monthly_30th;
|
||||
}
|
||||
else if (when.Day() == 31)
|
||||
{
|
||||
period = AlarmPeriod_Monthly_31st;
|
||||
}
|
||||
}
|
||||
else if (period == AlarmPeriod_Yearly)
|
||||
{
|
||||
if (when.Day() == 29 && when.Month() == 2)
|
||||
{
|
||||
// adjust alarm period to store target day of month
|
||||
// for when Feb 29th is target but following year isn't
|
||||
// a leap year it will trigger on the last day of Feb but
|
||||
// retain and trigger on specific day of month when
|
||||
// available
|
||||
period = AlarmPeriod_Yearly_Feb29th;
|
||||
}
|
||||
}
|
||||
|
||||
Alarm alarm(seconds, period);
|
||||
|
||||
// if the alarm was added that was already in the past,
|
||||
// we increment the when to the next repeat
|
||||
// for non-repeatable alarms this may expire them
|
||||
if (seconds <= _seconds)
|
||||
{
|
||||
alarm.IncrementWhen();
|
||||
}
|
||||
|
||||
if (alarm.Period == AlarmPeriod_Expired)
|
||||
{
|
||||
result = AlarmAddError_TimePast;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = AlarmAddError_CountExceeded;
|
||||
|
||||
for (uint8_t id = 0; id < _alarmsCount; id++)
|
||||
{
|
||||
if (_alarms[id].Period == AlarmPeriod_Expired)
|
||||
{
|
||||
_alarms[id] = alarm;
|
||||
result = id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// remove an existing alarm
|
||||
// id - previously returned id from AddAlarm()
|
||||
void RemoveAlarm(uint8_t id)
|
||||
{
|
||||
if (id < _alarmsCount)
|
||||
{
|
||||
_alarms[id].Period = AlarmPeriod_Expired;
|
||||
}
|
||||
}
|
||||
|
||||
// check if the alarm is still active
|
||||
// id - previously returned id from AddAlarm()
|
||||
bool IsAlarmActive(uint8_t id)
|
||||
{
|
||||
if (id < _alarmsCount)
|
||||
{
|
||||
return (_alarms[id].Period != AlarmPeriod_Expired);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// process all the alarms which can trigger callbacks
|
||||
// call at regular intervals, if you need seconds accuracy, call
|
||||
// every second.
|
||||
// There is little need to call this faster than a few
|
||||
// times per second but it doesn't hurt anything
|
||||
void ProcessAlarms()
|
||||
{
|
||||
uint32_t msNow = millis();
|
||||
uint32_t msDelta = (msNow - _msLast);
|
||||
|
||||
if (msDelta > 1000)
|
||||
{
|
||||
// update seconds based on passed time using millis()
|
||||
_seconds += msDelta / 1000;
|
||||
_msLast = msNow - (msDelta % 1000); // retain fractional second
|
||||
|
||||
// used a local seconds in case a callback changes it
|
||||
uint32_t seconds = _seconds;
|
||||
|
||||
for (uint8_t id = 0; id < _alarmsCount; id++)
|
||||
{
|
||||
if (_alarms[id].Period != AlarmPeriod_Expired)
|
||||
{
|
||||
if (_alarms[id].When <= seconds)
|
||||
{
|
||||
RtcDateTime alarm(_alarms[id].When);
|
||||
|
||||
if (_alarms[id].Period == AlarmPeriod_SingleFire)
|
||||
{
|
||||
// remove from list
|
||||
_alarms[id].Period = AlarmPeriod_Expired;
|
||||
}
|
||||
else
|
||||
{
|
||||
_alarms[id].IncrementWhen();
|
||||
}
|
||||
|
||||
// make callback
|
||||
V_CALLBACK(id, alarm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
struct Alarm
|
||||
{
|
||||
uint32_t When; // seconds from RtcDateTime.TotalSeconds()
|
||||
uint32_t Period;
|
||||
|
||||
Alarm(uint32_t when = 0, uint32_t period = AlarmPeriod_Expired) :
|
||||
When(when),
|
||||
Period(period)
|
||||
{
|
||||
}
|
||||
|
||||
void IncrementWhen()
|
||||
{
|
||||
switch (Period)
|
||||
{
|
||||
case AlarmPeriod_Expired:
|
||||
break;
|
||||
|
||||
case AlarmPeriod_SingleFire:
|
||||
Period = AlarmPeriod_Expired;
|
||||
break;
|
||||
|
||||
case AlarmPeriod_Yearly:
|
||||
{
|
||||
RtcDateTime temp(When);
|
||||
RtcDateTime next(temp.Year() + 1,
|
||||
temp.Month(),
|
||||
temp.Day(),
|
||||
temp.Hour(),
|
||||
temp.Minute(),
|
||||
temp.Second());
|
||||
When = next.TotalSeconds();
|
||||
}
|
||||
break;
|
||||
|
||||
case AlarmPeriod_Yearly_Feb29th:
|
||||
{
|
||||
RtcDateTime temp(When);
|
||||
uint16_t year = temp.Year() + 1;
|
||||
uint8_t day = 28;
|
||||
|
||||
if (RtcDateTime::IsLeapYear(year))
|
||||
{
|
||||
day = 29;
|
||||
}
|
||||
|
||||
RtcDateTime next(year,
|
||||
2,
|
||||
day,
|
||||
temp.Hour(),
|
||||
temp.Minute(),
|
||||
temp.Second());
|
||||
When = next.TotalSeconds();
|
||||
}
|
||||
break;
|
||||
|
||||
case AlarmPeriod_Monthly:
|
||||
case AlarmPeriod_Monthly_29th:
|
||||
case AlarmPeriod_Monthly_30th:
|
||||
case AlarmPeriod_Monthly_31st:
|
||||
{
|
||||
RtcDateTime temp(When);
|
||||
|
||||
uint16_t year = temp.Year();
|
||||
uint8_t month = temp.Month() + 1;
|
||||
uint8_t day;
|
||||
|
||||
if (month > 12)
|
||||
{
|
||||
year++;
|
||||
month = 1;
|
||||
}
|
||||
|
||||
if (Period == AlarmPeriod_Monthly)
|
||||
{
|
||||
// use the day of the month from previous When
|
||||
day = temp.Day();
|
||||
}
|
||||
else
|
||||
{
|
||||
// use the day of the month cached as it may have
|
||||
// been capped to the last day of the month in When
|
||||
day = 29 + (Period - AlarmPeriod_Monthly_29th);
|
||||
}
|
||||
|
||||
uint8_t daysInMonth = RtcDateTime::DaysInMonth(year, month);
|
||||
if (day > daysInMonth)
|
||||
{
|
||||
day = daysInMonth;
|
||||
}
|
||||
|
||||
RtcDateTime next(year,
|
||||
month,
|
||||
day,
|
||||
temp.Hour(),
|
||||
temp.Minute(),
|
||||
temp.Second());
|
||||
When = next.TotalSeconds();
|
||||
}
|
||||
break;
|
||||
|
||||
case AlarmPeriod_Weekly:
|
||||
When += c_WeekAsSeconds;
|
||||
break;
|
||||
|
||||
case AlarmPeriod_Daily:
|
||||
When += c_DayAsSeconds;
|
||||
break;
|
||||
|
||||
case AlarmPeriod_Hourly:
|
||||
When += c_HourAsSeconds;
|
||||
break;
|
||||
|
||||
default:
|
||||
When += Period;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Alarm* _alarms; // table of possible alarms
|
||||
uint8_t _alarmsCount; // max alarms in _alarms
|
||||
uint32_t _msLast; // the last call to millis()
|
||||
uint32_t _seconds; // the approximate date time, as seconds from 2000
|
||||
};
|
||||
|
||||
289
libraries/Rtc_by_Makuna/src/RtcDS1302.h
Normal file
289
libraries/Rtc_by_Makuna/src/RtcDS1302.h
Normal file
@@ -0,0 +1,289 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
RTC library
|
||||
|
||||
Written by Michael C. Miller.
|
||||
|
||||
I invest time and resources providing this open source code,
|
||||
please support me by dontating (see https://github.com/Makuna/Rtc)
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the Makuna/Rtc library.
|
||||
|
||||
Rtc is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Rtc is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with Rtc. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "RtcUtility.h"
|
||||
#include "RtcDateTime.h"
|
||||
#include "ThreeWire.h"
|
||||
|
||||
|
||||
//DS1302 Register Addresses
|
||||
const uint8_t DS1302_REG_TIMEDATE = 0x80;
|
||||
const uint8_t DS1302_REG_TIMEDATE_BURST = 0xBE;
|
||||
const uint8_t DS1302_REG_TCR = 0x90;
|
||||
const uint8_t DS1302_REG_RAM_BURST = 0xFE;
|
||||
const uint8_t DS1302_REG_RAMSTART = 0xc0;
|
||||
const uint8_t DS1302_REG_RAMEND = 0xfd;
|
||||
// ram read and write addresses are interleaved
|
||||
const uint8_t DS1302RamSize = 31;
|
||||
|
||||
|
||||
// DS1302 Trickle Charge Control Register Bits
|
||||
enum DS1302TcrResistor
|
||||
{
|
||||
DS1302TcrResistor_Disabled = 0,
|
||||
DS1302TcrResistor_2KOhm = B00000001,
|
||||
DS1302TcrResistor_4KOhm = B00000010,
|
||||
DS1302TcrResistor_8KOhm = B00000011,
|
||||
DS1302TcrResistor_MASK = B00000011,
|
||||
};
|
||||
|
||||
enum DS1302TcrDiodes
|
||||
{
|
||||
DS1302TcrDiodes_None = 0,
|
||||
DS1302TcrDiodes_One = B00000100,
|
||||
DS1302TcrDiodes_Two = B00001000,
|
||||
DS1302TcrDiodes_Disabled = B00001100,
|
||||
DS1302TcrDiodes_MASK = B00001100,
|
||||
};
|
||||
|
||||
enum DS1302TcrStatus
|
||||
{
|
||||
DS1302TcrStatus_Enabled = B10100000,
|
||||
DS1302TcrStatus_Disabled = B01010000,
|
||||
DS1302TcrStatus_MASK = B11110000,
|
||||
};
|
||||
|
||||
const uint8_t DS1302Tcr_Disabled = DS1302TcrStatus_Disabled | DS1302TcrDiodes_Disabled | DS1302TcrResistor_Disabled;
|
||||
|
||||
// DS1302 Clock Halt Register & Bits
|
||||
const uint8_t DS1302_REG_CH = 0x80; // bit in the seconds register
|
||||
const uint8_t DS1302_CH = 7;
|
||||
|
||||
// Write Protect Register & Bits
|
||||
const uint8_t DS1302_REG_WP = 0x8E;
|
||||
const uint8_t DS1302_WP = 7;
|
||||
|
||||
template<class T_WIRE_METHOD> class RtcDS1302
|
||||
{
|
||||
public:
|
||||
RtcDS1302(T_WIRE_METHOD& wire) :
|
||||
_wire(wire)
|
||||
{
|
||||
}
|
||||
|
||||
void Begin()
|
||||
{
|
||||
_wire.begin();
|
||||
}
|
||||
|
||||
bool GetIsWriteProtected()
|
||||
{
|
||||
uint8_t wp = getReg(DS1302_REG_WP);
|
||||
return !!(wp & _BV(DS1302_WP));
|
||||
}
|
||||
|
||||
void SetIsWriteProtected(bool isWriteProtected)
|
||||
{
|
||||
uint8_t wp = getReg(DS1302_REG_WP);
|
||||
if (isWriteProtected)
|
||||
{
|
||||
wp |= _BV(DS1302_WP);
|
||||
}
|
||||
else
|
||||
{
|
||||
wp &= ~_BV(DS1302_WP);
|
||||
}
|
||||
setReg(DS1302_REG_WP, wp);
|
||||
}
|
||||
|
||||
bool IsDateTimeValid()
|
||||
{
|
||||
return GetDateTime().IsValid();
|
||||
}
|
||||
|
||||
bool GetIsRunning()
|
||||
{
|
||||
uint8_t ch = getReg(DS1302_REG_CH);
|
||||
return !(ch & _BV(DS1302_CH));
|
||||
}
|
||||
|
||||
void SetIsRunning(bool isRunning)
|
||||
{
|
||||
uint8_t ch = getReg(DS1302_REG_CH);
|
||||
if (isRunning)
|
||||
{
|
||||
ch &= ~_BV(DS1302_CH);
|
||||
}
|
||||
else
|
||||
{
|
||||
ch |= _BV(DS1302_CH);
|
||||
}
|
||||
setReg(DS1302_REG_CH, ch);
|
||||
}
|
||||
|
||||
uint8_t GetTrickleChargeSettings()
|
||||
{
|
||||
uint8_t setting = getReg(DS1302_REG_TCR);
|
||||
return setting;
|
||||
}
|
||||
|
||||
void SetTrickleChargeSettings(uint8_t setting)
|
||||
{
|
||||
if ((setting & DS1302TcrResistor_MASK) == DS1302TcrResistor_Disabled)
|
||||
{
|
||||
// invalid resistor setting, set to disabled
|
||||
setting = DS1302Tcr_Disabled;
|
||||
}
|
||||
else if ((setting & DS1302TcrDiodes_MASK) == DS1302TcrDiodes_Disabled ||
|
||||
(setting & DS1302TcrDiodes_MASK) == DS1302TcrDiodes_None)
|
||||
{
|
||||
// invalid diode setting, set to disabled
|
||||
setting = DS1302Tcr_Disabled;
|
||||
}
|
||||
else if ((setting & DS1302TcrStatus_MASK) != DS1302TcrStatus_Enabled)
|
||||
{
|
||||
// invalid status setting, set to disabled
|
||||
setting = DS1302Tcr_Disabled;
|
||||
}
|
||||
|
||||
setReg(DS1302_REG_TCR, setting);
|
||||
}
|
||||
|
||||
void SetDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
// set the date time
|
||||
_wire.beginTransmission(DS1302_REG_TIMEDATE_BURST);
|
||||
|
||||
_wire.write(Uint8ToBcd(dt.Second()));
|
||||
_wire.write(Uint8ToBcd(dt.Minute()));
|
||||
_wire.write(Uint8ToBcd(dt.Hour())); // 24 hour mode only
|
||||
_wire.write(Uint8ToBcd(dt.Day()));
|
||||
_wire.write(Uint8ToBcd(dt.Month()));
|
||||
|
||||
// RTC Hardware Day of Week is 1-7, 1 = Monday
|
||||
// convert our Day of Week to Rtc Day of Week
|
||||
uint8_t rtcDow = RtcDateTime::ConvertDowToRtc(dt.DayOfWeek());
|
||||
|
||||
_wire.write(Uint8ToBcd(rtcDow));
|
||||
_wire.write(Uint8ToBcd(dt.Year() - 2000));
|
||||
_wire.write(0); // no write protect, as all of this is ignored if it is protected
|
||||
|
||||
_wire.endTransmission();
|
||||
}
|
||||
|
||||
RtcDateTime GetDateTime()
|
||||
{
|
||||
_wire.beginTransmission(DS1302_REG_TIMEDATE_BURST | THREEWIRE_READFLAG);
|
||||
|
||||
uint8_t second = BcdToUint8(_wire.read() & 0x7F);
|
||||
uint8_t minute = BcdToUint8(_wire.read());
|
||||
uint8_t hour = BcdToBin24Hour(_wire.read());
|
||||
uint8_t dayOfMonth = BcdToUint8(_wire.read());
|
||||
uint8_t month = BcdToUint8(_wire.read());
|
||||
|
||||
_wire.read(); // throwing away day of week as we calculate it
|
||||
|
||||
uint16_t year = BcdToUint8(_wire.read()) + 2000;
|
||||
|
||||
_wire.read(); // throwing away write protect flag
|
||||
|
||||
_wire.endTransmission();
|
||||
|
||||
return RtcDateTime(year, month, dayOfMonth, hour, minute, second);
|
||||
}
|
||||
|
||||
void SetMemory(uint8_t memoryAddress, uint8_t value)
|
||||
{
|
||||
// memory addresses interleaved read and write addresses
|
||||
// so we need to calculate the offset
|
||||
uint8_t address = memoryAddress * 2 + DS1302_REG_RAMSTART;
|
||||
if (address <= DS1302_REG_RAMEND)
|
||||
{
|
||||
setReg(address, value);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t GetMemory(uint8_t memoryAddress)
|
||||
{
|
||||
uint8_t value = 0;
|
||||
// memory addresses interleaved read and write addresses
|
||||
// so we need to calculate the offset
|
||||
uint8_t address = memoryAddress * 2 + DS1302_REG_RAMSTART;
|
||||
if (address <= DS1302_REG_RAMEND)
|
||||
{
|
||||
value = getReg(address);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
uint8_t SetMemory(const uint8_t* pValue, uint8_t countBytes)
|
||||
{
|
||||
uint8_t countWritten = 0;
|
||||
|
||||
_wire.beginTransmission(DS1302_REG_RAM_BURST);
|
||||
|
||||
while (countBytes > 0 && countWritten < DS1302RamSize)
|
||||
{
|
||||
_wire.write(*pValue++);
|
||||
countBytes--;
|
||||
countWritten++;
|
||||
}
|
||||
|
||||
_wire.endTransmission();
|
||||
|
||||
return countWritten;
|
||||
}
|
||||
|
||||
uint8_t GetMemory(uint8_t* pValue, uint8_t countBytes)
|
||||
{
|
||||
uint8_t countRead = 0;
|
||||
|
||||
_wire.beginTransmission(DS1302_REG_RAM_BURST | THREEWIRE_READFLAG);
|
||||
|
||||
while (countBytes > 0 && countRead < DS1302RamSize)
|
||||
{
|
||||
*pValue++ = _wire.read();
|
||||
countRead++;
|
||||
countBytes--;
|
||||
}
|
||||
|
||||
_wire.endTransmission();
|
||||
|
||||
return countRead;
|
||||
}
|
||||
|
||||
private:
|
||||
T_WIRE_METHOD& _wire;
|
||||
|
||||
uint8_t getReg(uint8_t regAddress)
|
||||
{
|
||||
_wire.beginTransmission(regAddress | THREEWIRE_READFLAG);
|
||||
uint8_t regValue = _wire.read();
|
||||
_wire.endTransmission();
|
||||
return regValue;
|
||||
}
|
||||
|
||||
void setReg(uint8_t regAddress, uint8_t regValue)
|
||||
{
|
||||
_wire.beginTransmission(regAddress);
|
||||
_wire.write(regValue);
|
||||
_wire.endTransmission();
|
||||
}
|
||||
};
|
||||
|
||||
284
libraries/Rtc_by_Makuna/src/RtcDS1307.h
Normal file
284
libraries/Rtc_by_Makuna/src/RtcDS1307.h
Normal file
@@ -0,0 +1,284 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
RTC library
|
||||
|
||||
Written by Michael C. Miller.
|
||||
|
||||
I invest time and resources providing this open source code,
|
||||
please support me by dontating (see https://github.com/Makuna/Rtc)
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the Makuna/Rtc library.
|
||||
|
||||
Rtc is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Rtc is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with Rtc. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "RtcUtility.h"
|
||||
#include "RtcDateTime.h"
|
||||
|
||||
//I2C Slave Address
|
||||
const uint8_t DS1307_ADDRESS = 0x68;
|
||||
|
||||
//DS1307 Register Addresses
|
||||
const uint8_t DS1307_REG_TIMEDATE = 0x00;
|
||||
const uint8_t DS1307_REG_STATUS = 0x00;
|
||||
const uint8_t DS1307_REG_CONTROL = 0x07;
|
||||
const uint8_t DS1307_REG_RAMSTART = 0x08;
|
||||
const uint8_t DS1307_REG_RAMEND = 0x3f;
|
||||
const uint8_t DS1307_REG_RAMSIZE = DS1307_REG_RAMEND - DS1307_REG_RAMSTART;
|
||||
|
||||
//DS1307 Register Data Size if not just 1
|
||||
const size_t DS1307_REG_TIMEDATE_SIZE = 7;
|
||||
|
||||
// DS1307 Control Register Bits
|
||||
const uint8_t DS1307_RS0 = 0;
|
||||
const uint8_t DS1307_RS1 = 1;
|
||||
const uint8_t DS1307_SQWE = 4;
|
||||
const uint8_t DS1307_OUT = 7;
|
||||
|
||||
// DS1307 Status Register Bits
|
||||
const uint8_t DS1307_CH = 7;
|
||||
|
||||
enum DS1307SquareWaveOut
|
||||
{
|
||||
DS1307SquareWaveOut_1Hz = 0b00010000,
|
||||
DS1307SquareWaveOut_4kHz = 0b00010001,
|
||||
DS1307SquareWaveOut_8kHz = 0b00010010,
|
||||
DS1307SquareWaveOut_32kHz = 0b00010011,
|
||||
DS1307SquareWaveOut_High = 0b10000000,
|
||||
DS1307SquareWaveOut_Low = 0b00000000,
|
||||
};
|
||||
|
||||
template<class T_WIRE_METHOD> class RtcDS1307
|
||||
{
|
||||
public:
|
||||
RtcDS1307(T_WIRE_METHOD& wire) :
|
||||
_wire(wire),
|
||||
_lastError(Rtc_Wire_Error_None)
|
||||
{
|
||||
}
|
||||
|
||||
void Begin()
|
||||
{
|
||||
_wire.begin();
|
||||
}
|
||||
|
||||
void Begin(int sda, int scl)
|
||||
{
|
||||
_wire.begin(sda, scl);
|
||||
}
|
||||
|
||||
uint8_t LastError()
|
||||
{
|
||||
return _lastError;
|
||||
}
|
||||
|
||||
bool IsDateTimeValid()
|
||||
{
|
||||
return GetIsRunning();
|
||||
}
|
||||
|
||||
bool GetIsRunning()
|
||||
{
|
||||
uint8_t sreg = getReg(DS1307_REG_STATUS);
|
||||
return (!(sreg & _BV(DS1307_CH)) && (_lastError == Rtc_Wire_Error_None));
|
||||
}
|
||||
|
||||
void SetIsRunning(bool isRunning)
|
||||
{
|
||||
uint8_t sreg = getReg(DS1307_REG_STATUS);
|
||||
|
||||
if (isRunning)
|
||||
{
|
||||
sreg &= ~_BV(DS1307_CH);
|
||||
}
|
||||
else
|
||||
{
|
||||
sreg |= _BV(DS1307_CH);
|
||||
}
|
||||
|
||||
setReg(DS1307_REG_STATUS, sreg);
|
||||
}
|
||||
|
||||
void SetDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
// retain running state
|
||||
uint8_t sreg = getReg(DS1307_REG_STATUS) & _BV(DS1307_CH);
|
||||
|
||||
// set the date time
|
||||
_wire.beginTransmission(DS1307_ADDRESS);
|
||||
_wire.write(DS1307_REG_TIMEDATE);
|
||||
|
||||
_wire.write(Uint8ToBcd(dt.Second()) | sreg);
|
||||
_wire.write(Uint8ToBcd(dt.Minute()));
|
||||
_wire.write(Uint8ToBcd(dt.Hour())); // 24 hour mode only
|
||||
|
||||
// RTC Hardware Day of Week is 1-7, 1 = Monday
|
||||
// convert our Day of Week to Rtc Day of Week
|
||||
uint8_t rtcDow = RtcDateTime::ConvertDowToRtc(dt.DayOfWeek());
|
||||
|
||||
_wire.write(Uint8ToBcd(rtcDow));
|
||||
_wire.write(Uint8ToBcd(dt.Day()));
|
||||
_wire.write(Uint8ToBcd(dt.Month()));
|
||||
_wire.write(Uint8ToBcd(dt.Year() - 2000));
|
||||
|
||||
_lastError = _wire.endTransmission();
|
||||
}
|
||||
|
||||
RtcDateTime GetDateTime()
|
||||
{
|
||||
_wire.beginTransmission(DS1307_ADDRESS);
|
||||
_wire.write(DS1307_REG_TIMEDATE);
|
||||
_lastError = _wire.endTransmission();
|
||||
if (_lastError != Rtc_Wire_Error_None)
|
||||
{
|
||||
RtcDateTime(0);
|
||||
}
|
||||
|
||||
size_t bytesRead = _wire.requestFrom(DS1307_ADDRESS, DS1307_REG_TIMEDATE_SIZE);
|
||||
if (DS1307_REG_TIMEDATE_SIZE != bytesRead)
|
||||
{
|
||||
_lastError = Rtc_Wire_Error_Unspecific;
|
||||
RtcDateTime(0);
|
||||
}
|
||||
|
||||
uint8_t second = BcdToUint8(_wire.read() & 0x7F);
|
||||
uint8_t minute = BcdToUint8(_wire.read());
|
||||
uint8_t hour = BcdToBin24Hour(_wire.read());
|
||||
|
||||
_wire.read(); // throwing away day of week as we calculate it
|
||||
|
||||
uint8_t dayOfMonth = BcdToUint8(_wire.read());
|
||||
uint8_t month = BcdToUint8(_wire.read());
|
||||
uint16_t year = BcdToUint8(_wire.read()) + 2000;
|
||||
|
||||
return RtcDateTime(year, month, dayOfMonth, hour, minute, second);
|
||||
}
|
||||
|
||||
void SetMemory(uint8_t memoryAddress, uint8_t value)
|
||||
{
|
||||
uint8_t address = memoryAddress + DS1307_REG_RAMSTART;
|
||||
if (address <= DS1307_REG_RAMEND)
|
||||
{
|
||||
setReg(address, value);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t GetMemory(uint8_t memoryAddress)
|
||||
{
|
||||
uint8_t value = 0;
|
||||
uint8_t address = memoryAddress + DS1307_REG_RAMSTART;
|
||||
if (address <= DS1307_REG_RAMEND)
|
||||
{
|
||||
value = getReg(address);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
uint8_t SetMemory(uint8_t memoryAddress, const uint8_t* pValue, uint8_t countBytes)
|
||||
{
|
||||
uint8_t address = memoryAddress + DS1307_REG_RAMSTART;
|
||||
uint8_t countWritten = 0;
|
||||
if (address <= DS1307_REG_RAMEND)
|
||||
{
|
||||
_wire.beginTransmission(DS1307_ADDRESS);
|
||||
_wire.write(address);
|
||||
|
||||
while (countBytes > 0 && address <= DS1307_REG_RAMEND)
|
||||
{
|
||||
_wire.write(*pValue++);
|
||||
address++;
|
||||
countBytes--;
|
||||
countWritten++;
|
||||
}
|
||||
|
||||
_lastError = _wire.endTransmission();
|
||||
}
|
||||
return countWritten;
|
||||
}
|
||||
|
||||
size_t GetMemory(uint8_t memoryAddress, uint8_t* pValue, size_t countBytes)
|
||||
{
|
||||
uint8_t address = memoryAddress + DS1307_REG_RAMSTART;
|
||||
size_t countRead = 0;
|
||||
if (address <= DS1307_REG_RAMEND)
|
||||
{
|
||||
if (countBytes > DS1307_REG_RAMSIZE)
|
||||
{
|
||||
countBytes = DS1307_REG_RAMSIZE;
|
||||
}
|
||||
|
||||
_wire.beginTransmission(DS1307_ADDRESS);
|
||||
_wire.write(address);
|
||||
_lastError = _wire.endTransmission();
|
||||
if (_lastError != Rtc_Wire_Error_None)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
countRead = _wire.requestFrom(DS1307_ADDRESS, countBytes);
|
||||
countBytes = countRead;
|
||||
|
||||
while (countBytes-- > 0)
|
||||
{
|
||||
*pValue++ = _wire.read();
|
||||
}
|
||||
}
|
||||
|
||||
return countRead;
|
||||
}
|
||||
|
||||
void SetSquareWavePin(DS1307SquareWaveOut pinMode)
|
||||
{
|
||||
setReg(DS1307_REG_CONTROL, pinMode);
|
||||
}
|
||||
|
||||
private:
|
||||
T_WIRE_METHOD& _wire;
|
||||
uint8_t _lastError;
|
||||
|
||||
uint8_t getReg(uint8_t regAddress)
|
||||
{
|
||||
_wire.beginTransmission(DS1307_ADDRESS);
|
||||
_wire.write(regAddress);
|
||||
_lastError = _wire.endTransmission();
|
||||
if (_lastError != Rtc_Wire_Error_None)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// control register
|
||||
size_t bytesRead = _wire.requestFrom(DS1307_ADDRESS, (size_t)1);
|
||||
if (1 != bytesRead)
|
||||
{
|
||||
_lastError = Rtc_Wire_Error_Unspecific;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t regValue = _wire.read();
|
||||
return regValue;
|
||||
}
|
||||
|
||||
void setReg(uint8_t regAddress, uint8_t regValue)
|
||||
{
|
||||
_wire.beginTransmission(DS1307_ADDRESS);
|
||||
_wire.write(regAddress);
|
||||
_wire.write(regValue);
|
||||
_lastError = _wire.endTransmission();
|
||||
}
|
||||
};
|
||||
|
||||
683
libraries/Rtc_by_Makuna/src/RtcDS3231.h
Normal file
683
libraries/Rtc_by_Makuna/src/RtcDS3231.h
Normal file
@@ -0,0 +1,683 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
RTC library
|
||||
|
||||
Written by Michael C. Miller.
|
||||
|
||||
I invest time and resources providing this open source code,
|
||||
please support me by dontating (see https://github.com/Makuna/Rtc)
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the Makuna/Rtc library.
|
||||
|
||||
Rtc is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Rtc is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with Rtc. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "RtcUtility.h"
|
||||
#include "RtcDateTime.h"
|
||||
#include "RtcTemperature.h"
|
||||
|
||||
|
||||
//I2C Slave Address
|
||||
const uint8_t DS3231_ADDRESS = 0x68;
|
||||
|
||||
//DS3231 Register Addresses
|
||||
const uint8_t DS3231_REG_TIMEDATE = 0x00;
|
||||
const uint8_t DS3231_REG_ALARMONE = 0x07;
|
||||
const uint8_t DS3231_REG_ALARMTWO = 0x0B;
|
||||
|
||||
const uint8_t DS3231_REG_CONTROL = 0x0E;
|
||||
const uint8_t DS3231_REG_STATUS = 0x0F;
|
||||
const uint8_t DS3231_REG_AGING = 0x10;
|
||||
|
||||
const uint8_t DS3231_REG_TEMP = 0x11;
|
||||
|
||||
|
||||
//DS3231 Register Data Size if not just 1
|
||||
const size_t DS3231_REG_TIMEDATE_SIZE = 7;
|
||||
const size_t DS3231_REG_ALARMONE_SIZE = 4;
|
||||
const size_t DS3231_REG_ALARMTWO_SIZE = 3;
|
||||
|
||||
const size_t DS3231_REG_TEMP_SIZE = 2;
|
||||
|
||||
// DS3231 Control Register Bits
|
||||
const uint8_t DS3231_A1IE = 0;
|
||||
const uint8_t DS3231_A2IE = 1;
|
||||
const uint8_t DS3231_INTCN = 2;
|
||||
const uint8_t DS3231_RS1 = 3;
|
||||
const uint8_t DS3231_RS2 = 4;
|
||||
const uint8_t DS3231_CONV = 5;
|
||||
const uint8_t DS3231_BBSQW = 6;
|
||||
const uint8_t DS3231_EOSC = 7;
|
||||
const uint8_t DS3231_AIEMASK = (_BV(DS3231_A1IE) | _BV(DS3231_A2IE));
|
||||
const uint8_t DS3231_RSMASK = (_BV(DS3231_RS1) | _BV(DS3231_RS2));
|
||||
|
||||
// DS3231 Status Register Bits
|
||||
const uint8_t DS3231_A1F = 0;
|
||||
const uint8_t DS3231_A2F = 1;
|
||||
const uint8_t DS3231_BSY = 2;
|
||||
const uint8_t DS3231_EN32KHZ = 3;
|
||||
const uint8_t DS3231_OSF = 7;
|
||||
const uint8_t DS3231_AIFMASK = (_BV(DS3231_A1F) | _BV(DS3231_A2F));
|
||||
|
||||
|
||||
// seconds accuracy
|
||||
enum DS3231AlarmOneControl
|
||||
{
|
||||
// bit order: A1M4 DY/DT A1M3 A1M2 A1M1
|
||||
DS3231AlarmOneControl_HoursMinutesSecondsDayOfMonthMatch = 0x00,
|
||||
DS3231AlarmOneControl_OncePerSecond = 0x17,
|
||||
DS3231AlarmOneControl_SecondsMatch = 0x16,
|
||||
DS3231AlarmOneControl_MinutesSecondsMatch = 0x14,
|
||||
DS3231AlarmOneControl_HoursMinutesSecondsMatch = 0x10,
|
||||
DS3231AlarmOneControl_HoursMinutesSecondsDayOfWeekMatch = 0x08,
|
||||
};
|
||||
|
||||
class DS3231AlarmOne
|
||||
{
|
||||
public:
|
||||
DS3231AlarmOne( uint8_t dayOf,
|
||||
uint8_t hour,
|
||||
uint8_t minute,
|
||||
uint8_t second,
|
||||
DS3231AlarmOneControl controlFlags) :
|
||||
_flags(controlFlags),
|
||||
_dayOf(dayOf),
|
||||
_hour(hour),
|
||||
_minute(minute),
|
||||
_second(second)
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t DayOf() const
|
||||
{
|
||||
return _dayOf;
|
||||
}
|
||||
|
||||
uint8_t Hour() const
|
||||
{
|
||||
return _hour;
|
||||
}
|
||||
|
||||
uint8_t Minute() const
|
||||
{
|
||||
return _minute;
|
||||
}
|
||||
|
||||
uint8_t Second() const
|
||||
{
|
||||
return _second;
|
||||
}
|
||||
|
||||
DS3231AlarmOneControl ControlFlags() const
|
||||
{
|
||||
return _flags;
|
||||
}
|
||||
|
||||
bool operator == (const DS3231AlarmOne& other) const
|
||||
{
|
||||
return (_dayOf == other._dayOf &&
|
||||
_hour == other._hour &&
|
||||
_minute == other._minute &&
|
||||
_second == other._second &&
|
||||
_flags == other._flags);
|
||||
}
|
||||
|
||||
bool operator != (const DS3231AlarmOne& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
protected:
|
||||
DS3231AlarmOneControl _flags;
|
||||
|
||||
uint8_t _dayOf;
|
||||
uint8_t _hour;
|
||||
uint8_t _minute;
|
||||
uint8_t _second;
|
||||
};
|
||||
|
||||
// minutes accuracy
|
||||
enum DS3231AlarmTwoControl
|
||||
{
|
||||
// bit order: A2M4 DY/DT A2M3 A2M2
|
||||
DS3231AlarmTwoControl_HoursMinutesDayOfMonthMatch = 0x00,
|
||||
DS3231AlarmTwoControl_OncePerMinute = 0x0b,
|
||||
DS3231AlarmTwoControl_MinutesMatch = 0x0a,
|
||||
DS3231AlarmTwoControl_HoursMinutesMatch = 0x08,
|
||||
DS3231AlarmTwoControl_HoursMinutesDayOfWeekMatch = 0x04,
|
||||
};
|
||||
|
||||
class DS3231AlarmTwo
|
||||
{
|
||||
public:
|
||||
DS3231AlarmTwo( uint8_t dayOf,
|
||||
uint8_t hour,
|
||||
uint8_t minute,
|
||||
DS3231AlarmTwoControl controlFlags) :
|
||||
_flags(controlFlags),
|
||||
_dayOf(dayOf),
|
||||
_hour(hour),
|
||||
_minute(minute)
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t DayOf() const
|
||||
{
|
||||
return _dayOf;
|
||||
}
|
||||
|
||||
uint8_t Hour() const
|
||||
{
|
||||
return _hour;
|
||||
}
|
||||
|
||||
uint8_t Minute() const
|
||||
{
|
||||
return _minute;
|
||||
}
|
||||
|
||||
DS3231AlarmTwoControl ControlFlags() const
|
||||
{
|
||||
return _flags;
|
||||
}
|
||||
|
||||
bool operator == (const DS3231AlarmTwo& other) const
|
||||
{
|
||||
return (_dayOf == other._dayOf &&
|
||||
_hour == other._hour &&
|
||||
_minute == other._minute &&
|
||||
_flags == other._flags);
|
||||
}
|
||||
|
||||
bool operator != (const DS3231AlarmTwo& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
protected:
|
||||
DS3231AlarmTwoControl _flags;
|
||||
|
||||
uint8_t _dayOf;
|
||||
uint8_t _hour;
|
||||
uint8_t _minute;
|
||||
};
|
||||
|
||||
|
||||
enum DS3231SquareWaveClock
|
||||
{
|
||||
DS3231SquareWaveClock_1Hz = 0b00000000,
|
||||
DS3231SquareWaveClock_1kHz = 0b00001000,
|
||||
DS3231SquareWaveClock_4kHz = 0b00010000,
|
||||
DS3231SquareWaveClock_8kHz = 0b00011000,
|
||||
};
|
||||
|
||||
enum DS3231SquareWavePinMode
|
||||
{
|
||||
DS3231SquareWavePin_ModeNone,
|
||||
DS3231SquareWavePin_ModeAlarmOne,
|
||||
DS3231SquareWavePin_ModeAlarmTwo,
|
||||
// note: the same as DS3231SquareWavePin_ModeAlarmOne | DS3231SquareWavePin_ModeAlarmTwo
|
||||
DS3231SquareWavePin_ModeAlarmBoth,
|
||||
DS3231SquareWavePin_ModeClock
|
||||
};
|
||||
|
||||
enum DS3231AlarmFlag
|
||||
{
|
||||
DS3231AlarmFlag_Alarm1 = 0x01,
|
||||
DS3231AlarmFlag_Alarm2 = 0x02,
|
||||
DS3231AlarmFlag_AlarmBoth = 0x03,
|
||||
};
|
||||
|
||||
template<class T_WIRE_METHOD> class RtcDS3231
|
||||
{
|
||||
public:
|
||||
RtcDS3231(T_WIRE_METHOD& wire) :
|
||||
_wire(wire),
|
||||
_lastError(Rtc_Wire_Error_None)
|
||||
{
|
||||
}
|
||||
|
||||
void Begin()
|
||||
{
|
||||
_wire.begin();
|
||||
}
|
||||
|
||||
void Begin(int sda, int scl)
|
||||
{
|
||||
_wire.begin(sda, scl);
|
||||
}
|
||||
|
||||
uint8_t LastError()
|
||||
{
|
||||
return _lastError;
|
||||
}
|
||||
|
||||
bool IsDateTimeValid()
|
||||
{
|
||||
uint8_t status = getReg(DS3231_REG_STATUS);
|
||||
return (!(status & _BV(DS3231_OSF)) && (_lastError == Rtc_Wire_Error_None));
|
||||
}
|
||||
|
||||
bool GetIsRunning()
|
||||
{
|
||||
uint8_t creg = getReg(DS3231_REG_CONTROL);
|
||||
return (!(creg & _BV(DS3231_EOSC)) && (_lastError == Rtc_Wire_Error_None));
|
||||
}
|
||||
|
||||
void SetIsRunning(bool isRunning)
|
||||
{
|
||||
uint8_t creg = getReg(DS3231_REG_CONTROL);
|
||||
if (isRunning)
|
||||
{
|
||||
creg &= ~_BV(DS3231_EOSC);
|
||||
}
|
||||
else
|
||||
{
|
||||
creg |= _BV(DS3231_EOSC);
|
||||
}
|
||||
setReg(DS3231_REG_CONTROL, creg);
|
||||
}
|
||||
|
||||
void SetDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
// clear the invalid flag
|
||||
uint8_t status = getReg(DS3231_REG_STATUS);
|
||||
status &= ~_BV(DS3231_OSF); // clear the flag
|
||||
setReg(DS3231_REG_STATUS, status);
|
||||
|
||||
// set the date time
|
||||
_wire.beginTransmission(DS3231_ADDRESS);
|
||||
_wire.write(DS3231_REG_TIMEDATE);
|
||||
|
||||
_wire.write(Uint8ToBcd(dt.Second()));
|
||||
_wire.write(Uint8ToBcd(dt.Minute()));
|
||||
_wire.write(Uint8ToBcd(dt.Hour())); // 24 hour mode only
|
||||
|
||||
uint8_t year = dt.Year() - 2000;
|
||||
uint8_t centuryFlag = 0;
|
||||
|
||||
if (year >= 100)
|
||||
{
|
||||
year -= 100;
|
||||
centuryFlag = _BV(7);
|
||||
}
|
||||
|
||||
// RTC Hardware Day of Week is 1-7, 1 = Monday
|
||||
// convert our Day of Week to Rtc Day of Week
|
||||
uint8_t rtcDow = RtcDateTime::ConvertDowToRtc(dt.DayOfWeek());
|
||||
|
||||
_wire.write(Uint8ToBcd(rtcDow));
|
||||
|
||||
_wire.write(Uint8ToBcd(dt.Day()));
|
||||
_wire.write(Uint8ToBcd(dt.Month()) | centuryFlag);
|
||||
_wire.write(Uint8ToBcd(year));
|
||||
|
||||
_lastError = _wire.endTransmission();
|
||||
}
|
||||
|
||||
RtcDateTime GetDateTime()
|
||||
{
|
||||
_wire.beginTransmission(DS3231_ADDRESS);
|
||||
_wire.write(DS3231_REG_TIMEDATE);
|
||||
_lastError = _wire.endTransmission();
|
||||
if (_lastError != Rtc_Wire_Error_None)
|
||||
{
|
||||
return RtcDateTime(0);
|
||||
}
|
||||
|
||||
size_t bytesRead = _wire.requestFrom(DS3231_ADDRESS, DS3231_REG_TIMEDATE_SIZE);
|
||||
if (DS3231_REG_TIMEDATE_SIZE != bytesRead)
|
||||
{
|
||||
_lastError = Rtc_Wire_Error_Unspecific;
|
||||
return RtcDateTime(0);
|
||||
}
|
||||
|
||||
uint8_t second = BcdToUint8(_wire.read() & 0x7F);
|
||||
uint8_t minute = BcdToUint8(_wire.read());
|
||||
uint8_t hour = BcdToBin24Hour(_wire.read());
|
||||
|
||||
_wire.read(); // throwing away day of week as we calculate it
|
||||
|
||||
uint8_t dayOfMonth = BcdToUint8(_wire.read());
|
||||
uint8_t monthRaw = _wire.read();
|
||||
uint16_t year = BcdToUint8(_wire.read()) + 2000;
|
||||
|
||||
if (monthRaw & _BV(7)) // century wrap flag
|
||||
{
|
||||
year += 100;
|
||||
}
|
||||
uint8_t month = BcdToUint8(monthRaw & 0x7f);
|
||||
|
||||
|
||||
return RtcDateTime(year, month, dayOfMonth, hour, minute, second);
|
||||
}
|
||||
|
||||
RtcTemperature GetTemperature()
|
||||
{
|
||||
_wire.beginTransmission(DS3231_ADDRESS);
|
||||
_wire.write(DS3231_REG_TEMP);
|
||||
_lastError = _wire.endTransmission();
|
||||
if (_lastError != Rtc_Wire_Error_None)
|
||||
{
|
||||
return RtcTemperature(0);
|
||||
}
|
||||
|
||||
// Temperature is represented as a 10-bit code with a resolution
|
||||
// of 1/4th °C and is accessable as a signed 16-bit integer at
|
||||
// locations 11h and 12h.
|
||||
//
|
||||
// | r11h | DP | r12h |
|
||||
// Bit: 15 14 13 12 11 10 9 8 . 7 6 5 4 3 2 1 0 -1 -2
|
||||
// s i i i i i i i . f f 0 0 0 0 0 0
|
||||
//
|
||||
// As it takes (8) right-shifts to register the decimal point (DP) to
|
||||
// the right of the 0th bit, the overall word scaling equals 256.
|
||||
//
|
||||
// For example, at +/- 25.25°C, concatenated registers <r11h:r12h> =
|
||||
// 256 * (+/- 25+(1/4)) = +/- 6464, or 1940h / E6C0h.
|
||||
|
||||
size_t bytesRead = _wire.requestFrom(DS3231_ADDRESS, DS3231_REG_TEMP_SIZE);
|
||||
if (DS3231_REG_TEMP_SIZE != bytesRead)
|
||||
{
|
||||
_lastError = Rtc_Wire_Error_Unspecific;
|
||||
return RtcTemperature(0);
|
||||
}
|
||||
|
||||
int8_t r11h = _wire.read(); // MS byte, signed temperature
|
||||
return RtcTemperature( r11h, _wire.read() ); // LS byte is r12h
|
||||
}
|
||||
|
||||
void Enable32kHzPin(bool enable)
|
||||
{
|
||||
uint8_t sreg = getReg(DS3231_REG_STATUS);
|
||||
|
||||
if (enable == true)
|
||||
{
|
||||
sreg |= _BV(DS3231_EN32KHZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
sreg &= ~_BV(DS3231_EN32KHZ);
|
||||
}
|
||||
|
||||
setReg(DS3231_REG_STATUS, sreg);
|
||||
}
|
||||
|
||||
void SetSquareWavePin(DS3231SquareWavePinMode pinMode, bool enableWhileInBatteryBackup = true)
|
||||
{
|
||||
uint8_t creg = getReg(DS3231_REG_CONTROL);
|
||||
|
||||
// clear all relevant bits to a known "off" state
|
||||
creg &= ~(DS3231_AIEMASK | _BV(DS3231_BBSQW));
|
||||
creg |= _BV(DS3231_INTCN); // set INTCN to disables clock SQW
|
||||
|
||||
if (pinMode != DS3231SquareWavePin_ModeNone)
|
||||
{
|
||||
if (pinMode == DS3231SquareWavePin_ModeClock)
|
||||
{
|
||||
creg &= ~_BV(DS3231_INTCN); // clear INTCN to enable clock SQW
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pinMode & DS3231SquareWavePin_ModeAlarmOne)
|
||||
{
|
||||
creg |= _BV(DS3231_A1IE);
|
||||
}
|
||||
if (pinMode & DS3231SquareWavePin_ModeAlarmTwo)
|
||||
{
|
||||
creg |= _BV(DS3231_A2IE);
|
||||
}
|
||||
}
|
||||
|
||||
if (enableWhileInBatteryBackup)
|
||||
{
|
||||
creg |= _BV(DS3231_BBSQW); // set enable int/sqw while in battery backup flag
|
||||
}
|
||||
}
|
||||
setReg(DS3231_REG_CONTROL, creg);
|
||||
}
|
||||
|
||||
void SetSquareWavePinClockFrequency(DS3231SquareWaveClock freq)
|
||||
{
|
||||
uint8_t creg = getReg(DS3231_REG_CONTROL);
|
||||
|
||||
creg &= ~DS3231_RSMASK; // Set to 0
|
||||
creg |= (freq & DS3231_RSMASK); // Set freq bits
|
||||
|
||||
setReg(DS3231_REG_CONTROL, creg);
|
||||
}
|
||||
|
||||
|
||||
void SetAlarmOne(const DS3231AlarmOne& alarm)
|
||||
{
|
||||
_wire.beginTransmission(DS3231_ADDRESS);
|
||||
_wire.write(DS3231_REG_ALARMONE);
|
||||
|
||||
_wire.write(Uint8ToBcd(alarm.Second()) | ((alarm.ControlFlags() & 0x01) << 7));
|
||||
_wire.write(Uint8ToBcd(alarm.Minute()) | ((alarm.ControlFlags() & 0x02) << 6));
|
||||
_wire.write(Uint8ToBcd(alarm.Hour()) | ((alarm.ControlFlags() & 0x04) << 5)); // 24 hour mode only
|
||||
|
||||
uint8_t rtcDow = alarm.DayOf();
|
||||
if (alarm.ControlFlags() == DS3231AlarmOneControl_HoursMinutesSecondsDayOfWeekMatch)
|
||||
{
|
||||
rtcDow = RtcDateTime::ConvertDowToRtc(rtcDow);
|
||||
}
|
||||
|
||||
_wire.write(Uint8ToBcd(rtcDow) | ((alarm.ControlFlags() & 0x18) << 3));
|
||||
|
||||
_lastError = _wire.endTransmission();
|
||||
}
|
||||
|
||||
void SetAlarmTwo(const DS3231AlarmTwo& alarm)
|
||||
{
|
||||
_wire.beginTransmission(DS3231_ADDRESS);
|
||||
_wire.write(DS3231_REG_ALARMTWO);
|
||||
|
||||
_wire.write(Uint8ToBcd(alarm.Minute()) | ((alarm.ControlFlags() & 0x01) << 7));
|
||||
_wire.write(Uint8ToBcd(alarm.Hour()) | ((alarm.ControlFlags() & 0x02) << 6)); // 24 hour mode only
|
||||
|
||||
// convert our Day of Week to Rtc Day of Week if needed
|
||||
uint8_t rtcDow = alarm.DayOf();
|
||||
if (alarm.ControlFlags() == DS3231AlarmTwoControl_HoursMinutesDayOfWeekMatch)
|
||||
{
|
||||
rtcDow = RtcDateTime::ConvertDowToRtc(rtcDow);
|
||||
}
|
||||
|
||||
_wire.write(Uint8ToBcd(rtcDow) | ((alarm.ControlFlags() & 0x0c) << 4));
|
||||
|
||||
_lastError = _wire.endTransmission();
|
||||
}
|
||||
|
||||
DS3231AlarmOne GetAlarmOne()
|
||||
{
|
||||
_wire.beginTransmission(DS3231_ADDRESS);
|
||||
_wire.write(DS3231_REG_ALARMONE);
|
||||
_lastError = _wire.endTransmission();
|
||||
if (_lastError != Rtc_Wire_Error_None)
|
||||
{
|
||||
return DS3231AlarmOne(0, 0, 0, 0, DS3231AlarmOneControl_HoursMinutesSecondsDayOfMonthMatch);
|
||||
}
|
||||
|
||||
size_t bytesRead = _wire.requestFrom(DS3231_ADDRESS, DS3231_REG_ALARMONE_SIZE);
|
||||
if (DS3231_REG_ALARMONE_SIZE != bytesRead)
|
||||
{
|
||||
_lastError = Rtc_Wire_Error_Unspecific;
|
||||
return DS3231AlarmOne(0, 0, 0, 0, DS3231AlarmOneControl_HoursMinutesSecondsDayOfMonthMatch);
|
||||
}
|
||||
|
||||
uint8_t raw = _wire.read();
|
||||
uint8_t flags = (raw & 0x80) >> 7;
|
||||
uint8_t second = BcdToUint8(raw & 0x7F);
|
||||
|
||||
raw = _wire.read();
|
||||
flags |= (raw & 0x80) >> 6;
|
||||
uint8_t minute = BcdToUint8(raw & 0x7F);
|
||||
|
||||
raw = _wire.read();
|
||||
flags |= (raw & 0x80) >> 5;
|
||||
uint8_t hour = BcdToBin24Hour(raw & 0x7f);
|
||||
|
||||
raw = _wire.read();
|
||||
flags |= (raw & 0xc0) >> 3;
|
||||
uint8_t dayOf = BcdToUint8(raw & 0x3f);
|
||||
|
||||
if (flags == DS3231AlarmOneControl_HoursMinutesSecondsDayOfWeekMatch)
|
||||
{
|
||||
dayOf = RtcDateTime::ConvertRtcToDow(dayOf);
|
||||
}
|
||||
|
||||
return DS3231AlarmOne(dayOf, hour, minute, second, (DS3231AlarmOneControl)flags);
|
||||
}
|
||||
|
||||
DS3231AlarmTwo GetAlarmTwo()
|
||||
{
|
||||
_wire.beginTransmission(DS3231_ADDRESS);
|
||||
_wire.write(DS3231_REG_ALARMTWO);
|
||||
_lastError = _wire.endTransmission();
|
||||
if (_lastError != Rtc_Wire_Error_None)
|
||||
{
|
||||
return DS3231AlarmTwo(0, 0, 0, DS3231AlarmTwoControl_HoursMinutesDayOfMonthMatch);
|
||||
}
|
||||
|
||||
size_t bytesRead = _wire.requestFrom(DS3231_ADDRESS, DS3231_REG_ALARMTWO_SIZE);
|
||||
if (DS3231_REG_ALARMTWO_SIZE != bytesRead)
|
||||
{
|
||||
_lastError = Rtc_Wire_Error_Unspecific;
|
||||
return DS3231AlarmTwo(0, 0, 0, DS3231AlarmTwoControl_HoursMinutesDayOfMonthMatch);
|
||||
}
|
||||
|
||||
uint8_t raw = _wire.read();
|
||||
uint8_t flags = (raw & 0x80) >> 7;
|
||||
uint8_t minute = BcdToUint8(raw & 0x7F);
|
||||
|
||||
raw = _wire.read();
|
||||
flags |= (raw & 0x80) >> 6;
|
||||
uint8_t hour = BcdToBin24Hour(raw & 0x7f);
|
||||
|
||||
raw = _wire.read();
|
||||
flags |= (raw & 0xc0) >> 4;
|
||||
uint8_t dayOf = BcdToUint8(raw & 0x3f);
|
||||
|
||||
if (flags == DS3231AlarmTwoControl_HoursMinutesDayOfWeekMatch)
|
||||
{
|
||||
dayOf = RtcDateTime::ConvertRtcToDow(dayOf);
|
||||
}
|
||||
|
||||
return DS3231AlarmTwo(dayOf, hour, minute, (DS3231AlarmTwoControl)flags);
|
||||
}
|
||||
|
||||
// Latch must be called after an alarm otherwise it will not
|
||||
// trigger again
|
||||
DS3231AlarmFlag LatchAlarmsTriggeredFlags()
|
||||
{
|
||||
uint8_t sreg = getReg(DS3231_REG_STATUS);
|
||||
uint8_t alarmFlags = (sreg & DS3231_AIFMASK);
|
||||
sreg &= ~DS3231_AIFMASK; // clear the flags
|
||||
setReg(DS3231_REG_STATUS, sreg);
|
||||
return (DS3231AlarmFlag)alarmFlags;
|
||||
}
|
||||
|
||||
DS3231AlarmFlag LatchAlarmOneFlag()
|
||||
{
|
||||
uint8_t sreg = getReg(DS3231_REG_STATUS);
|
||||
uint8_t alarmFlags = (sreg & _BV(DS3231_A1F));
|
||||
sreg &= ~_BV(DS3231_A1F); // clear alarm flag 1
|
||||
setReg(DS3231_REG_STATUS, sreg);
|
||||
return (DS3231AlarmFlag)alarmFlags;
|
||||
}
|
||||
|
||||
DS3231AlarmFlag LatchAlarmTwoFlag()
|
||||
{
|
||||
uint8_t sreg = getReg(DS3231_REG_STATUS);
|
||||
uint8_t alarmFlags = (sreg & _BV(DS3231_A2F));
|
||||
sreg &= ~_BV(DS3231_A2F); // clear alarm flag 2
|
||||
setReg(DS3231_REG_STATUS, sreg);
|
||||
return (DS3231AlarmFlag)alarmFlags;
|
||||
}
|
||||
|
||||
bool GetAlarmOneTriggered()
|
||||
{
|
||||
uint8_t sreg = getReg(DS3231_REG_STATUS);
|
||||
return (sreg & _BV(DS3231_A1F));
|
||||
}
|
||||
|
||||
bool GetAlarmTwoTriggered()
|
||||
{
|
||||
uint8_t sreg = getReg(DS3231_REG_STATUS);
|
||||
return (sreg & _BV(DS3231_A2F));
|
||||
}
|
||||
|
||||
void ForceTemperatureCompensationUpdate(bool block)
|
||||
{
|
||||
uint8_t creg = getReg(DS3231_REG_CONTROL);
|
||||
creg |= _BV(DS3231_CONV); // Write CONV bit
|
||||
setReg(DS3231_REG_CONTROL, creg);
|
||||
|
||||
while (block && (creg & _BV(DS3231_CONV)) != 0)
|
||||
{
|
||||
// Block until CONV is 0
|
||||
creg = getReg(DS3231_REG_CONTROL);
|
||||
}
|
||||
}
|
||||
|
||||
int8_t GetAgingOffset()
|
||||
{
|
||||
return getReg(DS3231_REG_AGING);
|
||||
}
|
||||
|
||||
void SetAgingOffset(int8_t value)
|
||||
{
|
||||
setReg(DS3231_REG_AGING, value);
|
||||
}
|
||||
|
||||
protected:
|
||||
T_WIRE_METHOD& _wire;
|
||||
uint8_t _lastError;
|
||||
|
||||
uint8_t getReg(uint8_t regAddress)
|
||||
{
|
||||
_wire.beginTransmission(DS3231_ADDRESS);
|
||||
_wire.write(regAddress);
|
||||
_lastError = _wire.endTransmission();
|
||||
if (_lastError != Rtc_Wire_Error_None)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// control register
|
||||
size_t bytesRead = _wire.requestFrom(DS3231_ADDRESS, (uint8_t)1);
|
||||
if (1 != bytesRead)
|
||||
{
|
||||
_lastError = Rtc_Wire_Error_Unspecific;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t regValue = _wire.read();
|
||||
return regValue;
|
||||
}
|
||||
|
||||
void setReg(uint8_t regAddress, uint8_t regValue)
|
||||
{
|
||||
_wire.beginTransmission(DS3231_ADDRESS);
|
||||
_wire.write(regAddress);
|
||||
_wire.write(regValue);
|
||||
_lastError = _wire.endTransmission();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
124
libraries/Rtc_by_Makuna/src/RtcDS3232.h
Normal file
124
libraries/Rtc_by_Makuna/src/RtcDS3232.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
RTC library
|
||||
|
||||
Written by Michael C. Miller.
|
||||
|
||||
I invest time and resources providing this open source code,
|
||||
please support me by dontating (see https://github.com/Makuna/Rtc)
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the Makuna/Rtc library.
|
||||
|
||||
Rtc is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Rtc is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with Rtc. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RtcDS3231.h"
|
||||
|
||||
// DS3232 is the same as the DS3231 except it has SRAM
|
||||
//
|
||||
//
|
||||
//I2C Slave Address
|
||||
const uint8_t DS3232_ADDRESS = DS3231_ADDRESS;
|
||||
|
||||
const uint8_t DS3232_REG_SRAMFIRST = 0x14;
|
||||
const uint8_t DS3232_REG_SRAMLAST = 0xff;
|
||||
|
||||
const uint8_t DS3232_REG_SRAMSIZE = DS3232_REG_SRAMLAST - DS3232_REG_SRAMFIRST + 1;
|
||||
|
||||
template<class T_WIRE_METHOD> class RtcDS3232 :
|
||||
public RtcDS3231<T_WIRE_METHOD>
|
||||
{
|
||||
public:
|
||||
RtcDS3232(T_WIRE_METHOD& wire) :
|
||||
RtcDS3231<T_WIRE_METHOD>( wire )
|
||||
{
|
||||
}
|
||||
|
||||
void SetMemory(uint8_t memoryAddress, uint8_t value)
|
||||
{
|
||||
uint8_t address = memoryAddress + DS3232_REG_SRAMFIRST;
|
||||
if (address <= DS3232_REG_SRAMLAST)
|
||||
{
|
||||
this->setReg(address, value);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t GetMemory(uint8_t memoryAddress)
|
||||
{
|
||||
uint8_t value = 0;
|
||||
uint8_t address = memoryAddress + DS3232_REG_SRAMFIRST;
|
||||
if (address <= DS3232_REG_SRAMLAST)
|
||||
{
|
||||
value = this->getReg(address);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
uint8_t SetMemory(uint8_t memoryAddress, const uint8_t* pValue, uint8_t countBytes)
|
||||
{
|
||||
uint8_t address = memoryAddress + DS3232_REG_SRAMFIRST;
|
||||
uint8_t countWritten = 0;
|
||||
if (address <= DS3232_REG_SRAMLAST)
|
||||
{
|
||||
this->_wire.beginTransmission(DS3232_ADDRESS);
|
||||
this->_wire.write(address);
|
||||
|
||||
while (countBytes > 0 && address <= DS3232_REG_SRAMLAST)
|
||||
{
|
||||
this->_wire.write(*pValue++);
|
||||
address++;
|
||||
countBytes--;
|
||||
countWritten++;
|
||||
}
|
||||
|
||||
this->_lastError = this->_wire.endTransmission();
|
||||
}
|
||||
return countWritten;
|
||||
}
|
||||
|
||||
size_t GetMemory(uint8_t memoryAddress, uint8_t* pValue, size_t countBytes)
|
||||
{
|
||||
uint8_t address = memoryAddress + DS3232_REG_SRAMFIRST;
|
||||
size_t countRead = 0;
|
||||
if (address <= DS3232_REG_SRAMLAST)
|
||||
{
|
||||
if (countBytes > DS3232_REG_SRAMSIZE)
|
||||
{
|
||||
countBytes = DS3232_REG_SRAMSIZE;
|
||||
}
|
||||
|
||||
this->_wire.beginTransmission(DS3232_ADDRESS);
|
||||
this->_wire.write(address);
|
||||
this->_lastError = this->_wire.endTransmission();
|
||||
if (this->_lastError != Rtc_Wire_Error_None)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
countRead = this->_wire.requestFrom(DS3232_ADDRESS, countBytes);
|
||||
countBytes = countRead;
|
||||
|
||||
while (countBytes-- > 0)
|
||||
{
|
||||
*pValue++ = this->_wire.read();
|
||||
}
|
||||
}
|
||||
|
||||
return countRead;
|
||||
}
|
||||
|
||||
};
|
||||
721
libraries/Rtc_by_Makuna/src/RtcDS3234.h
Normal file
721
libraries/Rtc_by_Makuna/src/RtcDS3234.h
Normal file
@@ -0,0 +1,721 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
RTC library
|
||||
|
||||
Written by Michael C. Miller.
|
||||
|
||||
I invest time and resources providing this open source code,
|
||||
please support me by dontating (see https://github.com/Makuna/Rtc)
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the Makuna/Rtc library.
|
||||
|
||||
Rtc is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Rtc is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with Rtc. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <SPI.h>
|
||||
#include "RtcUtility.h"
|
||||
#include "RtcDateTime.h"
|
||||
#include "RtcTemperature.h"
|
||||
|
||||
|
||||
|
||||
//DS3234 Register Addresses
|
||||
const uint8_t DS3234_REG_WRITE_FLAG = 0x80;
|
||||
|
||||
const uint8_t DS3234_REG_TIMEDATE = 0x00;
|
||||
|
||||
const uint8_t DS3234_REG_ALARMONE = 0x07;
|
||||
const uint8_t DS3234_REG_ALARMTWO = 0x0B;
|
||||
|
||||
const uint8_t DS3234_REG_CONTROL = 0x0E;
|
||||
const uint8_t DS3234_REG_STATUS = 0x0F;
|
||||
const uint8_t DS3234_REG_AGING = 0x10;
|
||||
|
||||
const uint8_t DS3234_REG_TEMP = 0x11;
|
||||
|
||||
const uint8_t DS3234_REG_RAM_ADDRESS = 0x18;
|
||||
const uint8_t DS3234_REG_RAM_DATA = 0x19;
|
||||
|
||||
const uint8_t DS3234_RAMSTART = 0x00;
|
||||
const uint8_t DS3234_RAMEND = 0xFF;
|
||||
const uint8_t DS3234_RAMSIZE = DS3234_RAMEND - DS3234_RAMSTART;
|
||||
|
||||
// DS3234 Control Register Bits
|
||||
const uint8_t DS3234_A1IE = 0;
|
||||
const uint8_t DS3234_A2IE = 1;
|
||||
const uint8_t DS3234_INTCN = 2;
|
||||
const uint8_t DS3234_RS1 = 3;
|
||||
const uint8_t DS3234_RS2 = 4;
|
||||
const uint8_t DS3234_CONV = 5;
|
||||
const uint8_t DS3234_BBSQW = 6;
|
||||
const uint8_t DS3234_EOSC = 7;
|
||||
const uint8_t DS3234_AIEMASK = (_BV(DS3234_A1IE) | _BV(DS3234_A2IE));
|
||||
const uint8_t DS3234_RSMASK = (_BV(DS3234_RS1) | _BV(DS3234_RS2));
|
||||
|
||||
// DS3234 Status Register Bits
|
||||
const uint8_t DS3234_A1F = 0;
|
||||
const uint8_t DS3234_A2F = 1;
|
||||
const uint8_t DS3234_BSY = 2;
|
||||
const uint8_t DS3234_EN32KHZ = 3;
|
||||
const uint8_t DS3234_CRATE0 = 4;
|
||||
const uint8_t DS3234_CRATE1 = 5;
|
||||
const uint8_t DS3234_BB32KHZ = 6;
|
||||
const uint8_t DS3234_OSF = 7;
|
||||
const uint8_t DS3234_AIFMASK = (_BV(DS3234_A1F) | _BV(DS3234_A2F));
|
||||
const uint8_t DS3234_CRATEMASK = (_BV(DS3234_CRATE0) | _BV(DS3234_CRATE1));
|
||||
|
||||
// seconds accuracy
|
||||
enum DS3234AlarmOneControl
|
||||
{
|
||||
// bit order: A1M4 DY/DT A1M3 A1M2 A1M1
|
||||
DS3234AlarmOneControl_HoursMinutesSecondsDayOfMonthMatch = 0x00,
|
||||
DS3234AlarmOneControl_OncePerSecond = 0x17,
|
||||
DS3234AlarmOneControl_SecondsMatch = 0x16,
|
||||
DS3234AlarmOneControl_MinutesSecondsMatch = 0x14,
|
||||
DS3234AlarmOneControl_HoursMinutesSecondsMatch = 0x10,
|
||||
DS3234AlarmOneControl_HoursMinutesSecondsDayOfWeekMatch = 0x08,
|
||||
};
|
||||
|
||||
class DS3234AlarmOne
|
||||
{
|
||||
public:
|
||||
DS3234AlarmOne( uint8_t dayOf,
|
||||
uint8_t hour,
|
||||
uint8_t minute,
|
||||
uint8_t second,
|
||||
DS3234AlarmOneControl controlFlags) :
|
||||
_flags(controlFlags),
|
||||
_dayOf(dayOf),
|
||||
_hour(hour),
|
||||
_minute(minute),
|
||||
_second(second)
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t DayOf() const
|
||||
{
|
||||
return _dayOf;
|
||||
}
|
||||
|
||||
uint8_t Hour() const
|
||||
{
|
||||
return _hour;
|
||||
}
|
||||
|
||||
uint8_t Minute() const
|
||||
{
|
||||
return _minute;
|
||||
}
|
||||
|
||||
uint8_t Second() const
|
||||
{
|
||||
return _second;
|
||||
}
|
||||
|
||||
DS3234AlarmOneControl ControlFlags() const
|
||||
{
|
||||
return _flags;
|
||||
}
|
||||
|
||||
bool operator == (const DS3234AlarmOne& other) const
|
||||
{
|
||||
return (_dayOf == other._dayOf &&
|
||||
_hour == other._hour &&
|
||||
_minute == other._minute &&
|
||||
_second == other._second &&
|
||||
_flags == other._flags);
|
||||
}
|
||||
|
||||
bool operator != (const DS3234AlarmOne& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
protected:
|
||||
DS3234AlarmOneControl _flags;
|
||||
|
||||
uint8_t _dayOf;
|
||||
uint8_t _hour;
|
||||
uint8_t _minute;
|
||||
uint8_t _second;
|
||||
};
|
||||
|
||||
// minutes accuracy
|
||||
enum DS3234AlarmTwoControl
|
||||
{
|
||||
// bit order: A2M4 DY/DT A2M3 A2M2
|
||||
DS3234AlarmTwoControl_HoursMinutesDayOfMonthMatch = 0x00,
|
||||
DS3234AlarmTwoControl_OncePerMinute = 0x0b,
|
||||
DS3234AlarmTwoControl_MinutesMatch = 0x0a,
|
||||
DS3234AlarmTwoControl_HoursMinutesMatch = 0x08,
|
||||
DS3234AlarmTwoControl_HoursMinutesDayOfWeekMatch = 0x04,
|
||||
};
|
||||
|
||||
class DS3234AlarmTwo
|
||||
{
|
||||
public:
|
||||
DS3234AlarmTwo( uint8_t dayOf,
|
||||
uint8_t hour,
|
||||
uint8_t minute,
|
||||
DS3234AlarmTwoControl controlFlags) :
|
||||
_flags(controlFlags),
|
||||
_dayOf(dayOf),
|
||||
_hour(hour),
|
||||
_minute(minute)
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t DayOf() const
|
||||
{
|
||||
return _dayOf;
|
||||
}
|
||||
|
||||
uint8_t Hour() const
|
||||
{
|
||||
return _hour;
|
||||
}
|
||||
|
||||
uint8_t Minute() const
|
||||
{
|
||||
return _minute;
|
||||
}
|
||||
|
||||
DS3234AlarmTwoControl ControlFlags() const
|
||||
{
|
||||
return _flags;
|
||||
}
|
||||
|
||||
bool operator == (const DS3234AlarmTwo& other) const
|
||||
{
|
||||
return (_dayOf == other._dayOf &&
|
||||
_hour == other._hour &&
|
||||
_minute == other._minute &&
|
||||
_flags == other._flags);
|
||||
}
|
||||
|
||||
bool operator != (const DS3234AlarmTwo& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
protected:
|
||||
DS3234AlarmTwoControl _flags;
|
||||
|
||||
uint8_t _dayOf;
|
||||
uint8_t _hour;
|
||||
uint8_t _minute;
|
||||
};
|
||||
|
||||
|
||||
enum DS3234SquareWaveClock
|
||||
{
|
||||
DS3234SquareWaveClock_1Hz = 0b00000000,
|
||||
DS3234SquareWaveClock_1kHz = 0b00001000,
|
||||
DS3234SquareWaveClock_4kHz = 0b00010000,
|
||||
DS3234SquareWaveClock_8kHz = 0b00011000,
|
||||
};
|
||||
|
||||
enum DS3234SquareWavePinMode
|
||||
{
|
||||
DS3234SquareWavePin_ModeNone,
|
||||
DS3234SquareWavePin_ModeBatteryBackup,
|
||||
DS3234SquareWavePin_ModeClock,
|
||||
DS3234SquareWavePin_ModeAlarmOne,
|
||||
DS3234SquareWavePin_ModeAlarmTwo,
|
||||
DS3234SquareWavePin_ModeAlarmBoth
|
||||
};
|
||||
|
||||
enum DS3234TempCompensationRate
|
||||
{
|
||||
DS3234TempCompensationRate_64Seconds,
|
||||
DS3234TempCompensationRate_128Seconds,
|
||||
DS3234TempCompensationRate_256Seconds,
|
||||
DS3234TempCompensationRate_512Seconds,
|
||||
};
|
||||
|
||||
enum DS3234AlarmFlag
|
||||
{
|
||||
DS3234AlarmFlag_Alarm1 = 0x01,
|
||||
DS3234AlarmFlag_Alarm2 = 0x02,
|
||||
DS3234AlarmFlag_AlarmBoth = 0x03,
|
||||
};
|
||||
|
||||
const SPISettings c_Ds3234SpiSettings(1000000, MSBFIRST, SPI_MODE1); // CPHA must be used, so mode 1 or mode 3 are valid
|
||||
|
||||
template<class T_SPI_METHOD> class RtcDS3234
|
||||
{
|
||||
public:
|
||||
RtcDS3234(T_SPI_METHOD& spi, uint8_t csPin) :
|
||||
_spi(spi),
|
||||
_csPin(csPin)
|
||||
{
|
||||
}
|
||||
|
||||
void Begin()
|
||||
{
|
||||
UnselectChip();
|
||||
pinMode(_csPin, OUTPUT);
|
||||
}
|
||||
|
||||
bool IsDateTimeValid()
|
||||
{
|
||||
uint8_t status = getReg(DS3234_REG_STATUS);
|
||||
return !(status & _BV(DS3234_OSF));
|
||||
}
|
||||
|
||||
bool GetIsRunning()
|
||||
{
|
||||
uint8_t creg = getReg(DS3234_REG_CONTROL);
|
||||
return !(creg & _BV(DS3234_EOSC));
|
||||
}
|
||||
|
||||
void SetIsRunning(bool isRunning)
|
||||
{
|
||||
uint8_t creg = getReg(DS3234_REG_CONTROL);
|
||||
if (isRunning)
|
||||
{
|
||||
creg &= ~_BV(DS3234_EOSC);
|
||||
}
|
||||
else
|
||||
{
|
||||
creg |= _BV(DS3234_EOSC);
|
||||
}
|
||||
setReg(DS3234_REG_CONTROL, creg);
|
||||
}
|
||||
|
||||
void SetDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
// clear the invalid flag
|
||||
uint8_t status = getReg(DS3234_REG_STATUS);
|
||||
status &= ~_BV(DS3234_OSF); // clear the flag
|
||||
setReg(DS3234_REG_STATUS, status);
|
||||
|
||||
// set the date time
|
||||
_spi.beginTransaction(c_Ds3234SpiSettings);
|
||||
SelectChip();
|
||||
_spi.transfer(DS3234_REG_TIMEDATE | DS3234_REG_WRITE_FLAG);
|
||||
|
||||
_spi.transfer(Uint8ToBcd(dt.Second()));
|
||||
_spi.transfer(Uint8ToBcd(dt.Minute()));
|
||||
_spi.transfer(Uint8ToBcd(dt.Hour())); // 24 hour mode only
|
||||
|
||||
uint8_t year = dt.Year() - 2000;
|
||||
uint8_t centuryFlag = 0;
|
||||
|
||||
if (year >= 100)
|
||||
{
|
||||
year -= 100;
|
||||
centuryFlag = _BV(7);
|
||||
}
|
||||
|
||||
// RTC Hardware Day of Week is 1-7, 1 = Monday
|
||||
// convert our Day of Week to Rtc Day of Week
|
||||
uint8_t rtcDow = RtcDateTime::ConvertDowToRtc(dt.DayOfWeek());
|
||||
|
||||
_spi.transfer(Uint8ToBcd(rtcDow));
|
||||
|
||||
_spi.transfer(Uint8ToBcd(dt.Day()));
|
||||
_spi.transfer(Uint8ToBcd(dt.Month()) | centuryFlag);
|
||||
_spi.transfer(Uint8ToBcd(year));
|
||||
UnselectChip();
|
||||
_spi.endTransaction();
|
||||
}
|
||||
|
||||
RtcDateTime GetDateTime()
|
||||
{
|
||||
_spi.beginTransaction(c_Ds3234SpiSettings);
|
||||
SelectChip();
|
||||
|
||||
_spi.transfer(DS3234_REG_TIMEDATE);
|
||||
|
||||
uint8_t second = BcdToUint8(_spi.transfer(0));
|
||||
uint8_t minute = BcdToUint8(_spi.transfer(0));
|
||||
uint8_t hour = BcdToBin24Hour(_spi.transfer(0));
|
||||
|
||||
_spi.transfer(0); // throwing away day of week as we calculate it
|
||||
|
||||
uint8_t dayOfMonth = BcdToUint8(_spi.transfer(0));
|
||||
uint8_t monthRaw = _spi.transfer(0);
|
||||
uint16_t year = BcdToUint8(_spi.transfer(0)) + 2000;
|
||||
|
||||
UnselectChip();
|
||||
_spi.endTransaction();
|
||||
|
||||
if (monthRaw & _BV(7)) // century wrap flag
|
||||
{
|
||||
year += 100;
|
||||
}
|
||||
uint8_t month = BcdToUint8(monthRaw & 0x7f);
|
||||
|
||||
return RtcDateTime(year, month, dayOfMonth, hour, minute, second);
|
||||
}
|
||||
|
||||
RtcTemperature GetTemperature()
|
||||
{
|
||||
_spi.beginTransaction(c_Ds3234SpiSettings);
|
||||
SelectChip();
|
||||
_spi.transfer(DS3234_REG_TEMP);
|
||||
|
||||
// Temperature is represented as a 10-bit code with a resolution
|
||||
// of 1/4th °C and is accessable as a signed 16-bit integer at
|
||||
// locations 11h and 12h.
|
||||
//
|
||||
// | r11h | DP | r12h |
|
||||
// Bit: 15 14 13 12 11 10 9 8 . 7 6 5 4 3 2 1 0 -1 -2
|
||||
// s i i i i i i i . f f 0 0 0 0 0 0
|
||||
//
|
||||
// As it takes (8) right-shifts to register the decimal point (DP) to
|
||||
// the right of the 0th bit, the overall word scaling equals 256.
|
||||
//
|
||||
// For example, at +/- 25.25°C, concatenated registers <r11h:r12h> =
|
||||
// 256 * (+/- 25+(1/4)) = +/- 6464, or 1940h / E6C0h.
|
||||
|
||||
int8_t ms = _spi.transfer(0); // MS byte, signed temperature
|
||||
uint8_t ls = _spi.transfer(0); // LS byte is r12h
|
||||
|
||||
UnselectChip();
|
||||
_spi.endTransaction();
|
||||
|
||||
return RtcTemperature(ms, ls); // LS byte is r12h
|
||||
}
|
||||
|
||||
void Enable32kHzPin(bool enable)
|
||||
{
|
||||
uint8_t sreg = getReg(DS3234_REG_STATUS);
|
||||
|
||||
if (enable == true)
|
||||
{
|
||||
sreg |= _BV(DS3234_EN32KHZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
sreg &= ~_BV(DS3234_EN32KHZ);
|
||||
}
|
||||
|
||||
setReg(DS3234_REG_STATUS, sreg);
|
||||
}
|
||||
|
||||
void SetSquareWavePin(DS3234SquareWavePinMode pinMode)
|
||||
{
|
||||
uint8_t creg = getReg(DS3234_REG_CONTROL);
|
||||
|
||||
// clear all relevant bits to a known "off" state
|
||||
creg &= ~(DS3234_AIEMASK | _BV(DS3234_BBSQW));
|
||||
creg |= _BV(DS3234_INTCN); // set INTCN to disables SQW
|
||||
|
||||
switch (pinMode)
|
||||
{
|
||||
case DS3234SquareWavePin_ModeNone:
|
||||
break;
|
||||
|
||||
case DS3234SquareWavePin_ModeBatteryBackup:
|
||||
creg |= _BV(DS3234_BBSQW); // set battery backup flag
|
||||
creg &= ~_BV(DS3234_INTCN); // clear INTCN to enable SQW
|
||||
break;
|
||||
|
||||
case DS3234SquareWavePin_ModeClock:
|
||||
creg &= ~_BV(DS3234_INTCN); // clear INTCN to enable SQW
|
||||
break;
|
||||
|
||||
case DS3234SquareWavePin_ModeAlarmOne:
|
||||
creg |= _BV(DS3234_A1IE);
|
||||
break;
|
||||
|
||||
case DS3234SquareWavePin_ModeAlarmTwo:
|
||||
creg |= _BV(DS3234_A2IE);
|
||||
break;
|
||||
|
||||
case DS3234SquareWavePin_ModeAlarmBoth:
|
||||
creg |= _BV(DS3234_A1IE) | _BV(DS3234_A2IE);
|
||||
break;
|
||||
}
|
||||
|
||||
setReg(DS3234_REG_CONTROL, creg);
|
||||
}
|
||||
|
||||
void SetSquareWavePinClockFrequency(DS3234SquareWaveClock freq)
|
||||
{
|
||||
uint8_t creg = getReg(DS3234_REG_CONTROL);
|
||||
|
||||
creg &= ~DS3234_RSMASK; // Set to 0
|
||||
creg |= (freq & DS3234_RSMASK); // Set freq bits
|
||||
|
||||
setReg(DS3234_REG_CONTROL, creg);
|
||||
}
|
||||
|
||||
|
||||
void SetAlarmOne(const DS3234AlarmOne& alarm)
|
||||
{
|
||||
_spi.beginTransaction(c_Ds3234SpiSettings);
|
||||
SelectChip();
|
||||
|
||||
_spi.transfer(DS3234_REG_ALARMONE | DS3234_REG_WRITE_FLAG);
|
||||
|
||||
_spi.transfer(Uint8ToBcd(alarm.Second()) | ((alarm.ControlFlags() & 0x01) << 7));
|
||||
_spi.transfer(Uint8ToBcd(alarm.Minute()) | ((alarm.ControlFlags() & 0x02) << 6));
|
||||
_spi.transfer(Uint8ToBcd(alarm.Hour()) | ((alarm.ControlFlags() & 0x04) << 5)); // 24 hour mode only
|
||||
|
||||
uint8_t rtcDow = alarm.DayOf();
|
||||
if (alarm.ControlFlags() == DS3234AlarmOneControl_HoursMinutesSecondsDayOfWeekMatch)
|
||||
{
|
||||
rtcDow = RtcDateTime::ConvertDowToRtc(rtcDow);
|
||||
}
|
||||
|
||||
_spi.transfer(Uint8ToBcd(rtcDow) | ((alarm.ControlFlags() & 0x18) << 3));
|
||||
|
||||
UnselectChip();
|
||||
_spi.endTransaction();
|
||||
}
|
||||
|
||||
void SetAlarmTwo(const DS3234AlarmTwo& alarm)
|
||||
{
|
||||
_spi.beginTransaction(c_Ds3234SpiSettings);
|
||||
SelectChip();
|
||||
|
||||
_spi.transfer(DS3234_REG_ALARMTWO | DS3234_REG_WRITE_FLAG);
|
||||
|
||||
_spi.transfer(Uint8ToBcd(alarm.Minute()) | ((alarm.ControlFlags() & 0x01) << 7));
|
||||
_spi.transfer(Uint8ToBcd(alarm.Hour()) | ((alarm.ControlFlags() & 0x02) << 6)); // 24 hour mode only
|
||||
|
||||
// convert our Day of Week to Rtc Day of Week if needed
|
||||
uint8_t rtcDow = alarm.DayOf();
|
||||
if (alarm.ControlFlags() == DS3234AlarmTwoControl_HoursMinutesDayOfWeekMatch)
|
||||
{
|
||||
rtcDow = RtcDateTime::ConvertDowToRtc(rtcDow);
|
||||
}
|
||||
|
||||
_spi.transfer(Uint8ToBcd(rtcDow) | ((alarm.ControlFlags() & 0x0c) << 4));
|
||||
|
||||
UnselectChip();
|
||||
_spi.endTransaction();
|
||||
}
|
||||
|
||||
DS3234AlarmOne GetAlarmOne()
|
||||
{
|
||||
_spi.beginTransaction(c_Ds3234SpiSettings);
|
||||
SelectChip();
|
||||
|
||||
_spi.transfer(DS3234_REG_ALARMONE);
|
||||
|
||||
uint8_t raw = _spi.transfer(0);
|
||||
uint8_t flags = (raw & 0x80) >> 7;
|
||||
uint8_t second = BcdToUint8(raw & 0x7F);
|
||||
|
||||
raw = _spi.transfer(0);
|
||||
flags |= (raw & 0x80) >> 6;
|
||||
uint8_t minute = BcdToUint8(raw & 0x7F);
|
||||
|
||||
raw = _spi.transfer(0);
|
||||
flags |= (raw & 0x80) >> 5;
|
||||
uint8_t hour = BcdToBin24Hour(raw & 0x7f);
|
||||
|
||||
raw = _spi.transfer(0);
|
||||
flags |= (raw & 0xc0) >> 3;
|
||||
uint8_t dayOf = BcdToUint8(raw & 0x3f);
|
||||
|
||||
UnselectChip();
|
||||
_spi.endTransaction();
|
||||
|
||||
if (flags == DS3234AlarmOneControl_HoursMinutesSecondsDayOfWeekMatch)
|
||||
{
|
||||
dayOf = RtcDateTime::ConvertRtcToDow(dayOf);
|
||||
}
|
||||
|
||||
return DS3234AlarmOne(dayOf, hour, minute, second, (DS3234AlarmOneControl)flags);
|
||||
}
|
||||
|
||||
DS3234AlarmTwo GetAlarmTwo()
|
||||
{
|
||||
_spi.beginTransaction(c_Ds3234SpiSettings);
|
||||
SelectChip();
|
||||
|
||||
_spi.transfer(DS3234_REG_ALARMTWO);
|
||||
|
||||
uint8_t raw = _spi.transfer(0);
|
||||
uint8_t flags = (raw & 0x80) >> 7;
|
||||
uint8_t minute = BcdToUint8(raw & 0x7F);
|
||||
|
||||
raw = _spi.transfer(0);
|
||||
flags |= (raw & 0x80) >> 6;
|
||||
uint8_t hour = BcdToBin24Hour(raw & 0x7f);
|
||||
|
||||
raw = _spi.transfer(0);
|
||||
flags |= (raw & 0xc0) >> 4;
|
||||
uint8_t dayOf = BcdToUint8(raw & 0x3f);
|
||||
|
||||
UnselectChip();
|
||||
_spi.endTransaction();
|
||||
|
||||
if (flags == DS3234AlarmTwoControl_HoursMinutesDayOfWeekMatch)
|
||||
{
|
||||
dayOf = RtcDateTime::ConvertRtcToDow(dayOf);
|
||||
}
|
||||
|
||||
return DS3234AlarmTwo(dayOf, hour, minute, (DS3234AlarmTwoControl)flags);
|
||||
}
|
||||
|
||||
// Latch must be called after an alarm otherwise it will not
|
||||
// trigger again
|
||||
DS3234AlarmFlag LatchAlarmsTriggeredFlags()
|
||||
{
|
||||
uint8_t sreg = getReg(DS3234_REG_STATUS);
|
||||
uint8_t alarmFlags = (sreg & DS3234_AIFMASK);
|
||||
sreg &= ~DS3234_AIFMASK; // clear the flags
|
||||
setReg(DS3234_REG_STATUS, sreg);
|
||||
return (DS3234AlarmFlag)alarmFlags;
|
||||
}
|
||||
|
||||
void SetTemperatureCompensationRate(DS3234TempCompensationRate rate)
|
||||
{
|
||||
uint8_t sreg = getReg(DS3234_REG_STATUS);
|
||||
|
||||
sreg &= ~DS3234_CRATEMASK;
|
||||
sreg |= (rate << DS3234_CRATE0);
|
||||
|
||||
setReg(DS3234_REG_STATUS, sreg);
|
||||
}
|
||||
|
||||
DS3234TempCompensationRate GetTemperatureCompensationRate()
|
||||
{
|
||||
uint8_t sreg = getReg(DS3234_REG_STATUS);
|
||||
return (sreg & DS3234_CRATEMASK) >> DS3234_CRATE0;
|
||||
}
|
||||
|
||||
void ForceTemperatureCompensationUpdate(bool block)
|
||||
{
|
||||
uint8_t creg = getReg(DS3234_REG_CONTROL);
|
||||
creg |= _BV(DS3234_CONV); // Write CONV bit
|
||||
setReg(DS3234_REG_CONTROL, creg);
|
||||
|
||||
while (block && (creg & _BV(DS3234_CONV)) != 0)
|
||||
{
|
||||
// Block until CONV is 0
|
||||
creg = getReg(DS3234_REG_CONTROL);
|
||||
}
|
||||
}
|
||||
|
||||
int8_t GetAgingOffset()
|
||||
{
|
||||
return getReg(DS3234_REG_AGING);
|
||||
}
|
||||
|
||||
void SetAgingOffset(int8_t value)
|
||||
{
|
||||
setReg(DS3234_REG_AGING, value);
|
||||
}
|
||||
|
||||
void SetMemory(uint8_t memoryAddress, uint8_t value)
|
||||
{
|
||||
SetMemory(memoryAddress, &value, 1);
|
||||
}
|
||||
|
||||
uint8_t GetMemory(uint8_t memoryAddress)
|
||||
{
|
||||
uint8_t value;
|
||||
|
||||
GetMemory(memoryAddress, &value, 1);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
uint8_t SetMemory(uint8_t memoryAddress, const uint8_t* pValue, uint8_t countBytes)
|
||||
{
|
||||
uint8_t countWritten = 0;
|
||||
|
||||
setReg(DS3234_REG_RAM_ADDRESS, memoryAddress);
|
||||
|
||||
_spi.beginTransaction(c_Ds3234SpiSettings);
|
||||
SelectChip();
|
||||
_spi.transfer(DS3234_REG_RAM_DATA | DS3234_REG_WRITE_FLAG);
|
||||
|
||||
while (countBytes > 0)
|
||||
{
|
||||
_spi.transfer(*pValue++);
|
||||
|
||||
countBytes--;
|
||||
countWritten++;
|
||||
}
|
||||
|
||||
UnselectChip();
|
||||
_spi.endTransaction();
|
||||
|
||||
return countWritten;
|
||||
}
|
||||
|
||||
uint8_t GetMemory(uint8_t memoryAddress, uint8_t* pValue, uint8_t countBytes)
|
||||
{
|
||||
// set address to read from
|
||||
setReg(DS3234_REG_RAM_ADDRESS, memoryAddress);
|
||||
|
||||
_spi.beginTransaction(c_Ds3234SpiSettings);
|
||||
SelectChip();
|
||||
_spi.transfer(DS3234_REG_RAM_DATA);
|
||||
|
||||
// read the data
|
||||
uint8_t countRead = 0;
|
||||
|
||||
while (countBytes-- > 0)
|
||||
{
|
||||
*pValue++ = _spi.transfer(0);
|
||||
countRead++;
|
||||
}
|
||||
|
||||
UnselectChip();
|
||||
_spi.endTransaction();
|
||||
|
||||
return countRead;
|
||||
}
|
||||
|
||||
private:
|
||||
T_SPI_METHOD& _spi;
|
||||
uint8_t _csPin;
|
||||
|
||||
void SelectChip()
|
||||
{
|
||||
digitalWrite(_csPin, LOW);
|
||||
}
|
||||
void UnselectChip()
|
||||
{
|
||||
digitalWrite(_csPin, HIGH);
|
||||
}
|
||||
|
||||
uint8_t getReg(uint8_t regAddress)
|
||||
{
|
||||
uint8_t regValue;
|
||||
_spi.beginTransaction(c_Ds3234SpiSettings);
|
||||
SelectChip();
|
||||
_spi.transfer(regAddress);
|
||||
regValue = _spi.transfer(0);
|
||||
UnselectChip();
|
||||
_spi.endTransaction();
|
||||
|
||||
return regValue;
|
||||
}
|
||||
|
||||
void setReg(uint8_t regAddress, uint8_t regValue)
|
||||
{
|
||||
_spi.beginTransaction(c_Ds3234SpiSettings);
|
||||
SelectChip();
|
||||
_spi.transfer(regAddress | DS3234_REG_WRITE_FLAG);
|
||||
_spi.transfer(regValue);
|
||||
UnselectChip();
|
||||
_spi.endTransaction();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
146
libraries/Rtc_by_Makuna/src/RtcDateTime.cpp
Normal file
146
libraries/Rtc_by_Makuna/src/RtcDateTime.cpp
Normal file
@@ -0,0 +1,146 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
RTC library
|
||||
|
||||
Written by Michael C. Miller.
|
||||
|
||||
I invest time and resources providing this open source code,
|
||||
please support me by dontating (see https://github.com/Makuna/Rtc)
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the Makuna/Rtc library.
|
||||
|
||||
Rtc is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Rtc is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with Rtc. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "RtcUtility.h"
|
||||
#include "RtcDateTime.h"
|
||||
|
||||
const uint8_t c_daysInMonth[] PROGMEM = { 31,28,31,30,31,30,31,31,30,31,30,31 };
|
||||
|
||||
|
||||
template <typename T> T DaysSinceFirstOfYear2000(uint16_t year, uint8_t month, uint8_t dayOfMonth)
|
||||
{
|
||||
T days = dayOfMonth;
|
||||
for (uint8_t indexMonth = 1; indexMonth < month; ++indexMonth)
|
||||
{
|
||||
days += pgm_read_byte(c_daysInMonth + indexMonth - 1);
|
||||
}
|
||||
if (month > 2 && year % 4 == 0)
|
||||
{
|
||||
days++;
|
||||
}
|
||||
return days + 365 * year + (year + 3) / 4 - 1;
|
||||
}
|
||||
|
||||
template <typename T> T SecondsIn(T days, uint8_t hours, uint8_t minutes, uint8_t seconds)
|
||||
{
|
||||
return ((days * 24L + hours) * 60 + minutes) * 60 + seconds;
|
||||
}
|
||||
|
||||
bool RtcDateTime::IsValid() const
|
||||
{
|
||||
// this just tests the most basic validity of the value ranges
|
||||
// and valid leap years
|
||||
// It does not check any time zone or daylight savings time
|
||||
if ((_month > 0 && _month < 13) &&
|
||||
(_dayOfMonth > 0 && _dayOfMonth < 32) &&
|
||||
(_hour < 24) &&
|
||||
(_minute < 60) &&
|
||||
(_second < 60))
|
||||
{
|
||||
// days in a month tests
|
||||
//
|
||||
if (_month == 2)
|
||||
{
|
||||
if (_dayOfMonth > 29)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (_dayOfMonth > 28)
|
||||
{
|
||||
// leap day
|
||||
// check year to make sure its a leap year
|
||||
uint16_t year = Year();
|
||||
|
||||
if ((year % 4) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((year % 100) == 0 &&
|
||||
(year % 400) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (_dayOfMonth == 31)
|
||||
{
|
||||
if ((((_month - 1) % 7) % 2) == 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t RtcDateTime::DayOfWeek() const
|
||||
{
|
||||
uint16_t days = DaysSinceFirstOfYear2000<uint16_t>(_yearFrom2000, _month, _dayOfMonth);
|
||||
return (days + 6) % 7; // Jan 1, 2000 is a Saturday, i.e. returns 6
|
||||
}
|
||||
|
||||
// 32-bit time; as seconds since 1/1/2000
|
||||
uint32_t RtcDateTime::TotalSeconds() const
|
||||
{
|
||||
uint16_t days = DaysSinceFirstOfYear2000<uint16_t>(_yearFrom2000, _month, _dayOfMonth);
|
||||
return SecondsIn<uint32_t>(days, _hour, _minute, _second);
|
||||
}
|
||||
|
||||
// 64-bit time; as seconds since 1/1/2000
|
||||
uint64_t RtcDateTime::TotalSeconds64() const
|
||||
{
|
||||
uint32_t days = DaysSinceFirstOfYear2000<uint32_t>(_yearFrom2000, _month, _dayOfMonth);
|
||||
return SecondsIn<uint64_t>(days, _hour, _minute, _second);
|
||||
}
|
||||
|
||||
// total days since 1/1/2000
|
||||
uint16_t RtcDateTime::TotalDays() const
|
||||
{
|
||||
return DaysSinceFirstOfYear2000<uint16_t>(_yearFrom2000, _month, _dayOfMonth);
|
||||
}
|
||||
|
||||
// return the next day that falls on the given day of week
|
||||
// if this day is that day of week, it will return this day
|
||||
RtcDateTime RtcDateTime::NextDayOfWeek(uint8_t dayOfWeek) const
|
||||
{
|
||||
uint8_t currentDayOfWeek = DayOfWeek();
|
||||
RtcDateTime result;
|
||||
int8_t delta = (dayOfWeek - currentDayOfWeek);
|
||||
|
||||
// only want time in the future
|
||||
if (delta < 0)
|
||||
{
|
||||
delta += 7;
|
||||
}
|
||||
|
||||
result = *this + (delta * c_DayAsSeconds);
|
||||
return result;
|
||||
}
|
||||
|
||||
705
libraries/Rtc_by_Makuna/src/RtcDateTime.h
Normal file
705
libraries/Rtc_by_Makuna/src/RtcDateTime.h
Normal file
@@ -0,0 +1,705 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
RTC library
|
||||
|
||||
Written by Michael C. Miller.
|
||||
|
||||
I invest time and resources providing this open source code,
|
||||
please support me by dontating (see https://github.com/Makuna/Rtc)
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the Makuna/Rtc library.
|
||||
|
||||
Rtc is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Rtc is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with Rtc. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// ESP32 complains if not included
|
||||
#if defined(ARDUINO_ARCH_ESP32)
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#include "RtcTimeZone.h"
|
||||
#include "RtcLocaleEnUs.h"
|
||||
#include "RtcLocaleEn.h"
|
||||
|
||||
enum DayOfWeek
|
||||
{
|
||||
DayOfWeek_Sunday = 0,
|
||||
DayOfWeek_Monday,
|
||||
DayOfWeek_Tuesday,
|
||||
DayOfWeek_Wednesday,
|
||||
DayOfWeek_Thursday,
|
||||
DayOfWeek_Friday,
|
||||
DayOfWeek_Saturday,
|
||||
};
|
||||
|
||||
const uint16_t c_OriginYear = 2000;
|
||||
const uint32_t c_UnixEpoch32 = 946684800; // Unix origin year is 1970
|
||||
const uint32_t c_NtpEpoch32FromUnixEpoch32 = 2208988800; // Ntp origin year is 1900
|
||||
const uint32_t c_NtpEpoch32 = c_UnixEpoch32 + c_NtpEpoch32FromUnixEpoch32;
|
||||
|
||||
extern const uint8_t c_daysInMonth[] PROGMEM;
|
||||
|
||||
const uint32_t c_MinuteAsSeconds = 60;
|
||||
const uint32_t c_HourAsSeconds = 60 * c_MinuteAsSeconds;
|
||||
const uint32_t c_DayAsSeconds = 24 * c_HourAsSeconds;
|
||||
const uint32_t c_WeekAsSeconds = 7 * c_DayAsSeconds;
|
||||
|
||||
|
||||
class RtcDateTime
|
||||
{
|
||||
public:
|
||||
explicit RtcDateTime(uint32_t secondsFrom2000 = 0)
|
||||
{
|
||||
_initWithSecondsFrom2000<uint32_t>(secondsFrom2000);
|
||||
}
|
||||
|
||||
RtcDateTime(uint16_t year,
|
||||
uint8_t month,
|
||||
uint8_t dayOfMonth,
|
||||
uint8_t hour,
|
||||
uint8_t minute,
|
||||
uint8_t second) :
|
||||
_yearFrom2000((year >= c_OriginYear) ? year - c_OriginYear : year),
|
||||
_month(month),
|
||||
_dayOfMonth(dayOfMonth),
|
||||
_hour(hour),
|
||||
_minute(minute),
|
||||
_second(second)
|
||||
{
|
||||
}
|
||||
|
||||
// RtcDateTime compileDateTime(__DATE__, __TIME__);
|
||||
// sample input: date = "Dec 06 2009", time = "12:34:56"
|
||||
RtcDateTime(const char* date, const char* time) :
|
||||
RtcDateTime(0)
|
||||
{
|
||||
// __DATE__ is always in english
|
||||
InitWithDateTimeFormatString<RtcLocaleEnUs>(F("MMM DD YYYY"), date);
|
||||
InitWithDateTimeFormatString<RtcLocaleEnUs>(F("hh:mm:ss"), time);
|
||||
}
|
||||
|
||||
bool IsValid() const;
|
||||
|
||||
uint16_t Year() const
|
||||
{
|
||||
return c_OriginYear + _yearFrom2000;
|
||||
}
|
||||
|
||||
uint8_t Month() const
|
||||
{
|
||||
return _month;
|
||||
}
|
||||
|
||||
uint8_t Day() const
|
||||
{
|
||||
return _dayOfMonth;
|
||||
}
|
||||
|
||||
uint8_t Hour() const
|
||||
{
|
||||
return _hour;
|
||||
}
|
||||
|
||||
uint8_t Minute() const
|
||||
{
|
||||
return _minute;
|
||||
}
|
||||
|
||||
uint8_t Second() const
|
||||
{
|
||||
return _second;
|
||||
}
|
||||
|
||||
// 0 = Sunday, 1 = Monday, ... 6 = Saturday
|
||||
uint8_t DayOfWeek() const;
|
||||
|
||||
// 32-bit time; as seconds since 1/1/2000
|
||||
uint32_t TotalSeconds() const;
|
||||
|
||||
// 64-bit time; as seconds since 1/1/2000
|
||||
uint64_t TotalSeconds64() const;
|
||||
|
||||
// total days since 1/1/2000
|
||||
uint16_t TotalDays() const;
|
||||
|
||||
// return the next day that falls on the given day of week
|
||||
// if this day is that day of week, it will return this day
|
||||
RtcDateTime NextDayOfWeek(uint8_t dayOfWeek) const;
|
||||
|
||||
/*
|
||||
causes mbiguous overload for 'operator+'
|
||||
making explicit doesn't solve it
|
||||
// add unsigned seconds
|
||||
void operator += (uint32_t seconds)
|
||||
{
|
||||
*this = *this + seconds;
|
||||
}
|
||||
|
||||
RtcDateTime operator + (uint32_t seconds) const
|
||||
{
|
||||
return RtcDateTime(TotalSeconds() + seconds);
|
||||
}
|
||||
*/
|
||||
|
||||
// add signed seconds
|
||||
void operator += (int32_t seconds)
|
||||
{
|
||||
*this = *this + seconds;
|
||||
}
|
||||
|
||||
RtcDateTime operator + (int32_t seconds) const
|
||||
{
|
||||
uint32_t totalSeconds = TotalSeconds();
|
||||
// never allowed to go before year 2000
|
||||
if (seconds < 0 && abs(seconds) > totalSeconds)
|
||||
{
|
||||
totalSeconds = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
totalSeconds += seconds;
|
||||
}
|
||||
return RtcDateTime(totalSeconds);
|
||||
}
|
||||
|
||||
// remove seconds
|
||||
void operator -= (uint32_t seconds)
|
||||
{
|
||||
*this = *this - seconds;
|
||||
}
|
||||
|
||||
RtcDateTime operator - (uint32_t seconds) const
|
||||
{
|
||||
return RtcDateTime(TotalSeconds() - seconds);
|
||||
}
|
||||
|
||||
bool operator == (const RtcDateTime& right)
|
||||
{
|
||||
return (this->TotalSeconds() == right.TotalSeconds());
|
||||
}
|
||||
|
||||
bool operator != (const RtcDateTime& right)
|
||||
{
|
||||
return (this->TotalSeconds() != right.TotalSeconds());
|
||||
}
|
||||
|
||||
bool operator <= (const RtcDateTime& right)
|
||||
{
|
||||
return (this->TotalSeconds() <= right.TotalSeconds());
|
||||
}
|
||||
|
||||
bool operator >= (const RtcDateTime& right)
|
||||
{
|
||||
return (this->TotalSeconds() >= right.TotalSeconds());
|
||||
}
|
||||
|
||||
bool operator < (const RtcDateTime& right)
|
||||
{
|
||||
return (this->TotalSeconds() < right.TotalSeconds());
|
||||
}
|
||||
|
||||
bool operator > (const RtcDateTime& right)
|
||||
{
|
||||
return (this->TotalSeconds() > right.TotalSeconds());
|
||||
}
|
||||
|
||||
// Epoch32 support
|
||||
[[deprecated("Use Unix32Time() instead.")]]
|
||||
uint32_t Epoch32Time() const
|
||||
{
|
||||
return TotalSeconds() + c_UnixEpoch32;
|
||||
}
|
||||
[[deprecated("Use InitWithUnix32Time() instead.")]]
|
||||
void InitWithEpoch32Time(uint32_t secondsSince1970)
|
||||
{
|
||||
_initWithSecondsFrom2000<uint32_t>(secondsSince1970 - c_UnixEpoch32);
|
||||
}
|
||||
|
||||
// Epoch64 support
|
||||
[[deprecated("Use Unix64Time() instead.")]]
|
||||
uint64_t Epoch64Time() const
|
||||
{
|
||||
return TotalSeconds64() + c_UnixEpoch32;
|
||||
}
|
||||
[[deprecated("Use InitWithUnix64Time() instead.")]]
|
||||
void InitWithEpoch64Time(uint64_t secondsSince1970)
|
||||
{
|
||||
_initWithSecondsFrom2000<uint64_t>(secondsSince1970 - c_UnixEpoch32);
|
||||
}
|
||||
|
||||
// Unix32 support
|
||||
uint32_t Unix32Time() const
|
||||
{
|
||||
return TotalSeconds() + c_UnixEpoch32;
|
||||
}
|
||||
void InitWithUnix32Time(uint32_t secondsSince1970)
|
||||
{
|
||||
_initWithSecondsFrom2000<uint32_t>(secondsSince1970 - c_UnixEpoch32);
|
||||
}
|
||||
// Unix64 support
|
||||
uint64_t Unix64Time() const
|
||||
{
|
||||
return TotalSeconds64() + c_UnixEpoch32;
|
||||
}
|
||||
void InitWithUnix64Time(uint64_t secondsSince1970)
|
||||
{
|
||||
_initWithSecondsFrom2000<uint64_t>(secondsSince1970 - c_UnixEpoch32);
|
||||
}
|
||||
|
||||
// Ntp32 support
|
||||
uint32_t Ntp32Time() const
|
||||
{
|
||||
return TotalSeconds() + c_NtpEpoch32;
|
||||
}
|
||||
void InitWithNtp32Time(uint32_t secondsSince1900)
|
||||
{
|
||||
_initWithSecondsFrom2000<uint32_t>(secondsSince1900 - c_NtpEpoch32);
|
||||
}
|
||||
// Ntp64 support
|
||||
uint64_t Ntp64Time() const
|
||||
{
|
||||
return TotalSeconds64() + c_NtpEpoch32;
|
||||
}
|
||||
void InitWithNtp64Time(uint64_t secondsSince1900)
|
||||
{
|
||||
_initWithSecondsFrom2000<uint64_t>(secondsSince1900 - c_NtpEpoch32);
|
||||
}
|
||||
|
||||
[[deprecated("Use InitWithDateTimeFormatString()")]]
|
||||
void InitWithIso8601(const char* date)
|
||||
{
|
||||
// sample input: date = "Sat, 06 Dec 2009 12:34:56 GMT"
|
||||
InitWithDateTimeFormatString<RtcLocaleEnUs>(F("*, DD MMM YYYY hh:mm:ss zzz"), date);
|
||||
}
|
||||
|
||||
//
|
||||
// https://www.w3.org/TR/NOTE-datetime
|
||||
// https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-date-and-time-format-strings
|
||||
// https://en.wikipedia.org/wiki/List_of_time_zone_abbreviations#:~:text=List%20of%20time%20zone%20abbreviations%20%20%20,%20%20UTC%2B08%3A00%20%2051%20more%20rows%20
|
||||
//
|
||||
// * - ignore until next char
|
||||
// ! = ignore until not next char
|
||||
//
|
||||
// YY - two digit year, assumes 2000 +
|
||||
// YYYY - four digit year
|
||||
//
|
||||
// M - full month name, arbitrary length until next char
|
||||
// MM - two digit month
|
||||
// MMM - abreviated month name, 3 chars
|
||||
//
|
||||
// DD - two digit day of month
|
||||
//
|
||||
// hh - hour
|
||||
// mm - minute
|
||||
// ss - seconds
|
||||
// sssss - seconds with decimal (12.34)
|
||||
//
|
||||
// z - +hh:mm or Z -
|
||||
// using this will adjust the time to UTC from the time zone
|
||||
// using this will adjust the time to UTC from the time zone
|
||||
// present in the string,
|
||||
// without it, it will ignore the timezone and return the local
|
||||
// zzz - time zone abbreviation
|
||||
// using this will adjust the time to UTC from the time zone
|
||||
// present in the string,
|
||||
// without it, it will ignore the timezone and return the local
|
||||
//
|
||||
// return - index last converted of datetime
|
||||
template <typename T_LOCALE = RtcLocaleEnUs> size_t InitWithDateTimeFormatString(
|
||||
const char* format,
|
||||
const char* datetime)
|
||||
{
|
||||
const char specifiers[] = "*!YMDhmsz";
|
||||
const char* scan = format;
|
||||
const char* convert = datetime;
|
||||
int32_t timezoneMinutes = 0;
|
||||
|
||||
// while chars in format and datetime
|
||||
while (*scan != '\0' && *datetime != '\0')
|
||||
{
|
||||
// find next token
|
||||
size_t iStart = strcspn(scan, specifiers);
|
||||
scan += iStart;
|
||||
convert += iStart;
|
||||
|
||||
if (*scan != '\0')
|
||||
{
|
||||
// find the end of the token
|
||||
size_t iEnd = 1;
|
||||
while (scan[iEnd] == *scan)
|
||||
{
|
||||
iEnd++;
|
||||
}
|
||||
size_t count = iEnd;
|
||||
size_t countConverted = 0;
|
||||
|
||||
// handy debug tracing
|
||||
//
|
||||
//Serial.print(scan[iStart]);
|
||||
//Serial.print(">");
|
||||
//Serial.print(convert);
|
||||
//Serial.print("< ");
|
||||
//Serial.print(count);
|
||||
//Serial.println();
|
||||
|
||||
switch (scan[iStart])
|
||||
{
|
||||
case '*':
|
||||
{
|
||||
// increment through convert until the matching char
|
||||
// from scan after the * token
|
||||
const char* skip = convert;
|
||||
while (*skip != '\0' && *skip != scan[iEnd])
|
||||
{
|
||||
skip++;
|
||||
}
|
||||
// include skipping extra matching char
|
||||
countConverted = skip - convert + 1;
|
||||
count++;
|
||||
|
||||
// handy debug tracing
|
||||
//
|
||||
//Serial.print("*>");
|
||||
//Serial.print(scan + count);
|
||||
//Serial.print("<->");
|
||||
//Serial.print(convert + countConverted);
|
||||
//Serial.print("< ");
|
||||
//Serial.print(count);
|
||||
//Serial.print("-");
|
||||
//Serial.print(countConverted);
|
||||
//Serial.println();
|
||||
}
|
||||
break;
|
||||
|
||||
case '!':
|
||||
{
|
||||
// increment through convert until the matching char
|
||||
// from scan after the * token is not present
|
||||
const char* skip = convert;
|
||||
while (*skip != '\0' && *skip == scan[iEnd])
|
||||
{
|
||||
skip++;
|
||||
}
|
||||
|
||||
countConverted = skip - convert;
|
||||
count++;
|
||||
|
||||
// handy debug tracing
|
||||
//
|
||||
//Serial.print("!>");
|
||||
//Serial.print(scan + count);
|
||||
//Serial.print("<->");
|
||||
//Serial.print(convert + countConverted);
|
||||
//Serial.print("< ");
|
||||
//Serial.print(count);
|
||||
//Serial.print("-");
|
||||
//Serial.print(countConverted);
|
||||
//Serial.println();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Y':
|
||||
if (count >= 4)
|
||||
{
|
||||
// only care about last three digits
|
||||
size_t offset = count - 3;
|
||||
scan += offset;
|
||||
convert += offset;
|
||||
count = 3;
|
||||
}
|
||||
countConverted = CharsToNumber<uint8_t>(convert, &_yearFrom2000, count);
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
if (*convert >= '0' && *convert <= '9')
|
||||
{
|
||||
if (count > 2)
|
||||
{
|
||||
return convert - datetime;
|
||||
}
|
||||
countConverted = CharsToNumber<uint8_t>(convert, &_month, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (count > 3)
|
||||
{
|
||||
return convert - datetime;
|
||||
}
|
||||
else if (count == 1)
|
||||
{
|
||||
const char* temp = convert;
|
||||
// increment temp until matching char after M
|
||||
while (*temp != scan[iEnd])
|
||||
{
|
||||
temp++;
|
||||
}
|
||||
|
||||
size_t monthCount = temp - convert;
|
||||
if (monthCount < 3)
|
||||
{
|
||||
return convert - datetime;
|
||||
}
|
||||
|
||||
_month = T_LOCALE::CharsToMonth(convert, monthCount);
|
||||
countConverted = monthCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
_month = T_LOCALE::CharsToMonth(convert, count);
|
||||
countConverted = count;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
countConverted = CharsToNumber<uint8_t>(convert, &_dayOfMonth, count);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
countConverted = CharsToNumber<uint8_t>(convert, &_hour, count);
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
countConverted = CharsToNumber<uint8_t>(convert, &_minute, count);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
countConverted = CharsToNumber<uint8_t>(convert, &_second, count);
|
||||
break;
|
||||
|
||||
case 'z':
|
||||
if (count == 1)
|
||||
{
|
||||
const char* temp = convert;
|
||||
|
||||
// +hh:mm or Z formated timezone
|
||||
// adjusting to local time
|
||||
if (*temp == '+' || *temp == '-')
|
||||
{
|
||||
uint8_t hours;
|
||||
uint8_t minutes;
|
||||
|
||||
int32_t timezoneSign = (*temp == '+') ? 1 : -1;
|
||||
temp++;
|
||||
temp += CharsToNumber<uint8_t>(temp, &hours, 2);
|
||||
temp++; // :
|
||||
temp += CharsToNumber<uint8_t>(temp, &minutes, 2);
|
||||
timezoneMinutes = (static_cast<int32_t>(hours) * 60 + minutes) * timezoneSign;
|
||||
|
||||
countConverted = temp - datetime;
|
||||
}
|
||||
else if (*temp == 'Z' || *temp == 'z')
|
||||
{
|
||||
// nothing to adjust,
|
||||
// zulu time is what we want
|
||||
countConverted = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return convert - datetime;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// zzz - abbreviation timezone format
|
||||
// adjust from local time
|
||||
countConverted = T_LOCALE::TimeZoneMinutesFromAbbreviation(&timezoneMinutes, convert);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (countConverted)
|
||||
{
|
||||
scan += count;
|
||||
convert += countConverted;
|
||||
}
|
||||
else
|
||||
{
|
||||
return convert - datetime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// adjust our time by the timezone to get GMT/Z
|
||||
// as by default RtcDateTime is GMT
|
||||
//
|
||||
*this -= timezoneMinutes * 60;
|
||||
|
||||
return convert - datetime;
|
||||
}
|
||||
|
||||
// Version of above but supporting PROGMEM for the format,
|
||||
// specifically the F("") use for format
|
||||
template <typename T_LOCALE = RtcLocaleEnUs> size_t InitWithDateTimeFormatString(
|
||||
const __FlashStringHelper* format,
|
||||
const char* datetime)
|
||||
{
|
||||
char ramFormat[32];
|
||||
|
||||
strncpy_P(ramFormat,
|
||||
reinterpret_cast<const char*>(format),
|
||||
countof(ramFormat));
|
||||
return InitWithDateTimeFormatString<T_LOCALE>(ramFormat, datetime);
|
||||
}
|
||||
|
||||
// convert our Day of Week to Rtc Day of Week
|
||||
// RTC Hardware Day of Week is 1-7, 1 = Monday
|
||||
static uint8_t ConvertDowToRtc(uint8_t dow)
|
||||
{
|
||||
if (dow == 0)
|
||||
{
|
||||
dow = 7;
|
||||
}
|
||||
return dow;
|
||||
}
|
||||
|
||||
// convert Rtc Day of Week to our Day of Week
|
||||
static uint8_t ConvertRtcToDow(uint8_t rtcDow)
|
||||
{
|
||||
return (rtcDow % 7);
|
||||
}
|
||||
|
||||
// returns the number days in the month
|
||||
// month (1-12)
|
||||
static uint8_t DaysInMonth(uint16_t year, uint8_t month)
|
||||
{
|
||||
uint8_t zMonth = 0;
|
||||
// cap and convert to zero based
|
||||
if (month != 0)
|
||||
{
|
||||
if (month > 11)
|
||||
{
|
||||
zMonth = 11;
|
||||
}
|
||||
else
|
||||
{
|
||||
zMonth = month - 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t days = pgm_read_byte(c_daysInMonth + zMonth);
|
||||
// check february for leap years
|
||||
if (month == 2 && IsLeapYear(year))
|
||||
{
|
||||
days++;
|
||||
}
|
||||
return days;
|
||||
}
|
||||
|
||||
static bool IsLeapYear(uint16_t year)
|
||||
{
|
||||
return ((year % 4) == 0);
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t _yearFrom2000;
|
||||
uint8_t _month;
|
||||
uint8_t _dayOfMonth;
|
||||
uint8_t _hour;
|
||||
uint8_t _minute;
|
||||
uint8_t _second;
|
||||
|
||||
template <typename T> void _initWithSecondsFrom2000(T secondsFrom2000)
|
||||
{
|
||||
_second = secondsFrom2000 % 60;
|
||||
T timeFrom2000 = secondsFrom2000 / 60;
|
||||
_minute = timeFrom2000 % 60;
|
||||
timeFrom2000 /= 60;
|
||||
_hour = timeFrom2000 % 24;
|
||||
T days = timeFrom2000 / 24;
|
||||
T leapDays;
|
||||
|
||||
for (_yearFrom2000 = 0;; ++_yearFrom2000)
|
||||
{
|
||||
leapDays = (_yearFrom2000 % 4 == 0) ? 1 : 0;
|
||||
if (days < 365U + leapDays)
|
||||
break;
|
||||
days -= 365 + leapDays;
|
||||
}
|
||||
for (_month = 1;; ++_month)
|
||||
{
|
||||
uint8_t daysPerMonth = pgm_read_byte(c_daysInMonth + _month - 1);
|
||||
if (leapDays && _month == 2)
|
||||
daysPerMonth++;
|
||||
if (days < daysPerMonth)
|
||||
break;
|
||||
days -= daysPerMonth;
|
||||
}
|
||||
_dayOfMonth = days + 1;
|
||||
}
|
||||
|
||||
// CharsToNumber - convert a series of chars to a number of the given type
|
||||
//
|
||||
// str - the pointer to string to process
|
||||
// result - the value converted from the string
|
||||
// count - the number of numerals to stop processing with
|
||||
// excludes leading non-numeral chars
|
||||
// return - the number to increment str for more processing,
|
||||
// 0 for failure
|
||||
template <typename T_NUMBER> size_t CharsToNumber(const char* str, T_NUMBER* result, size_t count)
|
||||
{
|
||||
const char* scan = str;
|
||||
bool converted = false;
|
||||
size_t left = count;
|
||||
|
||||
*result = 0;
|
||||
|
||||
// skip leading 0 and non numericals
|
||||
while (left && '\0' != *scan && ('0' >= *scan || '9' < *scan))
|
||||
{
|
||||
// only decrement left with numerals
|
||||
if (left && '0' == *scan)
|
||||
{
|
||||
converted = true;
|
||||
left--;
|
||||
}
|
||||
scan++;
|
||||
}
|
||||
|
||||
// calculate number until we hit non-numeral char
|
||||
while (left && '\0' != *scan && '0' <= *scan && *scan <= '9')
|
||||
{
|
||||
converted = true;
|
||||
|
||||
*result *= 10;
|
||||
*result += *scan - '0';
|
||||
|
||||
left--;
|
||||
scan++;
|
||||
}
|
||||
|
||||
// we ignore decimal numbers but we need to scan past them
|
||||
//
|
||||
if (left && '.' == *scan)
|
||||
{
|
||||
// skip decimal
|
||||
left--;
|
||||
scan++;
|
||||
|
||||
// continue to discard numerals
|
||||
while (left && '\0' != *scan && '0' <= *scan && *scan <= '9')
|
||||
{
|
||||
left--;
|
||||
scan++;
|
||||
}
|
||||
}
|
||||
|
||||
return converted ? scan - str : 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
509
libraries/Rtc_by_Makuna/src/RtcLocaleEn.cpp
Normal file
509
libraries/Rtc_by_Makuna/src/RtcLocaleEn.cpp
Normal file
@@ -0,0 +1,509 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
RTC library
|
||||
|
||||
Written by Michael C. Miller.
|
||||
|
||||
I invest time and resources providing this open source code,
|
||||
please support me by dontating (see https://github.com/Makuna/Rtc)
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the Makuna/Rtc library.
|
||||
|
||||
Rtc is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Rtc is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with Rtc. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "RtcUtility.h"
|
||||
#include "RtcTimeZone.h"
|
||||
#include "RtcLocaleEn.h"
|
||||
|
||||
// due to how PROGMEM works, strings must be declared standalone
|
||||
//
|
||||
const char stringACDT[] PROGMEM = "ACDT";
|
||||
const char stringACST[] PROGMEM = "ACST";
|
||||
const char stringACT[] PROGMEM = "ACT";
|
||||
const char stringACWST[] PROGMEM = "ACWST";
|
||||
const char stringADT[] PROGMEM = "ADT";
|
||||
const char stringAEDT[] PROGMEM = "AEDT";
|
||||
const char stringAEST[] PROGMEM = "AEST";
|
||||
const char stringAET[] PROGMEM = "AET";
|
||||
const char stringAFT[] PROGMEM = "AFT";
|
||||
const char stringAKDT[] PROGMEM = "AKDT";
|
||||
const char stringAKST[] PROGMEM = "AKST";
|
||||
const char stringALMT[] PROGMEM = "ALMT";
|
||||
const char stringAMST[] PROGMEM = "AMST";
|
||||
const char stringAMT[] PROGMEM = "AMT";
|
||||
const char stringANAT[] PROGMEM = "ANAT";
|
||||
const char stringAQTT[] PROGMEM = "AQTT";
|
||||
const char stringART[] PROGMEM = "ART";
|
||||
const char stringAST[] PROGMEM = "AST";
|
||||
const char stringAWST[] PROGMEM = "AWST";
|
||||
const char stringAZOST[] PROGMEM = "AZOST";
|
||||
const char stringAZOT[] PROGMEM = "AZOT";
|
||||
const char stringAZT[] PROGMEM = "AZT";
|
||||
const char stringBNT[] PROGMEM = "BNT";
|
||||
const char stringBIOT[] PROGMEM = "BIOT";
|
||||
const char stringBIT[] PROGMEM = "BIT";
|
||||
const char stringBOT[] PROGMEM = "BOT";
|
||||
const char stringBRST[] PROGMEM = "BRST";
|
||||
const char stringBRT[] PROGMEM = "BRT";
|
||||
const char stringBST[] PROGMEM = "BST";
|
||||
const char stringBTT[] PROGMEM = "BTT";
|
||||
const char stringCAT[] PROGMEM = "CAT";
|
||||
const char stringCCT[] PROGMEM = "CCT";
|
||||
const char stringCDT[] PROGMEM = "CDT";
|
||||
const char stringCEST[] PROGMEM = "CEST";
|
||||
const char stringCET[] PROGMEM = "CET";
|
||||
const char stringCHADT[] PROGMEM = "CHADT";
|
||||
const char stringCHAST[] PROGMEM = "CHAST";
|
||||
const char stringCHOT[] PROGMEM = "CHOT";
|
||||
const char stringCHOST[] PROGMEM = "CHOST";
|
||||
const char stringCHST[] PROGMEM = "CHST";
|
||||
const char stringCHUT[] PROGMEM = "CHUT";
|
||||
const char stringCIST[] PROGMEM = "CIST";
|
||||
const char stringCKT[] PROGMEM = "CKT";
|
||||
const char stringCLST[] PROGMEM = "CLST";
|
||||
const char stringCLT[] PROGMEM = "CLT";
|
||||
const char stringCOST[] PROGMEM = "COST";
|
||||
const char stringCOT[] PROGMEM = "COT";
|
||||
const char stringCST[] PROGMEM = "CST";
|
||||
const char stringCT[] PROGMEM = "CT";
|
||||
const char stringCVT[] PROGMEM = "CVT";
|
||||
const char stringCWST[] PROGMEM = "CWST";
|
||||
const char stringCXT[] PROGMEM = "CXT";
|
||||
const char stringDAVT[] PROGMEM = "DAVT";
|
||||
const char stringDDUT[] PROGMEM = "DDUT";
|
||||
const char stringDFT[] PROGMEM = "DFT";
|
||||
const char stringEASST[] PROGMEM = "EASST";
|
||||
const char stringEAST[] PROGMEM = "EAST";
|
||||
const char stringEAT[] PROGMEM = "EAT";
|
||||
const char stringECT[] PROGMEM = "ECT";
|
||||
const char stringEDT[] PROGMEM = "EDT";
|
||||
const char stringEEST[] PROGMEM = "EEST";
|
||||
const char stringEET[] PROGMEM = "EET";
|
||||
const char stringEGST[] PROGMEM = "EGST";
|
||||
const char stringEGT[] PROGMEM = "EGT";
|
||||
const char stringEST[] PROGMEM = "EST";
|
||||
const char stringET[] PROGMEM = "ET";
|
||||
const char stringFET[] PROGMEM = "FET";
|
||||
const char stringFJT[] PROGMEM = "FJT";
|
||||
const char stringFKST[] PROGMEM = "FKST";
|
||||
const char stringFKT[] PROGMEM = "FKT";
|
||||
const char stringFNT[] PROGMEM = "FNT";
|
||||
const char stringGALT[] PROGMEM = "GALT";
|
||||
const char stringGAMT[] PROGMEM = "GAMT";
|
||||
const char stringGET[] PROGMEM = "GET";
|
||||
const char stringGFT[] PROGMEM = "GFT";
|
||||
const char stringGILT[] PROGMEM = "GILT";
|
||||
const char stringGIT[] PROGMEM = "GIT";
|
||||
const char stringGMT[] PROGMEM = "GMT";
|
||||
const char stringGST[] PROGMEM = "GST";
|
||||
const char stringGYT[] PROGMEM = "GYT";
|
||||
const char stringHDT[] PROGMEM = "HDT";
|
||||
const char stringHAEC[] PROGMEM = "HAEC";
|
||||
const char stringHST[] PROGMEM = "HST";
|
||||
const char stringHKT[] PROGMEM = "HKT";
|
||||
const char stringHMT[] PROGMEM = "HMT";
|
||||
const char stringHOVST[] PROGMEM = "HOVST";
|
||||
const char stringHOVT[] PROGMEM = "HOVT";
|
||||
const char stringICT[] PROGMEM = "ICT";
|
||||
const char stringIDLW[] PROGMEM = "IDLW";
|
||||
const char stringIDT[] PROGMEM = "IDT";
|
||||
const char stringIOT[] PROGMEM = "IOT";
|
||||
const char stringIRDT[] PROGMEM = "IRDT";
|
||||
const char stringIRKT[] PROGMEM = "IRKT";
|
||||
const char stringIRST[] PROGMEM = "IRST";
|
||||
const char stringIST[] PROGMEM = "IST";
|
||||
const char stringJST[] PROGMEM = "JST";
|
||||
const char stringKALT[] PROGMEM = "KALT";
|
||||
const char stringKGT[] PROGMEM = "KGT";
|
||||
const char stringKOST[] PROGMEM = "KOST";
|
||||
const char stringKRAT[] PROGMEM = "KRAT";
|
||||
const char stringKST[] PROGMEM = "KST";
|
||||
const char stringLHST[] PROGMEM = "LHST";
|
||||
const char stringLINT[] PROGMEM = "LINT";
|
||||
const char stringMAGT[] PROGMEM = "MAGT";
|
||||
const char stringMART[] PROGMEM = "MART";
|
||||
const char stringMAWT[] PROGMEM = "MAWT";
|
||||
const char stringMDT[] PROGMEM = "MDT";
|
||||
const char stringMET[] PROGMEM = "MET";
|
||||
const char stringMEST[] PROGMEM = "MEST";
|
||||
const char stringMHT[] PROGMEM = "MHT";
|
||||
const char stringMIST[] PROGMEM = "MIST";
|
||||
const char stringMIT[] PROGMEM = "MIT";
|
||||
const char stringMMT[] PROGMEM = "MMT";
|
||||
const char stringMSK[] PROGMEM = "MSK";
|
||||
const char stringMST[] PROGMEM = "MST";
|
||||
const char stringMUT[] PROGMEM = "MUT";
|
||||
const char stringMVT[] PROGMEM = "MVT";
|
||||
const char stringMYT[] PROGMEM = "MYT";
|
||||
const char stringNCT[] PROGMEM = "NCT";
|
||||
const char stringNDT[] PROGMEM = "NDT";
|
||||
const char stringNFT[] PROGMEM = "NFT";
|
||||
const char stringNOVT[] PROGMEM = "NOVT";
|
||||
const char stringNPT[] PROGMEM = "NPT";
|
||||
const char stringNST[] PROGMEM = "NST";
|
||||
const char stringNT[] PROGMEM = "NT";
|
||||
const char stringNUT[] PROGMEM = "NUT";
|
||||
const char stringNZDT[] PROGMEM = "NZDT";
|
||||
const char stringNZST[] PROGMEM = "NZST";
|
||||
const char stringOMST[] PROGMEM = "OMST";
|
||||
const char stringORAT[] PROGMEM = "ORAT";
|
||||
const char stringPDT[] PROGMEM = "PDT";
|
||||
const char stringPET[] PROGMEM = "PET";
|
||||
const char stringPETT[] PROGMEM = "PETT";
|
||||
const char stringPGT[] PROGMEM = "PGT";
|
||||
const char stringPHOT[] PROGMEM = "PHOT";
|
||||
const char stringPHT[] PROGMEM = "PHT";
|
||||
const char stringPHST[] PROGMEM = "PHST";
|
||||
const char stringPKT[] PROGMEM = "PKT";
|
||||
const char stringPMDT[] PROGMEM = "PMDT";
|
||||
const char stringPMST[] PROGMEM = "PMST";
|
||||
const char stringPONT[] PROGMEM = "PONT";
|
||||
const char stringPST[] PROGMEM = "PST";
|
||||
const char stringPWT[] PROGMEM = "PWT";
|
||||
const char stringPYST[] PROGMEM = "PYST";
|
||||
const char stringPYT[] PROGMEM = "PYT";
|
||||
const char stringRET[] PROGMEM = "RET";
|
||||
const char stringROTT[] PROGMEM = "ROTT";
|
||||
const char stringSAKT[] PROGMEM = "SAKT";
|
||||
const char stringSAMT[] PROGMEM = "SAMT";
|
||||
const char stringSAST[] PROGMEM = "SAST";
|
||||
const char stringSBT[] PROGMEM = "SBT";
|
||||
const char stringSCT[] PROGMEM = "SCT";
|
||||
const char stringSDT[] PROGMEM = "SDT";
|
||||
const char stringSGT[] PROGMEM = "SGT";
|
||||
const char stringSLST[] PROGMEM = "SLST";
|
||||
const char stringSRET[] PROGMEM = "SRET";
|
||||
const char stringSRT[] PROGMEM = "SRT";
|
||||
const char stringSST[] PROGMEM = "SST";
|
||||
const char stringSYOT[] PROGMEM = "SYOT";
|
||||
const char stringTAHT[] PROGMEM = "TAHT";
|
||||
const char stringTHA[] PROGMEM = "THA";
|
||||
const char stringTFT[] PROGMEM = "TFT";
|
||||
const char stringTJT[] PROGMEM = "TJT";
|
||||
const char stringTKT[] PROGMEM = "TKT";
|
||||
const char stringTLT[] PROGMEM = "TLT";
|
||||
const char stringTMT[] PROGMEM = "TMT";
|
||||
const char stringTRT[] PROGMEM = "TRT";
|
||||
const char stringTOT[] PROGMEM = "TOT";
|
||||
const char stringTVT[] PROGMEM = "TVT";
|
||||
const char stringULAST[] PROGMEM = "ULAST";
|
||||
const char stringULAT[] PROGMEM = "ULAT";
|
||||
const char stringUTC[] PROGMEM = "UTC";
|
||||
const char stringUYST[] PROGMEM = "UYST";
|
||||
const char stringUYT[] PROGMEM = "UYT";
|
||||
const char stringUZT[] PROGMEM = "UZT";
|
||||
const char stringVET[] PROGMEM = "VET";
|
||||
const char stringVLAT[] PROGMEM = "VLAT";
|
||||
const char stringVOLT[] PROGMEM = "VOLT";
|
||||
const char stringVOST[] PROGMEM = "VOST";
|
||||
const char stringVUT[] PROGMEM = "VUT";
|
||||
const char stringWAKT[] PROGMEM = "WAKT";
|
||||
const char stringWAST[] PROGMEM = "WAST";
|
||||
const char stringWAT[] PROGMEM = "WAT";
|
||||
const char stringWEST[] PROGMEM = "WEST";
|
||||
const char stringWET[] PROGMEM = "WET";
|
||||
const char stringWIB[] PROGMEM = "WIB";
|
||||
const char stringWIT[] PROGMEM = "WIT";
|
||||
const char stringWITA[] PROGMEM = "WITA";
|
||||
const char stringWGST[] PROGMEM = "WGST";
|
||||
const char stringWGT[] PROGMEM = "WGT";
|
||||
const char stringWST[] PROGMEM = "WST";
|
||||
const char stringYAKT[] PROGMEM = "YAKT";
|
||||
const char stringYEKT[] PROGMEM = "YEKT";
|
||||
|
||||
|
||||
// collection in alphabetic order of abbreviation
|
||||
// duplicates commented out randomly (why are there duplicates in a standard?!)
|
||||
// IF YOU MODIFY THIS to your locale, please goto github and add an issue
|
||||
//
|
||||
const RtcTimeZone c_tzEn[] PROGMEM =
|
||||
{
|
||||
{ stringACDT, 10 * 60 + 30 }, // Australian Central Daylight Saving Time
|
||||
{ stringACST, 9 * 60 + 30 }, // Australian Central Standard Time
|
||||
{ stringACT, -5 * 60 }, // Acre Time
|
||||
// { stringACT, 8 * 60 + 0 }, // ASEAN Common Time (proposed)
|
||||
{ stringACWST, 8 * 60 + 45 }, // Australian Central Western Standard Time (unofficial)
|
||||
{ stringADT, -3 * 60 }, // Atlantic Daylight Time
|
||||
{ stringAEDT, 11 * 60 }, // Australian Eastern Daylight Saving Time
|
||||
{ stringAEST, 10 * 60 }, // Australian Eastern Standard Time
|
||||
{ stringAET, 10 * 60 }, // Australian Eastern Time
|
||||
{ stringAFT, 4 * 60 + 30 }, // Afghanistan Time
|
||||
{ stringAKDT, -8 * 60 }, // Alaska Daylight Time
|
||||
{ stringAKST, -9 * 60 }, // Alaska Standard Time
|
||||
{ stringALMT, 6 * 60 }, // Alma-Ata Time[1]
|
||||
{ stringAMST, -3 * 60 }, // Amazon Summer Time (Brazil)[2]
|
||||
{ stringAMT, -4 * 60 }, // Amazon Time (Brazil)[3]
|
||||
// { stringAMT, 4 * 60 }, // Armenia Time
|
||||
{ stringANAT, 12 * 60 }, // Anadyr Time[4]
|
||||
{ stringAQTT, 5 * 60 }, // Aqtobe Time[5]
|
||||
{ stringART, -3 * 60 }, // Argentina Time
|
||||
// { stringAST, 3 * 60 }, // Arabia Standard Time
|
||||
{ stringAST, -4 * 60 }, // Atlantic Standard Time
|
||||
{ stringAWST, 8 * 60 }, // Australian Western Standard Time
|
||||
{ stringAZOST, 0 }, // Azores Summer Time
|
||||
{ stringAZOT, -1 * 60 }, // Azores Standard Time
|
||||
{ stringAZT, 4 * 60 }, // Azerbaijan Time
|
||||
{ stringBNT, 8 * 60 }, // Brunei Time
|
||||
{ stringBIOT, 6 * 60 }, // British Indian Ocean Time
|
||||
{ stringBIT, -12 * 60 }, // Baker Island Time
|
||||
{ stringBOT, -4 * 60 }, // Bolivia Time
|
||||
{ stringBRST, -2 * 60 }, // Brasília Summer Time
|
||||
{ stringBRT, -3 * 60 }, // Brasília Time
|
||||
// { stringBST, 6 * 60 }, // Bangladesh Standard Time
|
||||
// { stringBST, 11 * 60 }, // Bougainville Standard Time[6]
|
||||
{ stringBST, 1 * 60 }, // British Summer Time (British Standard Time from Mar 1968 to Oct 1971)
|
||||
{ stringBTT, 6 * 60 }, // Bhutan Time
|
||||
{ stringCAT, 2 * 60 }, // Central Africa Time
|
||||
{ stringCCT, 6 * 60 + 30 }, // Cocos Islands Time
|
||||
{ stringCDT, -5 * 60 }, // Central Daylight Time (North America)
|
||||
// { stringCDT, -4 * 60 }, // Cuba Daylight Time[7]
|
||||
{ stringCEST, 2 * 60 }, // Central European Summer Time
|
||||
{ stringCET, 1 * 60 }, // Central European Time
|
||||
{ stringCHADT, 13 * 60 + 45 }, // Chatham Daylight Time
|
||||
{ stringCHAST, 12 * 60 + 45 }, // Chatham Standard Time
|
||||
{ stringCHOT, 8 * 60 }, // Choibalsan Standard Time
|
||||
{ stringCHOST, 9 * 60 }, // Choibalsan Summer Time
|
||||
{ stringCHST, 10 * 60 }, // Chamorro Standard Time
|
||||
{ stringCHUT, 10 * 60 }, // Chuuk Time
|
||||
{ stringCIST, -8 * 60 }, // Clipperton Island Standard Time
|
||||
{ stringCKT, -10 * 60 }, // Cook Island Time
|
||||
{ stringCLST, -3 * 60 }, // Chile Summer Time
|
||||
{ stringCLT, -4 * 60 }, // Chile Standard Time
|
||||
{ stringCOST, -4 * 60 }, // Colombia Summer Time
|
||||
{ stringCOT, -5 * 60 }, // Colombia Time
|
||||
{ stringCST, -6 * 60 }, // Central Standard Time (North America)
|
||||
// { stringCST, 8 * 60 }, // China Standard Time
|
||||
// { stringCST, -5 * 60 }, // Cuba Standard Time
|
||||
{ stringCT, -6 * 60 }, // Central Time
|
||||
{ stringCVT, -1 * 60 }, // Cape Verde Time
|
||||
{ stringCWST, 8 * 60 + 45 }, // Central Western Standard Time (Australia) unofficial
|
||||
{ stringCXT, 7 * 60 }, // Christmas Island Time
|
||||
{ stringDAVT, 7 * 60 }, // Davis Time
|
||||
{ stringDDUT, 10 * 60 }, // Dumont d'Urville Time
|
||||
{ stringDFT, 1 * 60 }, // AIX-specific equivalent of Central European Time[NB 1]
|
||||
{ stringEASST, -5 * 60 }, // Easter Island Summer Time
|
||||
{ stringEAST, -6 * 60 }, // Easter Island Standard Time
|
||||
{ stringEAT, 3 * 60 }, // East Africa Time
|
||||
{ stringECT, -4 * 60 }, // Eastern Caribbean Time (does not recognise DST)
|
||||
// { stringECT, -5 * 60 }, // Ecuador Time
|
||||
{ stringEDT, -4 * 60 }, // Eastern Daylight Time (North America)
|
||||
{ stringEEST, 3 * 60 }, // Eastern European Summer Time
|
||||
{ stringEET, 2 * 60 }, // Eastern European Time
|
||||
{ stringEGST, 0 }, // Eastern Greenland Summer Time
|
||||
{ stringEGT, -1 * 60 }, // Eastern Greenland Time
|
||||
{ stringEST, -5 * 60 }, // Eastern Standard Time (North America)
|
||||
{ stringET, -5 * 60 }, // Eastern Time (North America)
|
||||
{ stringFET, 3 * 60 }, // Further-eastern European Time
|
||||
{ stringFJT, 12 * 60 }, // Fiji Time
|
||||
{ stringFKST, -3 * 60 }, // Falkland Islands Summer Time
|
||||
{ stringFKT, -4 * 60 }, // Falkland Islands Time
|
||||
{ stringFNT, -2 * 60 }, // Fernando de Noronha Time
|
||||
{ stringGALT, -6 * 60 }, // Galápagos Time
|
||||
{ stringGAMT, -9 * 60 }, // Gambier Islands Time
|
||||
{ stringGET, 4 * 60 }, // Georgia Standard Time
|
||||
{ stringGFT, -3 * 60 }, // French Guiana Time
|
||||
{ stringGILT, 12 * 60 }, // Gilbert Island Time
|
||||
{ stringGIT, -9 * 60 }, // Gambier Island Time
|
||||
{ stringGMT, 0 }, // Greenwich Mean Time
|
||||
// { stringGST, -2 * 60 }, // South Georgia and the South Sandwich Islands Time
|
||||
{ stringGST, 4 * 60 }, // Gulf Standard Time
|
||||
{ stringGYT, -4 * 60 }, // Guyana Time
|
||||
{ stringHDT, -9 * 60 }, // Hawaii–Aleutian Daylight Time
|
||||
{ stringHAEC, 2 * 60 }, // Heure Avancée d'Europe Centrale French-language name for CEST
|
||||
{ stringHST, -10 * 60 }, // Hawaii–Aleutian Standard Time
|
||||
{ stringHKT, 8 * 60 }, // Hong Kong Time
|
||||
{ stringHMT, 5 * 60 }, // Heard and McDonald Islands Time
|
||||
{ stringHOVST, 8 * 60 }, // Hovd Summer Time (not used from 2017-present)
|
||||
{ stringHOVT, 7 * 60 }, // Hovd Time
|
||||
{ stringICT, 7 * 60 }, // Indochina Time
|
||||
{ stringIDLW, -12 * 60 }, // International Date Line West time zone
|
||||
{ stringIDT, 3 * 60 }, // Israel Daylight Time
|
||||
{ stringIOT, 3 * 60 }, // Indian Ocean Time
|
||||
{ stringIRDT, 4 * 60 + 30 }, // Iran Daylight Time
|
||||
{ stringIRKT, 8 * 60 }, // Irkutsk Time
|
||||
{ stringIRST, 3 * 60 + 30 }, // Iran Standard Time
|
||||
// { stringIST, 5 * 60 + 30 }, // Indian Standard Time
|
||||
// { stringIST, 1 * 60 }, // Irish Standard Time[8]
|
||||
{ stringIST, 2 * 60 }, // Israel Standard Time
|
||||
{ stringJST, 9 * 60 }, // Japan Standard Time
|
||||
{ stringKALT, 2 * 60 }, // Kaliningrad Time
|
||||
{ stringKGT, 6 * 60 }, // Kyrgyzstan Time
|
||||
{ stringKOST, 11 * 60 }, // Kosrae Time
|
||||
{ stringKRAT, 7 * 60 }, // Krasnoyarsk Time
|
||||
{ stringKST, 9 * 60 }, // Korea Standard Time
|
||||
{ stringLHST, 10 * 60 + 30 }, // Lord Howe Standard Time
|
||||
{ stringLHST, 11 * 60 }, // Lord Howe Summer Time
|
||||
{ stringLINT, 14 * 60 }, // Line Islands Time
|
||||
{ stringMAGT, 12 * 60 }, // Magadan Time
|
||||
{ stringMART, -(9 * 60 + 30) }, // Marquesas Islands Time
|
||||
{ stringMAWT, 5 * 60 }, // Mawson Station Time
|
||||
{ stringMDT, -6 * 60 }, // Mountain Daylight Time (North America)
|
||||
{ stringMET, 1 * 60 }, // Middle European Time (same zone as CET)
|
||||
{ stringMEST, 2 * 60 }, // Middle European Summer Time (same zone as CEST)
|
||||
{ stringMHT, 12 * 60 }, // Marshall Islands Time
|
||||
{ stringMIST, 11 * 60 }, // Macquarie Island Station Time
|
||||
{ stringMIT, -(9 * 60 + 30) }, // Marquesas Islands Time
|
||||
{ stringMMT, 6 * 60 + 30 }, // Myanmar Standard Time
|
||||
{ stringMSK, 3 * 60 }, // Moscow Time
|
||||
{ stringMST, 8 * 60 }, // Malaysia Standard Time
|
||||
{ stringMST, -7 * 60 }, // Mountain Standard Time (North America)
|
||||
{ stringMUT, 4 * 60 }, // Mauritius Time
|
||||
{ stringMVT, 5 * 60 }, // Maldives Time
|
||||
{ stringMYT, 8 * 60 }, // Malaysia Time
|
||||
{ stringNCT, 11 * 60 }, // New Caledonia Time
|
||||
{ stringNDT, -(2 * 60 + 30) }, // Newfoundland Daylight Time
|
||||
{ stringNFT, 11 * 60 }, // Norfolk Island Time
|
||||
{ stringNOVT, 7 * 60 }, // Novosibirsk Time [9]
|
||||
{ stringNPT, 5 * 60 + 45 }, // Nepal Time
|
||||
{ stringNST, -(3 * 60 + 30) }, // Newfoundland Standard Time
|
||||
{ stringNT, -(3 * 60 + 30) }, // Newfoundland Time
|
||||
{ stringNUT, -11 * 60 }, // Niue Time
|
||||
{ stringNZDT, 13 * 60 }, // New Zealand Daylight Time
|
||||
{ stringNZST, 12 * 60 }, // New Zealand Standard Time
|
||||
{ stringOMST, 6 * 60 }, // Omsk Time
|
||||
{ stringORAT, 5 * 60 }, // Oral Time
|
||||
{ stringPDT, -7 * 60 }, // Pacific Daylight Time (North America)
|
||||
{ stringPET, -5 * 60 }, // Peru Time
|
||||
{ stringPETT, 12 * 60 }, // Kamchatka Time
|
||||
{ stringPGT, 10 * 60 }, // Papua New Guinea Time
|
||||
{ stringPHOT, 13 * 60 }, // Phoenix Island Time
|
||||
{ stringPHT, 8 * 60 }, // Philippine Time
|
||||
{ stringPHST, 8 * 60 }, // Philippine Standard Time
|
||||
{ stringPKT, 5 * 60 }, // Pakistan Standard Time
|
||||
{ stringPMDT, -2 * 60 }, // Saint Pierre and Miquelon Daylight Time
|
||||
{ stringPMST, -3 * 60 }, // Saint Pierre and Miquelon Standard Time
|
||||
{ stringPONT, 11 * 60 }, // Pohnpei Standard Time
|
||||
{ stringPST, -8 * 60 }, // Pacific Standard Time (North America)
|
||||
{ stringPWT, 9 * 60 }, // Palau Time[10]
|
||||
{ stringPYST, -3 * 60 }, // Paraguay Summer Time[11]
|
||||
{ stringPYT, -4 * 60 }, // Paraguay Time[12]
|
||||
{ stringRET, 4 * 60 }, // Réunion Time
|
||||
{ stringROTT, -3 * 60 }, // Rothera Research Station Time
|
||||
{ stringSAKT, 11 * 60 }, // Sakhalin Island Time
|
||||
{ stringSAMT, 4 * 60 }, // Samara Time
|
||||
{ stringSAST, 2 * 60 }, // South African Standard Time
|
||||
{ stringSBT, 11 * 60 }, // Solomon Islands Time
|
||||
{ stringSCT, 4 * 60 }, // Seychelles Time
|
||||
{ stringSDT, -10 * 60 }, // Samoa Daylight Time
|
||||
{ stringSGT, 8 * 60 }, // Singapore Time
|
||||
{ stringSLST, 5 * 60 + 30 }, // Sri Lanka Standard Time
|
||||
{ stringSRET, 11 * 60 }, // Srednekolymsk Time
|
||||
{ stringSRT, -3 * 60 }, // Suriname Time
|
||||
// { stringSST, -11 * 60 }, // Samoa Standard Time
|
||||
{ stringSST, 8 * 60 }, // Singapore Standard Time
|
||||
{ stringSYOT, 3 * 60 }, // Showa Station Time
|
||||
{ stringTAHT, -10 * 60 }, // Tahiti Time
|
||||
{ stringTHA, 7 * 60 }, // Thailand Standard Time
|
||||
{ stringTFT, 5 * 60 }, // French Southern and Antarctic Time[13]
|
||||
{ stringTJT, 5 * 60 }, // Tajikistan Time
|
||||
{ stringTKT, 13 * 60 }, // Tokelau Time
|
||||
{ stringTLT, 9 * 60 }, // Timor Leste Time
|
||||
{ stringTMT, 5 * 60 }, // Turkmenistan Time
|
||||
{ stringTRT, 3 * 60 }, // Turkey Time
|
||||
{ stringTOT, 13 * 60 }, // Tonga Time
|
||||
{ stringTVT, 12 * 60 }, // Tuvalu Time
|
||||
{ stringULAST, 9 * 60 }, // Ulaanbaatar Summer Time
|
||||
{ stringULAT, 8 * 60 }, // Ulaanbaatar Standard Time
|
||||
{ stringUTC, 0 }, // Coordinated Universal Time
|
||||
{ stringUYST, -2 * 60 }, // Uruguay Summer Time
|
||||
{ stringUYT, -3 * 60 }, // Uruguay Standard Time
|
||||
{ stringUZT, 5 * 60 }, // Uzbekistan Time
|
||||
{ stringVET, -4 * 60 }, // Venezuelan Standard Time
|
||||
{ stringVLAT, 10 * 60 }, // Vladivostok Time
|
||||
{ stringVOLT, 3 * 60 }, // Volgograd Time
|
||||
{ stringVOST, 6 * 60 }, // Vostok Station Time
|
||||
{ stringVUT, 11 * 60 }, // Vanuatu Time
|
||||
{ stringWAKT, 12 * 60 }, // Wake Island Time
|
||||
{ stringWAST, 2 * 60 }, // West Africa Summer Time
|
||||
{ stringWAT, 1 * 60 }, // West Africa Time
|
||||
{ stringWEST, 1 * 60 }, // Western European Summer Time
|
||||
{ stringWET, 0}, // Western European Time
|
||||
{ stringWIB, 7 * 60 }, // Western Indonesian Time
|
||||
{ stringWIT, 9 * 60 }, // Eastern Indonesian Time
|
||||
{ stringWITA, 8 * 60 }, // Central Indonesia Time
|
||||
{ stringWGST, -2 * 60 }, // West Greenland Summer Time[14]
|
||||
{ stringWGT, -3 * 60 }, // West Greenland Time[15]
|
||||
{ stringWST, 8 * 60 }, // Western Standard Time
|
||||
{ stringYAKT, 9 * 60 }, // Yakutsk Time
|
||||
{ stringYEKT, 5 * 60 } // Yekaterinburg Time
|
||||
};
|
||||
|
||||
|
||||
uint8_t RtcLocaleEn::CharsToMonth(const char* monthChars, size_t count)
|
||||
{
|
||||
uint8_t month = 0;
|
||||
|
||||
// works for both standard abbreviations and full month names
|
||||
//
|
||||
if (count >= 3)
|
||||
{
|
||||
switch (tolower(monthChars[0]))
|
||||
{
|
||||
case 'j':
|
||||
if (tolower(monthChars[1]) == 'a')
|
||||
month = 1;
|
||||
else if (tolower(monthChars[2]) == 'n')
|
||||
month = 6;
|
||||
else
|
||||
month = 7;
|
||||
break;
|
||||
case 'f':
|
||||
month = 2;
|
||||
break;
|
||||
case 'a':
|
||||
month = tolower(monthChars[1]) == 'p' ? 4 : 8;
|
||||
break;
|
||||
case 'm':
|
||||
month = tolower(monthChars[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;
|
||||
}
|
||||
}
|
||||
return month;
|
||||
}
|
||||
|
||||
size_t RtcLocaleEn::TimeZoneMinutesFromAbbreviation(int32_t* minutes,
|
||||
const char* abbr)
|
||||
{
|
||||
RtcTimeZone entry;
|
||||
|
||||
*minutes = 0;
|
||||
|
||||
size_t result = RtcTimeZone::BinarySearchProgmemTable(&entry,
|
||||
abbr,
|
||||
c_tzEn,
|
||||
countof(c_tzEn));
|
||||
|
||||
if (result)
|
||||
{
|
||||
// found
|
||||
*minutes = entry.offset;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
41
libraries/Rtc_by_Makuna/src/RtcLocaleEn.h
Normal file
41
libraries/Rtc_by_Makuna/src/RtcLocaleEn.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
RTC library
|
||||
|
||||
Written by Michael C. Miller.
|
||||
|
||||
I invest time and resources providing this open source code,
|
||||
please support me by dontating (see https://github.com/Makuna/Rtc)
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the Makuna/Rtc library.
|
||||
|
||||
Rtc is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Rtc is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with Rtc. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
class RtcLocaleEn
|
||||
{
|
||||
public:
|
||||
static uint8_t CharsToMonth(const char* monthChars, size_t count);
|
||||
|
||||
// TimeZoneMinutesFromAbbreviation
|
||||
// searches known table for the abbreviation and provides the minutes offset
|
||||
//
|
||||
// *minutes - [out] variable filled with the minutes offset
|
||||
// returns - the number of chars parsed, usually 3 or 4. 0 if not found
|
||||
static size_t TimeZoneMinutesFromAbbreviation(int32_t* minutes, const char* abbr);
|
||||
};
|
||||
|
||||
136
libraries/Rtc_by_Makuna/src/RtcLocaleEnUs.cpp
Normal file
136
libraries/Rtc_by_Makuna/src/RtcLocaleEnUs.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
RTC library
|
||||
|
||||
Written by Michael C. Miller.
|
||||
|
||||
I invest time and resources providing this open source code,
|
||||
please support me by dontating (see https://github.com/Makuna/Rtc)
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the Makuna/Rtc library.
|
||||
|
||||
Rtc is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Rtc is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with Rtc. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "RtcUtility.h"
|
||||
#include "RtcTimeZone.h"
|
||||
#include "RtcLocaleEnUs.h"
|
||||
|
||||
// due to how PROGMEM works, strings must be declared standalone
|
||||
//
|
||||
const char stringADT[] PROGMEM = "ADT";
|
||||
const char stringAKDT[] PROGMEM = "AKDT";
|
||||
const char stringAKST[] PROGMEM = "AKST";
|
||||
const char stringAST[] PROGMEM = "AST";
|
||||
const char stringCDT[] PROGMEM = "CDT";
|
||||
const char stringCST[] PROGMEM = "CST";
|
||||
const char stringEDT[] PROGMEM = "EDT";
|
||||
const char stringEST[] PROGMEM = "EST";
|
||||
const char stringGMT[] PROGMEM = "GMT";
|
||||
const char stringHDT[] PROGMEM = "HDT";
|
||||
const char stringHST[] PROGMEM = "HST";
|
||||
const char stringMDT[] PROGMEM = "MDT";
|
||||
const char stringMST[] PROGMEM = "MST";
|
||||
const char stringPDT[] PROGMEM = "PDT";
|
||||
const char stringPST[] PROGMEM = "PST";
|
||||
const char stringUTC[] PROGMEM = "UTC";
|
||||
|
||||
// collection in alphabetic order of abbreviation
|
||||
//
|
||||
const RtcTimeZone c_tzEnUs[] PROGMEM =
|
||||
{
|
||||
{ stringADT, -3 * 60 }, // Atlantic Daylight Time
|
||||
{ stringAKDT, -8 * 60 }, // Alaska Daylight Time
|
||||
{ stringAKST, -9 * 60 }, // Alaska Standard Time
|
||||
{ stringAST, -4 * 60 }, // Atlantic Standard Time
|
||||
{ stringCDT, -5 * 60 }, // Central Daylight Time
|
||||
{ stringCST, -6 * 60 }, // Central Standard Time
|
||||
{ stringEDT, -4 * 60 }, // Eastern Daylight Time
|
||||
{ stringEST, -5 * 60 }, // Eastern Standard Time
|
||||
{ stringGMT, 0 }, // Greenwich Mean Time
|
||||
{ stringHDT, -9 * 60 }, // Hawaii–Aleutian Daylight Time
|
||||
{ stringHST, -10 * 60 }, // Hawaii–Aleutian Standard Time
|
||||
{ stringMDT, -6 * 60 }, // Mountain Daylight Time
|
||||
{ stringMST, -7 * 60 }, // Mountain Standard Time
|
||||
{ stringPDT, -7 * 60 }, // Pacific Daylight Time
|
||||
{ stringPST, -8 * 60 }, // Pacific Standard Time
|
||||
{ stringUTC, 0 }, // Cordinated Universal Time
|
||||
};
|
||||
|
||||
uint8_t RtcLocaleEnUs::CharsToMonth(const char* monthChars, size_t count)
|
||||
{
|
||||
uint8_t month = 0;
|
||||
|
||||
// works for both standard abbreviations and full month names
|
||||
//
|
||||
if (count >= 3)
|
||||
{
|
||||
switch (tolower(monthChars[0]))
|
||||
{
|
||||
case 'j':
|
||||
if (tolower(monthChars[1]) == 'a')
|
||||
month = 1;
|
||||
else if (tolower(monthChars[2]) == 'n')
|
||||
month = 6;
|
||||
else
|
||||
month = 7;
|
||||
break;
|
||||
case 'f':
|
||||
month = 2;
|
||||
break;
|
||||
case 'a':
|
||||
month = tolower(monthChars[1]) == 'p' ? 4 : 8;
|
||||
break;
|
||||
case 'm':
|
||||
month = tolower(monthChars[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;
|
||||
}
|
||||
}
|
||||
return month;
|
||||
}
|
||||
|
||||
size_t RtcLocaleEnUs::TimeZoneMinutesFromAbbreviation(int32_t* minutes,
|
||||
const char* abbr)
|
||||
{
|
||||
RtcTimeZone entry;
|
||||
|
||||
*minutes = 0;
|
||||
|
||||
size_t result = RtcTimeZone::BinarySearchProgmemTable(&entry,
|
||||
abbr,
|
||||
c_tzEnUs,
|
||||
countof(c_tzEnUs));
|
||||
|
||||
if (result)
|
||||
{
|
||||
// found
|
||||
*minutes = entry.offset;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
41
libraries/Rtc_by_Makuna/src/RtcLocaleEnUs.h
Normal file
41
libraries/Rtc_by_Makuna/src/RtcLocaleEnUs.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
RTC library
|
||||
|
||||
Written by Michael C. Miller.
|
||||
|
||||
I invest time and resources providing this open source code,
|
||||
please support me by dontating (see https://github.com/Makuna/Rtc)
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the Makuna/Rtc library.
|
||||
|
||||
Rtc is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Rtc is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with Rtc. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
class RtcLocaleEnUs
|
||||
{
|
||||
public:
|
||||
static uint8_t CharsToMonth(const char* monthChars, size_t count);
|
||||
|
||||
// TimeZoneMinutesFromAbbreviation
|
||||
// searches known table for the abbreviation and provides the minutes offset
|
||||
//
|
||||
// *minutes - [out] variable filled with the minutes offset
|
||||
// returns - the number of chars parsed, usually 3 or 4. 0 if not found
|
||||
static size_t TimeZoneMinutesFromAbbreviation(int32_t* minutes, const char* abbr);
|
||||
};
|
||||
|
||||
424
libraries/Rtc_by_Makuna/src/RtcPCF8563.h
Normal file
424
libraries/Rtc_by_Makuna/src/RtcPCF8563.h
Normal file
@@ -0,0 +1,424 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
RTC library
|
||||
|
||||
Written by Michael C. Miller.
|
||||
|
||||
I invest time and resources providing this open source code,
|
||||
please support me by dontating (see https://github.com/Makuna/Rtc)
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the Makuna/Rtc library.
|
||||
|
||||
Rtc is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Rtc is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with Rtc. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "RtcUtility.h"
|
||||
#include "RtcDateTime.h"
|
||||
|
||||
|
||||
//I2C Slave Address
|
||||
const uint8_t PCF8563_ADDRESS = 0x51;
|
||||
|
||||
//PCF8563 Register Addresses
|
||||
const uint8_t PCF8563_REG_CONTROL = 0x00;
|
||||
const uint8_t PCF8563_REG_STATUS = 0x01;
|
||||
const uint8_t PCF8563_REG_TIMEDATE = 0x02;
|
||||
const uint8_t PCF8563_REG_INTEGRITY = 0x02;
|
||||
const uint8_t PCF8563_REG_ALARM = 0x09;
|
||||
const uint8_t PCF8563_REG_CLKOUT_CONTROL = 0x0D;
|
||||
const uint8_t PCF8563_REG_TIMER_CONTROL = 0x0E;
|
||||
const uint8_t PCF8563_REG_TIMER = 0x0F;
|
||||
|
||||
//PCF8563 Register Data Size if not just 1
|
||||
const size_t PCF8563_REG_TIMEDATE_SIZE = 7;
|
||||
const size_t PCF8563_REG_ALARM_SIZE = 4;
|
||||
|
||||
// PCF8563 Valid Register Bits (PCF8563_REG_INTEGRITY)
|
||||
const uint8_t PCF8563_INTEGRITY_VALID = 7;
|
||||
|
||||
// PCF8563 Control Register Bits (PCF8563_REG_CONTROL)
|
||||
const uint8_t PCF8563_CONTROL_CLOCK = 5;
|
||||
|
||||
// PCF8563 Status Register Bits (PCF8563_REG_STATUS)
|
||||
const uint8_t PCF8563_STATUS_TIE = 0; // timer interrupt enable
|
||||
const uint8_t PCF8563_STATUS_AIE = 1; // alarm interrupt enable
|
||||
const uint8_t PCF8563_STATUS_TF = 2; // timer flag
|
||||
const uint8_t PCF8563_STATUS_AF = 3; // alarm flag
|
||||
const uint8_t PCF8563_STATUS_TITP = 4; // timer interrupt period config
|
||||
|
||||
|
||||
enum PCF8563SquareWavePinMode
|
||||
{
|
||||
PCF8563SquareWavePinMode_None = 0b00000000,
|
||||
PCF8563SquareWavePinMode_32kHz = 0b10000000,
|
||||
PCF8563SquareWavePinMode_1kHz = 0b10000001,
|
||||
PCF8563SquareWavePinMode_32Hz = 0b10000010,
|
||||
PCF8563SquareWavePinMode_1Hz = 0b10000011
|
||||
};
|
||||
|
||||
// defines the timer period for the timer and
|
||||
// when to trigger, minutes means at the top of the minute
|
||||
// and period of 60 seconds
|
||||
//
|
||||
enum PCF8563TimerMode
|
||||
{
|
||||
PCF8563TimerMode_None = 0b00000000,
|
||||
PCF8563TimerMode_4096thOfASecond = 0b10000000,
|
||||
PCF8563TimerMode_64thOfASecond = 0b10000001,
|
||||
PCF8563TimerMode_Seconds = 0b10000010,
|
||||
PCF8563TimerMode_Minutes = 0b10000011 // at the top of and by
|
||||
};
|
||||
|
||||
enum PCF8563AlarmControlFlags
|
||||
{
|
||||
PCF8563AlarmControl_MinuteMatch = 0x01,
|
||||
PCF8563AlarmControl_HourMatch = 0x02,
|
||||
PCF8563AlarmControl_DayOfMonthMatch = 0x04,
|
||||
PCF8563AlarmControl_DayOfWeekMatch = 0x08
|
||||
};
|
||||
|
||||
class PCF8563Alarm
|
||||
{
|
||||
public:
|
||||
PCF8563Alarm(uint8_t dayOfMonth,
|
||||
uint8_t hour,
|
||||
uint8_t minute,
|
||||
uint8_t dayOfWeek,
|
||||
uint8_t controlFlags) :
|
||||
_flags(controlFlags),
|
||||
_dayOfMonth(dayOfMonth),
|
||||
_hour(hour),
|
||||
_minute(minute),
|
||||
_dayOfWeek(dayOfWeek)
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t DayOfMonth() const
|
||||
{
|
||||
return _dayOfMonth;
|
||||
}
|
||||
|
||||
uint8_t Hour() const
|
||||
{
|
||||
return _hour;
|
||||
}
|
||||
|
||||
uint8_t Minute() const
|
||||
{
|
||||
return _minute;
|
||||
}
|
||||
|
||||
uint8_t DayOfWeek() const
|
||||
{
|
||||
return _dayOfWeek;
|
||||
}
|
||||
|
||||
uint8_t ControlFlags() const
|
||||
{
|
||||
return _flags;
|
||||
}
|
||||
|
||||
bool operator == (const PCF8563Alarm& other) const
|
||||
{
|
||||
return (_dayOfMonth == other._dayOfMonth &&
|
||||
_hour == other._hour &&
|
||||
_minute == other._minute &&
|
||||
_dayOfWeek == other._dayOfWeek &&
|
||||
_flags == other._flags);
|
||||
}
|
||||
|
||||
bool operator != (const PCF8563Alarm& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t _flags;
|
||||
|
||||
uint8_t _dayOfMonth;
|
||||
uint8_t _hour;
|
||||
uint8_t _minute;
|
||||
uint8_t _dayOfWeek;
|
||||
};
|
||||
|
||||
template<class T_WIRE_METHOD> class RtcPCF8563
|
||||
{
|
||||
public:
|
||||
RtcPCF8563(T_WIRE_METHOD& wire) :
|
||||
_wire(wire),
|
||||
_lastError(Rtc_Wire_Error_None)
|
||||
{
|
||||
}
|
||||
|
||||
void Begin()
|
||||
{
|
||||
_wire.begin();
|
||||
}
|
||||
|
||||
void Begin(int sda, int scl)
|
||||
{
|
||||
_wire.begin(sda, scl);
|
||||
}
|
||||
|
||||
uint8_t LastError()
|
||||
{
|
||||
return _lastError;
|
||||
}
|
||||
|
||||
bool IsDateTimeValid()
|
||||
{
|
||||
uint8_t status = getReg(PCF8563_REG_INTEGRITY);
|
||||
return (!(status & _BV(PCF8563_INTEGRITY_VALID)) && (_lastError == Rtc_Wire_Error_None));
|
||||
}
|
||||
|
||||
bool GetIsRunning()
|
||||
{
|
||||
uint8_t creg = getReg(PCF8563_REG_CONTROL);
|
||||
return (!(creg & _BV(PCF8563_CONTROL_CLOCK)) && (_lastError == Rtc_Wire_Error_None));
|
||||
}
|
||||
|
||||
void SetIsRunning(bool isRunning)
|
||||
{
|
||||
uint8_t creg = getReg(PCF8563_REG_CONTROL);
|
||||
if (isRunning)
|
||||
{
|
||||
creg &= ~_BV(PCF8563_CONTROL_CLOCK);
|
||||
}
|
||||
else
|
||||
{
|
||||
creg |= _BV(PCF8563_CONTROL_CLOCK);
|
||||
}
|
||||
setReg(PCF8563_REG_CONTROL, creg);
|
||||
}
|
||||
|
||||
void SetDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
// the invalid flag is part of seconds,
|
||||
// so is automatically cleared when it is set
|
||||
|
||||
// set the date time
|
||||
_wire.beginTransmission(PCF8563_ADDRESS);
|
||||
_wire.write(PCF8563_REG_TIMEDATE);
|
||||
|
||||
_wire.write(Uint8ToBcd(dt.Second()));
|
||||
_wire.write(Uint8ToBcd(dt.Minute()));
|
||||
_wire.write(Uint8ToBcd(dt.Hour())); // 24 hour mode only
|
||||
_wire.write(Uint8ToBcd(dt.Day()));
|
||||
// RTC Hardware Day of Week is the same as RtcDateTime
|
||||
_wire.write(dt.DayOfWeek());
|
||||
|
||||
uint8_t year = dt.Year() - 2000;
|
||||
uint8_t centuryFlag = 0;
|
||||
|
||||
if (year >= 100)
|
||||
{
|
||||
year -= 100;
|
||||
centuryFlag = _BV(7);
|
||||
}
|
||||
|
||||
_wire.write(Uint8ToBcd(dt.Month()) | centuryFlag);
|
||||
_wire.write(Uint8ToBcd(year));
|
||||
|
||||
_lastError = _wire.endTransmission();
|
||||
}
|
||||
|
||||
RtcDateTime GetDateTime()
|
||||
{
|
||||
_wire.beginTransmission(PCF8563_ADDRESS);
|
||||
_wire.write(PCF8563_REG_TIMEDATE);
|
||||
_lastError = _wire.endTransmission();
|
||||
if (_lastError != Rtc_Wire_Error_None)
|
||||
{
|
||||
return RtcDateTime(0);
|
||||
}
|
||||
|
||||
size_t bytesRead = _wire.requestFrom(PCF8563_ADDRESS, PCF8563_REG_TIMEDATE_SIZE);
|
||||
if (PCF8563_REG_TIMEDATE_SIZE != bytesRead)
|
||||
{
|
||||
_lastError = Rtc_Wire_Error_Unspecific;
|
||||
return RtcDateTime(0);
|
||||
}
|
||||
|
||||
uint8_t second = BcdToUint8(_wire.read() & 0x7F);
|
||||
uint8_t minute = BcdToUint8(_wire.read());
|
||||
uint8_t hour = BcdToBin24Hour(_wire.read());
|
||||
uint8_t dayOfMonth = BcdToUint8(_wire.read());
|
||||
_wire.read(); // throwing away day of week as we calculate it
|
||||
uint8_t monthRaw = _wire.read();
|
||||
uint16_t year = BcdToUint8(_wire.read()) + 2000;
|
||||
|
||||
if (monthRaw & _BV(7)) // century wrap flag
|
||||
{
|
||||
year += 100;
|
||||
}
|
||||
uint8_t month = BcdToUint8(monthRaw & 0x7f);
|
||||
|
||||
|
||||
return RtcDateTime(year, month, dayOfMonth, hour, minute, second);
|
||||
}
|
||||
|
||||
void SetSquareWavePin(PCF8563SquareWavePinMode pinMode)
|
||||
{
|
||||
setReg(PCF8563_REG_CLKOUT_CONTROL, pinMode);
|
||||
}
|
||||
|
||||
void SetAlarm(const PCF8563Alarm& alarm)
|
||||
{
|
||||
_wire.beginTransmission(PCF8563_ADDRESS);
|
||||
_wire.write(PCF8563_REG_ALARM);
|
||||
|
||||
uint8_t matchFlag = (alarm.ControlFlags() & PCF8563AlarmControl_MinuteMatch) ? 0x00 : 0x80;
|
||||
_wire.write(Uint8ToBcd(alarm.Minute()) | matchFlag);
|
||||
|
||||
matchFlag = (alarm.ControlFlags() & PCF8563AlarmControl_HourMatch) ? 0x00 : 0x80;
|
||||
_wire.write(Uint8ToBcd(alarm.Hour()) | matchFlag); // 24 hour mode only
|
||||
|
||||
matchFlag = (alarm.ControlFlags() & PCF8563AlarmControl_DayOfMonthMatch) ? 0x00 : 0x80;
|
||||
_wire.write(Uint8ToBcd(alarm.DayOfMonth()) | matchFlag);
|
||||
|
||||
matchFlag = (alarm.ControlFlags() & PCF8563AlarmControl_DayOfWeekMatch) ? 0x00 : 0x80;
|
||||
_wire.write(Uint8ToBcd(alarm.DayOfWeek()) | matchFlag);
|
||||
|
||||
_lastError = _wire.endTransmission();
|
||||
|
||||
if (_lastError == Rtc_Wire_Error_None)
|
||||
{
|
||||
// enable alarm
|
||||
uint8_t sreg = getReg(PCF8563_REG_STATUS);
|
||||
sreg &= ~_BV(PCF8563_STATUS_AF);
|
||||
sreg |= _BV(PCF8563_STATUS_AIE);
|
||||
setReg(PCF8563_REG_STATUS, sreg);
|
||||
}
|
||||
}
|
||||
|
||||
void StopAlarm()
|
||||
{
|
||||
uint8_t sreg = getReg(PCF8563_REG_STATUS);
|
||||
sreg &= ~(_BV(PCF8563_STATUS_AIE) | _BV(PCF8563_STATUS_AF));
|
||||
setReg(PCF8563_REG_STATUS, sreg);
|
||||
}
|
||||
|
||||
void SetTimer(PCF8563TimerMode mode, uint8_t time)
|
||||
{
|
||||
_wire.beginTransmission(PCF8563_ADDRESS);
|
||||
_wire.write(PCF8563_REG_TIMER_CONTROL);
|
||||
|
||||
_wire.write(mode);
|
||||
_wire.write(time);
|
||||
|
||||
_lastError = _wire.endTransmission();
|
||||
|
||||
if (_lastError == Rtc_Wire_Error_None)
|
||||
{
|
||||
// enable timer
|
||||
uint8_t sreg = getReg(PCF8563_REG_STATUS);
|
||||
sreg &= ~_BV(PCF8563_STATUS_TF);
|
||||
sreg |= _BV(PCF8563_STATUS_TIE) | _BV(PCF8563_STATUS_TITP);
|
||||
setReg(PCF8563_REG_STATUS, sreg);
|
||||
}
|
||||
}
|
||||
|
||||
void StopTimer()
|
||||
{
|
||||
uint8_t sreg = getReg(PCF8563_REG_STATUS);
|
||||
sreg &= ~_BV(PCF8563_STATUS_TF);
|
||||
sreg &= ~(_BV(PCF8563_STATUS_TIE) | _BV(PCF8563_STATUS_TITP));
|
||||
setReg(PCF8563_REG_STATUS, sreg);
|
||||
|
||||
if (_lastError == Rtc_Wire_Error_None)
|
||||
{
|
||||
setReg(PCF8563_REG_TIMER_CONTROL, PCF8563TimerMode_None);
|
||||
}
|
||||
}
|
||||
|
||||
// Latch must be called after an alarm otherwise it will not
|
||||
// trigger again?
|
||||
bool LatchAlarmTriggeredFlag()
|
||||
{
|
||||
uint8_t sreg = getReg(PCF8563_REG_STATUS);
|
||||
bool triggered = false;
|
||||
if (sreg & _BV(PCF8563_STATUS_AF))
|
||||
{
|
||||
triggered = true;
|
||||
sreg &= ~_BV(PCF8563_STATUS_AF);
|
||||
setReg(PCF8563_REG_STATUS, sreg);
|
||||
}
|
||||
return triggered;
|
||||
}
|
||||
|
||||
bool LatchTimerTriggeredFlag()
|
||||
{
|
||||
uint8_t sreg = getReg(PCF8563_REG_STATUS);
|
||||
bool triggered = false;
|
||||
if (sreg & _BV(PCF8563_STATUS_TF))
|
||||
{
|
||||
triggered = true;
|
||||
sreg &= ~_BV(PCF8563_STATUS_TF);
|
||||
setReg(PCF8563_REG_STATUS, sreg);
|
||||
}
|
||||
return triggered;
|
||||
}
|
||||
|
||||
bool GetAlarmTriggered()
|
||||
{
|
||||
uint8_t sreg = getReg(PCF8563_REG_STATUS);
|
||||
return (sreg & _BV(PCF8563_STATUS_AF));
|
||||
}
|
||||
|
||||
bool GetTimerTriggered()
|
||||
{
|
||||
uint8_t sreg = getReg(PCF8563_REG_STATUS);
|
||||
return (sreg & _BV(PCF8563_STATUS_TF));
|
||||
}
|
||||
|
||||
private:
|
||||
T_WIRE_METHOD& _wire;
|
||||
uint8_t _lastError;
|
||||
|
||||
uint8_t getReg(uint8_t regAddress)
|
||||
{
|
||||
_wire.beginTransmission(PCF8563_ADDRESS);
|
||||
_wire.write(regAddress);
|
||||
_lastError = _wire.endTransmission();
|
||||
if (_lastError != Rtc_Wire_Error_None)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// control register
|
||||
size_t bytesRead = _wire.requestFrom(PCF8563_ADDRESS, (uint8_t)1);
|
||||
if (1 != bytesRead)
|
||||
{
|
||||
_lastError = Rtc_Wire_Error_Unspecific;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t regValue = _wire.read();
|
||||
return regValue;
|
||||
}
|
||||
|
||||
void setReg(uint8_t regAddress, uint8_t regValue)
|
||||
{
|
||||
_wire.beginTransmission(PCF8563_ADDRESS);
|
||||
_wire.write(regAddress);
|
||||
_wire.write(regValue);
|
||||
_lastError = _wire.endTransmission();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
174
libraries/Rtc_by_Makuna/src/RtcTemperature.h
Normal file
174
libraries/Rtc_by_Makuna/src/RtcTemperature.h
Normal file
@@ -0,0 +1,174 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
RTC library
|
||||
|
||||
Written by Michael C. Miller.
|
||||
|
||||
I invest time and resources providing this open source code,
|
||||
please support me by dontating (see https://github.com/Makuna/Rtc)
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the Makuna/Rtc library.
|
||||
|
||||
Rtc is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Rtc is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with Rtc. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
class RtcTemperature
|
||||
{
|
||||
public:
|
||||
// Constructor
|
||||
// a) Merge RTC registers into signed scaled temperature (x256),
|
||||
// then bind to RTC resolution.
|
||||
// | r11h | DP | r12h |
|
||||
// Bit: 15 14 13 12 11 10 9 8 . 7 6 5 4 3 2 1 0 -1 -2
|
||||
// s i i i i i i i . f f 0 0 0 0 0 0
|
||||
//
|
||||
// b) Rescale to (x4) by right-shifting (6) bits
|
||||
// | | DP | |
|
||||
// Bit: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 . 1 0 -1 -2
|
||||
// s s s s s s s i i i i i i i f f 0 0
|
||||
RtcTemperature(int8_t highByteDegreesC, uint8_t lowByteDegreesC)
|
||||
{
|
||||
int16_t scaledDegC = ((highByteDegreesC << 8) | (lowByteDegreesC & 0xC0)) >> 6;
|
||||
_centiDegC = scaledDegC * 100 / 4;
|
||||
}
|
||||
|
||||
RtcTemperature(int16_t centiDegC = 0) :
|
||||
_centiDegC(centiDegC)
|
||||
{
|
||||
}
|
||||
|
||||
// Float temperature Celsius
|
||||
float AsFloatDegC()
|
||||
{
|
||||
return (float)_centiDegC / 100.0f;
|
||||
}
|
||||
|
||||
// Float temperature Fahrenheit
|
||||
float AsFloatDegF()
|
||||
{
|
||||
return AsFloatDegC() * 1.8f + 32.0f;
|
||||
}
|
||||
|
||||
// centi degrees (1/100th of a degree),
|
||||
int16_t AsCentiDegC()
|
||||
{
|
||||
return _centiDegC;
|
||||
}
|
||||
|
||||
void Print(Stream& target, uint8_t decimals = 2, char decimal = '.')
|
||||
{
|
||||
int16_t decimalDivisor = 1;
|
||||
int16_t integerPart;
|
||||
int16_t decimalPart;
|
||||
|
||||
{
|
||||
int16_t rounded = abs(_centiDegC);
|
||||
// round up as needed
|
||||
if (decimals == 0)
|
||||
{
|
||||
rounded += 50;
|
||||
}
|
||||
else if (decimals == 1)
|
||||
{
|
||||
rounded += 5;
|
||||
decimalDivisor = 10;
|
||||
}
|
||||
|
||||
integerPart = rounded / 100;
|
||||
decimalPart = (rounded % 100) / decimalDivisor;
|
||||
}
|
||||
|
||||
// test for zero before printing negative sign to not print-0.00
|
||||
if (_centiDegC < 0 && (integerPart != 0 || decimalPart != 0))
|
||||
{
|
||||
target.print('-');
|
||||
}
|
||||
|
||||
// print integer part
|
||||
target.print(integerPart);
|
||||
|
||||
// print decimal part
|
||||
if (decimals != 0)
|
||||
{
|
||||
target.print(decimal);
|
||||
|
||||
if (decimalPart != 0)
|
||||
{
|
||||
target.print(decimalPart);
|
||||
}
|
||||
else
|
||||
{
|
||||
// append zeros as requested
|
||||
while (decimals > 0)
|
||||
{
|
||||
target.print('0');
|
||||
decimals--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const RtcTemperature& other) const
|
||||
{
|
||||
return (_centiDegC == other._centiDegC);
|
||||
};
|
||||
|
||||
bool operator>(const RtcTemperature& other) const
|
||||
{
|
||||
return (_centiDegC > other._centiDegC);
|
||||
};
|
||||
|
||||
bool operator<(const RtcTemperature& other) const
|
||||
{
|
||||
return (_centiDegC < other._centiDegC);
|
||||
};
|
||||
|
||||
bool operator>=(const RtcTemperature& other) const
|
||||
{
|
||||
return (_centiDegC >= other._centiDegC);
|
||||
};
|
||||
|
||||
bool operator<=(const RtcTemperature& other) const
|
||||
{
|
||||
return (_centiDegC <= other._centiDegC);
|
||||
};
|
||||
|
||||
bool operator!=(const RtcTemperature& other) const
|
||||
{
|
||||
return (_centiDegC != other._centiDegC);
|
||||
};
|
||||
|
||||
RtcTemperature operator-(const RtcTemperature& right)
|
||||
{
|
||||
RtcTemperature result;
|
||||
|
||||
result._centiDegC = (_centiDegC - right._centiDegC);
|
||||
return result;
|
||||
}
|
||||
|
||||
RtcTemperature operator+(const RtcTemperature& right)
|
||||
{
|
||||
RtcTemperature result;
|
||||
|
||||
result._centiDegC = (_centiDegC + right._centiDegC);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected:
|
||||
int16_t _centiDegC; // 1/100th of a degree temperature (100 x degC)
|
||||
};
|
||||
113
libraries/Rtc_by_Makuna/src/RtcTimeZone.h
Normal file
113
libraries/Rtc_by_Makuna/src/RtcTimeZone.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
RTC library
|
||||
|
||||
Written by Michael C. Miller.
|
||||
|
||||
I invest time and resources providing this open source code,
|
||||
please support me by dontating (see https://github.com/Makuna/Rtc)
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the Makuna/Rtc library.
|
||||
|
||||
Rtc is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Rtc is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with Rtc. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
struct RtcTimeZone
|
||||
{
|
||||
const char* abbr; // progmem
|
||||
int32_t offset;
|
||||
|
||||
// searches the given table for the abbr match
|
||||
// result - the found entry
|
||||
// abbrSearch - the abbreviation to search for
|
||||
// table - the PROGMEM table of RtcTimeZone in alphabetical order
|
||||
// count - the number of entries in the table
|
||||
// returns: 0 for not found, strlen of abbr if found
|
||||
//
|
||||
static size_t BinarySearchProgmemTable(RtcTimeZone* result,
|
||||
const char* abbrSearch,
|
||||
const RtcTimeZone* table,
|
||||
size_t countTable)
|
||||
{
|
||||
size_t indexFront = 0;
|
||||
size_t indexEnd = countTable;
|
||||
size_t index = countTable / 2;
|
||||
|
||||
// binary search
|
||||
//
|
||||
while (indexFront < indexEnd)
|
||||
{
|
||||
RtcTimeZone entry;
|
||||
|
||||
// copy the entry from progmem
|
||||
// string members still reside in PROGMEM though
|
||||
memcpy_P(&entry, table + index, sizeof(RtcTimeZone));
|
||||
|
||||
auto match = strncmp_P(abbrSearch, entry.abbr, 4);
|
||||
|
||||
if (0 == match)
|
||||
{
|
||||
// found
|
||||
*result = entry;
|
||||
return strlen_P(entry.abbr);
|
||||
}
|
||||
else if (match < 0)
|
||||
{
|
||||
indexEnd = index;
|
||||
}
|
||||
else
|
||||
{
|
||||
indexFront = index + 1;
|
||||
}
|
||||
|
||||
// pick one between the front and end
|
||||
index = (indexEnd - indexFront) / 2 + indexFront;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// searches the given table for the abbr match
|
||||
// result - the found entry
|
||||
// abbrSearch - the abbreviation to search for
|
||||
// table - the PROGMEM table of RtcTimeZone to search
|
||||
// count - the number of entries in the table
|
||||
// returns: 0 for not found, strlen of abbr if found
|
||||
//
|
||||
static size_t LinearSearchProgmemTable(RtcTimeZone* result,
|
||||
const char* abbrSearch,
|
||||
const RtcTimeZone* table,
|
||||
size_t countTable)
|
||||
{
|
||||
for (size_t index = 0; index < countTable; index++)
|
||||
{
|
||||
RtcTimeZone entry;
|
||||
|
||||
// copy the entry from progmem
|
||||
// string members still reside in PROGMEM though
|
||||
memcpy_P(&entry, table + index, sizeof(RtcTimeZone));
|
||||
|
||||
if (0 == strncmp_P(abbrSearch, entry.abbr, 4))
|
||||
{
|
||||
*result = entry;
|
||||
return strlen_P(entry.abbr);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
59
libraries/Rtc_by_Makuna/src/RtcUtility.cpp
Normal file
59
libraries/Rtc_by_Makuna/src/RtcUtility.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
RTC library
|
||||
|
||||
Written by Michael C. Miller.
|
||||
|
||||
I invest time and resources providing this open source code,
|
||||
please support me by dontating (see https://github.com/Makuna/Rtc)
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the Makuna/Rtc library.
|
||||
|
||||
Rtc is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Rtc is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with Rtc. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "RtcUtility.h"
|
||||
|
||||
uint8_t BcdToUint8(uint8_t val)
|
||||
{
|
||||
return val - 6 * (val >> 4);
|
||||
}
|
||||
|
||||
uint8_t Uint8ToBcd(uint8_t val)
|
||||
{
|
||||
return val + 6 * (val / 10);
|
||||
}
|
||||
|
||||
uint8_t BcdToBin24Hour(uint8_t bcdHour)
|
||||
{
|
||||
uint8_t hour;
|
||||
if (bcdHour & 0x40)
|
||||
{
|
||||
// 12 hour mode, convert to 24
|
||||
bool isPm = ((bcdHour & 0x20) != 0);
|
||||
|
||||
hour = BcdToUint8(bcdHour & 0x1f);
|
||||
if (isPm)
|
||||
{
|
||||
hour += 12;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hour = BcdToUint8(bcdHour);
|
||||
}
|
||||
return hour;
|
||||
}
|
||||
87
libraries/Rtc_by_Makuna/src/RtcUtility.h
Normal file
87
libraries/Rtc_by_Makuna/src/RtcUtility.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
RTC library
|
||||
|
||||
Written by Michael C. Miller.
|
||||
|
||||
I invest time and resources providing this open source code,
|
||||
please support me by dontating (see https://github.com/Makuna/Rtc)
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the Makuna/Rtc library.
|
||||
|
||||
Rtc is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Rtc is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with Rtc. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// ESP32 complains if not included
|
||||
#if defined(ARDUINO_ARCH_ESP32)
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#if !defined(countof)
|
||||
#define countof(a) (sizeof(a) / sizeof(a[0]))
|
||||
#endif
|
||||
|
||||
// Arduino has no standard for attributing methods used for ISRs
|
||||
// even though some platforms require it, so to simplify the problem
|
||||
// for end users, this provides a standard ISR_ATTR
|
||||
#if !defined(ISR_ATTR)
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP8266)
|
||||
#define ISR_ATTR ICACHE_RAM_ATTR
|
||||
#elif defined(ARDUINO_ARCH_ESP32)
|
||||
#define ISR_ATTR ICACHE_RAM_ATTR
|
||||
#else
|
||||
#define ISR_ATTR
|
||||
#endif
|
||||
|
||||
#endif // !defined(ISR_ATTR)
|
||||
|
||||
// some platforms do not come with STL or properly defined one, specifically functional
|
||||
// if you see...
|
||||
// undefined reference to `std::__throw_bad_function_call()'
|
||||
// ...then you can either add the platform symbol to the list so RTC_NO_STL gets defined or
|
||||
// go to boards.txt and enable c++ by adding (teensy31.build.flags.libs=-lstdc++) and set to "smallest code" option in Arduino
|
||||
//
|
||||
#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR) || defined(STM32L432xx) || defined(STM32L476xx) || defined(ARDUINO_ARCH_SAM)
|
||||
#define RTC_NO_STL 1
|
||||
#endif
|
||||
|
||||
// While WIRE has return codes, there is no standard definition of what they are
|
||||
// within any headers; they are only documented on the website here
|
||||
// https://www.arduino.cc/reference/en/language/functions/communication/wire/endtransmission/
|
||||
// So we define our own "standard" for this RTC library that match those
|
||||
//
|
||||
enum Rtc_Wire_Error
|
||||
{
|
||||
Rtc_Wire_Error_None = 0,
|
||||
Rtc_Wire_Error_TxBufferOverflow,
|
||||
Rtc_Wire_Error_NoAddressableDevice,
|
||||
Rtc_Wire_Error_UnsupportedRequest,
|
||||
Rtc_Wire_Error_Unspecific,
|
||||
Rtc_Wire_Error_CommunicationTimeout
|
||||
};
|
||||
|
||||
// for some reason, the DUE board support does not define this, even though other non AVR archs do
|
||||
#ifndef _BV
|
||||
#define _BV(b) (1UL << (b))
|
||||
#endif
|
||||
|
||||
extern uint8_t BcdToUint8(uint8_t val);
|
||||
extern uint8_t Uint8ToBcd(uint8_t val);
|
||||
extern uint8_t BcdToBin24Hour(uint8_t bcdHour);
|
||||
|
||||
|
||||
127
libraries/Rtc_by_Makuna/src/ThreeWire.h
Normal file
127
libraries/Rtc_by_Makuna/src/ThreeWire.h
Normal file
@@ -0,0 +1,127 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
RTC library
|
||||
|
||||
Written by Michael C. Miller.
|
||||
|
||||
I invest time and resources providing this open source code,
|
||||
please support me by dontating (see https://github.com/Makuna/Rtc)
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
This file is part of the Makuna/Rtc library.
|
||||
|
||||
Rtc is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Rtc is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with Rtc. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
//ThreeWire command Read/Write flag
|
||||
const uint8_t THREEWIRE_READFLAG = 0x01;
|
||||
|
||||
class ThreeWire
|
||||
{
|
||||
public:
|
||||
ThreeWire(uint8_t ioPin, uint8_t clkPin, uint8_t cePin) :
|
||||
_ioPin(ioPin),
|
||||
_clkPin(clkPin),
|
||||
_cePin(cePin)
|
||||
{
|
||||
}
|
||||
|
||||
void begin() {
|
||||
resetPins();
|
||||
}
|
||||
|
||||
void end() {
|
||||
resetPins();
|
||||
}
|
||||
|
||||
void beginTransmission(uint8_t command) {
|
||||
digitalWrite(_cePin, LOW); // default, not enabled
|
||||
pinMode(_cePin, OUTPUT);
|
||||
|
||||
digitalWrite(_clkPin, LOW); // default, clock low
|
||||
pinMode(_clkPin, OUTPUT);
|
||||
|
||||
pinMode(_ioPin, OUTPUT);
|
||||
|
||||
digitalWrite(_cePin, HIGH); // start the session
|
||||
delayMicroseconds(4); // tCC = 4us
|
||||
|
||||
write(command, (command & THREEWIRE_READFLAG) == THREEWIRE_READFLAG);
|
||||
}
|
||||
|
||||
void endTransmission() {
|
||||
digitalWrite(_cePin, LOW);
|
||||
delayMicroseconds(4); // tCWH = 4us
|
||||
}
|
||||
|
||||
void write(uint8_t value, bool isDataRequestCommand = false) {
|
||||
for (uint8_t bit = 0; bit < 8; bit++) {
|
||||
digitalWrite(_ioPin, value & 0x01);
|
||||
delayMicroseconds(1); // tDC = 200ns
|
||||
|
||||
// clock up, data is read by DS1302
|
||||
digitalWrite(_clkPin, HIGH);
|
||||
delayMicroseconds(1); // tCH = 1000ns, tCDH = 800ns
|
||||
|
||||
// for the last bit before a read
|
||||
// Set IO line for input before the clock down
|
||||
if (bit == 7 && isDataRequestCommand) {
|
||||
pinMode(_ioPin, INPUT);
|
||||
}
|
||||
|
||||
digitalWrite(_clkPin, LOW);
|
||||
delayMicroseconds(1); // tCL=1000ns, tCDD=800ns
|
||||
|
||||
value >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t read() {
|
||||
uint8_t value = 0;
|
||||
|
||||
for (uint8_t bit = 0; bit < 8; bit++) {
|
||||
// first bit is present on io pin, so only clock the other
|
||||
// bits
|
||||
value |= (digitalRead(_ioPin) << bit);
|
||||
|
||||
// Clock up, prepare for next
|
||||
digitalWrite(_clkPin, HIGH);
|
||||
delayMicroseconds(1);
|
||||
|
||||
// Clock down, value is ready after some time.
|
||||
digitalWrite(_clkPin, LOW);
|
||||
delayMicroseconds(1); // tCL=1000ns, tCDD=800ns
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private:
|
||||
const uint8_t _ioPin;
|
||||
const uint8_t _clkPin;
|
||||
const uint8_t _cePin;
|
||||
|
||||
void resetPins() {
|
||||
// just making sure they are in a default low power use state
|
||||
// as required state is set when transmissions are started
|
||||
// three wire devices have internal pull downs so they will be low
|
||||
pinMode(_clkPin, INPUT);
|
||||
pinMode(_ioPin, INPUT);
|
||||
pinMode(_cePin, INPUT);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user