初始化提交
This commit is contained in:
165
arduino-cli/libraries/Rtc_by_Makuna/COPYING
Normal file
165
arduino-cli/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.
|
||||
22
arduino-cli/libraries/Rtc_by_Makuna/README.md
Normal file
22
arduino-cli/libraries/Rtc_by_Makuna/README.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# 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 jump on Gitter and ask away.
|
||||
[](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
arduino-cli/libraries/Rtc_by_Makuna/SUPPORT.md
Normal file
8
arduino-cli/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,135 @@
|
||||
|
||||
// CONNECTIONS:
|
||||
// DS1302 CLK/SCLK --> 5
|
||||
// DS1302 DAT/IO --> 4
|
||||
// DS1302 RST/CE --> 2
|
||||
// DS1302 VCC --> 3.3v - 5v
|
||||
// DS1302 GND --> GND
|
||||
|
||||
#include <ThreeWire.h>
|
||||
#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[20];
|
||||
|
||||
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,101 @@
|
||||
|
||||
// CONNECTIONS:
|
||||
// DS1302 CLK/SCLK --> 5
|
||||
// DS1302 DAT/IO --> 4
|
||||
// DS1302 RST/CE --> 2
|
||||
// DS1302 VCC --> 3.3v - 5v
|
||||
// DS1302 GND --> GND
|
||||
|
||||
#include <ThreeWire.h>
|
||||
#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[20];
|
||||
|
||||
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,172 @@
|
||||
|
||||
// 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 */
|
||||
|
||||
|
||||
const char data[] = "what time is it";
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(57600);
|
||||
|
||||
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();
|
||||
|
||||
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
|
||||
printDateTime(compiled);
|
||||
Serial.println();
|
||||
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (Rtc.LastError() != 0)
|
||||
{
|
||||
// we have a communications error
|
||||
// see https://www.arduino.cc/en/Reference/WireEndTransmission for
|
||||
// what the number means
|
||||
Serial.print("RTC communications error = ");
|
||||
Serial.println(Rtc.LastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
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(DS1307SquareWaveOut_Low);
|
||||
|
||||
/* 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);
|
||||
uint8_t written = Rtc.SetMemory(13, (const uint8_t*)data, sizeof(data) - 1); // remove the null terminator strings add
|
||||
Rtc.SetMemory(1, written);
|
||||
/* end of comment out section */
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (Rtc.LastError() != 0)
|
||||
{
|
||||
// we have a communications error
|
||||
// see https://www.arduino.cc/en/Reference/WireEndTransmission for
|
||||
// what the number means
|
||||
Serial.print("RTC communications error = ");
|
||||
Serial.println(Rtc.LastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void printDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
char datestring[20];
|
||||
|
||||
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,137 @@
|
||||
|
||||
// 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 */
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(57600);
|
||||
|
||||
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();
|
||||
|
||||
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
|
||||
printDateTime(compiled);
|
||||
Serial.println();
|
||||
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (Rtc.LastError() != 0)
|
||||
{
|
||||
// we have a communications error
|
||||
// see https://www.arduino.cc/en/Reference/WireEndTransmission for
|
||||
// what the number means
|
||||
Serial.print("RTC communications error = ");
|
||||
Serial.println(Rtc.LastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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.SetSquareWavePin(DS1307SquareWaveOut_Low);
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (Rtc.LastError() != 0)
|
||||
{
|
||||
// we have a communications error
|
||||
// see https://www.arduino.cc/en/Reference/WireEndTransmission for
|
||||
// what the number means
|
||||
Serial.print("RTC communications error = ");
|
||||
Serial.println(Rtc.LastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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(10000); // ten seconds
|
||||
}
|
||||
|
||||
#define countof(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
void printDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
char datestring[20];
|
||||
|
||||
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,207 @@
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(57600);
|
||||
|
||||
// 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();
|
||||
|
||||
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
|
||||
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (Rtc.LastError() != 0)
|
||||
{
|
||||
// we have a communications error
|
||||
// see https://www.arduino.cc/en/Reference/WireEndTransmission for
|
||||
// what the number means
|
||||
Serial.print("RTC communications error = ");
|
||||
Serial.println(Rtc.LastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
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(DS3231SquareWavePin_ModeAlarmBoth);
|
||||
|
||||
// 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);
|
||||
|
||||
// Alarm 2 set to trigger at the top of the minute
|
||||
DS3231AlarmTwo alarm2(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
DS3231AlarmTwoControl_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())
|
||||
{
|
||||
if (Rtc.LastError() != 0)
|
||||
{
|
||||
// we have a communications error
|
||||
// see https://www.arduino.cc/en/Reference/WireEndTransmission for
|
||||
// what the number means
|
||||
Serial.print("RTC communications error = ");
|
||||
Serial.println(Rtc.LastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
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
|
||||
DS3231AlarmFlag flag = Rtc.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[20];
|
||||
|
||||
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,197 @@
|
||||
|
||||
// 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 <RtcDS3231.h>
|
||||
#include <EepromAT24C32.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 <RtcDS3231.h>
|
||||
#include <EepromAT24C32.h>
|
||||
|
||||
RtcDS3231<TwoWire> Rtc(Wire);
|
||||
EepromAt24c32<TwoWire> RtcEeprom(Wire);
|
||||
|
||||
// if you have any of the address pins on the RTC soldered together
|
||||
// then you need to provide the state of those pins, 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
|
||||
const char data[] = "What time is it in Greenwich?";
|
||||
const uint16_t stringAddr = 64; // stored on page boundary
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(57600);
|
||||
|
||||
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();
|
||||
RtcEeprom.Begin();
|
||||
|
||||
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
|
||||
printDateTime(compiled);
|
||||
Serial.println();
|
||||
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (Rtc.LastError() != 0)
|
||||
{
|
||||
// we have a communications error
|
||||
// see https://www.arduino.cc/en/Reference/WireEndTransmission for
|
||||
// what the number means
|
||||
Serial.print("RTC communications error = ");
|
||||
Serial.println(Rtc.LastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
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.Enable32kHzPin(false);
|
||||
Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone);
|
||||
|
||||
/* comment out on a second run to see that the info is stored long term */
|
||||
// Store something in memory on the Eeprom
|
||||
|
||||
// store starting address of string
|
||||
RtcEeprom.SetMemory(0, stringAddr);
|
||||
// store the string, nothing longer than 32 bytes due to paging
|
||||
uint8_t written = RtcEeprom.SetMemory(stringAddr, (const uint8_t*)data, sizeof(data) - 1); // remove the null terminator strings add
|
||||
// store the length of the string
|
||||
RtcEeprom.SetMemory(1, written); // store the
|
||||
/* end of comment out section */
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (Rtc.LastError() != 0)
|
||||
{
|
||||
// we have a communications error
|
||||
// see https://www.arduino.cc/en/Reference/WireEndTransmission for
|
||||
// what the number means
|
||||
Serial.print("RTC communications error = ");
|
||||
Serial.println(Rtc.LastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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 = RtcEeprom.GetMemory(0);
|
||||
if (address != stringAddr)
|
||||
{
|
||||
Serial.print("address didn't match ");
|
||||
Serial.println(address);
|
||||
}
|
||||
|
||||
{
|
||||
// get the size of the data from address 1
|
||||
uint8_t count = RtcEeprom.GetMemory(1);
|
||||
uint8_t buff[64];
|
||||
|
||||
// get our data from the address with the given size
|
||||
uint8_t gotten = RtcEeprom.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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void printDateTime(const RtcDateTime& dt)
|
||||
{
|
||||
char datestring[20];
|
||||
|
||||
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,145 @@
|
||||
|
||||
// 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 */
|
||||
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(57600);
|
||||
|
||||
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();
|
||||
|
||||
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
|
||||
printDateTime(compiled);
|
||||
Serial.println();
|
||||
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (Rtc.LastError() != 0)
|
||||
{
|
||||
// we have a communications error
|
||||
// see https://www.arduino.cc/en/Reference/WireEndTransmission for
|
||||
// what the number means
|
||||
Serial.print("RTC communications error = ");
|
||||
Serial.println(Rtc.LastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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(DS3231SquareWavePin_ModeNone);
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
if (!Rtc.IsDateTimeValid())
|
||||
{
|
||||
if (Rtc.LastError() != 0)
|
||||
{
|
||||
// we have a communications error
|
||||
// see https://www.arduino.cc/en/Reference/WireEndTransmission for
|
||||
// what the number means
|
||||
Serial.print("RTC communications error = ");
|
||||
Serial.println(Rtc.LastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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[20];
|
||||
|
||||
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,100 @@
|
||||
|
||||
// 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 */
|
||||
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin(57600);
|
||||
|
||||
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();
|
||||
|
||||
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.Enable32kHzPin(false);
|
||||
Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone);
|
||||
}
|
||||
|
||||
void loop ()
|
||||
{
|
||||
RtcDateTime now = Rtc.GetDateTime();
|
||||
|
||||
printDateTime(now);
|
||||
Serial.println();
|
||||
|
||||
for(;;)
|
||||
{
|
||||
Rtc.SetIsRunning(false);
|
||||
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[20];
|
||||
|
||||
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,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[20];
|
||||
|
||||
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,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[20];
|
||||
|
||||
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,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[20];
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
148
arduino-cli/libraries/Rtc_by_Makuna/keywords.txt
Normal file
148
arduino-cli/libraries/Rtc_by_Makuna/keywords.txt
Normal file
@@ -0,0 +1,148 @@
|
||||
#######################################
|
||||
# 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
|
||||
RtcTemperature KEYWORD1
|
||||
RtcDateTime KEYWORD1
|
||||
DayOfWeek 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
|
||||
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
|
||||
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
|
||||
DayOfWeek_Sunday LITERAL1
|
||||
DayOfWeek_Monday LITERAL1
|
||||
DayOfWeek_Tuesday LITERAL1
|
||||
DayOfWeek_Wednesday LITERAL1
|
||||
DayOfWeek_Thursday LITERAL1
|
||||
DayOfWeek_Friday LITERAL1
|
||||
DayOfWeek_Saturday LITERAL1
|
||||
|
||||
13
arduino-cli/libraries/Rtc_by_Makuna/library.json
Normal file
13
arduino-cli/libraries/Rtc_by_Makuna/library.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "RTC",
|
||||
"keywords": "RTC, DS1302, DS1307, DS3231, DS3234, AT24C32, clock",
|
||||
"description": "A library that makes interfacing DS1302, DS1307, DS3231, and DS3234 Real Time Clock modules easy.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Makuna/Rtc.git"
|
||||
},
|
||||
"version": "2.3.5",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*"
|
||||
}
|
||||
|
||||
9
arduino-cli/libraries/Rtc_by_Makuna/library.properties
Normal file
9
arduino-cli/libraries/Rtc_by_Makuna/library.properties
Normal file
@@ -0,0 +1,9 @@
|
||||
name=Rtc by Makuna
|
||||
version=2.3.5
|
||||
author=Michael C. Miller (makuna@live.com)
|
||||
maintainer=Michael C. Miller (makuna@live.com)
|
||||
sentence=A library that makes interfacing DS1302, DS1307, DS3231, and DS3234 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=*
|
||||
112
arduino-cli/libraries/Rtc_by_Makuna/src/EepromAT24C32.h
Normal file
112
arduino-cli/libraries/Rtc_by_Makuna/src/EepromAT24C32.h
Normal file
@@ -0,0 +1,112 @@
|
||||
#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 = 0b111) :
|
||||
_address(AT24C32_ADDRESS | (addressBits & 0b00000111)),
|
||||
_wire(wire),
|
||||
_lastError(0)
|
||||
{
|
||||
}
|
||||
|
||||
void Begin()
|
||||
{
|
||||
_wire.begin();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
272
arduino-cli/libraries/Rtc_by_Makuna/src/RtcDS1302.h
Normal file
272
arduino-cli/libraries/Rtc_by_Makuna/src/RtcDS1302.h
Normal file
@@ -0,0 +1,272 @@
|
||||
|
||||
|
||||
#ifndef __RTCDS1302_H__
|
||||
#define __RTCDS1302_H__
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "RtcDateTime.h"
|
||||
#include "RtcUtility.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();
|
||||
}
|
||||
|
||||
|
||||
void Begin(int sda, int scl)
|
||||
{
|
||||
_wire.begin(sda, scl);
|
||||
}
|
||||
|
||||
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;
|
||||
goto apply;
|
||||
}
|
||||
if ((setting & DS1302TcrDiodes_MASK) == DS1302TcrDiodes_Disabled ||
|
||||
(setting & DS1302TcrDiodes_MASK) == DS1302TcrDiodes_None) {
|
||||
// invalid diode setting, set to disabled
|
||||
setting = DS1302Tcr_Disabled;
|
||||
goto apply;
|
||||
}
|
||||
if ((setting & DS1302TcrStatus_MASK) != DS1302TcrStatus_Enabled) {
|
||||
// invalid status setting, set to disabled
|
||||
setting = DS1302Tcr_Disabled;
|
||||
goto apply;
|
||||
}
|
||||
|
||||
apply:
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __RTCDS1302_H__
|
||||
259
arduino-cli/libraries/Rtc_by_Makuna/src/RtcDS1307.h
Normal file
259
arduino-cli/libraries/Rtc_by_Makuna/src/RtcDS1307.h
Normal file
@@ -0,0 +1,259 @@
|
||||
|
||||
|
||||
#ifndef __RTCDS1307_H__
|
||||
#define __RTCDS1307_H__
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "RtcDateTime.h"
|
||||
#include "RtcUtility.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 uint8_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(0)
|
||||
{
|
||||
}
|
||||
|
||||
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 == 0));
|
||||
}
|
||||
|
||||
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 != 0)
|
||||
{
|
||||
RtcDateTime(0);
|
||||
}
|
||||
|
||||
uint8_t bytesRead = _wire.requestFrom(DS1307_ADDRESS, DS1307_REG_TIMEDATE_SIZE);
|
||||
if (DS1307_REG_TIMEDATE_SIZE != bytesRead)
|
||||
{
|
||||
_lastError = 4;
|
||||
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;
|
||||
}
|
||||
|
||||
uint8_t GetMemory(uint8_t memoryAddress, uint8_t* pValue, uint8_t countBytes)
|
||||
{
|
||||
uint8_t address = memoryAddress + DS1307_REG_RAMSTART;
|
||||
uint8_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 != 0)
|
||||
{
|
||||
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 != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// control register
|
||||
uint8_t bytesRead = _wire.requestFrom(DS1307_ADDRESS, (uint8_t)1);
|
||||
if (1 != bytesRead)
|
||||
{
|
||||
_lastError = 4;
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __RTCDS1307_H__
|
||||
631
arduino-cli/libraries/Rtc_by_Makuna/src/RtcDS3231.h
Normal file
631
arduino-cli/libraries/Rtc_by_Makuna/src/RtcDS3231.h
Normal file
@@ -0,0 +1,631 @@
|
||||
|
||||
|
||||
#ifndef __RTCDS3231_H__
|
||||
#define __RTCDS3231_H__
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "RtcDateTime.h"
|
||||
#include "RtcTemperature.h"
|
||||
#include "RtcUtility.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 uint8_t DS3231_REG_TIMEDATE_SIZE = 7;
|
||||
const uint8_t DS3231_REG_ALARMONE_SIZE = 4;
|
||||
const uint8_t DS3231_REG_ALARMTWO_SIZE = 3;
|
||||
|
||||
const uint8_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(0)
|
||||
{
|
||||
}
|
||||
|
||||
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 == 0));
|
||||
}
|
||||
|
||||
bool GetIsRunning()
|
||||
{
|
||||
uint8_t creg = getReg(DS3231_REG_CONTROL);
|
||||
return (!(creg & _BV(DS3231_EOSC)) && (_lastError == 0));
|
||||
}
|
||||
|
||||
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 != 0)
|
||||
{
|
||||
return RtcDateTime(0);
|
||||
}
|
||||
|
||||
uint8_t bytesRead = _wire.requestFrom(DS3231_ADDRESS, DS3231_REG_TIMEDATE_SIZE);
|
||||
if (DS3231_REG_TIMEDATE_SIZE != bytesRead)
|
||||
{
|
||||
_lastError = 4;
|
||||
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 != 0)
|
||||
{
|
||||
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.
|
||||
|
||||
uint8_t bytesRead = _wire.requestFrom(DS3231_ADDRESS, DS3231_REG_TEMP_SIZE);
|
||||
if (DS3231_REG_TEMP_SIZE != bytesRead)
|
||||
{
|
||||
_lastError = 4;
|
||||
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 != 0)
|
||||
{
|
||||
return DS3231AlarmOne(0, 0, 0, 0, DS3231AlarmOneControl_HoursMinutesSecondsDayOfMonthMatch);
|
||||
}
|
||||
|
||||
uint8_t bytesRead = _wire.requestFrom(DS3231_ADDRESS, DS3231_REG_ALARMONE_SIZE);
|
||||
if (DS3231_REG_ALARMONE_SIZE != bytesRead)
|
||||
{
|
||||
_lastError = 4;
|
||||
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 != 0)
|
||||
{
|
||||
return DS3231AlarmTwo(0, 0, 0, DS3231AlarmTwoControl_HoursMinutesDayOfMonthMatch);
|
||||
}
|
||||
|
||||
uint8_t bytesRead = _wire.requestFrom(DS3231_ADDRESS, DS3231_REG_ALARMTWO_SIZE);
|
||||
if (DS3231_REG_ALARMTWO_SIZE != bytesRead)
|
||||
{
|
||||
_lastError = 4;
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private:
|
||||
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 != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// control register
|
||||
uint8_t bytesRead = _wire.requestFrom(DS3231_ADDRESS, (uint8_t)1);
|
||||
if (1 != bytesRead)
|
||||
{
|
||||
_lastError = 4;
|
||||
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();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // __RTCDS3231_H__
|
||||
699
arduino-cli/libraries/Rtc_by_Makuna/src/RtcDS3234.h
Normal file
699
arduino-cli/libraries/Rtc_by_Makuna/src/RtcDS3234.h
Normal file
@@ -0,0 +1,699 @@
|
||||
|
||||
|
||||
#ifndef __RTCDS3234_H__
|
||||
#define __RTCDS3234_H__
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <SPI.h>
|
||||
|
||||
#include "RtcDateTime.h"
|
||||
#include "RtcTemperature.h"
|
||||
#include "RtcUtility.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();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // __RTCDS3234_H__
|
||||
211
arduino-cli/libraries/Rtc_by_Makuna/src/RtcDateTime.cpp
Normal file
211
arduino-cli/libraries/Rtc_by_Makuna/src/RtcDateTime.cpp
Normal file
@@ -0,0 +1,211 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "RtcDateTime.h"
|
||||
|
||||
const uint8_t c_daysInMonth[] PROGMEM = { 31,28,31,30,31,30,31,31,30,31,30,31 };
|
||||
|
||||
RtcDateTime::RtcDateTime(uint32_t secondsFrom2000)
|
||||
{
|
||||
_initWithSecondsFrom2000<uint32_t>(secondsFrom2000);
|
||||
}
|
||||
|
||||
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 StringToUint8(const char* pString)
|
||||
{
|
||||
uint8_t value = 0;
|
||||
|
||||
// skip leading 0 and spaces
|
||||
while ('0' == *pString || *pString == ' ')
|
||||
{
|
||||
pString++;
|
||||
}
|
||||
|
||||
// calculate number until we hit non-numeral char
|
||||
while ('0' <= *pString && *pString <= '9')
|
||||
{
|
||||
value *= 10;
|
||||
value += *pString - '0';
|
||||
pString++;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
RtcDateTime::RtcDateTime(const char* date, const char* time)
|
||||
{
|
||||
// sample input: date = "Dec 06 2009", time = "12:34:56"
|
||||
_yearFrom2000 = StringToUint8(date + 9);
|
||||
// Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
|
||||
switch (date[0])
|
||||
{
|
||||
case 'J':
|
||||
if ( date[1] == 'a' )
|
||||
_month = 1;
|
||||
else if ( date[2] == 'n' )
|
||||
_month = 6;
|
||||
else
|
||||
_month = 7;
|
||||
break;
|
||||
case 'F':
|
||||
_month = 2;
|
||||
break;
|
||||
case 'A':
|
||||
_month = date[1] == 'p' ? 4 : 8;
|
||||
break;
|
||||
case 'M':
|
||||
_month = date[2] == 'r' ? 3 : 5;
|
||||
break;
|
||||
case 'S':
|
||||
_month = 9;
|
||||
break;
|
||||
case 'O':
|
||||
_month = 10;
|
||||
break;
|
||||
case 'N':
|
||||
_month = 11;
|
||||
break;
|
||||
case 'D':
|
||||
_month = 12;
|
||||
break;
|
||||
}
|
||||
_dayOfMonth = StringToUint8(date + 4);
|
||||
_hour = StringToUint8(time);
|
||||
_minute = StringToUint8(time + 3);
|
||||
_second = StringToUint8(time + 6);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void RtcDateTime::InitWithIso8601(const char* date)
|
||||
{
|
||||
// sample input: date = "Sat, 06 Dec 2009 12:34:56 GMT"
|
||||
_yearFrom2000 = StringToUint8(date + 13);
|
||||
// Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
|
||||
switch (date[8])
|
||||
{
|
||||
case 'J':
|
||||
if (date[1 + 8] == 'a')
|
||||
_month = 1;
|
||||
else if (date[2 + 8] == 'n')
|
||||
_month = 6;
|
||||
else
|
||||
_month = 7;
|
||||
break;
|
||||
case 'F':
|
||||
_month = 2;
|
||||
break;
|
||||
case 'A':
|
||||
_month = date[1 + 8] == 'p' ? 4 : 8;
|
||||
break;
|
||||
case 'M':
|
||||
_month = date[2 + 8] == 'r' ? 3 : 5;
|
||||
break;
|
||||
case 'S':
|
||||
_month = 9;
|
||||
break;
|
||||
case 'O':
|
||||
_month = 10;
|
||||
break;
|
||||
case 'N':
|
||||
_month = 11;
|
||||
break;
|
||||
case 'D':
|
||||
_month = 12;
|
||||
break;
|
||||
}
|
||||
_dayOfMonth = StringToUint8(date + 5);
|
||||
_hour = StringToUint8(date + 17);
|
||||
_minute = StringToUint8(date + 20);
|
||||
_second = StringToUint8(date + 23);
|
||||
}
|
||||
185
arduino-cli/libraries/Rtc_by_Makuna/src/RtcDateTime.h
Normal file
185
arduino-cli/libraries/Rtc_by_Makuna/src/RtcDateTime.h
Normal file
@@ -0,0 +1,185 @@
|
||||
|
||||
|
||||
#ifndef __RTCDATETIME_H__
|
||||
#define __RTCDATETIME_H__
|
||||
|
||||
// ESP32 complains if not included
|
||||
#if defined(ARDUINO_ARCH_ESP32)
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
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_Epoch32OfOriginYear = 946684800;
|
||||
extern const uint8_t c_daysInMonth[] PROGMEM;
|
||||
|
||||
class RtcDateTime
|
||||
{
|
||||
public:
|
||||
RtcDateTime(uint32_t secondsFrom2000 = 0);
|
||||
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__);
|
||||
RtcDateTime(const char* date, const char* 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;
|
||||
|
||||
// add seconds
|
||||
void operator += (uint32_t seconds)
|
||||
{
|
||||
RtcDateTime after = RtcDateTime( TotalSeconds() + seconds );
|
||||
*this = after;
|
||||
}
|
||||
|
||||
// remove seconds
|
||||
void operator -= (uint32_t seconds)
|
||||
{
|
||||
RtcDateTime before = RtcDateTime( TotalSeconds() - seconds );
|
||||
*this = before;
|
||||
}
|
||||
|
||||
// allows for comparisons to just work (==, <, >, <=, >=, !=)
|
||||
operator uint32_t() const
|
||||
{
|
||||
return TotalSeconds();
|
||||
}
|
||||
|
||||
// Epoch32 support
|
||||
uint32_t Epoch32Time() const
|
||||
{
|
||||
return TotalSeconds() + c_Epoch32OfOriginYear;
|
||||
}
|
||||
void InitWithEpoch32Time(uint32_t time)
|
||||
{
|
||||
_initWithSecondsFrom2000<uint32_t>(time - c_Epoch32OfOriginYear);
|
||||
}
|
||||
|
||||
// Epoch64 support
|
||||
uint64_t Epoch64Time() const
|
||||
{
|
||||
return TotalSeconds64() + c_Epoch32OfOriginYear;
|
||||
}
|
||||
void InitWithEpoch64Time(uint64_t time)
|
||||
{
|
||||
_initWithSecondsFrom2000<uint64_t>(time - c_Epoch32OfOriginYear);
|
||||
}
|
||||
|
||||
void InitWithIso8601(const char* date);
|
||||
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // __RTCDATETIME_H__
|
||||
153
arduino-cli/libraries/Rtc_by_Makuna/src/RtcTemperature.h
Normal file
153
arduino-cli/libraries/Rtc_by_Makuna/src/RtcTemperature.h
Normal file
@@ -0,0 +1,153 @@
|
||||
|
||||
|
||||
#ifndef __RTCTEMPERATURE_H__
|
||||
#define __RTCTEMPERATURE_H__
|
||||
|
||||
|
||||
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)
|
||||
};
|
||||
|
||||
#endif // __RTCTEMPERATURE_H__
|
||||
34
arduino-cli/libraries/Rtc_by_Makuna/src/RtcUtility.cpp
Normal file
34
arduino-cli/libraries/Rtc_by_Makuna/src/RtcUtility.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
#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;
|
||||
}
|
||||
35
arduino-cli/libraries/Rtc_by_Makuna/src/RtcUtility.h
Normal file
35
arduino-cli/libraries/Rtc_by_Makuna/src/RtcUtility.h
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
#ifndef __RTCUTILITY_H__
|
||||
#define __RTCUTILITY_H__
|
||||
|
||||
// ESP32 complains if not included
|
||||
#if defined(ARDUINO_ARCH_ESP32)
|
||||
#include <inttypes.h>
|
||||
#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)
|
||||
|
||||
|
||||
// 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);
|
||||
|
||||
#endif // __RTCUTILITY_H__
|
||||
99
arduino-cli/libraries/Rtc_by_Makuna/src/ThreeWire.h
Normal file
99
arduino-cli/libraries/Rtc_by_Makuna/src/ThreeWire.h
Normal file
@@ -0,0 +1,99 @@
|
||||
#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