diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..508b5b2 --- /dev/null +++ b/.clang-format @@ -0,0 +1,156 @@ +################################################################################ +## Google formatting file. Auto-generated from "LLVM" Style and then modified ## +## ## +## Date Developer Description ## +## ========== ========== =====================================================## +## 2020-07-05 SV-Zanshin Removed unknown options ## +## 2020-06-28 SV-Zanshin Changed indentation ## +## ## +################################################################################ +--- +Language: Cpp +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +##AlignConsecutiveMacros: true +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: true +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +#AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: true +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 100 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: true +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^' + Priority: 2 + - Regex: '^<.*\.h>' + Priority: 1 + - Regex: '^<.*' + Priority: 2 + - Regex: '.*' + Priority: 3 +IncludeIsMainRegex: '([-_](test|unittest))?$' +IndentCaseLabels: true +IndentPPDirectives: None +IndentWidth: 2 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Never +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +RawStringFormats: + - Language: Cpp + Delimiters: + - cc + - CC + - cpp + - Cpp + - CPP + - 'c++' + - 'C++' + CanonicalDelimiter: '' + BasedOnStyle: google + - Language: TextProto + Delimiters: + - pb + - PB + - proto + - PROTO + EnclosingFunctions: + - EqualsProto + - EquivToProto + - PARSE_PARTIAL_TEXT_PROTO + - PARSE_TEST_PROTO + - PARSE_TEXT_PROTO + - ParseTextOrDie + - ParseTextProtoOrDie + CanonicalDelimiter: '' + BasedOnStyle: google +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +TabWidth: 8 +UseTab: Never +... diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md index 083faf4..142a559 100644 --- a/.github/CODE_OF_CONDUCT.md +++ b/.github/CODE_OF_CONDUCT.md @@ -75,4 +75,4 @@ available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.ht For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq -![Zanshin Logo](https://www.sv-zanshin.com/r/images/site/gif/zanshinkanjitiny.gif) +[![Zanshin Logo](https://zanduino.github.io/Images/zanshinkanjitiny.gif) ](https://www.sv-zanshin.com) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index bdd9440..31cd97a 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -10,9 +10,11 @@ Push to your fork and submit a gitHub pull request. At this point the ball is no longer in your court but on our side. There will be a response within a couple of days, at most. -Some things that will increase the spped at which a pull request is completed: +Some things that will increase the speed at which a pull request is completed: * Write tests. -* Follow the existing coding style (comments are done with [doxygen](http://www.doxygen.nl/). -* Write as much information as a beginner would need to understand the problem and solution. +* Follow the existing coding style, using [Google Style Guide](https://google.github.io/styleguide/cppguide.html) +* Follow the existing program documentation style using [doxygen](http://www.doxygen.nl/) +* Write as much information as a beginner would need to understand the problem and solution +[![Zanshin Logo](https://zanduino.github.io/Images/zanshinkanjitiny.gif) ](https://www.sv-zanshin.com) \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 3c5171a..5185541 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,22 +1,31 @@ +--- +name: Bug report +about: Submit a bug report +title: {Add Short one-line Bug title} +labels: bug +assignees: SV-Zanshin + +--- + ## Expected Behavior -Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +_Detail what the expected program behavior should be, or what is expected to happen._ ## Actual Behavior -Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +_Detail what actually happens._ ## Steps to Reproduce the Problem +_Explain what needs to be done in order to reproduce the problem._ 1. - 1. - 1. + 2. + 3. ## Specifications - - Version: + - Library Version: + - IDE Version: - Platform: - Subsystem: - - -![Zanshin Logo](https://www.sv-zanshin.com/r/images/site/gif/zanshinkanjitiny.gif) + - _any other details needed to reproduce the problem_ diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 2c41ddd..eeead79 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,22 +1,20 @@ --- name: Feature request about: Suggest an idea for this project -title: '' -labels: '' -assignees: '' +title: {add one-line description of the feature request} +labels: enhancement +assignees: SV-Zanshin --- -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] +**Describe what the feature request is and if it solves an issue or adds functionality** +_A clear and concise description of what the problem is which would be solved by the feature request. Example "It would be helpful to add a function newFunc() to solve the problem of [...]"_ **Describe the solution you'd like** -A clear and concise description of what you want to happen. +_A clear and concise description of what you want to have changed or added._ **Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. +_A clear and concise description of any alternative solutions or features you've considered._ **Additional context** -Add any other context or screenshots about the feature request here. - -![Zanshin Logo](https://www.sv-zanshin.com/r/images/site/gif/zanshinkanjitiny.gif) +_Add any other context or screenshots about the feature request here._ \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/implementation-question.md b/.github/ISSUE_TEMPLATE/implementation-question.md new file mode 100644 index 0000000..15de2d7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/implementation-question.md @@ -0,0 +1,10 @@ +--- +name: Implementation Question +about: Ask a question about the library implementation +title: {One-Line descriptive question title} +labels: question +assignees: SV-Zanshin + +--- + +_Ask your question or post your comment here, adding any information, examples, links, etc. that someone would reasonably be expected to have in order to give a response._ diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d7a1b73..b9a1579 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,14 +1,14 @@ # Description -Please include a text summary of the change and which issue(s) is/are fixed or addressed. Should the change have any dependencies -then these should be listed here. +_Please include a text summary of the change and which issue(s) is/are fixed or addressed. Should the change have any dependencies +then these should be listed here._ Fixes # (issue) -In order to make tracking easier and to properly document the process, -pull requests should always refer to an active issue in the list - be it a bug fix or an enhancement or some other type of issue. +_In order to make tracking easier and to properly document the process, +pull requests should always refer to an active issue in the list - be it a bug fix or an enhancement or some other type of issue._ ## Type of change -Please delete options that are not relevant. +_Please delete options that are not relevant._ - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) @@ -17,7 +17,7 @@ Please delete options that are not relevant. # How Has This Been Tested? -Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration +_Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration_ - [ ] Test A - [ ] Test B @@ -25,7 +25,8 @@ Please describe the tests that you ran to verify your changes. Provide instructi **Test Configuration**: * Arduino version: * Arduino Hardware: -* SDK: (Arduino IDE, Atmel Studio, etc.) +* SDK: (Arduino IDE, Atmel Studio, Visual Studio, Visual Micro, etc.) +* Development sytem: (Windows, Web, Linux, etc.) # Checklist: @@ -33,10 +34,13 @@ Please describe the tests that you ran to verify your changes. Provide instructi - [ ] I have performed a self-review of my own code - [ ] My code follows the style guidelines of this project - [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] The code adheres to the [Google Style Guide](https://google.github.io/styleguide/cppguide.html) +- [ ] The code follows the existing program documentation style using [doxygen](http://www.doxygen.nl/) - [ ] I have made corresponding changes to the documentation / Wiki Page(s) - [ ] My changes generate no new warnings +- [ ] The automated TRAVIS-CI run has a status of "passed" - [ ] I have checked potential areas where regression errors could occur and have found no issues - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes -![Zanshin Logo](https://www.sv-zanshin.com/r/images/site/gif/zanshinkanjitiny.gif) +[![Zanshin Logo](https://zanduino.github.io/Images/zanshinkanjitiny.gif) ](https://www.sv-zanshin.com) diff --git a/.github/README.md b/.github/README.md index ba838ab..00049e0 100644 --- a/.github/README.md +++ b/.github/README.md @@ -10,4 +10,4 @@ The DS3231M is available as a SO8 or SO16 package and runs on both 3V and 5V sys ## Description A detailed description of the library along with further details are available at the GitHub [DS3231M Wiki](https://github.com/SV-Zanshin/DS3231M/wiki). This includes wiring information and sample sketches that illustrate the library and it's functionality. -![Zanshin Logo](https://www.sv-zanshin.com/r/images/site/gif/zanshinkanjitiny.gif) +[![Zanshin Logo](https://zanduino.github.io/Images/zanshinkanjitiny.gif) ](https://www.sv-zanshin.com) diff --git a/.travis.yml b/.travis.yml index 31169e8..ab400fe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,11 +3,12 @@ ## ## ## Date Developer Comments ## ## ========== =================== ================================================================= ## -## 2020-05-11 Arnd@SV-Zanshin Removed uneeded install libraries ## -## 2019-02-02 Arnd@SV-Zanshin Uncommented doxygen callorrected PRETTYNAME ## -## 2019-01-27 Arnd@SV-Zanshin Corrected PRETTYNAME ## -## 2019-01-20 Arnd@SV-Zanshin Linked to Adafruit script rather than manually defining all tests ## -## 2019-01-19 Arnd@SV-Zanshin Initial coding ## +## 2020-09-28 SV-Zanshin Issue #14, added clang-format checking ## +## 2020-05-11 SV-Zanshin Removed uneeded install libraries ## +## 2019-02-02 SV-Zanshin Uncommented doxygen callorrected PRETTYNAME ## +## 2019-01-27 SV-Zanshin Corrected PRETTYNAME ## +## 2019-01-20 SV-Zanshin Linked to Adafruit script rather than manually defining all tests ## +## 2019-01-19 SV-Zanshin Initial coding ## ## ## ###################################################################################################### language: c @@ -21,6 +22,16 @@ branches: git: depth: false quiet: true + addons: + apt: + sources: + - llvm-toolchain-trusty-5.0 + - key_url: 'http://apt.llvm.org/llvm-snapshot.gpg.key' + packages: + - python3-pip + - python3-wheel + - clang-format-5.0 + env: global: - PRETTYNAME="SV-Zanshin Maxim Integrated DS3231M I2C Thermometer Arduino Library" @@ -28,6 +39,7 @@ env: before_install: - source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/install.sh) + - curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/run-clang-format.py > run-clang-format.py install: diff --git a/Doxyfile b/Doxyfile index a7576a2..e744038 100644 --- a/Doxyfile +++ b/Doxyfile @@ -3,12 +3,13 @@ ## ## ## Date Developer Comments ## ## ========== =================== ================================================================= ## +## 2020-06-04 Arnd@SV-Zanshin Updated version to v1.0.5 ## ## 2020-05-11 Arnd@SV-Zanshin Removed all comments in order to compact this file ## ## ## ###################################################################################################### DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = DS3231M -PROJECT_NUMBER = "Version 1.0.3" +PROJECT_NUMBER = "Version 1.0.5" PROJECT_BRIEF = "Arduino Library for DS3231M Real-Time clock" PROJECT_LOGO = OUTPUT_DIRECTORY = @@ -283,4 +284,4 @@ MAX_DOT_GRAPH_DEPTH = 0 DOT_TRANSPARENT = NO DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES -DOT_CLEANUP = YES \ No newline at end of file +DOT_CLEANUP = YES diff --git a/examples/Set/Set.ino b/examples/Set/Set.ino index f4c48c7..234fd4b 100644 --- a/examples/Set/Set.ino +++ b/examples/Set/Set.ino @@ -2,23 +2,24 @@ @section Set_intro_section Description -Example program for using the DS3231M library which allows access to the DS3231M real-time-clock chip. The library -as well as the most current version of this program is available at GitHub using the address -https://github.com/SV-Zanshin/DS3231M and a more detailed description of this program (and the library) can be -found at https://github.com/SV-Zanshin/DS3231M/wiki/Demo.ino \n\n +Example program for using the DS3231M library which allows access to the DS3231M real-time-clock +chip. The library as well as the most current version of this program is available at GitHub using +the address https://github.com/SV-Zanshin/DS3231M and a more detailed description of this program +(and the library) can be found at https://github.com/SV-Zanshin/DS3231M/wiki/Demo.ino \n\n -The DS3231M library uses the standard SPI Wire library for communications with the RTC chip and has also used the -class definitions of the standard RTClib library from Adafruit/Jeelabs. The data sheet for the DS3231M is located -at https://datasheets.maximintegrated.com/en/ds/DS3231M.pdf. +The DS3231M library uses the standard SPI Wire library for communications with the RTC chip and has +also used the class definitions of the standard RTClib library from Adafruit/Jeelabs. The data sheet +for the DS3231M is located at https://datasheets.maximintegrated.com/en/ds/DS3231M.pdf. @section Setlicense __**GNU General Public License v3.0**__ -This program is free software: you can redistribute it and/or modify it under the terms of the GNU General -Public License as published by the Free Software Foundation, either version 3 of the License, or (at your -option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with this program. If not, see . +This program is free software: you can redistribute it and/or modify it under the terms of the GNU +General Public License as published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. This program is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have +received a copy of the GNU General Public License along with this program. If not, see +. @section Setauthor Author @@ -27,38 +28,38 @@ Written by Arnd\@SV-Zanshin @section Setversions Changelog Version | Date | Developer | Comments -------- | ---------- | ----------------------------- | --------------------------------------------------- +------- | ---------- | ----------------------------- | --------------------------------------------- 1.0.3 | 2019-10-16 | https://github.com/simmunity | Corrected "inputBuffer" issue 1.0.2 | 2019-02-02 | https://github.com/SV-Zanshin | Issue #7 - convert documentation to Doxygen -1.0.1 | 2019-01-27 | https://github.com/SV-Zanshin | Issue #5. Changes to sscanf() for Esp32 Implementation +1.0.1 | 2019-01-27 | https://github.com/SV-Zanshin | Issue #5. Changes to sscanf() for Esp32 1.0.0 | 2017-08-13 | https://github.com/SV-Zanshin | Initial coding */ -#include // Include the DS3231M RTC library -/******************************************************************************************************************* -** Declare all program constants ** -*******************************************************************************************************************/ -const uint32_t SERIAL_SPEED = 115200; ///< Set the baud rate for Serial I/O -const uint8_t SPRINTF_BUFFER_SIZE = 32; ///< Buffer size for sprintf() -const uint8_t LED_PIN = 13; ///< Built-in Arduino green LED pin +#include // Include the DS3231M RTC library +/*************************************************************************************************** +** Declare all program constants ** +***************************************************************************************************/ +const uint32_t SERIAL_SPEED = 115200; ///< Set the baud rate for Serial I/O +const uint8_t SPRINTF_BUFFER_SIZE = 32; ///< Buffer size for sprintf() +const uint8_t LED_PIN = 13; ///< Built-in Arduino green LED pin -/******************************************************************************************************************* -** Declare global variables and instantiate classes ** -*******************************************************************************************************************/ -DS3231M_Class DS3231M; ///< Create an instance of the DS3231M class +/*************************************************************************************************** +** Declare global variables and instantiate classes ** +***************************************************************************************************/ +DS3231M_Class DS3231M; ///< Create an instance of the DS3231M class -void setup() -{ - /*************************************************************************************************************//*! - * @brief Arduino method called once at startup to initialize the system - * @details This is an Arduino IDE method which is called first upon boot or restart. It is only called one time - * and then control goes to the main "loop()" method, from which control never returns - * @return void - *****************************************************************************************************************/ - pinMode(LED_PIN,OUTPUT); // Make the LED light an output pin +void setup() { + /*! + @brief Arduino method called once at startup to initialize the system + @details This is an Arduino IDE method which is called first upon boot or restart. It is only + called one time and then control goes to the main "loop()" method, from which control + never returns + @return void + */ + pinMode(LED_PIN, OUTPUT); // Make the LED light an output pin Serial.begin(SERIAL_SPEED); - #ifdef __AVR_ATmega32U4__ // If this is a 32U4 processor, then wait for the serial interface to initialize - delay(3000); - #endif +#ifdef __AVR_ATmega32U4__ // If this is a 32U4 processor, then wait for the serial + delay(3000); // interface to initialize +#endif Serial.print(F("\nStarting Set program\n")); Serial.print(F("- Compiled with c++ version ")); Serial.print(F(__VERSION__)); @@ -67,117 +68,113 @@ void setup() Serial.print(F(" at ")); Serial.print(F(__TIME__)); Serial.print(F("\n")); - while (!DS3231M.begin()) // Initialize RTC communications + while (!DS3231M.begin()) // Initialize RTC communications { Serial.println(F("Unable to find DS3231MM. Checking again in 3s.")); delay(3000); - } // of loop until device is located - DS3231M.pinSquareWave(); // Make INT/SQW pin toggle at 1Hz + } // of loop until device is located + DS3231M.pinSquareWave(); // Make INT/SQW pin toggle at 1Hz Serial.println(F("DS3231M initialized.")); - DS3231M.adjust(); // Set to library compile Date/Time + DS3231M.adjust(); // Set to library compile Date/Time Serial.print(F("DS3231M chip temperature is ")); - Serial.print(DS3231M.temperature()/100.0,1); // Value is in 100ths of a degree - Serial.println("\xC2\xB0""C"); + Serial.print(DS3231M.temperature() / 100.0, 1); // Value is in 100ths of a degree + Serial.println( + "\xC2\xB0" + "C"); Serial.println(F("\nEnter the following serial command:")); Serial.println(F("SETDATE yyyy-mm-dd hh:mm:ss")); -} // of method setup() +} // of method setup() -void readCommand() -{ - /*************************************************************************************************************//*! - * @brief Read incoming data from the Serial port - * @details This function checks the serial port to see if there has been any input. If there is data it is read - * until a terminator is discovered and then the command is parsed and acted upon - * @return void - *****************************************************************************************************************/ - static char text_buffer[SPRINTF_BUFFER_SIZE]; ///< Buffer for sprintf()/sscanf() - static uint8_t text_index = 0; ///< Variable for buffer position - while (Serial.available()) // Loop while there is incoming serial data +void readCommand() { + /*! + @brief Read incoming data from the Serial port + @details This function checks the serial port to see if there has been any input. If there is + data it is read until a terminator is discovered and then the command is parsed and + acted upon + @return void + */ + static char text_buffer[SPRINTF_BUFFER_SIZE]; ///< Buffer for sprintf()/sscanf() + static uint8_t text_index = 0; ///< Variable for buffer position + while (Serial.available()) // Loop while there is incoming serial data { - text_buffer[text_index] = Serial.read(); // Get the next byte of data + text_buffer[text_index] = Serial.read(); // Get the next byte of data // keep on reading until a newline shows up or the buffer is full - if (text_buffer[text_index] != '\n' && text_index < SPRINTF_BUFFER_SIZE) - { + if (text_buffer[text_index] != '\n' && text_index < SPRINTF_BUFFER_SIZE) { text_index++; - } - else - { + } else { text_buffer[text_index] = 0; // Add the termination character for (uint8_t i = 0; i < text_index; i++) // Convert the whole input buffer to uppercase { text_buffer[i] = toupper(text_buffer[i]); - } // for-next all characters in buffer + } // for-next all characters in buffer Serial.print(F("\nCommand \"")); Serial.write(text_buffer); Serial.print(F("\" received.\n")); - /************************************************************************************************************* - ** Parse the single-line command and perform the appropriate action. The current list of commands ** - ** understood are as follows: ** - ** ** - ** SETDATE - Set the device time ** - ** ** - *************************************************************************************************************/ - enum commands { SetDate, Unknown_Command }; // enumerate all commands - commands command; // declare enumerated type - char workBuffer[SPRINTF_BUFFER_SIZE]; // Buffer to hold string compare - sscanf(text_buffer,"%s %*s",workBuffer); // Parse the string for first word - if (!strcmp(workBuffer, "SETDATE")) - { - command = SetDate; // Set command number when found - } - else - { - command = Unknown_Command; // Otherwise set to not found - } // if-then-else a known command - unsigned int tokens,year,month,day,hour,minute,second; // Variables to hold parsed date/time - switch (command) - { - /*********************************************************************************************************** - ** Set the device time and date ** - ***********************************************************************************************************/ + /********************************************************************************************* + ** Parse the single-line command and perform the appropriate action. The current list of ** + ** commands understood are as follows: ** + ** ** + ** SETDATE - Set the device time ** + ** ** + *********************************************************************************************/ + enum commands { SetDate, Unknown_Command }; // enumerate all commands + commands command; // declare enumerated type + char workBuffer[SPRINTF_BUFFER_SIZE]; // Buffer to hold string compare + sscanf(text_buffer, "%s %*s", workBuffer); // Parse the string for first word + if (!strcmp(workBuffer, "SETDATE")) { + command = SetDate; // Set command number when found + } else { + command = Unknown_Command; // Otherwise set to not found + } // if-then-else a known command + unsigned int tokens, year, month, day, hour, minute, + second; // Variables to hold parsed date/time + switch (command) { + /********************************* + ** Set the device time and date ** + *********************************/ case SetDate: // Use sscanf() to parse the date/time into component variables - tokens = sscanf(text_buffer,"%*s %u-%u-%u %u:%u:%u;",&year,&month,&day,&hour,&minute,&second); - if (tokens != 6) // Check to see if it was parsed correctly + tokens = sscanf(text_buffer, "%*s %u-%u-%u %u:%u:%u;", &year, &month, &day, &hour, + &minute, &second); + if (tokens != 6) // Check to see if it was parsed correctly { Serial.print(F("Unable to parse date/time\n")); - } - else - { - DS3231M.adjust(DateTime(year,month,day,hour,minute,second)); // Adjust the RTC date/time + } else { + DS3231M.adjust( + DateTime(year, month, day, hour, minute, second)); // Adjust the RTC date/time Serial.print(F("Date has been set.")); - } // of if-then-else the date could be parsed + } // of if-then-else the date could be parsed break; - /*********************************************************************************************************** - ** Unknown command ** - ***********************************************************************************************************/ - case Unknown_Command: // Show options on bad command + /******************** + ** Unknown command ** + ********************/ + case Unknown_Command: // Show options on bad command default: Serial.println(F("Unknown command. Valid commands are:")); Serial.println(F("SETDATE yyyy-mm-dd hh:mm:ss")); - } // of switch statement to execute commands - text_index = 0; // reset the counter - } // of if-then-else we've received full command - } // of if-then there is something in our input buffer -} // of method readCommand + } // of switch statement to execute commands + text_index = 0; // reset the counter + } // of if-then-else we've received full command + } // of if-then there is something in our input buffer +} // of method readCommand -void loop() -{ - /*************************************************************************************************************//*! - * @brief Arduino method for the main program loop - * @details This is the main program for the Arduino IDE, it is an infinite loop and keeps on repeating. - * @return void - *****************************************************************************************************************/ +void loop() { + /*! + @brief Arduino method for the main program loop + @details This is the main program for the Arduino IDE, it is an infinite loop and keeps on + repeating + @return void + */ static uint8_t secs; - DateTime now = DS3231M.now(); // get the current time from device - if (secs != now.second()) // Output if seconds have changed + DateTime now = DS3231M.now(); // get the current time from device + if (secs != now.second()) // Output if seconds have changed { - // Use sprintf() to pretty print the date/time with leading zeros - char output_buffer[SPRINTF_BUFFER_SIZE]; ///< Temporary buffer for sprintf() - sprintf(output_buffer,"%04d-%02d-%02d %02d:%02d:%02d", now.year(), now.month(), - now.day(), now.hour(), now.minute(), now.second()); + // Use sprintf() to pretty print the date/time with leading zeros + char output_buffer[SPRINTF_BUFFER_SIZE]; ///< Temporary buffer for sprintf() + sprintf(output_buffer, "%04d-%02d-%02d %02d:%02d:%02d", now.year(), now.month(), now.day(), + now.hour(), now.minute(), now.second()); Serial.println(output_buffer); - secs = now.second(); // Set the counter variable - } // of if the seconds have changed - readCommand(); // See if serial port has incoming data -} // of method loop() \ No newline at end of file + secs = now.second(); // Set the counter variable + } // of if the seconds have changed + readCommand(); // See if serial port has incoming data +} // of method loop() diff --git a/keywords.txt b/keywords.txt index 98046c1..2225971 100644 --- a/keywords.txt +++ b/keywords.txt @@ -16,6 +16,7 @@ begin KEYWORD2 adjust KEYWORD2 now KEYWORD2 temperature KEYWORD2 +isStopped KEYWORD2 setAlarm KEYWORD2 isAlarm KEYWORD2 clearAlarm KEYWORD2 diff --git a/library.properties b/library.properties index 2f5d4d3..6ebde7e 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=DS3231M -version=1.0.4 +version=1.0.5 author=https://github.com/SV-Zanshin maintainer=https://github.com/SV-Zanshin sentence=Arduino library to use the Maxim Integrated DS3231M RTC (Real-Time-Clock) diff --git a/src/DS3231M.cpp b/src/DS3231M.cpp index 564d03e..118ce8b 100644 --- a/src/DS3231M.cpp +++ b/src/DS3231M.cpp @@ -1,555 +1,550 @@ -/***************************************************************************************************************//*! -* @file DS3231M.cpp -* @section DS3231Mcpp_intro_section Description -* Arduino Library to access the Maxim DS3231M Real Time Clock\n\n -* See main library header file for details -******************************************************************************************************************/ -#include "DS3231M.h" // Include the header definition -const uint8_t daysInMonth [] PROGMEM={31,28,31,30,31,30,31,31,30,31,30,31}; ///< Numbers of days in each month +/*! + @file DS3231M.cpp + @section DS3231Mcpp_intro_section Description + Arduino Library to access the Maxim DS3231M Real Time Clock\n\n + See main library header file for details +*/ +#include "DS3231M.h" // Include the header definition +const uint8_t daysInMonth[] PROGMEM = {31, 28, 31, 30, 31, 30, + 31, 31, 30, 31, 30, 31}; ///< Numbers of days in each month -static uint16_t date2days(uint16_t y, uint8_t m, uint8_t d) -{ - /*************************************************************************************************************//*! - * @brief returns the number of days from a given Y M D value - * @param[in] y Years - * @param[in] m Months - * @param[in] d Days - * @return Number of days from a given Y/M/D value - ****************************************************************************************************************/ - if (y >= 2000) - { - y -= 2000; // Remove year offset - } // if-then year is past 2000 - uint16_t days = d; // Store numbers of days - for (uint8_t i = 1; i < m; ++i) - { - days += pgm_read_byte(daysInMonth + i - 1); // Add number of days for each month - } // for-next each month - if (m > 2 && y % 4 == 0) - { - ++days; // Deal with leap years - } // if-then leap year - return days + 365 * y + (y + 3) / 4 - 1; // Return computed value -} // of method date2days -static long time2long(uint16_t days, uint8_t h, uint8_t m, uint8_t s) -{ - /*************************************************************************************************************//*! - * @brief returns the number of seconds from a given D H M S value - * @param[in] d Days - * @param[in] h Hours - * @param[in] m Minutes - * @param[in] s Seconds - * @return Number of seconds from a given Day/Hour/Minute/Second value - ****************************************************************************************************************/ +static uint16_t date2days(uint16_t y, uint8_t m, uint8_t d) { + /*! + @brief returns the number of days from a given Y M D value + @param[in] y Years + @param[in] m Months + @param[in] d Days + @return Number of days from a given Y/M/D value + */ + if (y >= 2000) { + y -= 2000; // Remove year offset + } // if-then year is past 2000 + uint16_t days = d; // Store numbers of days + for (uint8_t i = 1; i < m; ++i) { + days += pgm_read_byte(daysInMonth + i - 1); // Add number of days for each month + } // for-next each month + if (m > 2 && y % 4 == 0) { + ++days; // Deal with leap years + } // if-then leap year + return days + 365 * y + (y + 3) / 4 - 1; // Return computed value +} // of method date2days +static long time2long(uint16_t days, uint8_t h, uint8_t m, uint8_t s) { + /*! + @brief returns the number of seconds from a given D H M S value + @param[in] d Days + @param[in] h Hours + @param[in] m Minutes + @param[in] s Seconds + @return Number of seconds from a given Day/Hour/Minute/Second value + */ return ((days * 24L + h) * 60 + m) * 60 + s; -} // of method time2long() -static uint8_t conv2d(const char* p) -{ - /*************************************************************************************************************//*! - * @brief converts character string representation to decimal - * @param[in] p Input character array with length of 2 bytes - * @return Integer representation of value in array - ****************************************************************************************************************/ +} // of method time2long() +static uint8_t conv2d(const char* p) { + /*! + @brief converts character string representation to decimal + @param[in] p Input character array with length of 2 bytes + @return Integer representation of value in array + */ uint8_t v = 0; - if ('0' <= *p && *p <= '9') - { - v = *p - '0'; // set to integer value - } // if-then character is in range - return 10 * v + *++p - '0'; // shift MSB character over left and add 2nd character -} // of method conv2d -DateTime::DateTime (uint32_t t) -{ - /*************************************************************************************************************//*! - * @brief Class Constructor (Overloaded) - * @details Class Constructor for DateTime instantiates the class. This is an overloaded class constructor so there - * are multiple definitions. This implementation ignores time zones and DST changes. It also ignores leap - * seconds, see http://en.wikipedia.org/wiki/Leap_second - * @param[in] t Input time in seconds - ****************************************************************************************************************/ - t -= SECONDS_FROM_1970_TO_2000; // bring to 2000 timestamp from 1970 + if ('0' <= *p && *p <= '9') { + v = *p - '0'; // set to integer value + } // if-then character is in range + return 10 * v + *++p - '0'; // shift MSB character over left and add 2nd character +} // of method conv2d +DateTime::DateTime(uint32_t t) { + /*! + @brief Class Constructor (Overloaded) + @details Class Constructor for DateTime instantiates the class. This is an overloaded class + constructor so there are multiple definitions. This implementation ignores time + zones and DST changes. It also ignores leap seconds, see + http://en.wikipedia.org/wiki/Leap_second for details + @param[in] t Input time in seconds + */ + t -= SECONDS_FROM_1970_TO_2000; // bring to 2000 timestamp from 1970 ss = t % 60; t /= 60; mm = t % 60; t /= 60; - hh = t % 24; + hh = t % 24; uint16_t days = t / 24; - uint8_t leap; - for (yOff = 0; ; ++yOff) - { + uint8_t leap; + for (yOff = 0;; ++yOff) { leap = yOff % 4 == 0; - if (days < (uint16_t)365 + leap) - { + if (days < (uint16_t)365 + leap) { break; - } // if-then not a leap + } // if-then not a leap days -= 365 + leap; - } // of for-next each year - for (m = 1; ; ++m) - { + } // of for-next each year + for (m = 1;; ++m) { uint8_t daysPerMonth = pgm_read_byte(daysInMonth + m - 1); - if (leap && m == 2) - { + if (leap && m == 2) { ++daysPerMonth; - } // if-then - if (days < daysPerMonth) - { + } // if-then + if (days < daysPerMonth) { break; - } // if-then not a leap + } // if-then not a leap days -= daysPerMonth; - } // of for-next each month + } // of for-next each month d = days + 1; -} // of method DateTime() -DateTime::DateTime (uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec) -{ - /*************************************************************************************************************//*! - * @brief Class Constructor (Overloaded) - * @details Class Constructor for DateTime instantiates the class. This is an overloaded class constructor so - * there are multiple definitions. This implementation ignores time zones and DST changes. It also - * ignores leapseconds, see http://en.wikipedia.org/wiki/Leap_second - * @param[in] year Year - * @param[in] month Month - * @param[in] day Day - * @param[in] hour Hour - * @param[in] min Minute - * @param[in] sec Second - ******************************************************************************************************************/ if (year >= 2000) - { +} // of method DateTime() +DateTime::DateTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, + uint8_t sec) { + /*! + @brief Class Constructor (Overloaded) + @details Class Constructor for DateTime instantiates the class. This is an overloaded class + constructor so there are multiple definitions. This implementation ignores time zones + and DST changes. It also ignores leapseconds, see + http://en.wikipedia.org/wiki/Leap_second for details + @param[in] year Year + @param[in] month Month + @param[in] day Day + @param[in] hour Hour + @param[in] min Minute + @param[in] sec Second + + */ + if (year >= 2000) { year -= 2000; - } // if-then year past 2000 + } // if-then year past 2000 yOff = year; - m = month; - d = day; - hh = hour; - mm = min; - ss = sec; -} // of method DateTime() -/***************************************************************************************************************//*! -* @brief Class Constructor (Overloaded) -* @details Class Constructor for DateTime instantiates the class. This is an overloaded class constructor so there -* are multiple definitions. This implementation ignores time zones and DST changes. It also ignores leap -* seconds, see http://en.wikipedia.org/wiki/Leap_second. -* @param[in] copy DateTime class to instantiate class with -******************************************************************************************************************/ -DateTime::DateTime (const DateTime& copy):yOff(copy.yOff),m(copy.m),d(copy.d),hh(copy.hh),mm(copy.mm),ss(copy.ss){} -DateTime::DateTime (const char* date, const char* time) -{ - /*************************************************************************************************************//*! - * @brief Class Constructor (Overloaded) - * @details Class Constructor for DateTime instantiates the class. This is an overloaded class constructor so there - * are multiple definitions. This implementation ignores time zones and DST changes. It also ignores leap - * seconds, see http://en.wikipedia.org/wiki/Leap_second. This version uses a string representation of the - * date and time to instantiate. The date and time arrive in string format as follows: date = "Dec 26 2009", - * time = "12:34:56" - * @param[in] date Character buffer with year value in MMM DD YYYY format - * @param[in] time Character buffer with time value in HH:MM:SS format - ****************************************************************************************************************/ - yOff = conv2d(date + 9); // Compute the year offset - switch (date[0]) - { - case 'J': m = (date[1] == 'a') ? 1 : ((date[2] == 'n') ? 6 : 7); break; // Jan Jun Jul - case 'F': m = 2; break; // Feb - case 'A': m = date[2] == 'r' ? 4 : 8; break; // Apr Aug - case 'M': m = date[2] == 'r' ? 3 : 5; break; // May - case 'S': m = 9; break; // Sep - case 'O': m = 10; break; // Oct - case 'N': m = 11; break; // Nov - case 'D': m = 12; break; // Dec - } // of switch for the month - d = conv2d(date + 4); + m = month; + d = day; + hh = hour; + mm = min; + ss = sec; +} // of method DateTime() +/*! + @brief Class Constructor (Overloaded) + @details Class Constructor for DateTime instantiates the class. This is an overloaded class + constructor so there are multiple definitions. This implementation ignores time zones + and DST changes. It also ignores leapseconds, see + http://en.wikipedia.org/wiki/Leap_second for details + @param[in] copy DateTime class to instantiate class with +*/ +DateTime::DateTime(const DateTime& copy) + : yOff(copy.yOff), m(copy.m), d(copy.d), hh(copy.hh), mm(copy.mm), ss(copy.ss) {} +DateTime::DateTime(const char* date, const char* time) { + /*! + @brief Class Constructor (Overloaded) + @details Class Constructor for DateTime instantiates the class. This is an overloaded class + constructor so there are multiple definitions. This implementation ignores time zones + and DST changes. It also ignores leapseconds, see + http://en.wikipedia.org/wiki/Leap_second for details. This version uses a string + representation of the date and time to instantiate. The date and time arrive in string + format as follows: date = "Dec 26 2009", time = "12:34:56" + @param[in] date Character buffer with year value in MMM DD YYYY format + @param[in] time Character buffer with time value in HH:MM:SS format + */ + yOff = conv2d(date + 9); // Compute the year offset + switch (date[0]) { + case 'J': + m = (date[1] == 'a') ? 1 : ((date[2] == 'n') ? 6 : 7); + break; // Jan Jun Jul + case 'F': + m = 2; + break; // Feb + case 'A': + m = date[2] == 'r' ? 4 : 8; + break; // Apr Aug + case 'M': + m = date[2] == 'r' ? 3 : 5; + break; // May + case 'S': + m = 9; + break; // Sep + case 'O': + m = 10; + break; // Oct + case 'N': + m = 11; + break; // Nov + case 'D': + m = 12; + break; // Dec + } // of switch for the month + d = conv2d(date + 4); hh = conv2d(time); mm = conv2d(time + 3); ss = conv2d(time + 6); -} // of method DateTime() -DateTime::DateTime (const __FlashStringHelper* date, const __FlashStringHelper* time) -{ - /*************************************************************************************************************//*! - * @brief Class Constructor (Overloaded) - * @details Class Constructor for DateTime instantiates the class. This is an overloaded class constructor so - * there are multiple definitions. This implementation ignores time zones and DST changes. It also - * ignores leap seconds, see http://en.wikipedia.org/wiki/Leap_second. This version uses the compiled - * in Date and Time - * @param[in] date Character buffer with year value in MMM DD YYYY format - * @param[in] time Character buffer with time value in HH:MM:SS format - ****************************************************************************************************************/ +} // of method DateTime() +DateTime::DateTime(const __FlashStringHelper* date, const __FlashStringHelper* time) { + /*! + brief Class Constructor (Overloaded) + details Class Constructor for DateTime instantiates the class. This is an overloaded class + constructor so there are multiple definitions. This implementation ignores time zones + and DST changes. It also ignores leapseconds, see + http://en.wikipedia.org/wiki/Leap_second for details. This version uses the compiled + in Date and Time + @param[in] date Character buffer with year value in MMM DD YYYY format + @param[in] time Character buffer with time value in HH:MM:SS format + */ char ybuff[11], tbuff[9]; - memcpy_P(ybuff, date, 11); // copy flash string to memory - memcpy_P(tbuff, time, 9); // copy flash string to memory - DateTime(ybuff, tbuff); // Use the string version to instantiate -} // of method DateTime() -uint8_t DateTime::dayOfTheWeek() const -{ - /*************************************************************************************************************//*! - * @brief Return the day-of-week - * @details Monday = 1, Sunday = 7 - * @return DOW with Monday-Sunday 1-7 - ****************************************************************************************************************/ - uint16_t day = date2days(yOff, m, d); // compute the number of days - return (day + 6) % 7; // Jan 1, 2000 is a Saturday, i.e. 6 -} // of method dayOfTheWeek() -uint32_t DateTime::unixtime(void) const -{ - /*************************************************************************************************************//*! - * @brief return the UNIX time, which is seconds since 1970-01-01 00:00:00 - * @return UNIX Time (seconds since 1970-01-01 00:00:00) - ****************************************************************************************************************/ - uint32_t t; // Declare return variable - uint16_t days = date2days(yOff, m, d); // Compute days - t = time2long(days, hh, mm, ss); // Compute seconds - t += SECONDS_FROM_1970_TO_2000; // Add seconds from 1970 to 2000 + memcpy_P(ybuff, date, 11); // copy flash string to memory + memcpy_P(tbuff, time, 9); // copy flash string to memory + DateTime(ybuff, tbuff); // Use the string version to instantiate +} // of method DateTime() +uint8_t DateTime::dayOfTheWeek() const { + /*! + @brief Return the day-of-week + @details Monday = 1, Sunday = 7 + @return DOW with Monday-Sunday 1-7 + */ + uint16_t day = date2days(yOff, m, d); // compute the number of days + return (day + 6) % 7; // Jan 1, 2000 is a Saturday, i.e. 6 +} // of method dayOfTheWeek() +uint32_t DateTime::unixtime(void) const { + /*! + @brief return the UNIX time, which is seconds since 1970-01-01 00:00:00 + @return UNIX Time (seconds since 1970-01-01 00:00:00) + */ + uint32_t t; // Declare return variable + uint16_t days = date2days(yOff, m, d); // Compute days + t = time2long(days, hh, mm, ss); // Compute seconds + t += SECONDS_FROM_1970_TO_2000; // Add seconds from 1970 to 2000 return t; -} // of method unixtime() -long DateTime::secondstime(void) const -{ - /*************************************************************************************************************//*! - * @brief return the time in seconds since 2000-01-01 00:00:00 - * @return Seconds since 2000-01-01 00:00:00 - ****************************************************************************************************************/ - long t; +} // of method unixtime() +long DateTime::secondstime(void) const { + /*! + @brief return the time in seconds since 2000-01-01 00:00:00 + @return Seconds since 2000-01-01 00:00:00 + */ + long t; uint16_t days = date2days(yOff, m, d); - t = time2long(days, hh, mm, ss); + t = time2long(days, hh, mm, ss); return t; -} // of method secondstime() -DateTime DateTime::operator+(const TimeSpan& span) -{ - /*************************************************************************************************************//*! - * @brief Overloaded addition function definition - * @param[in] span TimeSpan to add - * @return new DateTime value - ****************************************************************************************************************/ +} // of method secondstime() +DateTime DateTime::operator+(const TimeSpan& span) { + /*! + @brief Overloaded addition function definition + @param[in] span TimeSpan to add + @return new DateTime value + */ return DateTime(unixtime() + span.totalseconds()); -} // of overloaded + function -DateTime DateTime::operator-(const TimeSpan& span) -{ - /*************************************************************************************************************//*! - * @brief Overloaded subtraction function definition - * @param[in] span TimeSpan to subtract - * @return new DateTime value - ****************************************************************************************************************/ +} // of overloaded + function +DateTime DateTime::operator-(const TimeSpan& span) { + /*! + @brief Overloaded subtraction function definition + @param[in] span TimeSpan to subtract + @return new DateTime value + */ return DateTime(unixtime() - span.totalseconds()); -} // of overloaded - function -TimeSpan DateTime::operator-(const DateTime& right) -{ - /*************************************************************************************************************//*! - * @brief Overloaded subtraction function definition - * @param[in] right DateTime to subtract - * @return new DateTime value - ****************************************************************************************************************/ - return TimeSpan(unixtime()-right.unixtime()); -} // of overloaded - function -/***************************************************************************************************************//*! -* @brief TimeSpan class constructor (Overloaded) -* @param[in] seconds Number of seconds -******************************************************************************************************************/ -TimeSpan::TimeSpan (int32_t seconds): _seconds(seconds) {} -/***************************************************************************************************************//*! -* @brief TimeSpan class constructor (Overloaded) -* @param[in] days Number of Days -* @param[in] hours Number of Hours -* @param[in] minutes Number of Minutes -* @param[in] seconds Number of Seconds -******************************************************************************************************************/ -TimeSpan::TimeSpan (int16_t days,int8_t hours,int8_t minutes,int8_t seconds): - _seconds((int32_t)days*86400L+(int32_t)hours*3600+(int32_t)minutes*60+seconds) {} -/***************************************************************************************************************//*! -* @brief TimeSpan class constructor (Overloaded) -* @param[in] copy TimeSpan to use to instantiate class -******************************************************************************************************************/ -TimeSpan::TimeSpan (const TimeSpan& copy): _seconds(copy._seconds) {} -TimeSpan TimeSpan::operator+(const TimeSpan& right) -{ - /*************************************************************************************************************//*! - * @brief TimeSpan class addition (Overloaded) - * @param[in] right TimeSpan to use to add to value - * @return Sum of two TimeSpans - ****************************************************************************************************************/ - return TimeSpan(_seconds+right._seconds); -} // of overloaded add -TimeSpan TimeSpan::operator-(const TimeSpan& right) -{ - /************************************************************************************************************//*! - * @brief TimeSpan class subtraction (Overloaded) - * @param[in] right TimeSpan to use to subtract from value - * @return Difference value - ****************************************************************************************************************/ - return TimeSpan(_seconds-right._seconds); -} // of overloaded subtract -DS3231M_Class::DS3231M_Class() {} ///< Unused class constructor -DS3231M_Class::~DS3231M_Class() {} ///< Unused class destructor -bool DS3231M_Class::begin(const uint32_t i2cSpeed) -{ - /*************************************************************************************************************//*! - * @brief starts I2C communications with the device - * @param[in] i2cSpeed I2C Speed to use for communications - * @return Boolean status of the initialization - ****************************************************************************************************************/ - Wire.begin(); // Start I2C as master device - Wire.setClock(i2cSpeed); // Set I2C clock speed - Wire.beginTransmission(DS3231M_ADDRESS); // Address the DS3231M - uint8_t errorCode = Wire.endTransmission(); // See if there's a device present - if (errorCode == 0) // If we have a DS3231M - { - writeByte(DS3231M_RTCHOUR,readByte(DS3231M_RTCHOUR)&B10111111); // Force use of 24 hour clock by turning off bit - } // of if-then device detected - else +} // of overloaded - function +TimeSpan DateTime::operator-(const DateTime& right) { + /*! + @brief Overloaded subtraction function definition + @param[in] right DateTime to subtract + @return new DateTime value + */ + return TimeSpan(unixtime() - right.unixtime()); +} // of overloaded - function +/*! + @brief TimeSpan class constructor (Overloaded) + @param[in] seconds Number of seconds +*/ +TimeSpan::TimeSpan(int32_t seconds) : _seconds(seconds) {} +/*! + @brief TimeSpan class constructor (Overloaded) + @param[in] days Number of Days + @param[in] hours Number of Hours + @param[in] minutes Number of Minutes + @param[in] seconds Number of Seconds +*/ +TimeSpan::TimeSpan(int16_t days, int8_t hours, int8_t minutes, int8_t seconds) + : _seconds((int32_t)days * 86400L + (int32_t)hours * 3600 + (int32_t)minutes * 60 + seconds) {} +/*! + @brief TimeSpan class constructor (Overloaded) + @param[in] copy TimeSpan to use to instantiate class +*/ +TimeSpan::TimeSpan(const TimeSpan& copy) : _seconds(copy._seconds) {} +TimeSpan TimeSpan::operator+(const TimeSpan& right) { + /*! + @brief TimeSpan class addition (Overloaded) + @param[in] right TimeSpan to use to add to value + @return Sum of two TimeSpans + */ + return TimeSpan(_seconds + right._seconds); +} // of overloaded add +TimeSpan TimeSpan::operator-(const TimeSpan& right) { + /*! + @brief TimeSpan class subtraction (Overloaded) + @param[in] right TimeSpan to use to subtract from value + @return Difference value + */ + return TimeSpan(_seconds - right._seconds); +} // of overloaded subtract +DS3231M_Class::DS3231M_Class() {} ///< Unused class constructor +DS3231M_Class::~DS3231M_Class() {} ///< Unused class destructor +bool DS3231M_Class::begin(const uint32_t i2cSpeed) { + /*! + @brief starts I2C communications with the device + @param[in] i2cSpeed I2C Speed to use for communications + @return Boolean status of the initialization + */ + Wire.begin(); // Start I2C as master device + Wire.setClock(i2cSpeed); // Set I2C clock speed + Wire.beginTransmission(DS3231M_ADDRESS); // Address the DS3231M + uint8_t errorCode = Wire.endTransmission(); // See if there's a device present + if (errorCode == 0) // If we have a DS3231M { + writeByte(DS3231M_RTCHOUR, readByte(DS3231M_RTCHOUR) & + B10111111); // Force use of 24 hour clock by turning off bit + } // of if-then device detected + else { return false; } return true; -} // of method begin() -uint8_t DS3231M_Class::readByte(const uint8_t addr) -{ - /************************************************************************************************************//*! - * @brief reads 1 byte from the specified I2C memory address - * @param[in] addr Memory/Register address - * @return byte read from specified address - ****************************************************************************************************************/ - Wire.beginTransmission(DS3231M_ADDRESS); // Address the I2C device - Wire.write(addr); // Send the register address to read - _TransmissionStatus = Wire.endTransmission(); // Close transmission - Wire.requestFrom(DS3231M_ADDRESS, (uint8_t)1); // Request 1 byte of data - return Wire.read(); // read it and return it -} // of method readByte() -void DS3231M_Class::writeByte(const uint8_t addr, const uint8_t data) -{ - /*************************************************************************************************************//*! - * @brief writes 1 byte to the specified I2C memory address - * @param[in] addr Memory/Register address - * @param[in] data Byte to write - ****************************************************************************************************************/ - Wire.beginTransmission(DS3231M_ADDRESS); // Address the I2C device - Wire.write(addr); // Send the register address to write - Wire.write(data); // Send the data to write - _TransmissionStatus = Wire.endTransmission(); // Close transmission -} // of method writeByte() -uint8_t DS3231M_Class::bcd2int(const uint8_t bcd) -{ - /*************************************************************************************************************//*! - * @brief converts a BCD encoded value into number representation - * @details Takes a byte of BCD (Binard coded Decimal) and converts to the binary integer representation - * @param[in] bcd Binary-Coded-Decimal source byte - * @return Unsigned integer value - ****************************************************************************************************************/ - return ((bcd/16 * 10) + (bcd % 16)); -} // of method bcd2int -uint8_t DS3231M_Class::int2bcd(const uint8_t dec) -{ - /***************************************************************************************************************//*! - * @brief converts a byte to BCD - * @details Takes an unsigned byte and converts to BCD (Binard coded Decimal) - * @param[in] dec Unsigned integer value - * @return Binary-Coded-Decimal value - ******************************************************************************************************************/ - return ((dec/10 * 16) + (dec % 10)); -} // of method int2bcd -void DS3231M_Class::adjust() -{ - /*************************************************************************************************************//*! - * @brief sets the current date/time (Overloaded) - * @details This is an overloaded function, if called with no parameters then the RTC is set to the date/time when - * the program was compiled and uploaded. Otherwise the values are set, but the oscillator is stopped - * during the process and needs to be restarted upon completion - ******************************************************************************************************************/ - adjust(DateTime(F(__DATE__), F(__TIME__))); // Set to compile time -} // of method adjust -void DS3231M_Class::adjust(const DateTime& dt) -{ - /*************************************************************************************************************//*! - * @brief sets the current date/time (Overloaded) - * @details This is an overloaded function, if called with no parameters then the RTC is set to the date/time when - * the program was compiled and uploaded. Otherwise the values are set, but the oscillator is stopped - * during the process and needs to be restarted upon completion - * @param[in] dt DateTime value to set the clock to - *****************************************************************************************************************/ - writeByte(DS3231M_RTCSEC,int2bcd(dt.second()%60)); // Write seconds, keep device off - writeByte(DS3231M_RTCMIN,int2bcd(dt.minute()%60)); // Write the minutes value - writeByte(DS3231M_RTCHOUR,int2bcd(dt.hour()%24)); // Also re-sets the 24Hour clock on - writeByte(DS3231M_RTCWKDAY,dt.dayOfTheWeek()); // Update the weekday - writeByte(DS3231M_RTCDATE,int2bcd(dt.day())); // Write the day of month - writeByte(DS3231M_RTCMTH,int2bcd(dt.month())); // Month, ignore century bit - writeByte(DS3231M_RTCYEAR,int2bcd(dt.year()-2000)); // Write the year - writeByte(DS3231M_STATUS,readByte(DS3231M_STATUS)&B01111111); // Unset OSC flag bit if set - writeByte(DS3231M_CONTROL,readByte(DS3231M_CONTROL)&B01111111); // Unset EOSC flag bit if set - _SetUnixTime = now().unixtime(); // Store time of last change -} // of method adjust -DateTime DS3231M_Class::now() -{ - /*************************************************************************************************************//*! - * @brief returns the current date/time - * @return Current Date/Time - ****************************************************************************************************************/ +} // of method begin() +uint8_t DS3231M_Class::readByte(const uint8_t addr) { + /*! + @brief reads 1 byte from the specified I2C memory address + @param[in] addr Memory/Register address + @return byte read from specified address + */ + Wire.beginTransmission(DS3231M_ADDRESS); // Address the I2C device + Wire.write(addr); // Send the register address to read + _TransmissionStatus = Wire.endTransmission(); // Close transmission + Wire.requestFrom(DS3231M_ADDRESS, (uint8_t)1); // Request 1 byte of data + return Wire.read(); // read it and return it +} // of method readByte() +void DS3231M_Class::writeByte(const uint8_t addr, const uint8_t data) { + /*! + @brief writes 1 byte to the specified I2C memory address + @param[in] addr Memory/Register address + @param[in] data Byte to write + */ Wire.beginTransmission(DS3231M_ADDRESS); // Address the I2C device - Wire.write(DS3231M_RTCSEC); // Start at specified register + Wire.write(addr); // Send the register address to write + Wire.write(data); // Send the data to write _TransmissionStatus = Wire.endTransmission(); // Close transmission - Wire.requestFrom(DS3231M_ADDRESS, (uint8_t)7); // Request 7 bytes of data - if(Wire.available()==7) // Wait until the data is ready - { - _ss = bcd2int(Wire.read() & 0x7F); // Mask high bit in seconds - _mm = bcd2int(Wire.read() & 0x7F); // Mask high bit in minutes - _hh = bcd2int(Wire.read() & 0x3F); // Mask 2 high bits in hours and clamp to 0-23 - Wire.read(); // Read and ignore Day-Of-Week register - _d = bcd2int(Wire.read() & 0x3F); // Mask 2 high bits for day of month - _m = bcd2int(Wire.read() & 0x1F); // Mask 3 high bits for Month - _y = bcd2int(Wire.read()) + 2000; // Add 2000 to internal year - } // of if-then there is data to be read - return DateTime (_y, _m, _d, _hh, _mm, _ss); // Return class value -} // of method now() -int32_t DS3231M_Class::temperature() -{ - /*************************************************************************************************************//*! - * @brief returns the internal temperature in tenths of degrees Celsius - * @details Using 1/10 of degrees allows use of integer rather than floating point - * @return temperature in 1/10 degrees Celsius - ****************************************************************************************************************/ - int32_t temp = readByte(DS3231M_TEMPERATURE)<<8; // read MSB - temp |= readByte(DS3231M_TEMPERATURE+1); // get LSB - temp = temp>>6; // Shift over 6 bits - if (temp & 0x200) - { - temp |= 0xFC00; // keep negative by setting bits - } // if-then a negative number - temp = temp*100/4; // value is in .25C increments - return temp; // Return computed temperature -} // of method temperature() -void DS3231M_Class::setAlarm(const uint8_t alarmType, const DateTime dt, const bool state ) -{ - /*************************************************************************************************************//*! - * @brief will set one of the 2 alarms - * @details As the two alarms aren't identical in what will trigger them, this call chooses which alarm to set - * depending upon the "alarmType" parameter value. - * @param[in] alarmType Alarm Type, see the alarm type enumerated values - * @param[in] dt Date/Time to set the alarm to - * @param[in] state Alarm Enable state - ****************************************************************************************************************/ - if (alarmType >= UnknownAlarm) +} // of method writeByte() +uint8_t DS3231M_Class::bcd2int(const uint8_t bcd) { + /*! + @brief converts a BCD encoded value into number representation + @details Takes a byte of BCD (Binard coded Decimal) and converts to the binary integer + representation + @param[in] bcd Binary-Coded-Decimal source byte + @return Unsigned integer value + */ + return ((bcd / 16 * 10) + (bcd % 16)); +} // of method bcd2int +uint8_t DS3231M_Class::int2bcd(const uint8_t dec) { + /*! + @brief converts a byte to BCD + @details Takes an unsigned byte and converts to BCD (Binard coded Decimal) + @param[in] dec Unsigned integer value + @return Binary-Coded-Decimal value + */ + return ((dec / 10 * 16) + (dec % 10)); +} // of method int2bcd +void DS3231M_Class::adjust() { + /*! + @brief sets the current date/time (Overloaded) + @details This is an overloaded function, if called with no parameters then the RTC is set to + the date/time when the program was compiled and uploaded. Otherwise the values are + set, but the oscillator is stopped during the process and needs to be restarted upon + completion + */ + adjust(DateTime(F(__DATE__), F(__TIME__))); // Set to compile time +} // of method adjust +void DS3231M_Class::adjust(const DateTime& dt) { + /*! + @brief sets the current date/time (Overloaded) + @details This is an overloaded function, if called with no parameters then the RTC is set to + the date/time when the program was compiled and uploaded. Otherwise the values are + set, but the oscillator is stopped during the process and needs to be restarted upon + completion + @param[in] dt DateTime value to set the clock to + */ + writeByte(DS3231M_RTCSEC, int2bcd(dt.second() % 60)); // Write seconds, keep device off + writeByte(DS3231M_RTCMIN, int2bcd(dt.minute() % 60)); // Write the minutes value + writeByte(DS3231M_RTCHOUR, int2bcd(dt.hour() % 24)); // Also resets the 24Hour clock on + writeByte(DS3231M_RTCWKDAY, dt.dayOfTheWeek()); // Update the weekday + writeByte(DS3231M_RTCDATE, int2bcd(dt.day())); // Write the day of month + writeByte(DS3231M_RTCMTH, int2bcd(dt.month())); // Month, ignore century bit + writeByte(DS3231M_RTCYEAR, int2bcd(dt.year() - 2000)); // Write the year + writeByte(DS3231M_STATUS, readByte(DS3231M_STATUS) & B01111111); // Unset OSC flag bit if set + writeByte(DS3231M_CONTROL, readByte(DS3231M_CONTROL) & B01111111); // Unset EOSC flag bit if set + _SetUnixTime = now().unixtime(); // Store time of last change +} // of method adjust +DateTime DS3231M_Class::now() { + /*! + @brief returns the current date/time + @return Current Date/Time + */ + Wire.beginTransmission(DS3231M_ADDRESS); // Address the I2C device + Wire.write(DS3231M_RTCSEC); // Start at specified register + _TransmissionStatus = Wire.endTransmission(); // Close transmission + Wire.requestFrom(DS3231M_ADDRESS, (uint8_t)7); // Request 7 bytes of data + if (Wire.available() == 7) // Wait until the data is ready { - return; // Don't do anything if out-of-range - } // if-then out of range alarm type - if (alarmType> 6; // Shift over 6 bits + if (temp & 0x200) { + temp |= 0xFC00; // keep negative by setting bits + } // if-then a negative number + temp = temp * 100 / 4; // value is in .25C increments + return temp; // Return computed temperature +} // of method temperature() +bool DS3231M_Class::isStopped() { + /*! + @brief Check to see if the oscillator is running + @return return false if the oscillator is running, otherwise return true + */ + return (readByte(DS3231M_STATUS) >> 7); // shift OSF register bit to LSB for true/false +} // of method isAlarm() +void DS3231M_Class::setAlarm(const uint8_t alarmType, const DateTime dt, const bool state) { + /*! + @brief will set one of the 2 alarms + @details As the two alarms aren't identical in what will trigger them, this call chooses which + alarm to set depending upon the "alarmType" parameter value. + @param[in] alarmType Alarm Type, see the alarm type enumerated values + @param[in] dt Date/Time to set the alarm to + @param[in] state Alarm Enable state + */ + if (alarmType >= UnknownAlarm) { + return; // Don't do anything if out-of-range + } // if-then out of range alarm type + if (alarmType < everyMinute) // These types go to alarm 1 { - writeByte(DS3231M_ALM1SEC,int2bcd(dt.second())); // Set seconds value - writeByte(DS3231M_ALM1MIN,int2bcd(dt.minute())); // Set minutes value - writeByte(DS3231M_ALM1HOUR,int2bcd(dt.hour())); // Set hours value - if (alarmType == secondsMinutesHoursDateMatch) // Set either day of month or day + writeByte(DS3231M_ALM1SEC, int2bcd(dt.second())); // Set seconds value + writeByte(DS3231M_ALM1MIN, int2bcd(dt.minute())); // Set minutes value + writeByte(DS3231M_ALM1HOUR, int2bcd(dt.hour())); // Set hours value + if (alarmType == secondsMinutesHoursDateMatch) // Set either day of month or day { writeByte(DS3231M_ALM1DATE, int2bcd(dt.day())); - } - else - { + } else { writeByte(DS3231M_ALM1DATE, int2bcd(dt.dayOfTheWeek())); - } // if-then-else DateMathc - if(alarmType0 && dow<8) // If parameter is in range, then set the register +} // of method weekdayRead() +uint8_t DS3231M_Class::weekdayWrite(const uint8_t dow) { + /*! + @brief Writes the weekday (1-7) to the register and returns the new setting + @details Values are 1-7 + @param[in] dow Day of Week to write + @return returns the dow input value unless out-of-range + */ + uint8_t retval = 0; // assume we have an error + if (dow > 0 && dow < 8) // If parameter is in range, then set the register { - writeByte(DS3231M_RTCWKDAY,dow); - retval = dow; - } // of if-then we have a good DOW + writeByte(DS3231M_RTCWKDAY, dow); + retval = dow; + } // of if-then we have a good DOW return retval; -} // of method weekdayWrite() -void DS3231M_Class::pinAlarm() -{ - /*************************************************************************************************************//*! - * @brief Sets the control register flag to make the INT/SQW Pin get pulled up on an alarm - ****************************************************************************************************************/ - writeByte(DS3231M_CONTROL,readByte(DS3231M_CONTROL)|0x4); // Set bit 3 to on -} // of method pinAlarm() -void DS3231M_Class::pinSquareWave() -{ - /*************************************************************************************************************//*! - * @brief Sets the control register flag to make the INT/SQW Pin produce a 1Hz signal - ****************************************************************************************************************/ - writeByte(DS3231M_CONTROL,readByte(DS3231M_CONTROL)&~0x4); -} // of method pinSquareWave() +} // of method weekdayWrite() +void DS3231M_Class::pinAlarm() { + /*! + @brief Sets the control register flag to make the INT/SQW Pin get pulled up on an alarm + */ + writeByte(DS3231M_CONTROL, readByte(DS3231M_CONTROL) | 0x4); // Set bit 3 to on +} // of method pinAlarm() +void DS3231M_Class::pinSquareWave() { + /*! + @brief Sets the control register flag to make the INT/SQW Pin produce a 1Hz signal + */ + writeByte(DS3231M_CONTROL, readByte(DS3231M_CONTROL) & ~0x4); +} // of method pinSquareWave() diff --git a/src/DS3231M.h b/src/DS3231M.h index 28ffb29..57dd951 100644 --- a/src/DS3231M.h +++ b/src/DS3231M.h @@ -1,182 +1,203 @@ -/***************************************************************************************************************//*! -* @file DS3231M.h -* -* @mainpage Arduino Library Header to access the Maxim DS3231M Real Time Clock -* -* @section intro_section Description -* -* Class definition header for the DS3231M real-time-clock from Maxim integrated, described at -* https://www.maximintegrated.com/en/products/digital/real-time-clocks/DS3231M.html. The DS3231M's data sheet is -* located at https://datasheets.maximintegrated.com/en/ds/DS3231M.pdf \n\n -* -* The most recent version of this library can be found at https://github.com/SV-Zanshin/DS3231M and a detailed -* library description is on the library's wiki at https://github.com/SV-Zanshin/DS3231M/wiki \n\n -* -* Use is made of portions of Adafruit's RTClib Version 1.2.0 at https://github.com/adafruit/RTClib which is a fork -* of the original RTClib from Jeelabs. The code encompasses simple classes for time and date. -* -* @section license __**GNU General Public License v3.0**__ -* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General -* Public License as published by the Free Software Foundation, either version 3 of the License, or (at your -* option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY -* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -* @section author Author -* -* Written by Arnd\@SV-Zanshin -* -* @section versions Changelog -* -* Version| Date | Developer | Comments -* ------ | ---------- | ----------------------------- | -------- -* 1.0.4 | 2020-05-17 | https://github.com/neocao123 | Issue #12 - overflow on hours was allowed -* 1.0.4 | 2020-05-17 | https://github.com/SV-Zanshin | Cleaned up comments -* 1.0.4 | 2019-08-18 | https://github.com/lagg070988 | Issue #9 - PinAlarm & PinSquareWave logic corrected -* 1.0.4 | 2019-02-02 | https://github.com/SV-Zanshin | Issue #8 - converted documentation to doxygen -* 1.0.3 | 2019-01-27 | https://github.com/SV-Zanshin | Issue #4 - incorrect datatype for I2C causes overflow -* 1.0.2 | 2018-07-02 | https://github.com/SV-Zanshin | Added guard code against multiple I2C Speed definitions -* 1.0.2 | 2018-06-30 | https://github.com/SV-Zanshin | Issue #3 - Allow 400KHz I2C bus speed to be set -* 1.0.0 | 2017-08-19 | https://github.com/SV-Zanshin | Initial release -* 1.0.0b | 2017-08-13 | https://github.com/SV-Zanshin | Initial coding +/*! @file DS3231M.h + + @mainpage Arduino Library Header to access the Maxim DS3231M Real Time Clock + + @section intro_section Description + + Class definition header for the DS3231M real-time-clock from Maxim integrated, described at + https://www.maximintegrated.com/en/products/digital/real-time-clocks/DS3231M.html. The DS3231M's + data sheet is located at https://datasheets.maximintegrated.com/en/ds/DS3231M.pdf \n\n + + The most recent version of this library can be found at https://github.com/SV-Zanshin/DS3231M and a + detailed library description is on the library's wiki at https://github.com/SV-Zanshin/DS3231M/wiki + \n\n + + Use is made of portions of Adafruit's RTClib Version 1.2.0 at https://github.com/adafruit/RTClib + which is a fork of the original RTClib from Jeelabs. The code encompasses simple classes for time + and date. + + @section license __**GNU General Public License v3.0**__ + This program is free software: you can redistribute it and/or modify it under the terms of the GNU + General Public License as published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. This program is distributed in the hope that it + will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should + have received a copy of the GNU General Public License along with this program. If not, see + . + + @section author Author + + Written by Arnd\@SV-Zanshin + + @section versions Changelog + + Version| Date | Developer | Comments + ------ | ---------- | ---------- | -------- + 1.0.5 | 2020-09-28 | gvisca44 | Issue #13 - add function "isStopped()" + 1.0.5 | 2020-09-28 | SV-Zanshin | Issue #14 - Reformat using clang-format + 1.0.4 | 2020-05-17 | neocao123 | Issue #12 - overflow on hours was allowed + 1.0.4 | 2020-05-17 | SV-Zanshin | Cleaned up comments + 1.0.4 | 2019-08-18 | lagg070988 | Issue #9 - PinAlarm & PinSquareWave logic corrected + 1.0.4 | 2019-02-02 | SV-Zanshin | Issue #8 - converted documentation to doxygen + 1.0.3 | 2019-01-27 | SV-Zanshin | Issue #4 - incorrect datatype for I2C causes overflow + 1.0.2 | 2018-07-02 | SV-Zanshin | Added guard code against multiple I2C Speed definitions + 1.0.2 | 2018-06-30 | SV-Zanshin | Issue #3 - Allow 400KHz I2C bus speed to be set + 1.0.0 | 2017-08-19 | SV-Zanshin | Initial release + 1.0.0b | 2017-08-13 | SV-Zanshin | Initial coding */ -#include "Arduino.h" // Arduino data type definitions -#include // Standard I2C "Wire" library + +#include // Standard I2C "Wire" library + +#include "Arduino.h" // Arduino data type definitions #ifndef DS3231M_h - /*! @brief Guard code definition to prevent multiple definitions */ - #define DS3231M_h - -/***************************************************************************************************************//*! -* @brief Declare the enumerated type for the various type of alarm that can be set -*******************************************************************************************************************/ -enum alarmTypes {everySecond,secondsMatch,secondsMinutesMatch,secondsMinutesHoursMatch,secondsMinutesHoursDateMatch, - secondsMinutesHoursDayMatch,everyMinute,minutesMatch,minutesHoursMatch,minutesHoursDateMatch, - minutesHoursDayMatch,UnknownAlarm}; - -/***************************************************************************************************************** -** Declare classes used in within the class ** -*****************************************************************************************************************/ -class TimeSpan; ///< TimeSpan class definition - -/***************************************************************************************************************** -** Declare constants used in the class ** -*****************************************************************************************************************/ - #ifndef I2C_MODES - /*! @brief Guard code definition to prevent multiple definitions */ - #define I2C_MODES - const uint32_t I2C_STANDARD_MODE = 100000; ///< Default normal I2C 100KHz speed - const uint32_t I2C_FAST_MODE = 400000; ///< Fast mode with 400KHz - #endif - const uint32_t SECONDS_PER_DAY = 86400; ///< 60 secs * 60 mins * 24 hours - const uint32_t SECONDS_FROM_1970_TO_2000 = 946684800; ///< Number of seconds betwen 1970/1/1 to 2000/1/1 - const uint8_t DS3231M_ADDRESS = 0x68; ///< Fixed I2C Address for DS3231M - const uint8_t DS3231M_RTCSEC = 0x00; ///< DS3231 RTCSEC Register Address - const uint8_t DS3231M_RTCMIN = 0x01; ///< DS3231 RTCMIN Register Address - const uint8_t DS3231M_RTCHOUR = 0x02; ///< DS3231 RTCHOUR Register Address - const uint8_t DS3231M_RTCWKDAY = 0x03; ///< DS3231 RTCWKDAY Register Address - const uint8_t DS3231M_RTCDATE = 0x04; ///< DS3231 RTCDATE Register Address - const uint8_t DS3231M_RTCMTH = 0x05; ///< DS3231 RTCMTH Register Address - const uint8_t DS3231M_RTCYEAR = 0x06; ///< DS3231 RTCYEAR Register Address - const uint8_t DS3231M_ALM1SEC = 0x07; ///< DS3231 ALM1SEC Register Address - const uint8_t DS3231M_ALM1MIN = 0x08; ///< DS3231 ALM1MIN Register Address - const uint8_t DS3231M_ALM1HOUR = 0x09; ///< DS3231 ALM1HOUR Register Address - const uint8_t DS3231M_ALM1DATE = 0x0A; ///< DS3231 ALM1DATE Register Address - const uint8_t DS3231M_ALM2MIN = 0x0B; ///< DS3231 ALM2SEC Register Address - const uint8_t DS3231M_ALM2HOUR = 0x0C; ///< DS3231 ALM2HOUR Register Address - const uint8_t DS3231M_ALM2DATE = 0x0D; ///< DS3231 ALM2DATE Register Address - const uint8_t DS3231M_CONTROL = 0x0E; ///< DS3231 CONTROL Register Address - const uint8_t DS3231M_STATUS = 0x0F; ///< DS3231 STATUS Register Address - const uint8_t DS3231M_AGING = 0x10; ///< DS3231 AGING Register Address - const uint8_t DS3231M_TEMPERATURE = 0x11; ///< DS3231 TEMPERATURE Register Address - -/***************************************************************************************************************//*! -* @brief Simple general-purpose date/time class -* @details Class has no TZ / DST / leap second handling. Copied from RTClib. For further information on this -* implementation see https://github.com/SV-Zanshin/DS3231M/wiki/DateTimeClass -*******************************************************************************************************************/ - class DateTime - { - public: - DateTime (uint32_t t=0); - DateTime (uint16_t year,uint8_t month,uint8_t day,uint8_t hour=0,uint8_t min=0,uint8_t sec=0); // // - DateTime (const DateTime& copy); - DateTime (const char* date, const char* time); - DateTime (const __FlashStringHelper* date, const __FlashStringHelper* time); - uint16_t year() const { return 2000 + yOff; } ///< Return the year - uint8_t month() const { return m; } ///< Return the month - uint8_t day() const { return d; } ///< Return the day - uint8_t hour() const { return hh; } ///< Return the hour - uint8_t minute() const { return mm; } ///< Return the minute - uint8_t second() const { return ss; } ///< Return the second - uint8_t dayOfTheWeek() const; - long secondstime() const; - uint32_t unixtime(void) const; - DateTime operator+(const TimeSpan& span); // addition - DateTime operator-(const TimeSpan& span); // subtraction - TimeSpan operator-(const DateTime& right); // subtraction - protected: - uint8_t yOff, ///< Year Offset - m, ///< Months - d, ///< Days - hh, ///< Hours - mm, ///< Minutes - ss; ///< Seconds - }; // of class DateTime definition - -/***************************************************************************************************************//*! -* @brief Simple general-purpose TimeSpan -* @details Timespan class which can represent changes in time with seconds accuracy. Copied from RTClib. For -* further information see ** https://github.com/SV-Zanshin/DS3231M/wiki/TimeSpanClass -*******************************************************************************************************************/ - class TimeSpan - { - public: - TimeSpan (int32_t seconds = 0); - TimeSpan (int16_t days, int8_t hours, int8_t minutes, int8_t seconds); - TimeSpan (const TimeSpan& copy); - int16_t days() const { return _seconds / 86400L; } ///< Return days in span - int8_t hours() const { return _seconds / 3600 % 24; } ///< Return hours in span - int8_t minutes() const { return _seconds / 60 % 60; } ///< Return minutes in span - int8_t seconds() const { return _seconds % 60; } ///< Return seconds in span - int32_t totalseconds() const { return _seconds; } ///< Return total span in seconds - TimeSpan operator+(const TimeSpan& right); - TimeSpan operator-(const TimeSpan& right); - protected: - int32_t _seconds; ///< internal seconds variable - }; // of class TimeSpan definition - -/***************************************************************************************************************//*! -* @brief Main DS3231M class definition for the Real-Time clock -*******************************************************************************************************************/ - class DS3231M_Class - { - public: - DS3231M_Class(); - ~DS3231M_Class(); // Class destructor - bool begin(const uint32_t i2cSpeed = I2C_STANDARD_MODE); // Start I2C Communications - void adjust(); // Set the date and time to compile - void adjust(const DateTime& dt); // Set the date and time - DateTime now(); // return time - int32_t temperature(); // return clock temp in 100x °C - void setAlarm(const uint8_t alarmType, const DateTime dt, const bool state = true ); // Set an Alarm - bool isAlarm(); // Return if alarm is triggered - void clearAlarm(); // Clear the alarm state flag - void kHz32(const bool state); // Turn 32kHz output on or off - int8_t getAgingOffset(); // Get the clock's aging offset - int8_t setAgingOffset(const int8_t agingOffset); // Set the clock's aging offset - uint8_t weekdayRead(); // Read weekday from RTC - uint8_t weekdayWrite(const uint8_t dow); // Write weekday to RTC - void pinAlarm(); // Make the INTSQW go up on alarm - void pinSquareWave(); // Make the INTSQW be a 1Hz signal - private: - uint8_t readByte(const uint8_t addr); // Read 1 byte from address on I2C - void writeByte(const uint8_t addr, const uint8_t data); // Write 1 byte at address to I2C - uint8_t bcd2int(const uint8_t bcd); // convert BCD digits to integer - uint8_t int2bcd(const uint8_t dec); // convert integer to BCD - uint8_t _TransmissionStatus = 0; ///< Status of I2C transmission - uint32_t _SetUnixTime = 0; ///< UNIX time when clock last set - uint8_t _ss,_mm,_hh,_d,_m; ///< Define date components - uint16_t _y; ///< Define date components - }; // of DS3231M class definition -#endif \ No newline at end of file +/*! @brief Guard code definition to prevent multiple definitions */ +#define DS3231M_h + +/************************************************************************************************** +** Declare enumerated types ** +* ************************************************************************************************/ +/*! @brief Declare the enumerated type for the various type of alarm that can be set */ +enum alarmTypes { + everySecond, + secondsMatch, + secondsMinutesMatch, + secondsMinutesHoursMatch, + secondsMinutesHoursDateMatch, + secondsMinutesHoursDayMatch, + everyMinute, + minutesMatch, + minutesHoursMatch, + minutesHoursDateMatch, + minutesHoursDayMatch, + UnknownAlarm +}; + +/************************************************************************************************** +** Declare classes used in within the class ** +**************************************************************************************************/ +class TimeSpan; ///< TimeSpan class definition + +/************************************************************************************************** +** Declare constants used in the class ** +**************************************************************************************************/ +#ifndef I2C_MODES +/*! @brief Guard code definition to prevent multiple definitions */ +#define I2C_MODES +const uint32_t I2C_STANDARD_MODE = 100000; ///< Default normal I2C 100KHz speed +const uint32_t I2C_FAST_MODE = 400000; ///< Fast mode with 400KHz +#endif +const uint32_t SECONDS_PER_DAY = 86400; ///< 60 secs * 60 mins * 24 hours +const uint32_t SECONDS_FROM_1970_TO_2000 = 946684800; ///< Seconds between 1970/1/1 to 2000/1/1 +const uint8_t DS3231M_ADDRESS = 0x68; ///< Fixed I2C Address for DS3231M +const uint8_t DS3231M_RTCSEC = 0x00; ///< DS3231 RTCSEC Register Address +const uint8_t DS3231M_RTCMIN = 0x01; ///< DS3231 RTCMIN Register Address +const uint8_t DS3231M_RTCHOUR = 0x02; ///< DS3231 RTCHOUR Register Address +const uint8_t DS3231M_RTCWKDAY = 0x03; ///< DS3231 RTCWKDAY Register Address +const uint8_t DS3231M_RTCDATE = 0x04; ///< DS3231 RTCDATE Register Address +const uint8_t DS3231M_RTCMTH = 0x05; ///< DS3231 RTCMTH Register Address +const uint8_t DS3231M_RTCYEAR = 0x06; ///< DS3231 RTCYEAR Register Address +const uint8_t DS3231M_ALM1SEC = 0x07; ///< DS3231 ALM1SEC Register Address +const uint8_t DS3231M_ALM1MIN = 0x08; ///< DS3231 ALM1MIN Register Address +const uint8_t DS3231M_ALM1HOUR = 0x09; ///< DS3231 ALM1HOUR Register Address +const uint8_t DS3231M_ALM1DATE = 0x0A; ///< DS3231 ALM1DATE Register Address +const uint8_t DS3231M_ALM2MIN = 0x0B; ///< DS3231 ALM2SEC Register Address +const uint8_t DS3231M_ALM2HOUR = 0x0C; ///< DS3231 ALM2HOUR Register Address +const uint8_t DS3231M_ALM2DATE = 0x0D; ///< DS3231 ALM2DATE Register Address +const uint8_t DS3231M_CONTROL = 0x0E; ///< DS3231 CONTROL Register Address +const uint8_t DS3231M_STATUS = 0x0F; ///< DS3231 STATUS Register Address +const uint8_t DS3231M_AGING = 0x10; ///< DS3231 AGING Register Address +const uint8_t DS3231M_TEMPERATURE = 0x11; ///< DS3231 TEMPERATURE Register Address + +/*! + @brief Simple general-purpose date/time class + @details Class has no TZ / DST / leap second handling. Copied from RTClib. For further + information on this implementation see + https://github.com/SV-Zanshin/DS3231M/wiki/DateTimeClass +*/ +class DateTime { + public: + DateTime(uint32_t t = 0); + DateTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour = 0, uint8_t min = 0, + uint8_t sec = 0); // // + DateTime(const DateTime& copy); + DateTime(const char* date, const char* time); + DateTime(const __FlashStringHelper* date, const __FlashStringHelper* time); + uint16_t year() const { return 2000 + yOff; } ///< Return the year + uint8_t month() const { return m; } ///< Return the month + uint8_t day() const { return d; } ///< Return the day + uint8_t hour() const { return hh; } ///< Return the hour + uint8_t minute() const { return mm; } ///< Return the minute + uint8_t second() const { return ss; } ///< Return the second + uint8_t dayOfTheWeek() const; + long secondstime() const; + uint32_t unixtime(void) const; + DateTime operator+(const TimeSpan& span); // addition + DateTime operator-(const TimeSpan& span); // subtraction + TimeSpan operator-(const DateTime& right); // subtraction + protected: + uint8_t yOff, ///< Year Offset + m, ///< Months + d, ///< Days + hh, ///< Hours + mm, ///< Minutes + ss; ///< Seconds +}; // of class DateTime definition + +/*! + @brief Simple general-purpose TimeSpan + @details Timespan class which can represent changes in time with seconds accuracy. Copied from + RTClib. For further infos see ** + https://github.com/SV-Zanshin/DS3231M/wiki/TimeSpanClass +*/ +class TimeSpan { + public: + TimeSpan(int32_t seconds = 0); + TimeSpan(int16_t days, int8_t hours, int8_t minutes, int8_t seconds); + TimeSpan(const TimeSpan& copy); + int16_t days() const { return _seconds / 86400L; } ///< Return days in span + int8_t hours() const { return _seconds / 3600 % 24; } ///< Return hours in span + int8_t minutes() const { return _seconds / 60 % 60; } ///< Return minutes in span + int8_t seconds() const { return _seconds % 60; } ///< Return seconds in span + int32_t totalseconds() const { return _seconds; } ///< Return total span in seconds + TimeSpan operator+(const TimeSpan& right); + TimeSpan operator-(const TimeSpan& right); + + protected: + int32_t _seconds; ///< internal seconds variable +}; // of class TimeSpan definition + +/*! + @brief Main DS3231M class definition for the Real-Time clock +*/ +class DS3231M_Class { + public: + DS3231M_Class(); + ~DS3231M_Class(); // Class destructor + bool begin(const uint32_t i2cSpeed = I2C_STANDARD_MODE); // Start I2C Communications + void adjust(); // Set the date and time to compile + void adjust(const DateTime& dt); // Set the date and time + DateTime now(); // return time + int32_t temperature(); // return clock temp in 100x °C + bool isStopped(); // Return true if Oscillator stopped + void setAlarm(const uint8_t alarmType, const DateTime dt, + const bool state = true); // Set an Alarm + bool isAlarm(); // Return if alarm is triggered + void clearAlarm(); // Clear the alarm state flag + void kHz32(const bool state); // Turn 32kHz output on or off + int8_t getAgingOffset(); // Get the clock's aging offset + int8_t setAgingOffset(const int8_t agingOffset); // Set the clock's aging offset + uint8_t weekdayRead(); // Read weekday from RTC + uint8_t weekdayWrite(const uint8_t dow); // Write weekday to RTC + void pinAlarm(); // Make INTSQW go up on alarm + void pinSquareWave(); // Make INTSQW be a 1Hz signal + private: + uint8_t readByte(const uint8_t addr); // Read 1 byte from I2C address + void writeByte(const uint8_t addr, const uint8_t data); // Write 1 byte at I2Caddress + uint8_t bcd2int(const uint8_t bcd); // convert BCD digits to integer + uint8_t int2bcd(const uint8_t dec); // convert integer to BCD + uint8_t _TransmissionStatus = 0; ///< Status of I2C transmission + uint32_t _SetUnixTime = 0; ///< UNIXtime for clock last set + uint8_t _ss, _mm, _hh, _d, _m; ///< Define date components + uint16_t _y; ///< Define date components +}; // of DS3231M class definition +#endif