Dump from SVN

This commit is contained in:
Fándly Gergő
2019-08-08 17:09:21 +03:00
parent 9ec84017e4
commit 37522d26fc
118 changed files with 85533 additions and 0 deletions

17
firmware/lib/Rtc-master/.gitattributes vendored Normal file
View File

@ -0,0 +1,17 @@
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain

43
firmware/lib/Rtc-master/.gitignore vendored Normal file
View File

@ -0,0 +1,43 @@
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
# =========================
# Operating System Files
# =========================
# OSX
# =========================
.DS_Store
.AppleDouble
.LSOverride
# Thumbnails
._*
# Files that might appear on external disk
.Spotlight-V100
.Trashes
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

View 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.

View File

@ -0,0 +1,25 @@
# Rtc
Arduino Real Time Clock library.
An RTC library with deep device support.
[![Donate](http://img.shields.io/paypal/donate.png?color=yellow)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6AA97KE54UJR4)
Now supports esp8266.
Now supports SoftwareWire library.
For quick questions jump on Gitter and ask away.
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](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.

View File

@ -0,0 +1,151 @@
// 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())
{
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())
{
// Common Cuases:
// 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(") = \"");
while (gotten > 0)
{
Serial.print((char)buff[count - gotten]);
gotten--;
}
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);
}

View File

@ -0,0 +1,116 @@
// 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())
{
// Common Cuases:
// 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())
{
// Common Cuases:
// 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);
}

View File

@ -0,0 +1,185 @@
// 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 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())
{
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())
{
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);
}

View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{969D9575-C911-4B46-BC8C-88C6A9086115}</ProjectGuid>
<RootNamespace>DS3231_Alarms</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
</Project>

View File

@ -0,0 +1,82 @@
/*
Editor: http://www.visualmicro.com
visual micro and the arduino ide ignore this code during compilation. this code is automatically maintained by visualmicro, manual changes to this file will be overwritten
the contents of the Visual Micro sketch sub folder can be deleted prior to publishing a project
all non-arduino files created by visual micro and all visual studio project or solution files can be freely deleted and are not required to compile a sketch (do not delete your own code!).
note: debugger breakpoints are stored in '.sln' or '.asln' files, knowledge of last uploaded breakpoints is stored in the upload.vmps.xml file. Both files are required to continue a previous debug session without needing to compile and upload again
Hardware: Arduino Mega w/ ATmega2560 (Mega 2560), Platform=avr, Package=arduino
*/
#ifndef _VSARDUINO_H_
#define _VSARDUINO_H_
#define __AVR_ATmega2560__
#define ARDUINO 161
#define ARDUINO_MAIN
#define __AVR__
#define __avr__
#define F_CPU 16000000L
#define __cplusplus
#define GCC_VERSION 40801
#define ARDUINO_ARCH_AVR
#define ARDUINO_AVR_MEGA2560
#define __inline__
#define __asm__(x)
#define __extension__
//#define __ATTR_PURE__
//#define __ATTR_CONST__
#define __inline__
//#define __asm__
#define __volatile__
#define GCC_VERSION 40801
#define volatile(va_arg)
typedef void *__builtin_va_list;
#define __builtin_va_start
#define __builtin_va_end
//#define __DOXYGEN__
#define __attribute__(x)
#define NOINLINE __attribute__((noinline))
#define prog_void
#define PGM_VOID_P int
#define NEW_H
/*
#ifndef __ATTR_CONST__
#define __ATTR_CONST__ __attribute__((__const__))
#endif
#ifndef __ATTR_MALLOC__
#define __ATTR_MALLOC__ __attribute__((__malloc__))
#endif
#ifndef __ATTR_NORETURN__
#define __ATTR_NORETURN__ __attribute__((__noreturn__))
#endif
#ifndef __ATTR_PURE__
#define __ATTR_PURE__ __attribute__((__pure__))
#endif
*/
typedef unsigned char byte;
extern "C" void __cxa_pure_virtual() {;}
#include <arduino.h>
#include <pins_arduino.h>
#undef F
#define F(string_literal) ((const PROGMEM char *)(string_literal))
#undef cli
#define cli()
#define pgm_read_byte(address_short)
#define pgm_read_word(address_short)
#define pgm_read_word2(address_short)
#define digitalPinToPort(P)
#define digitalPinToBitMask(P)
#define digitalPinToTimer(P)
#define analogInPinToBit(P)
#define portOutputRegister(P)
#define portInputRegister(P)
#define portModeRegister(P)
#include <DS3231_Alarms.ino>
#endif

View File

@ -0,0 +1,123 @@
// 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())
{
// Common Cuases:
// 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())
{
// Common Cuases:
// 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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -0,0 +1,93 @@
#######################################
# Syntax Coloring Map RTC
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
DS3231AlarmOne KEYWORD1
DS3231AlarmTwo KEYWORD1
RtcDS3231 KEYWORD1
RtcTemperature KEYWORD1
RtcDateTime KEYWORD1
DayOfWeek KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
Begin KEYWORD2
IsDateTimeValid KEYWORD2
GetIsRunning KEYWORD2
SetIsRunning 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
GetAgingOffset KEYWORD2
SetAgingOffset KEYWORD2
AsFloat KEYWORD2
AsWholeDegrees KEYWORD2
GetFractional KEYWORD2
Year KEYWORD2
Month KEYWORD2
Day KEYWORD2
Hour KEYWORD2
Minute KEYWORD2
Second KEYWORD2
DayOfWeek KEYWORD2
TotalSeconds KEYWORD2
DayOf KEYWORD2
ControlFlags KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
DS3231SquareWaveClock_1Hz LITERAL1
DS3231SquareWaveClock_1kHz LITERAL1
DS3231SquareWaveClock_4kHz LITERAL1
DS3231SquareWaveClock_8kHz LITERAL1
DS3231SquareWavePin_ModeNone LITERAL1
DS3231SquareWavePin_ModeBatteryBackup 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
DS1307SquareWaveOut_1Hz LITERAL1
DS1307SquareWaveOut_4kHz LITERAL1
DS1307SquareWaveOut_8kHz LITERAL1
DS1307SquareWaveOut_32kHz LITERAL1
DS1307SquareWaveOut_High LITERAL1
DS1307SquareWaveOut_Low LITERAL1
DayOfWeek_Sunday LITERAL1
DayOfWeek_Monday LITERAL1
DayOfWeek_Tuesday LITERAL1
DayOfWeek_Wednesday LITERAL1
DayOfWeek_Thursday LITERAL1
DayOfWeek_Friday LITERAL1
DayOfWeek_Saturday LITERAL1

View File

@ -0,0 +1,14 @@
{
"name": "RTC",
"keywords": "RTC, DS1307, DS3231, clock",
"description": "A library that makes interfacing DS1307 and DS3231 Real Time Clock modules easy.",
"repository":
{
"type": "git",
"url": "https://github.com/Makuna/Rtc.git"
},
"version": "2.1.0",
"frameworks": "arduino",
"platforms": "*"
}

View File

@ -0,0 +1,9 @@
name=Rtc by Makuna
version=2.1.0
author=Michael C. Miller (makuna@live.com)
maintainer=Michael C. Miller (makuna@live.com)
sentence=A library that makes interfacing DS1307 and DS3231 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=*

View File

@ -0,0 +1,225 @@
#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)
{
}
void Begin()
{
_wire.begin();
}
bool IsDateTimeValid()
{
return GetIsRunning();
}
bool GetIsRunning()
{
uint8_t sreg = getReg(DS1307_REG_STATUS);
return !(sreg & _BV(DS1307_CH));
}
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));
_wire.endTransmission();
}
RtcDateTime GetDateTime()
{
_wire.beginTransmission(DS1307_ADDRESS);
_wire.write(DS1307_REG_TIMEDATE);
_wire.endTransmission();
_wire.requestFrom(DS1307_ADDRESS, DS1307_REG_TIMEDATE_SIZE);
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++;
}
_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);
_wire.endTransmission();
_wire.requestFrom(DS1307_ADDRESS, countBytes);
while (countBytes-- > 0)
{
*pValue++ = _wire.read();
countRead++;
}
}
return countRead;
}
void SetSquareWavePin(DS1307SquareWaveOut pinMode)
{
setReg(DS1307_REG_CONTROL, pinMode);
}
private:
T_WIRE_METHOD& _wire;
uint8_t getReg(uint8_t regAddress)
{
_wire.beginTransmission(DS1307_ADDRESS);
_wire.write(regAddress);
_wire.endTransmission();
// control register
_wire.requestFrom(DS1307_ADDRESS, (uint8_t)1);
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);
_wire.endTransmission();
}
};
#endif // __RTCDS1307_H__

