├── .gitattributes ├── extras ├── images │ └── watchdog_image.png └── License.txt ├── library.properties ├── library.json ├── .gitignore ├── keywords.txt ├── examples ├── WatchDog_ATtiny84x_Example │ └── WatchDog_ATtiny84x_Example.ino └── WatchDog_Uno_Example │ └── WatchDog_Uno_Example.ino ├── WatchDog.h ├── README.md └── WatchDog.cpp /.gitattributes: -------------------------------------------------------------------------------- 1 | extras/* linguist-documentation -------------------------------------------------------------------------------- /extras/images/watchdog_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nadavmatalon/WatchDog/HEAD/extras/images/watchdog_image.png -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=WatchDog 2 | version=1.2.0 3 | author=Nadav Matalon 4 | maintainer=Nadav Matalon 5 | sentence=WatchDog Timer Functions 6 | paragraph=WatchDog Timer Functions 7 | url=https://github.com/nadavmatalon/WatchDog 8 | category=Timing 9 | architectures=avr -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "WatchDog", 3 | "version": "1.2.0", 4 | "frameworks": "AVR", 5 | "license": "MIT", 6 | "keywords": "WatchDog, Timer, Interrupt", 7 | "description": "WatchDog Timer Functions", 8 | "downloadUrl": "https://github.com/nadavmatalon/WatchDog/archive/master.zip", 9 | "authors": 10 | { 11 | "name": "Nadav Matalon", 12 | "maintainer": true 13 | }, 14 | "repository": 15 | { 16 | "type": "git", 17 | "url": "https://github.com/NadavMatalon/WatchDog" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | # Ignore bundler config. 8 | /.bundle 9 | 10 | # Ignore all logfiles and tempfiles. 11 | /log/*.log 12 | /tmp 13 | 14 | # Ignore other unneeded files. 15 | doc/ 16 | *.swp 17 | bin/*/ 18 | *build-* 19 | *~ 20 | .project 21 | .DS_Store 22 | .idea 23 | .secret 24 | build-tmp/ 25 | Makefile 26 | debug.txt 27 | .ycm_extra_conf.pyc 28 | .ropeproject -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For WatchDog 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | WatchDog KEYWORD1 10 | 11 | ####################################### 12 | # Instances (KEYWORD2) 13 | ####################################### 14 | 15 | ####################################### 16 | # Methods and Functions (KEYWORD2) 17 | ####################################### 18 | 19 | init KEYWORD2 20 | start KEYWORD2 21 | stop KEYWORD2 22 | status KEYWORD2 23 | getPeriod KEYWORD2 24 | setPeriod KEYWORD2 25 | checkPeriod KEYWORD2 26 | 27 | ####################################### 28 | # Constants (LITERAL1) 29 | ####################################### 30 | 31 | OVF_16MS LITERAL1 32 | OVF_32MS LITERAL1 33 | OVF_64MS LITERAL1 34 | OVF_125MS LITERAL1 35 | OVF_250MS LITERAL1 36 | OVF_500MS LITERAL1 37 | OVF_1000MS LITERAL1 38 | OVF_2000MS LITERAL1 39 | OVF_4000MS LITERAL1 40 | OVF_8000MS LITERAL1 41 | START LITERAL1 42 | STOP LITERAL1 43 | 44 | ####################################### 45 | # Built-In Variables (LITERAL2) 46 | ####################################### 47 | 48 | ovf_period_t LITERAL2 49 | ovf_status_t LITERAL2 50 | -------------------------------------------------------------------------------- /extras/License.txt: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * Title: PCA9536 Driver (4-Channel GPIO I2C Expander) 3 | * Author: Nadav Matalon 4 | * IDE: Arduino IDE (1.6.12) 5 | **************************************************************************/ 6 | 7 | The MIT License (MIT) 8 | Copyright (c) 2016 Nadav Matalon 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /examples/WatchDog_ATtiny84x_Example/WatchDog_ATtiny84x_Example.ino: -------------------------------------------------------------------------------- 1 | /* 2 | WATCHDOG LIBRARY - ATTINY84x EXAMPLE 3 | ------------------------------------ 4 | 5 | INTRODUCTION 6 | ------------ 7 | Many AVR's include an 'Enhanced Watchdog Timer' (WDT) which runs independently on a separate on-chip 128KHz oscilliator. 8 | The Watchdog Timer is typically used for pre-defined system reset duties (i.e. as a fail-safe or protection mechanism 9 | against system crashes). However, given that it has its own interrupt vector, the WatchDog Timer may also be used 10 | as a regular (albeit relatively restricted) time counter for managing a user-defined Interrupt Service Routine (ISR). 11 | 12 | Taking advantage of the above characteristics of the WatchDog Timer, the present light-weight library contains a small 13 | collection of functions for controlling this Timer in its capacity as an interrupt generator. In other words, the user 14 | can select the overflow period (in mS) of the timer, as well as compose the content of the ISR (Interrupt Service Routine) 15 | which is set to run on each overflow event (e.g. getting a sensor reading every 500mS or blinking a LED at the rate of 16 | once per second). 17 | 18 | Importantly, behind the scenes, the 'reset' capabilities of the WatchDog timer are entirely disabled by the library, 19 | leaving only the overflow time-counting mechanism and corresponding interrupt service routine to run as they normally do. 20 | Hence, no system reset is preformed when using any of the library's functions. 21 | 22 | It is also worth mentioning that in order to keep the memory footprint of the library to a minimum, no objects are 23 | instantiated during its operation and only one variable is stored in the system (namely: the WatchDog Timer's selected 24 | overflow period). 25 | 26 | For more details about the WatchDog Timer see relevant AVR datasheet. 27 | 28 | HW SETUP 29 | -------- 30 | The minimal hardware setup for running this example includes the following connections to the ATtiny84A / ATtiny841: 31 | - PIN 1 (VCC) - Connect to 5V source 32 | - PIN 10 (PA3) - Connect to LED anode (with LED's cathode going to GND via appropriate resistor) 33 | [Note that physical PIN 10 (PA3) on the ATtiny84A is referred to as Pin 7 in the Arduino mapping] 34 | - PIN 14 (GND) - Connect to Common-Ground 35 | - DECOUPLING - Connect a 100nF ceramic capacitor between VCC and GND of the ATtiny 36 | 37 | BUG REPORTS 38 | ----------- 39 | Please report any bugs/issues/suggestions in the Github Repository of this library at: 40 | https://github.com/nadavmatalon/WatchDog/issues 41 | 42 | LICENSE 43 | ------- 44 | The MIT License (MIT) 45 | Copyright (c) 2016 Nadav Matalon 46 | 47 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 48 | documentation files (the "Software"), to deal in the Software without restriction, including without 49 | limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 50 | the Software, and to permit persons to whom the Software is furnished to do so, subject to the following 51 | conditions: 52 | 53 | The above copyright notice and this permission notice shall be included in all copies or substantial 54 | portions of the Software. 55 | 56 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 57 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 58 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 59 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 60 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 61 | */ 62 | 63 | #include "WatchDog.h" 64 | 65 | const byte LED_PIN = 7; // Physical Pin 10 (PA3) 66 | 67 | unsigned long timeNow; 68 | 69 | void setup() { 70 | pinMode(LED_PIN, OUTPUT); 71 | digitalWrite(LED_PIN, LOW); 72 | WatchDog::init(blinkISR, OVF_500MS); 73 | timeNow = millis(); 74 | } 75 | 76 | void loop() { 77 | if (millis() - timeNow >= 3000) { 78 | (WatchDog::getPeriod() == 500) ? WatchDog::setPeriod(OVF_250MS) : WatchDog::setPeriod(OVF_500MS); 79 | timeNow = millis(); 80 | } 81 | } 82 | 83 | void blinkISR() { // watchdog timer interrupt service routine 84 | digitalWrite(LED_PIN, !digitalRead(LED_PIN)); 85 | } -------------------------------------------------------------------------------- /examples/WatchDog_Uno_Example/WatchDog_Uno_Example.ino: -------------------------------------------------------------------------------- 1 | /* 2 | WATCHDOG LIBRARY - ARDUINO UNO EXAMPLE 3 | -------------------------------------- 4 | 5 | INTRODUCTION 6 | ------------ 7 | 8 | Many AVR's include an 'Enhanced Watchdog Timer' (WDT) which runs independently on a separate on-chip 128KHz oscilliator. 9 | The Watchdog Timer is typically used for pre-defined system reset duties (i.e. as a fail-safe or protection mechanism 10 | against system crashes). However, given that it has its own interrupt vector, the WatchDog Timer may also be used 11 | as a regular (albeit relatively restricted) time counter for managing a user-defined Interrupt Service Routine (ISR). 12 | 13 | Taking advantage of the above characteristics of the WatchDog Timer, the present light-weight library contains a small 14 | collection of functions for controlling this Timer in its capacity as an interrupt generator. In other words, the user 15 | can select the overflow period (in mS) of the timer, as well as compose the content of the ISR (Interrupt Service Routine) 16 | which is set to run on each overflow event (e.g. getting a sensor reading every 500mS or blinking a LED at the rate of 17 | once per second). 18 | 19 | Importantly, behind the scenes, the 'reset' capabilities of the WatchDog timer are entirely disabled by the library, 20 | leaving only the overflow time-counting mechanism and corresponding interrupt service routine to run as they normally do. 21 | Hence, no system reset is preformed when using any of the library's functions. 22 | 23 | It is also worth mentioning that in order to keep the memory footprint of the library to a minimum, no objects are 24 | instantiated during its operation and only one variable is stored in the system (namely: the WatchDog Timer's selected 25 | overflow period). 26 | 27 | For more details about the WatchDog Timer, see the ATmega328P DATASHEET: 28 | http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_datasheet.pdf 29 | 30 | HW SETUP & RUNNING EXAMPLE 31 | -------------------------- 32 | There is no need for any external components in order to run this sketch as it uses the built-in LED on Pin 13 of 33 | the Arduino. 34 | 35 | To run this exmple, simply upload the sketch to the Arduino, open the Seria Monitor (set the baud-rate to 9600 if needed), 36 | and follow the on-screen instructions. 37 | 38 | BUG REPORTS 39 | ----------- 40 | Please report any bugs/issues/suggestions in the Github Repository of this library at: 41 | https://github.com/nadavmatalon/WatchDog/issues 42 | 43 | LICENSE 44 | ------- 45 | The MIT License (MIT) 46 | Copyright (c) 2016 Nadav Matalon 47 | 48 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 49 | documentation files (the "Software"), to deal in the Software without restriction, including without 50 | limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 51 | the Software, and to permit persons to whom the Software is furnished to do so, subject to the following 52 | conditions: 53 | 54 | The above copyright notice and this permission notice shall be included in all copies or substantial 55 | portions of the Software. 56 | 57 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 58 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 59 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 60 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 61 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 62 | */ 63 | 64 | #include "WatchDog.h" 65 | 66 | const byte LED_PIN = 13; 67 | 68 | int cmd; 69 | 70 | unsigned long timeNow = 0; 71 | 72 | void setup() { 73 | Serial.begin(9600); 74 | pinMode(LED_PIN, OUTPUT); 75 | WatchDog::init(blinkISR, 500); 76 | printMenu(); 77 | } 78 | 79 | void loop() { 80 | 81 | if (millis() - timeNow >= 750) { 82 | Serial.println(timeNow); 83 | timeNow = millis(); 84 | } 85 | 86 | if (Serial.available() > 0) { 87 | cmd = Serial.read(); 88 | if (cmd == '0') { 89 | if (WatchDog::status()) { 90 | WatchDog::stop(); 91 | Serial.print(F("\n\nwatchdog stopped\n\n")); 92 | } else { 93 | Serial.print(F("\n\nwatchdog already stopped\n\n")); 94 | } 95 | } else if (cmd == '1') { 96 | if (WatchDog::status() && WatchDog::getPeriod()) { 97 | Serial.print(F("\n\nwatchdog already running\n\n")); 98 | } else if (!WatchDog::status() && !WatchDog::getPeriod()) { 99 | Serial.print(F("\n\nwatchdog not started (invalid overflow period)\n\n")); 100 | } else { 101 | WatchDog::start(); 102 | Serial.print(F("\n\nwatchdog re-started\n\n")); 103 | } 104 | } else if (cmd == '2') { 105 | Serial.print(WatchDog::status() ? (F("\n\nwatchdog running\n\n")) : (F("\n\nwatchdog stopped\n\n"))); 106 | } else if (cmd == '3') { 107 | Serial.print(F("\n\nwatchdog overflow period: ")); 108 | Serial.print(WatchDog::getPeriod()); 109 | Serial.print(F("mS\n\n")); 110 | } else if (cmd == '4') { 111 | WatchDog::setPeriod(OVF_250MS); 112 | Serial.print(F("\n\nwatchdog overflow period set to: 250mS\n\n")); 113 | } else if (cmd == '5') { 114 | WatchDog::setPeriod(OVF_500MS); 115 | Serial.print(F("\n\nwatchdog overflow period set to: 500mS\n\n")); 116 | } else if (cmd == '6') { 117 | WatchDog::setPeriod(OVF_1000MS); 118 | Serial.print(F("\n\nwatchdog overflow period set to: 1000mS\n\n")); 119 | } else if ((cmd == 'm') || (cmd == 'M')) { 120 | printMenu(); 121 | } 122 | } 123 | } 124 | 125 | void blinkISR() { // watchdog timer interrupt service routine 126 | digitalWrite(LED_PIN, !digitalRead(LED_PIN)); 127 | } 128 | 129 | void printMenu() { 130 | Serial.print(F("\n\nWatchDog Timer Functions: \ 131 | \nSend 0 to Stop WatchDog Timer \ 132 | \nSend 1 to (Re-)Start WatchDog Timer \ 133 | \nSend 2 for WatchDog Timer Status \ 134 | \nSend 3 for WatchDog Timer Overflow Period \ 135 | \nSend 4 to Set WatchDog Timer Overflow Period to 250mS \ 136 | \nSend 5 to Set WatchDog Timer Overflow Period to 500mS \ 137 | \nSend 6 to Set WatchDog Timer Overflow Period to 1000mS \ 138 | \nSend M to Re-Print This Menu \ 139 | \n(Running numbers show elapsed time in mS to indicate no reset) \ 140 | \n\n")); 141 | } 142 | -------------------------------------------------------------------------------- /WatchDog.h: -------------------------------------------------------------------------------- 1 | /*==============================================================================================================* 2 | 3 | @file WatchDog.h 4 | @author Nadav Matalon 5 | @license MIT (c) 2016 Nadav Matalon 6 | 7 | WatchDog Timer Functions 8 | 9 | Ver. 1.0.0 - First release (17.11.16) 10 | Ver. 1.1.0 - Added user-definible overflow period (18.11.16) 11 | Ver. 1.2.0 - Added support for ATtiny441/841 (5.12.16) 12 | 13 | *===============================================================================================================* 14 | INTRODUCTION 15 | *===============================================================================================================* 16 | 17 | Many AVR's include an 'Enhanced Watchdog Timer' (WDT) which runs independently on a separate on-chip 128KHz oscilliator. 18 | The Watchdog Timer is typically used for pre-defined system reset duties (i.e. as a fail-safe or protection mechanism 19 | against system crashes). However, given that it has its own interrupt vector, the WatchDog Timer may also be used 20 | as a regular (albeit relatively restricted) time counter for managing a user-defined Interrupt Service Routine (ISR). 21 | 22 | Taking advantage of the above characteristics of the WatchDog Timer, the present light-weight library contains a small 23 | collection of functions for controlling this Timer in its capacity as an interrupt generator. In other words, the user 24 | can select the overflow period (in mS) of the timer, as well as compose the content of the ISR (Interrupt Service Routine) 25 | which is set to run on each overflow event (e.g. getting a sensor reading every 500mS or blinking a LED at the rate of 26 | once per second). 27 | 28 | Importantly, behind the scenes, the 'reset' capabilities of the WatchDog timer are entirely disabled by the library, 29 | leaving only the overflow time-counting mechanism and corresponding interrupt service routine to run as they normally do. 30 | Hence, no system reset is preformed when using any of the library's functions. 31 | 32 | It is also worth mentioning that in order to keep the memory footprint of the library to a minimum, no objects are 33 | instantiated during its operation and only one variable is stored in the system (namely: the timer's selected 34 | overflow period). 35 | 36 | For more details about the WatchDog Timer, see the ATmega328P Datasheet: 37 | http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_datasheet.pdf 38 | 39 | *===============================================================================================================* 40 | BUG REPORTS 41 | *===============================================================================================================* 42 | 43 | Please report any bugs/issues/suggestions at the Github Repo of this library at: 44 | https://github.com/nadavmatalon/WatchDog 45 | 46 | *===============================================================================================================* 47 | LICENSE 48 | *===============================================================================================================* 49 | 50 | The MIT License (MIT) 51 | Copyright (c) 2016 Nadav Matalon 52 | 53 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 54 | documentation files (the "Software"), to deal in the Software without restriction, including without 55 | limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 56 | the Software, and to permit persons to whom the Software is furnished to do so, subject to the following 57 | conditions: 58 | 59 | The above copyright notice and this permission notice shall be included in all copies or substantial 60 | portions of the Software. 61 | 62 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 63 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 64 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 65 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 66 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 67 | 68 | *==============================================================================================================*/ 69 | 70 | #if 1 71 | __asm volatile ("nop"); 72 | #endif 73 | 74 | #ifndef WatchDog_h 75 | #define WatchDog_h 76 | 77 | #if !defined(ARDUINO_ARCH_AVR) 78 | #error The WatchDog library only supports AVR processors 79 | #endif 80 | 81 | #include 82 | 83 | namespace Watchdog { 84 | // 7 6 5 4 3 2 1 0 85 | typedef enum:byte { // WDIF WDIE WDP[3] WDCE WDE WDP[2] WDP[1] WDP[0] 86 | OVF_16MS = 64, // 0 1 0 0 0 0 0 0 87 | OVF_32MS = 65, // 0 1 0 0 0 0 0 1 88 | OVF_64MS = 66, // 0 1 0 0 0 0 1 0 89 | OVF_125MS = 67, // 0 1 0 0 0 0 1 1 90 | OVF_250MS = 68, // 0 1 0 0 0 0 0 0 91 | OVF_500MS = 69, // 0 1 0 0 0 1 0 0 92 | OVF_1000MS = 70, // 0 1 0 0 0 1 0 1 93 | OVF_2000MS = 71, // 0 1 0 0 0 1 1 1 94 | OVF_4000MS = 96, // 0 1 1 0 0 0 0 0 95 | OVF_8000MS = 97 // 0 1 1 0 0 0 0 1 96 | } ovf_period_t; 97 | 98 | typedef enum:byte { 99 | STOP = 0, 100 | START = 1 101 | } ovf_status_t; 102 | 103 | class WatchDog { 104 | public: 105 | static void init(void (*isrFunc)()); 106 | static void init(void (*isrFunc)(), ovf_period_t OvfPeriod); 107 | static void init(void (*isrFunc)(), ovf_status_t OvfStatus); 108 | static void init(void (*isrFunc)(), unsigned int CustomPeriod); 109 | static void init(void (*isrFunc)(), ovf_period_t OvfPeriod, ovf_status_t OvfStatus); 110 | static void init(void (*isrFunc)(), unsigned int CustomPeriod, ovf_status_t OvfStatus); 111 | static void start(); 112 | static void stop(); 113 | static byte status(); 114 | static unsigned int getPeriod(); 115 | static void setPeriod(ovf_period_t newPeriod); 116 | static void setPeriod(unsigned int customPeriod); 117 | static byte checkPeriod(unsigned int periodValue); 118 | void attachInterrupt(void (*isr)()); 119 | void attachInterrupt(void (*isr)(), ovf_period_t selectedPeriod); 120 | static void (*isrCallback)(); 121 | static void isrDefaultUnused(); 122 | static volatile unsigned int ovfTop; 123 | static volatile unsigned int ovfCounter; 124 | private: 125 | static ovf_period_t ovfPeriod; 126 | }; 127 | } 128 | 129 | using namespace Watchdog; 130 | 131 | extern WatchDog Wdog1; 132 | 133 | #endif 134 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # WatchDog 3 | 4 | [![Platform Badge](https://img.shields.io/badge/platform-AVR-orange.svg)](http://www.atmel.com/products/microcontrollers/avr/) 5 |            6 | [![SemVer](https://img.shields.io/badge/SemVer-1.2.0-brightgreen.svg)](http://semver.org/) 7 |            8 | [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) 9 | 10 | ## INTRODUCTION 11 | 12 | Many AVR's containn an 'Enhanced Watchdog Timer' (WDT) which runs independently on a separate on-chip 128KHz oscilliator. The Watchdog Timer is typically used for pre-defined system reset duties (i.e. as a fail-safe or protection mechanism against system crashes). However, given that it has its own interrupt vector, the WatchDog Timer may also be used as a regular (albeit relatively restricted) time counter for managing a user-defined Interrupt Service Routine (ISR). 13 | 14 | Taking advantage of the above characteristics of the WatchDog Timer, the present light-weight library contains a small collection of functions for controlling this Timer in its capacity as an interrupt generator. In other words, the user can select the overflow period (in mS) of the timer, as well as compose the content of the ISR (Interrupt Service Routine) which is set to run on each overflow event (e.g. getting a sensor reading every 500mS or blinking a LED at the rate of once per second). 15 | 16 | Importantly, behind the scenes, the 'reset' capabilities of the WatchDog timer are entirely disabled by the library, leaving only the overflow time-counting mechanism and corresponding interrupt service routine to run as they normally do. Hence, no system reset is preformed when using any of the library's functions. 17 | 18 | It is also worth mentioning that in order to keep the memory footprint of the library to a minimum, no objects are instantiated during its operation and only one variable is stored in the system (namely: the timer's selected overflow period). 19 | 20 | For more details about the WatchDog Timer, see the relevant datasheet. 21 | 22 | WATCHDOG 23 | 24 | Source: [ATmega328P DATASHEET](http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_datasheet.pdf) 25 | 26 | ## Repository Contents 27 | 28 | - **WatchDog.h** - Library Header file. 29 | - **WatchDog.cpp** - Library Compilation file. 30 | - **/examples** 31 | - **/WatchDog_Uno_Example** 32 | - **WatchDog_Uno_Example.ino** - illustration code for using the WatchDog Timer library running on an Arduino Uno with a user-interface via the Serial Monitor. 33 | - **/WatchDog_ATtiny84x_Example** 34 | - **WatchDog_ATtiny84x_Example.ino** - illustration code for using the WatchDog Timer library running on an ATtiny441/841 or an ATtiny84A with feedback via a blinking LED. 35 | - **/extras** 36 | - **License.txt** - A cope of the end-user license agreement. 37 | - **/images** 38 | - **watchdog_image.png** - Functional diagram of the AVR WatchDog Timer. 39 | - **keywords.txt** - Keywords for this library which will be highlighted in sketches within the Arduino IDE. 40 | - **library.properties** - General library properties for the Arduino's IDE (>1.5) Library Package Manager. 41 | - **README.md** - The readme file for this library. 42 | - **library.json** - JSON file for the Arduino's IDE (>1.5) Package Manager. 43 | 44 | 45 | ## GENERAL NOTES 46 | 47 | 1) __Conflict with Arduino's Delay Functions__ 48 | 49 | Like any other time-dependant element, use of [delay()](https://www.arduino.cc/en/Reference/Delay), [delayMicroseconds()](https://www.arduino.cc/en/Reference/DelayMicroseconds) and the like is fundamentally incompatible with the normal, on-going operation of the WatchDog Timer and should therefore be avoided (apart from minimal and necessay exceptions where the cost in terms of time-keeping accuracy can be reasonably tolerated). 50 | 51 | 2) __Timer's Limited Speed & Accuracy__ 52 | 53 | Although the WatchDog Timer, as operated by the current library, may have noumerous potential applications, its speed and accuracy are relatively limited and therefore it is not advisable to use this Timer for ultra-fast, time-critical missions. 54 | 55 | 3) __User-Defined Overflow Period__ 56 | 57 | The library ebables users to select a pre-defined overflow period lengths based on one of the WatchDog Timer's base pre-scaler values, or alternatively, to define a custom length overflow period. With regard to the latter, it is important to note that the custom length period (in mS) must consist of a value that is evenly divisible by at least one of the said pre-scaler base values. For example, a custom period of 750mS is valid as it is divisible by the base pre-scaler value 250mS without a reminder. However, a custom period of 117mS is invalid as it cannot be divided by any of the pre-scaler base values without a reminder. In this context, the user can use the WatchDog::checkPeriod() function in order to see if a custom value is indeed valid or not. 58 | 59 | 60 | ## LIBRARY INSTALLATION & SETUP 61 | 62 | Begin by installing the library either by using the Arduino IDE's Installation Wizard (Arduino Version >1.5) or simply download the library's ZIP folder from GITHUB, extract it, and copy the extraxcted folder to your Arduino 'libraries' folder. 63 | 64 | Next, include the library at the top of the sketch as follows: 65 | 66 | ``` 67 | #include "WatchDog.h" 68 | ``` 69 | 70 | With the library installed & included in the sketch, the following functions can be used directly to manage the WatchDog Timer: 71 | 72 | >Note that using these functions requires preceding them with the library name (see the [usage examples](https://github.com/nadavmatalon/WatchDog/blob/master/examples) for a more detailed implementation): 73 | 74 | 75 | ## LIBRARY FUNCTIONS 76 | 77 | __WatchDog::init();__ 78 | Parameters:   ISR_function_name, ovf_period_t (optional), ovf_status_t or unsigned int (optional, but must be a valid value). 79 | Points to note in this context: 80 | 1) There are no parentheses follwing the ISR_function_name 81 | 2) ovf_period_t params (optional): OVF_16MS / OVF_32MS / OVF_64MS / OVF_125MS / OVF_250MS / OVF_500MS / OVF_1000MS [default] / OVF_2000MS / OVF_4000MS / OVF_8000MS or user-defined custom overflow period (value must be divisible by one of the WatchDog Timer's base pre-scaler values (i.e. 16 / 32 / 64 / 125 / etc.) 82 | 3) ovf_status_t params (optional): START [default] / STOP (determines whether the WatchDog Timer automatically starts running or not after the overflow period is set. 83 | Description:   Initializes the WatchDog timer with a user-defined ISR function name and (optionally) overflow period [default: 1000mS] and (also optionally) start or stop status. Place this function in the setup() section of the sketch. 84 | Returns:        None 85 | 86 | __WatchDog::start();__ 87 | Parameters:   None 88 | Description:   Starts the WatchDog Timer (or Se-starts the latter if it was previously stopped). 89 | Returns:        None 90 | 91 | __WatchDog::stop();__ 92 | Parameters:   None 93 | Description:   Stops the WatchDog Timer. 94 | Returns:        None 95 | 96 | __WatchDog::status();__ 97 | Parameters:   None 98 | Description:   Gets the current status of the WatchDog Timer (0 = Stopped / 1 = Running). 99 | Returns:        byte 100 | 101 | __WatchDog::getPeriod();__ 102 | Parameters:   None 103 | Description:   Gets the current overflow period of the WatchDog Timer (in mS). Returns 0 if period has not been defined (e.g. prior to initialization or if an attempt was made to define the overflow period with an invalid value. 104 | Returns:        unsigned int 105 | 106 | __WatchDog::setPeriod();__ 107 | Parameters:   ovf_period_t (OVF_16MS / OVF_32MS / OVF_64MS / OVF_125MS / OVF_250MS / OVF_500MS / OVF_1000MS / OVF_2000MS / OVF_4000MS / OVF_8000MS) or unsigned int (optional, must be a valid value) 108 | Description:   Sets the current overflow period of the WatchDog Timer. 109 | Returns:        None 110 | 111 | __WatchDog::checkPeriod();__ 112 | Parameters:   unsigned int 113 | Description:   Determines if a custom value for the WatchDog Timer's overflow period is valid (0 = invalid / 1 = valid) 114 | Returns:        byte 115 | 116 | 117 | ## RUNNING THE EXAMPLE SKETCHES 118 | 119 | 1) Start the Arduino IDE and open the relevant example sketch 120 | 2) Upload the sketch to the Arduino 121 | 3) For the ATtiny84/ATiny841 which don't have built-in serial communication, Connect an LED to the relevant pin with an approprite resistor. 122 | 4) For the Arduino Uno, open the Serial Communications Window (make sure the baud-rate is set to 9600 or change it in the sketch to match your Serial Port's buad-rate) and follow the on-screen instructions 123 | 124 | ## BUG REPORTS 125 | 126 | Please report any issues/bugs/suggestions at the [Issues](https://github.com/nadavmatalon/WatchDog/issues) section of this Github repository. 127 | 128 | ## TODO 129 | 130 | ## VERSION HISTORY 131 | 132 | __Ver. 1.0.0__ - First release (17.11.16) 133 | __Ver. 1.1.0__ - Added user-definible overflow period (18.11.16) 134 | __Ver. 1.2.0__ - Added support for ATtiny441/841 (5.12.16) 135 | 136 | ## LICENSE 137 | 138 | [The MIT License (MIT)](https://opensource.org/licenses/MIT) 139 | Copyright (c) 2016 Nadav Matalon 140 | 141 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 142 | 143 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 144 | 145 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 146 | 147 | 148 | -------------------------------------------------------------------------------- /WatchDog.cpp: -------------------------------------------------------------------------------- 1 | /*===================================================================================================================================* 2 | 3 | @file WatchDog.cpp 4 | @author Nadav Matalon 5 | @license MIT (c) 2016 Nadav Matalon 6 | 7 | WatchDog Timer Functionality 8 | 9 | Ver. 1.0.0 - First release (17.11.16) 10 | Ver. 1.1.0 - Added user-definible overflow period (18.11.16) 11 | Ver. 1.2.0 - Added compatibility for ATtiny441/841 (5.12.16) 12 | 13 | *===================================================================================================================================* 14 | LICENSE 15 | *===================================================================================================================================* 16 | 17 | The MIT License (MIT) 18 | Copyright (c) 2016 Nadav Matalon 19 | 20 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 21 | documentation files (the "Software"), to deal in the Software without restriction, including without 22 | limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 23 | the Software, and to permit persons to whom the Software is furnished to do so, subject to the following 24 | conditions: 25 | 26 | The above copyright notice and this permission notice shall be included in all copies or substantial 27 | portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 30 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 31 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 32 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 33 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 34 | 35 | *===================================================================================================================================*/ 36 | 37 | #if 1 38 | __asm volatile ("nop"); 39 | #endif 40 | 41 | #include "WatchDog.h" 42 | 43 | WatchDog Wdog1; // preinstatiate for watcdog ISR function implementation 44 | 45 | ovf_period_t WatchDog::ovfPeriod; // class variable for storing the ovf period 46 | volatile unsigned int WatchDog::ovfTop = 0; // class variable for storing overflow counter top 47 | volatile unsigned int WatchDog::ovfCounter = 0; // class variable for storing number of overflows 48 | 49 | /*===================================================================================================================================* 50 | INITIALIZE (DEFAULT OVERFLOW PERIOD & DEFAULT STATUS) 51 | *===================================================================================================================================*/ 52 | // ISR PARAMS: User-Defined Function Name for WatchDog Timer ISR (without parentheses) 53 | 54 | void WatchDog::init(void (*isrFunc)()) { 55 | WatchDog::setPeriod(OVF_1000MS); // set overflow period to library default (1000mS) 56 | WatchDog::start(); // start the watchdog timer 57 | Wdog1.attachInterrupt(isrFunc); // activate user-defined interrupt service routine 58 | } 59 | 60 | /*===================================================================================================================================* 61 | INITIALIZE (PRE-DEFINED OVERFLOW PERIOD & DEFAULT STATUS) 62 | *===================================================================================================================================*/ 63 | // ISR PARAMS: User-Defined Function Name for WatchDog Timer ISR (without parentheses) 64 | // PERIOD PARAMS: OVF_16MS / OVF_32MS / OVF_64MS / OVF_125MS / OVF_250MS / 65 | // OVF_500MS / OVF_1000MS / OVF_2000MS / OVF_4000MS / OVF_8000MS 66 | 67 | void WatchDog::init(void (*isrFunc)(), ovf_period_t OvfPeriod) { 68 | WatchDog::setPeriod(OvfPeriod); // set overflow period to one of the pre-defined values 69 | WatchDog::start(); // start the watchdog timer 70 | Wdog1.attachInterrupt(isrFunc); // activate user-defined interrupt service routine 71 | } 72 | 73 | /*===================================================================================================================================* 74 | INITIALIZE (DEFAULT OVERFLOW PERIOD & PRE-DEFINED STATUS) 75 | *===================================================================================================================================*/ 76 | // ISR PARAMS: User-Defined Function Name for WatchDog Timer ISR (without parentheses) 77 | // STATUS PARAMS: STOP / START 78 | 79 | void WatchDog::init(void (*isrFunc)(), ovf_status_t OvfStatus) { 80 | WatchDog::setPeriod(OVF_1000MS); // set overflow period to default (1000mS) 81 | OvfStatus ? WatchDog::start() : WatchDog::stop(); // start or stop the watchdog timer 82 | Wdog1.attachInterrupt(isrFunc); // activate user-defined interrupt service routine 83 | } 84 | 85 | /*===================================================================================================================================* 86 | INITIALIZE (USER-DEFINED OVERFLOW PERIOD & DEFAULT STATUS) 87 | *===================================================================================================================================*/ 88 | // ISR PARAMS: User-Defined Function Name for WatchDog Timer ISR (without parentheses) 89 | // CUSTOM VALUE: Value must be divisible by one of the watchdog base pre-scaler values (i.e. 16 / 32 / 64 / 125 / etc.) 90 | 91 | void WatchDog::init(void (*isrFunc)(), unsigned int CustomPeriod) { 92 | WatchDog::setPeriod(CustomPeriod); // set overflow period to user-defined value (if valid) 93 | if (WatchDog::ovfPeriod) WatchDog::start(); // start watchdog timer if custom value is valid 94 | Wdog1.attachInterrupt(isrFunc); // setup user-defined interrupt service routine 95 | } 96 | 97 | /*===================================================================================================================================* 98 | INITIALIZE (PRE-DEFINED OVERFLOW PERIOD & PRE-DEFINED STATUS) 99 | *===================================================================================================================================*/ 100 | // ISR PARAMS: User-Defined Function Name for WatchDog Timer ISR (without parentheses) 101 | // PERIOD PARAMS: OVF_16MS / OVF_32MS / OVF_64MS / OVF_125MS / OVF_250MS / 102 | // OVF_500MS / OVF_1000MS / OVF_2000MS / OVF_4000MS / OVF_8000MS 103 | // STATUS PARAMS: STOP / START 104 | // CUSTOM VALUE: Value must be divisible by one of the watchdog base pre-scaler values (i.e. 16 / 32 / 64 / 125 / etc.) 105 | 106 | void WatchDog::init(void (*isrFunc)(), ovf_period_t OvfPeriod, ovf_status_t OvfStatus) { 107 | WatchDog::setPeriod(OvfPeriod); // set overflow period to one of the pre-defined values 108 | OvfStatus ? WatchDog::start() : WatchDog::stop(); // start or stop watchdog timer 109 | Wdog1.attachInterrupt(isrFunc); // activate user-defined interrupt service routine 110 | } 111 | 112 | /*===================================================================================================================================* 113 | INITIALIZE (USER-DEFINED OVERFLOW PERIOD & PRE-DEFINED STATUS) 114 | *===================================================================================================================================*/ 115 | // ISR PARAMS: User-Defined Function Name for WatchDog Timer ISR (without parentheses) 116 | // STATUS PARAMS: STOP / START 117 | // CUSTOM VALUE: Value must be divisible by one of the watchdog base pre-scaler values (i.e. 16 / 32 / 64 / 125 / etc.) 118 | 119 | void WatchDog::init(void (*isrFunc)(), unsigned int CustomPeriod, ovf_status_t OvfStatus) { 120 | WatchDog::setPeriod(CustomPeriod); // set overflow period to user-defined value (if valid) 121 | if (OvfStatus && WatchDog::ovfPeriod) WatchDog::start(); // start watchdog timer if custom value is valid 122 | Wdog1.attachInterrupt(isrFunc); // activate user-defined interrupt service routine 123 | } 124 | 125 | /*===================================================================================================================================* 126 | START WATCHDOG TIMER 127 | *===================================================================================================================================*/ 128 | 129 | void WatchDog::start() { 130 | #if defined(__AVR_ATtiny841__) // if using ATtiny841... 131 | noInterrupts(); // disable global interrupts (cli) 132 | bitClear(MCUSR, WDRF); // clear WDRF to enable clearing of WDE 133 | CCP = 0xD8; // write 'change enable' signature to Config Change Protection register 134 | WDTCSR = WatchDog::ovfPeriod; // turn on WatchDog timer 135 | interrupts(); // enable global interrupts (sei) 136 | #else // for all other AVRs... 137 | noInterrupts(); // disable global interrupts (cli) 138 | bitClear(MCUSR, WDRF); // clear WDRF to enable clearing of WDE 139 | WDTCSR = (1 << WDCE) | (1 << WDE); // set relevant bits to enter watchdog timer configuration mode 140 | WDTCSR = WatchDog::ovfPeriod; // turn on WatchDog timer 141 | interrupts(); // enable global interrupts (sei) 142 | #endif 143 | } 144 | 145 | /*===================================================================================================================================* 146 | STOP WATCHDOG TIMER 147 | *===================================================================================================================================*/ 148 | 149 | void WatchDog::stop() { 150 | #if defined(__AVR_ATtiny841__) // if using ATtiny841... 151 | noInterrupts(); // disable global interrupts (cli) 152 | bitClear(MCUSR, WDRF); // clear WDRF to enable clearing of WDE 153 | CCP = 0xD8; // write 'change enable' signature to Config Change Protection register 154 | WDTCSR = 0; // turn off WatchDog timer 155 | interrupts(); // enable global interrupts (sei) 156 | #else // for all other AVRs... 157 | noInterrupts(); // disable global interrupts (cli) 158 | bitClear(MCUSR, WDRF); // clear WDRF to enable clearing of WDE 159 | WDTCSR = (1 << WDCE) | (1 << WDE); // set relevant bits to enter watchdog timer configuration mode 160 | WDTCSR = 0; // turn off WatchDog timer 161 | interrupts(); // enable global interrupts (sei) 162 | #endif 163 | } 164 | 165 | /*===================================================================================================================================* 166 | WATCHDOG STATUS (0 = STOPPED / 1 = RUNNING) 167 | *===================================================================================================================================*/ 168 | 169 | byte WatchDog::status() { 170 | return (WDTCSR ? 1 : 0); // watchdog timer status 171 | } 172 | 173 | /*===================================================================================================================================* 174 | GET WATCHDOG OVERFLOW PERIOD (in mS) 175 | *===================================================================================================================================*/ 176 | 177 | unsigned int WatchDog::getPeriod() { 178 | switch (WatchDog::ovfPeriod) { 179 | case (OVF_16MS) : return 16 * (ovfTop + 1); break; 180 | case (OVF_32MS) : return 32 * (ovfTop + 1); break; 181 | case (OVF_64MS) : return 64 * (ovfTop + 1); break; 182 | case (OVF_125MS) : return 125 * (ovfTop + 1); break; 183 | case (OVF_250MS) : return 250 * (ovfTop + 1); break; 184 | case (OVF_500MS) : return 500 * (ovfTop + 1); break; 185 | case (OVF_1000MS): return 1000 * (ovfTop + 1); break; 186 | case (OVF_2000MS): return 2000 * (ovfTop + 1); break; 187 | case (OVF_4000MS): return 4000 * (ovfTop + 1); break; 188 | case (OVF_8000MS): return 8000 * (ovfTop + 1); break; 189 | default: return 0; break; // return 0 if overflow period is not defined 190 | } 191 | } 192 | 193 | /*===================================================================================================================================* 194 | SET WATCHDOG OVERFLOW PERIOD (PRE-DEFINED VALUE, in mS) 195 | // PARAMS: OVF_16MS / OVF_32MS / OVF_64MS / OVF_125MS / OVF_250MS / 196 | // OVF_500MS / OVF_1000MS / OVF_2000MS / OVF_4000MS / OVF_8000MS 197 | *===================================================================================================================================*/ 198 | 199 | void WatchDog::setPeriod(ovf_period_t newPeriod) { 200 | byte status = WatchDog::status(); 201 | WatchDog::ovfPeriod = newPeriod; // update new overflow period value 202 | status ? WatchDog::start() : WatchDog::stop(); // start or stop timer based on state prior to change 203 | } 204 | 205 | /*===================================================================================================================================* 206 | SET WATCHDOG OVERFLOW PERIOD (USER-DEFINED VALUE, in mS) 207 | *===================================================================================================================================*/ 208 | 209 | void WatchDog::setPeriod(unsigned int customPeriod) { 210 | if (customPeriod % 8000 == 0) { ovfTop = (customPeriod / 8000) - 1; WatchDog::setPeriod(OVF_8000MS); } 211 | else if (customPeriod % 4000 == 0) { ovfTop = (customPeriod / 4000) - 1; WatchDog::setPeriod(OVF_4000MS); } 212 | else if (customPeriod % 2000 == 0) { ovfTop = (customPeriod / 2000) - 1; WatchDog::setPeriod(OVF_2000MS); } 213 | else if (customPeriod % 1000 == 0) { ovfTop = (customPeriod / 1000) - 1; WatchDog::setPeriod(OVF_1000MS); } 214 | else if (customPeriod % 500 == 0) { ovfTop = (customPeriod / 500) - 1; WatchDog::setPeriod(OVF_500MS); } 215 | else if (customPeriod % 250 == 0) { ovfTop = (customPeriod / 250) - 1; WatchDog::setPeriod(OVF_250MS); } 216 | else if (customPeriod % 125 == 0) { ovfTop = (customPeriod / 125) - 1; WatchDog::setPeriod(OVF_125MS); } 217 | else if (customPeriod % 64 == 0) { ovfTop = (customPeriod / 64) - 1; WatchDog::setPeriod(OVF_64MS); } 218 | else if (customPeriod % 32 == 0) { ovfTop = (customPeriod / 32) - 1; WatchDog::setPeriod(OVF_32MS); } 219 | else if (customPeriod % 16 == 0) { ovfTop = (customPeriod / 16) - 1; WatchDog::setPeriod(OVF_16MS); } 220 | else WatchDog::stop(); // set 'ovfPeriod' to 0 & stop watchdog if requested value is not divisable by 16mS 221 | } 222 | 223 | /*===================================================================================================================================* 224 | CHECK VALIDITY OF OVERFLOW PERIOD VALUE 225 | *===================================================================================================================================*/ 226 | 227 | byte WatchDog::checkPeriod(unsigned int periodValue) { 228 | return ((periodValue % 16 == 0) || (periodValue % 32 == 0) || (periodValue % 64 == 0) || (periodValue % 125 == 0) || 229 | (periodValue % 250 == 0) || (periodValue % 500 == 0) || (periodValue % 1000 == 0) || (periodValue % 2000 == 0) || 230 | (periodValue % 4000 == 0) || (periodValue % 8000 == 0)); 231 | } 232 | 233 | /*===================================================================================================================================* 234 | USER-DEFINED WATCHDOG OVERFLOW INTERRUPT SERVICE ROUTINE FUNCTIONS 235 | *===================================================================================================================================*/ 236 | 237 | void WatchDog::attachInterrupt(void (*isr)()) { 238 | isrCallback = isr; 239 | } 240 | 241 | void WatchDog::attachInterrupt(void (*isr)(), ovf_period_t selectedPeriod) { 242 | attachInterrupt(isr); 243 | } 244 | 245 | void (*WatchDog::isrCallback)() = WatchDog::isrDefaultUnused; 246 | 247 | void WatchDog::isrDefaultUnused() {} 248 | 249 | /*===================================================================================================================================* 250 | BUILT-IN WATCHDOG INTERRUPT SERVICE ROUTINE 251 | *===================================================================================================================================*/ 252 | 253 | ISR(WDT_vect) { 254 | if (WatchDog::ovfCounter < WatchDog::ovfTop) { 255 | WatchDog::ovfCounter++; 256 | } else { 257 | WatchDog::ovfCounter = 0; 258 | Wdog1.isrCallback(); 259 | } 260 | } 261 | 262 | --------------------------------------------------------------------------------