View File

@ -0,0 +1,576 @@
#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_ModeBatteryBackup,
DS3231SquareWavePin_ModeClock,
DS3231SquareWavePin_ModeAlarmOne,
DS3231SquareWavePin_ModeAlarmTwo,
DS3231SquareWavePin_ModeAlarmBoth
};
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)
{
}
void Begin()
{
_wire.begin();
}
bool IsDateTimeValid()
{
uint8_t status = getReg(DS3231_REG_STATUS);
return !(status & _BV(DS3231_OSF));
}
bool GetIsRunning()
{
uint8_t creg = getReg(DS3231_REG_CONTROL);
return !(creg & _BV(DS3231_EOSC));
}
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));
_wire.endTransmission();
}
RtcDateTime GetDateTime()
{
_wire.beginTransmission(DS3231_ADDRESS);
_wire.write(DS3231_REG_TIMEDATE);
_wire.endTransmission();
_wire.requestFrom(DS3231_ADDRESS, DS3231_REG_TIMEDATE_SIZE);
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);
_wire.endTransmission();
// Temperature is represented as a 10-bit code with a resolution
// of 1/4th <20>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<EFBFBD>C, concatenated registers <r11h:r12h> =
// 256 * (+/- 25+(1/4)) = +/- 6464, or 1940h / E6C0h.
_wire.requestFrom(DS3231_ADDRESS, DS3231_REG_TEMP_SIZE);
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)
{
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 SQW
switch (pinMode)
{
case DS3231SquareWavePin_ModeNone:
break;
case DS3231SquareWavePin_ModeBatteryBackup:
creg |= _BV(DS3231_BBSQW); // set battery backup flag
creg &= ~_BV(DS3231_INTCN); // clear INTCN to enable SQW
break;
case DS3231SquareWavePin_ModeClock:
creg &= ~_BV(DS3231_INTCN); // clear INTCN to enable SQW
break;
case DS3231SquareWavePin_ModeAlarmOne:
creg |= _BV(DS3231_A1IE);
break;
case DS3231SquareWavePin_ModeAlarmTwo:
creg |= _BV(DS3231_A2IE);
break;
case DS3231SquareWavePin_ModeAlarmBoth:
creg |= _BV(DS3231_A1IE) | _BV(DS3231_A2IE);
break;
}
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));
_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));
_wire.endTransmission();
}
DS3231AlarmOne GetAlarmOne()
{
_wire.beginTransmission(DS3231_ADDRESS);
_wire.write(DS3231_REG_ALARMONE);
_wire.endTransmission();
_wire.requestFrom(DS3231_ADDRESS, DS3231_REG_ALARMONE_SIZE);
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);
_wire.endTransmission();
_wire.requestFrom(DS3231_ADDRESS, DS3231_REG_ALARMTWO_SIZE);
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 getReg(uint8_t regAddress)
{
_wire.beginTransmission(DS3231_ADDRESS);
_wire.write(regAddress);
_wire.endTransmission();
// control register
_wire.requestFrom(DS3231_ADDRESS, (uint8_t)1);
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);
_wire.endTransmission();
}
};
#endif // __RTCDS3231_H__

View File

@ -0,0 +1,154 @@
#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);
}
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 26 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
}
uint32_t RtcDateTime::TotalSeconds() const
{
uint16_t days = DaysSinceFirstOfYear2000<uint16_t>(_yearFrom2000, _month, _dayOfMonth);
return SecondsIn<uint32_t>(days, _hour, _minute, _second);
}
uint64_t RtcDateTime::TotalSeconds64() const
{
uint32_t days = DaysSinceFirstOfYear2000<uint32_t>(_yearFrom2000, _month, _dayOfMonth);
return SecondsIn<uint64_t>(days, _hour, _minute, _second);
}
void RtcDateTime::InitWithIso8601(const char* date)
{
// sample input: date = "Sat, 26 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);
}

View File

@ -0,0 +1,178 @@
#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);
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 times as seconds since 1/1/2000
uint32_t TotalSeconds() const;
uint64_t TotalSeconds64() 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__

View 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__

View 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;
}

View File

@ -0,0 +1,19 @@
#ifndef __RTCUTILITY_H__
#define __RTCUTILITY_H__
// ESP32 complains if not included
#if defined(ARDUINO_ARCH_ESP32)
#include <inttypes.h>
#endif
// 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__