From 6e778593d684f21814d29d489a1d167c003d1413 Mon Sep 17 00:00:00 2001 From: Khoi Hoang <57012152+khoih-prog@users.noreply.github.com> Date: Sun, 10 Jan 2021 21:06:42 -0500 Subject: [PATCH] v1.2.0 ### Releases v1.2.0 1. Add better debug feature. 2. Optimize code and examples to reduce RAM usage 3. Add Table of Contents --- README.md | 279 +++++++++++++----- examples/Argument_None/Argument_None.ino | 109 +++---- examples/Change_Interval/Change_Interval.ino | 83 +++--- .../ISR_16_Timers_Array.ino | 184 ++++++------ .../ISR_16_Timers_Array_Complex.ino | 86 +++--- examples/ISR_RPM_Measure/ISR_RPM_Measure.ino | 79 ++--- .../ISR_Timer_Complex_Ethernet.ino | 115 ++++---- examples/RPM_Measure/RPM_Measure.ino | 74 +++-- examples/SwitchDebounce/SwitchDebounce.ino | 94 +++--- .../TimerInterruptLEDDemo.ino | 76 +++-- .../TimerInterruptTest/TimerInterruptTest.ino | 91 +++--- library.json | 6 +- library.properties | 2 +- src/SAMDUETimerInterrupt.h | 72 ++--- src/SAMDUE_ISR_Timer-Impl.h | 56 ++-- src/SAMDUE_ISR_Timer.h | 51 ++-- src/TimerInterrupt_Generic_Debug.h | 77 +++++ src_cpp/SAMDUETimerInterrupt.h | 72 ++--- src_cpp/SAMDUE_ISR_Timer.cpp | 52 ++-- src_cpp/SAMDUE_ISR_Timer.h | 53 ++-- src_cpp/TimerInterrupt_Generic_Debug.h | 77 +++++ src_h/SAMDUETimerInterrupt.h | 67 ++--- src_h/SAMDUE_ISR_Timer-Impl.h | 56 ++-- src_h/SAMDUE_ISR_Timer.h | 51 ++-- src_h/TimerInterrupt_Generic_Debug.h | 77 +++++ 25 files changed, 1259 insertions(+), 780 deletions(-) create mode 100644 src/TimerInterrupt_Generic_Debug.h create mode 100644 src_cpp/TimerInterrupt_Generic_Debug.h create mode 100644 src_h/TimerInterrupt_Generic_Debug.h diff --git a/README.md b/README.md index 111eb08..5c8fb12 100644 --- a/README.md +++ b/README.md @@ -9,17 +9,100 @@ --- --- -## Features +## Table of Contents + +* [Why do we need this SAMD_TimerInterrupt library](#why-do-we-need-this-samd_timerinterrupt-library) + * [Features](#features) + * [Why using ISR-based Hardware Timer Interrupt is better](#why-using-isr-based-hardware-timer-interrupt-is-better) + * [Currently supported Boards](#currently-supported-boards) + * [Important Notes about ISR](#important-notes-about-isr) +* [Changelog](#changelog) + * [Releases v1.2.0](#releases-v120) + * [Releases v1.1.1](#releases-v111) + * [Releases v1.0.1](#releases-v101) + * [Releases v1.0.0](#releases-v100) +* [Prerequisites](#prerequisites) +* [Installation](#installation) + * [Use Arduino Library Manager](#use-arduino-library-manager) + * [Manual Install](#manual-install) + * [VS Code & PlatformIO](#vs-code--platformio) +* [Packages' Patches](#packages-patches) + * [1. For Arduino SAM DUE boards](#1-for-arduino-sam-due-boards) +* [Libraries' Patches](#libraries-patches) + * [1. For application requiring 2K+ HTML page](#1-for-application-requiring-2k-html-page) + * [2. For Ethernet library](#2-for-ethernet-library) + * [3. For EthernetLarge library](#3-for-ethernetlarge-library) + * [4. For Etherne2 library](#4-for-ethernet2-library) + * [5. For Ethernet3 library](#5-for-ethernet3-library) + * [6. For UIPEthernet library](#6-for-uipethernet-library) + * [7. For fixing ESP32 compile error](#7-for-fixing-esp32-compile-error) +* [HOWTO Fix `Multiple Definitions` Linker Error](#howto-fix-multiple-definitions-linker-error) +* [New from v1.0.1](#new-from-v101) +* [Usage](#usage) + * [1. Using only Hardware Timer directly](#1-using-only-hardware-timer-directly) + * [1.1 Init Hardware Timer](#11-init-hardware-timer) + * [1.2 Set Hardware Timer Interval and attach Timer Interrupt Handler function](#12-set-hardware-timer-interval-and-attach-timer-interrupt-handler-function) + * [2. Using 16 ISR_based Timers from 1 Hardware Timer](#2-using-16-isr_based-timers-from-1-hardware-timer) + * [2.1 Init Hardware Timer and ISR-based Timer](#21-init-hardware-timer-and-isr-based-timer) + * [2.2 Set Hardware Timer Interval and attach Timer Interrupt Handler functions](#22-set-hardware-timer-interval-and-attach-timer-interrupt-handler-functions) +* [Examples](#examples) + * [ 1. Argument_None](examples/Argument_None) + * [ 2. ISR_16_Timers_Array](examples/ISR_16_Timers_Array) + * [ 3. ISR_RPM_Measure](examples/ISR_RPM_Measure) + * [ 4. ISR_Timer_Complex_Ethernet](examples/ISR_Timer_Complex_Ethernet) + * [ 5. RPM_Measure](examples/RPM_Measure) + * [ 6. SwitchDebounce](examples/SwitchDebounce) + * [ 7. TimerInterruptTest](examples/TimerInterruptTest) + * [ 8. TimerInterruptLEDDemo](examples/TimerInterruptLEDDemo) + * [ 9. **Change_Interval**](examples/Change_Interval) + * [ 10. **ISR_16_Timers_Array_Complex**](examples/ISR_16_Timers_Array_Complex) +* [Example ISR_16_Timers_Array_Complex](#example-isr_16_timers_array_complex) +* [Debug Terminal Output Samples](#debug-terminal-output-samples) + * [1. ISR_Timer_Complex_Ethernet on Arduino SAM DUE](#1-isr_timer_complex_ethernet-on-arduino-sam-due) + * [2. TimerInterruptTest on Arduino SAM DUE](#2-timerinterrupttest-on-arduino-sam-due) + * [3. ISR_16_Timers_Array on Arduino SAM DUE](#3-isr_16_timers_array-on-arduino-sam-due) + * [4. Change_Interval on Arduino SAM DUE](#4-change_interval-on-arduino-sam-due) + * [5. ISR_16_Timers_Array_Complex on Arduino SAM DUE](#5-isr_16_timers_array_complex-on-arduino-sam-due) +* [Debug](#debug) +* [Troubleshooting](#troubleshooting) +* [Releases](#releases) +* [Issues](#issues) +* [TO DO](#to-do) +* [DONE](#done) +* [Contributions and Thanks](#contributions-and-thanks) +* [Contributing](#contributing) +* [License](#license) +* [Copyright](#copyright) + +--- +--- + +### Why do we need this [SAMD_TimerInterrupt library](https://github.com/khoih-prog/SAMD_TimerInterrupt) + +### Features This library enables you to use Interrupt from Hardware Timers on an SAM-DUE-based board. As **Hardware Timers are rare, and very precious assets** of any board, this library now enables you to use up to **16 ISR-based Timers, while consuming only 1 Hardware Timer**. Timers' interval is very long (**ulong millisecs**). -### Why do we need this Hardware Timer Interrupt? +Now with these new **16 ISR-based timers**, the maximum interval is **practically unlimited** (limited only by unsigned long miliseconds) while **the accuracy is nearly perfect** compared to software timers. + +The most important feature is they're ISR-based timers. Therefore, their executions are **not blocked by bad-behaving functions / tasks**. This important feature is absolutely necessary for mission-critical tasks. + +The [**ISR_Timer_Complex**](examples/ISR_Timer_Complex) example will demonstrate the nearly perfect accuracy compared to software timers by printing the actual elapsed millisecs of each type of timers. + +Being ISR-based timers, their executions are not blocked by bad-behaving functions / tasks, such as connecting to WiFi, Internet and Blynk services. You can also have many `(up to 16)` timers to use. + +This non-being-blocked important feature is absolutely necessary for mission-critical tasks. + +You'll see blynkTimer Software is blocked while system is connecting to WiFi / Internet / Blynk, as well as by blocking task +in loop(), using delay() function as an example. The elapsed time then is very unaccurate + +### Why using ISR-based Hardware Timer Interrupt is better Imagine you have a system with a **mission-critical** function, measuring water level and control the sump pump or doing something much more important. You normally use a software timer to poll, or even place the function in loop(). But what if another function is **blocking** the loop() or setup(). -So your function **might not be executed on-time or not at all, and the result would be disastrous.** +So your function **might not be executed, and the result would be disastrous.** You'd prefer to have your function called, no matter what happening with other functions (busy loop, bug, etc.). @@ -35,7 +118,13 @@ The catch is **your function is now part of an ISR (Interrupt Service Routine), --- -#### Important Notes: +### Currently supported Boards + + - **Arduino SAM DUE**. + +--- + +### Important Notes about ISR 1. Inside the attached function, **delay() won’t work and the value returned by millis() will not increment.** Serial data received while in the function may be lost. You should declare as **volatile any variables that you modify within the attached function.** @@ -44,6 +133,14 @@ The catch is **your function is now part of an ISR (Interrupt Service Routine), --- --- +## Changelog + +### Releases v1.2.0 + +1. Add better debug feature. +2. Optimize code and examples to reduce RAM usage +3. Add Table of Contents + ### Releases v1.1.1 1. Add example [**Change_Interval**](examples/Change_Interval) and [**ISR_16_Timers_Array_Complex**](examples/ISR_16_Timers_Array_Complex) @@ -55,9 +152,6 @@ The catch is **your function is now part of an ISR (Interrupt Service Routine), 2. Using cpp code besides Impl.h code to use if Multiple-Definition linker error3. 3. Add complicated example [ISR_16_Timers_Array](examples/ISR_16_Timers_Array) utilizing and demonstrating the full usage of 16 independent ISR Timers based on just 1 Hardware Timer. -#### Supported Boards - - - **Arduino SAM DUE**. --- --- @@ -99,7 +193,7 @@ Another way to install is to: 1. Install [VS Code](https://code.visualstudio.com/) 2. Install [PlatformIO](https://platformio.org/platformio-ide) -3. Install [**SAMDUE_TimerInterrupt** library](https://platformio.org/lib/show/11428/SAMDUE_TimerInterrupt) or [**SAMDUE_TimerInterrupt** library](https://platformio.org/lib/show/11428/SAMDUE_TimerInterrupt) by using [Library Manager](https://platformio.org/lib/show/11467/SAMDUE_TimerInterrupt/installation). Search for **SAMDUE_TimerInterrupt** in [Platform.io Author's Libraries](https://platformio.org/lib/search?query=author:%22Khoi%20Hoang%22) +3. Install [**SAMDUE_TimerInterrupt** library](https://platformio.org/lib/show/11467/SAMDUE_TimerInterrupt) or [**SAMDUE_TimerInterrupt** library](https://platformio.org/lib/show/11428/SAMDUE_TimerInterrupt) by using [Library Manager](https://platformio.org/lib/show/11467/SAMDUE_TimerInterrupt/installation). Search for **SAMDUE_TimerInterrupt** in [Platform.io Author's Libraries](https://platformio.org/lib/search?query=author:%22Khoi%20Hoang%22) 4. Use included [platformio.ini](platformio/platformio.ini) file from examples to ensure that all dependent libraries will installed automatically. Please visit documentation for the other options and examples at [Project Configuration File](https://docs.platformio.org/page/projectconf.html) --- @@ -107,7 +201,9 @@ Another way to install is to: ### Packages' Patches - 1. **To be able to compile and run on SAM DUE boards**, you have to copy the whole [SAM DUE](Packages_Patches/arduino/hardware/sam/1.6.12) directory into Arduino sam directory (~/.arduino15/packages/arduino/hardware/sam/1.6.12). +#### 1. For Arduino SAM DUE boards + + **To be able to compile and run on SAM DUE boards**, you have to copy the whole [SAM DUE](Packages_Patches/arduino/hardware/sam/1.6.12) directory into Arduino sam directory (~/.arduino15/packages/arduino/hardware/sam/1.6.12). Supposing the Arduino SAM core version is 1.6.12. This file must be copied into the directory: @@ -121,58 +217,64 @@ This file must be copied into the directory: --- --- -### Optional Libraries' Patches +### Libraries' Patches + +#### Notes: These patches are totally optional and necessary only when you use the related Ethernet library and get certain error or issues. -##### Notes: These patches are totally optional and necessary only when you use the related Ethernet library and get certain error or issues. +#### 1. For application requiring 2K+ HTML page -1. If your application requires 2K+ HTML page, the current [`Ethernet library`](https://www.arduino.cc/en/Reference/Ethernet) must be modified if you are using W5200/W5500 Ethernet shields. W5100 is not supported for 2K+ buffer. If you use boards requiring different CS/SS pin for W5x00 Ethernet shield, for example ESP32, ESP8266, nRF52, etc., you also have to modify the following libraries to be able to specify the CS/SS pin correctly. +If your application requires 2K+ HTML page, the current [`Ethernet library`](https://www.arduino.cc/en/Reference/Ethernet) must be modified if you are using W5200/W5500 Ethernet shields. W5100 is not supported for 2K+ buffer. If you use boards requiring different CS/SS pin for W5x00 Ethernet shield, for example ESP32, ESP8266, nRF52, etc., you also have to modify the following libraries to be able to specify the CS/SS pin correctly. -2. To fix [`Ethernet library`](https://www.arduino.cc/en/Reference/Ethernet), just copy these following files into the [`Ethernet library`](https://www.arduino.cc/en/Reference/Ethernet) directory to overwrite the old files: +#### 2. For Ethernet library + +To fix [`Ethernet library`](https://www.arduino.cc/en/Reference/Ethernet), just copy these following files into the [`Ethernet library`](https://www.arduino.cc/en/Reference/Ethernet) directory to overwrite the old files: - [Ethernet.h](LibraryPatches/Ethernet/src/Ethernet.h) - [Ethernet.cpp](LibraryPatches/Ethernet/src/Ethernet.cpp) - [EthernetServer.cpp](LibraryPatches/Ethernet/src/EthernetServer.cpp) - [w5100.h](LibraryPatches/Ethernet/src/utility/w5100.h) - [w5100.cpp](LibraryPatches/Ethernet/src/utility/w5100.cpp) -3. To fix [`EthernetLarge library`](https://github.com/OPEnSLab-OSU/EthernetLarge), just copy these following files into the [`EthernetLarge library`](https://github.com/OPEnSLab-OSU/EthernetLarge) directory to overwrite the old files: +#### 3. For EthernetLarge library + +To fix [`EthernetLarge library`](https://github.com/OPEnSLab-OSU/EthernetLarge), just copy these following files into the [`EthernetLarge library`](https://github.com/OPEnSLab-OSU/EthernetLarge) directory to overwrite the old files: - [EthernetLarge.h](LibraryPatches/EthernetLarge/src/EthernetLarge.h) - [EthernetLarge.cpp](LibraryPatches/EthernetLarge/src/EthernetLarge.cpp) - [EthernetServer.cpp](LibraryPatches/EthernetLarge/src/EthernetServer.cpp) - [w5100.h](LibraryPatches/EthernetLarge/src/utility/w5100.h) - [w5100.cpp](LibraryPatches/EthernetLarge/src/utility/w5100.cpp) -4. To fix [`Ethernet2 library`](https://github.com/khoih-prog/Ethernet2), just copy these following files into the [`Ethernet2 library`](https://github.com/khoih-prog/Ethernet2) directory to overwrite the old files: + +#### 4. For Ethernet2 library + +To fix [`Ethernet2 library`](https://github.com/khoih-prog/Ethernet2), just copy these following files into the [`Ethernet2 library`](https://github.com/khoih-prog/Ethernet2) directory to overwrite the old files: - [Ethernet2.h](LibraryPatches/Ethernet2/src/Ethernet2.h) - [Ethernet2.cpp](LibraryPatches/Ethernet2/src/Ethernet2.cpp) -To add UDP Multicast support, necessary for this [**UPnP_Generic library**](https://github.com/khoih-prog/UPnP_Generic): +To add UDP Multicast support, necessary for the [**UPnP_Generic library**](https://github.com/khoih-prog/UPnP_Generic): - [EthernetUdp2.h](LibraryPatches/Ethernet2/src/EthernetUdp2.h) - [EthernetUdp2.cpp](LibraryPatches/Ethernet2/src/EthernetUdp2.cpp) +#### 5. For Ethernet3 library + 5. To fix [`Ethernet3 library`](https://github.com/sstaub/Ethernet3), just copy these following files into the [`Ethernet3 library`](https://github.com/sstaub/Ethernet3) directory to overwrite the old files: - [Ethernet3.h](LibraryPatches/Ethernet3/src/Ethernet3.h) - [Ethernet3.cpp](LibraryPatches/Ethernet3/src/Ethernet3.cpp) -6. **To be able to compile and run on nRF52 boards with ENC28J60 using UIPEthernet library**, you have to copy these following files into the UIPEthernet `utility` directory to overwrite the old files: - -- For [UIPEthernet v2.0.8](https://github.com/UIPEthernet/UIPEthernet) +#### 6. For UIPEthernet library - - [UIPEthernet.h](LibraryPatches/UIPEthernet/UIPEthernet.h) - - [UIPEthernet.cpp](LibraryPatches/UIPEthernet/UIPEthernet.cpp) - - [Enc28J60Network.h](LibraryPatches/UIPEthernet/utility/Enc28J60Network.h) - - [Enc28J60Network.cpp](LibraryPatches/UIPEthernet/utility/Enc28J60Network.cpp) +***To be able to compile and run on nRF52 boards with ENC28J60 using UIPEthernet library***, you have to copy these following files into the UIPEthernet `utility` directory to overwrite the old files: -- For [UIPEthernet v2.0.9](https://github.com/UIPEthernet/UIPEthernet) +- [UIPEthernet.h](LibraryPatches/UIPEthernet/UIPEthernet.h) +- [UIPEthernet.cpp](LibraryPatches/UIPEthernet/UIPEthernet.cpp) +- [Enc28J60Network.h](LibraryPatches/UIPEthernet/utility/Enc28J60Network.h) +- [Enc28J60Network.cpp](LibraryPatches/UIPEthernet/utility/Enc28J60Network.cpp) - - [UIPEthernet.h](LibraryPatches/UIPEthernet-2.0.9/UIPEthernet.h) - - [UIPEthernet.cpp](LibraryPatches/UIPEthernet-2.0.9/UIPEthernet.cpp) - - [Enc28J60Network.h](LibraryPatches/UIPEthernet-2.0.9/utility/Enc28J60Network.h) - - [Enc28J60Network.cpp](LibraryPatches/UIPEthernet-2.0.9/utility/Enc28J60Network.cpp) - -7. Check if you need to install the UIPthernet patch [new SAMD core F3/F4 compatibility](https://github.com/UIPEthernet/UIPEthernet/commit/c6d6519a260166b722b9cee5dd1f0fb2682e6782) to avoid errors `#include HardwareSPI.h` on some SAMD boards (Nucleo-32 F303K8, etc.) +#### 7. For fixing ESP32 compile error +To fix [`ESP32 compile error`](https://github.com/espressif/arduino-esp32), just copy the following file into the [`ESP32`](https://github.com/espressif/arduino-esp32) cores/esp32 directory (e.g. ./arduino-1.8.12/hardware/espressif/cores/esp32) to overwrite the old file: +- [Server.h](LibraryPatches/esp32/cores/esp32/Server.h) --- --- @@ -213,11 +315,6 @@ You'll see blynkTimer Software is blocked while system is connecting to WiFi / I in loop(), using delay() function as an example. The elapsed time then is very unaccurate --- - -## Supported Boards - -- **SAM DUE** - --- ## Usage @@ -268,7 +365,7 @@ void setup() } ``` -### 2. Using 16 ISR_based Timers from 1 Hardware Timers +### 2. Using 16 ISR_based Timers from 1 Hardware Timer #### 2.1 Init Hardware Timer and ISR-based Timer @@ -374,9 +471,12 @@ void setup() #error This code is designed to run on SAM DUE board / platform! Please check your Tools->Board setting. #endif -// These define's must be placed at the beginning before #include "SAMDTimerInterrupt.h" -// Don't define SAMDUE_TIMER_INTERRUPT_DEBUG > 0. Only for special ISR debugging only. Can hang the system. -#define SAMDUE_TIMER_INTERRUPT_DEBUG 1 +// These define's must be placed at the beginning before #include "SAMDUETimerInterrupt.h" +// _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 +// Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. +// Don't define TIMER_INTERRUPT_DEBUG > 2. Only for special ISR debugging only. Can hang the system. +#define TIMER_INTERRUPT_DEBUG 0 +#define _TIMERINTERRUPT_LOGLEVEL_ 0 #include "SAMDUETimerInterrupt.h" #include "SAMDUE_ISR_Timer.h" @@ -405,7 +505,7 @@ SAMDUE_ISR_Timer ISR_Timer; #define LED_TOGGLE_INTERVAL_MS 2000L -void TimerHandler(void) +void TimerHandler() { static bool toggle = false; static int timeRun = 0; @@ -427,7 +527,7 @@ void TimerHandler(void) #define NUMBER_ISR_TIMERS 16 -typedef void (*irqCallback) (void); +typedef void (*irqCallback) (); ///////////////////////////////////////////////// @@ -614,17 +714,20 @@ void simpleTimerDoingSomething2s() unsigned long currMillis = millis(); - Serial.println("SimpleTimer : " + String(SIMPLE_TIMER_MS / 1000) + ", ms = " + String(currMillis) - + ", Dms : " + String(currMillis - previousMillis)); + Serial.print(F("SimpleTimer : "));Serial.print(SIMPLE_TIMER_MS / 1000); + Serial.print(F(", ms : ")); Serial.print(currMillis); + Serial.print(F(", Dms : ")); Serial.println(currMillis - previousMillis); - for (int i = 0; i < NUMBER_ISR_TIMERS; i++) + for (uint16_t i = 0; i < NUMBER_ISR_TIMERS; i++) { #if USE_COMPLEX_STRUCT - Serial.println("Timer : " + String(i) + ", programmed : " + String(curISRTimerData[i].TimerInterval) - + ", actual : " + String(curISRTimerData[i].deltaMillis)); + Serial.print(F("Timer : ")); Serial.print(i); + Serial.print(F(", programmed : ")); Serial.print(curISRTimerData[i].TimerInterval); + Serial.print(F(", actual : ")); Serial.println(curISRTimerData[i].deltaMillis); #else - Serial.println("Timer : " + String(i) + ", programmed : " + String(TimerInterval[i]) - + ", actual : " + String(deltaMillis[i])); + Serial.print(F("Timer : ")); Serial.print(i); + Serial.print(F(", programmed : ")); Serial.print(TimerInterval[i]); + Serial.print(F(", actual : ")); Serial.println(deltaMillis[i]); #endif } @@ -639,10 +742,7 @@ uint16_t attachDueInterrupt(double microseconds, timerCallback callback, const c uint16_t timerNumber = dueTimerInterrupt.getTimerNumber(); - Serial.print(TimerName); - Serial.print(" attached to Timer("); - Serial.print(timerNumber); - Serial.println(")"); + Serial.print(TimerName); Serial.print(F(" attached to Timer(")); Serial.print(timerNumber); Serial.println(F(")")); return timerNumber; } @@ -654,10 +754,12 @@ void setup() Serial.begin(115200); while (!Serial); - Serial.println("\nStarting ISR_16_Timers_Array_Complex on " + String(BOARD_NAME)); + delay(100); + + Serial.print(F("\nStarting ISR_16_Timers_Array_Complex on ")); Serial.println(BOARD_NAME); Serial.println(SAMDUE_TIMER_INTERRUPT_VERSION); - Serial.println("CPU Frequency = " + String(F_CPU / 1000000) + " MHz"); - Serial.println("Timer Frequency = " + String(SystemCoreClock / 1000000) + " MHz"); + Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("Timer Frequency = ")); Serial.print(SystemCoreClock / 1000000); Serial.println(F(" MHz")); // Interval in microsecs attachDueInterrupt(HW_TIMER_INTERVAL_US, TimerHandler, "ITimer"); @@ -666,7 +768,7 @@ void setup() // Just to demonstrate, don't use too many ISR Timers if not absolutely necessary // You can use up to 16 timer for each ISR_Timer - for (int i = 0; i < NUMBER_ISR_TIMERS; i++) + for (uint8_t i = 0; i < NUMBER_ISR_TIMERS; i++) { #if USE_COMPLEX_STRUCT curISRTimerData[i].previousMillis = startMillis; @@ -701,13 +803,15 @@ void loop() ### Debug Terminal Output Samples -1. The following is the sample terminal output when running example [ISR_Timer_Complex_Ethernet](examples/ISR_Timer_Complex_Ethernet) on **Arduino SAM DUE** to demonstrate the accuracy of ISR Hardware Timer, **especially when system is very busy**. The ISR timer is **programmed for 2s, is activated exactly after 2.000s !!!** +### 1. ISR_Timer_Complex_Ethernet on Arduino SAM DUE + +The following is the sample terminal output when running example [ISR_Timer_Complex_Ethernet](examples/ISR_Timer_Complex_Ethernet) on **Arduino SAM DUE** to demonstrate the accuracy of ISR Hardware Timer, **especially when system is very busy**. The ISR timer is **programmed for 2s, is activated exactly after 2.000s !!!** While software timer, **programmed for 2s, is activated after 10.917s !!!**. Then in loop(), it's also activated **every 3s**. ``` Starting ISR_Timer_Complex_Ethernet on SAM DUE -SAMDUE_TimerInterrupt v1.1.1 +SAMDUE_TimerInterrupt v1.2.0 CPU Frequency = 84 MHz Using Timer(0) = TC0, channel = 0, IRQ = TC0_IRQn Timer(0), us = 50000.00 @@ -792,11 +896,13 @@ blynkDoingSomething2s: Delta programmed ms = 2000, actual = 3000 --- -2. The following is the sample terminal output when running example [**TimerInterruptTest**](examples/TimerInterruptTest) on **Arduino SAM DUE** to demonstrate how to start/stop Hardware Timers. +### 2. TimerInterruptTest on Arduino SAM DUE + +The following is the sample terminal output when running example [**TimerInterruptTest**](examples/TimerInterruptTest) on **Arduino SAM DUE** to demonstrate how to start/stop Hardware Timers. ``` Starting TimerInterruptTest on SAM DUE -SAMDUE_TimerInterrupt v1.1.1 +SAMDUE_TimerInterrupt v1.2.0 CPU Frequency = 84 MHz Timer Frequency = 84 MHz Using Timer(0) = TC0, channel = 0, IRQ = TC0_IRQn @@ -853,11 +959,13 @@ Stop ITimer0, millis() = 45009 --- -3. The following is the sample terminal output when running example [**ISR_16_Timers_Array**](examples/ISR_16_Timers_Array) on **Arduino SAM DUE** to demonstrate the accuracy and how to use 16 ISR Timers from just 1 Hardware Timer. +### 3. ISR_16_Timers_Array on Arduino SAM DUE + +The following is the sample terminal output when running example [**ISR_16_Timers_Array**](examples/ISR_16_Timers_Array) on **Arduino SAM DUE** to demonstrate the accuracy and how to use 16 ISR Timers from just 1 Hardware Timer. ``` Starting ISR_16_Timers_Array on SAM DUE -SAMDUE_TimerInterrupt v1.1.1 +SAMDUE_TimerInterrupt v1.2.0 CPU Frequency = 84 MHz Timer Frequency = 84 MHz Using Timer(0) = TC0, channel = 0, IRQ = TC0_IRQn @@ -919,11 +1027,13 @@ simpleTimer2s: Dms=2000, actual=11111 --- -4. The following is the sample terminal output when running example [Change_Interval](examples/Change_Interval) to demonstrate how to change Timer Interval on-the-fly +### 4. Change_Interval on Arduino SAM DUE + +The following is the sample terminal output when running example [Change_Interval](examples/Change_Interval) to demonstrate how to change Timer Interval on-the-fly ``` Starting Change_Interval on SAM DUE -SAMDUE_TimerInterrupt v1.1.1 +SAMDUE_TimerInterrupt v1.2.0 CPU Frequency = 84 MHz Timer Frequency = 84 MHz Using Timer(0) = TC0, channel = 0, IRQ = TC0_IRQn @@ -955,7 +1065,9 @@ Time = 90009, Timer0Count = 139, Timer1Count = 69 --- -5. The following is the sample terminal output when running new example [ISR_16_Timers_Array_Complex](examples/ISR_16_Timers_Array_Complex) on **Arduino SAM DUE** to demonstrate the accuracy of ISR Hardware Timer, **especially when system is very busy or blocked**. The 16 independent ISR timers are **programmed to be activated repetitively after certain intervals, is activated exactly after that programmed interval !!!** +### 5. ISR_16_Timers_Array_Complex on Arduino SAM DUE + +The following is the sample terminal output when running new example [ISR_16_Timers_Array_Complex](examples/ISR_16_Timers_Array_Complex) on **Arduino SAM DUE** to demonstrate the accuracy of ISR Hardware Timer, **especially when system is very busy or blocked**. The 16 independent ISR timers are **programmed to be activated repetitively after certain intervals, is activated exactly after that programmed interval !!!** While software timer, **programmed for 2s, is activated after 10.000s in loop()!!!**. @@ -1077,6 +1189,39 @@ Timer : 15, programmed : 80000, actual : 80000 --- --- +### Debug + +Debug is enabled by default on Serial. + +You can also change the debugging level (_TIMERINTERRUPT_LOGLEVEL_) from 0 to 4 + +```cpp +// These define's must be placed at the beginning before #include "SAMDUE_TimerInterrupt.h" +// _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 +// Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. +#define TIMER_INTERRUPT_DEBUG 0 +#define _TIMERINTERRUPT_LOGLEVEL_ 0 +``` + +--- + +### Troubleshooting + +If you get compilation errors, more often than not, you may need to install a newer version of the core for Arduino boards. + +Sometimes, the library will only work if you update the board core to the latest version because I am using newly added functions. + +--- +--- + +## Releases + +### Releases v1.2.0 + +1. Add better debug feature. +2. Optimize code and examples to reduce RAM usage +3. Add Table of Contents + ### Releases v1.1.1 1. Add example [**Change_Interval**](examples/Change_Interval) and [**ISR_16_Timers_Array_Complex**](examples/ISR_16_Timers_Array_Complex) @@ -1096,7 +1241,7 @@ Timer : 15, programmed : 80000, actual : 80000 --- --- -### Issues ### +### Issues Submit issues to: [SAMDUE_TimerInterrupt issues](https://github.com/khoih-prog/SAMDUE_TimerInterrupt/issues) @@ -1113,6 +1258,8 @@ Submit issues to: [SAMDUE_TimerInterrupt issues](https://github.com/khoih-prog/S 1. Basic hardware timers for SAM DUE. 2. More hardware-initiated software-enabled timers 3. Longer time interval +4. Similar features for remaining Arduino boards such as ESP32, ESP8266, STM32, nRF52, mbed-nRF52, Teensy, etc. +5. Add Table of Contents --- --- diff --git a/examples/Argument_None/Argument_None.ino b/examples/Argument_None/Argument_None.ino index e7b3737..11c3bad 100644 --- a/examples/Argument_None/Argument_None.ino +++ b/examples/Argument_None/Argument_None.ino @@ -1,30 +1,31 @@ /**************************************************************************************************************************** - Argument_None.ino - For SAM DUE boards - Written by Khoi Hoang + Argument_None.ino + For SAM DUE boards + Written by Khoi Hoang - Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt - Licensed under MIT license + Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt + Licensed under MIT license - Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by - unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. - The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers - Therefore, their executions are not blocked by bad-behaving functions / tasks. - This important feature is absolutely necessary for mission-critical tasks. + Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by + unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. + The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers + Therefore, their executions are not blocked by bad-behaving functions / tasks. + This important feature is absolutely necessary for mission-critical tasks. - Based on SimpleTimer - A timer library for Arduino. - Author: mromani@ottotecnica.com - Copyright (c) 2010 OTTOTECNICA Italy + Based on SimpleTimer - A timer library for Arduino. + Author: mromani@ottotecnica.com + Copyright (c) 2010 OTTOTECNICA Italy - Based on BlynkTimer.h - Author: Volodymyr Shymanskyy + Based on BlynkTimer.h + Author: Volodymyr Shymanskyy - Version: 1.1.1 + Version: 1.2.0 - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.1 K Hoang 06/11/2020 Initial coding - 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.1 K Hoang 06/11/2020 Initial coding + 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + 1.2.0 K.Hoang 10/01/2021 Add better debug feature. Optimize code and examples to reduce RAM usage *****************************************************************************************************************************/ /* @@ -43,9 +44,12 @@ #error This code is designed to run on SAM DUE board / platform! Please check your Tools->Board setting. #endif -// These define's must be placed at the beginning before #include "SAMDTimerInterrupt.h" -// Don't define SAMDUE_TIMER_INTERRUPT_DEBUG > 0. Only for special ISR debugging only. Can hang the system. -#define SAMDUE_TIMER_INTERRUPT_DEBUG 1 +// These define's must be placed at the beginning before #include "SAMDUETimerInterrupt.h" +// _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 +// Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. +// Don't define TIMER_INTERRUPT_DEBUG > 2. Only for special ISR debugging only. Can hang the system. +#define TIMER_INTERRUPT_DEBUG 0 +#define _TIMERINTERRUPT_LOGLEVEL_ 0 #include "SAMDUETimerInterrupt.h" @@ -71,39 +75,40 @@ volatile uint32_t preMillisTimer1 = 0; volatile uint32_t preMillisTimer2 = 0; volatile uint32_t preMillisTimer3 = 0; -void TimerHandler0(void) +void TimerHandler0() { - static bool toggle = false; + static bool toggle0 = false; static bool started = false; - static uint32_t curMillis = 0; - + if (!started) { started = true; pinMode(LED_BUILTIN, OUTPUT); } -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 0) +#if (TIMER_INTERRUPT_DEBUG > 0) + static uint32_t curMillis = 0; + curMillis = millis(); if (curMillis > TIMER0_INTERVAL_MS) { - Serial.println("ITimer0: millis() = " + String(curMillis) + ", delta = " + String(curMillis - preMillisTimer0)); + Serial.print("ITimer0: millis() = "); Serial.print(curMillis); + Serial.print(", delta = "); Serial.println(curMillis - preMillisTimer0); } preMillisTimer0 = curMillis; #endif //timer interrupt toggles pin LED_BUILTIN - digitalWrite(LED_BUILTIN, toggle); - toggle = !toggle; + digitalWrite(LED_BUILTIN, toggle0); + toggle0 = !toggle0; } -void TimerHandler1(void) +void TimerHandler1() { - static bool toggle = false; + static bool toggle1 = false; static bool started = false; - static uint32_t curMillis = 0; if (!started) { @@ -111,48 +116,53 @@ void TimerHandler1(void) pinMode(LED_BLUE, OUTPUT); } -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 0) +#if (TIMER_INTERRUPT_DEBUG > 0) + static uint32_t curMillis = 0; + curMillis = millis(); if (curMillis > TIMER1_INTERVAL_MS) { - Serial.println("ITimer1: millis() = " + String(curMillis) + ", delta = " + String(curMillis - preMillisTimer1)); + Serial.print("ITimer1: millis() = "); Serial.print(curMillis); + Serial.print(", delta = "); Serial.println(curMillis - preMillisTimer1); } preMillisTimer1 = curMillis; #endif //timer interrupt toggles outputPin - digitalWrite(LED_BLUE, toggle); - toggle = !toggle; + digitalWrite(LED_BLUE, toggle1); + toggle1 = !toggle1; } -void TimerHandler2(void) +void TimerHandler2() { -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 0) +#if (TIMER_INTERRUPT_DEBUG > 0) static uint32_t curMillis = 0; curMillis = millis(); if (curMillis > TIMER2_INTERVAL_MS) { - Serial.println("ITimer2: millis() = " + String(curMillis) + ", delta = " + String(curMillis - preMillisTimer2)); + Serial.print("ITimer2: millis() = "); Serial.print(curMillis); + Serial.print(", delta = "); Serial.println(curMillis - preMillisTimer2); } preMillisTimer2 = curMillis; #endif } -void TimerHandler3(void) +void TimerHandler3() { -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 0) +#if (TIMER_INTERRUPT_DEBUG > 0) static uint32_t curMillis = 0; curMillis = millis(); if (curMillis > TIMER3_INTERVAL_MS) { - Serial.println("ITimer3: millis() = " + String(curMillis) + ", delta = " + String(curMillis - preMillisTimer3)); + Serial.print("ITimer3: millis() = "); Serial.print(curMillis); + Serial.print(", delta = "); Serial.println(curMillis - preMillisTimer3); } preMillisTimer3 = curMillis; @@ -167,10 +177,7 @@ uint16_t attachDueInterrupt(double microseconds, timerCallback callback, const c uint16_t timerNumber = dueTimerInterrupt.getTimerNumber(); - Serial.print(TimerName); - Serial.print(" attached to Timer("); - Serial.print(timerNumber); - Serial.println(")"); + Serial.print(TimerName); Serial.print(F(" attached to Timer(")); Serial.print(timerNumber); Serial.println(F(")")); return timerNumber; } @@ -182,10 +189,10 @@ void setup() delay(100); - Serial.println("\nStarting Argument_None on " + String(BOARD_NAME)); + Serial.print(F("\nStarting Argument_None on ")); Serial.println(BOARD_NAME); Serial.println(SAMDUE_TIMER_INTERRUPT_VERSION); - Serial.println("CPU Frequency = " + String(F_CPU / 1000000) + " MHz"); - Serial.println("Timer Frequency = " + String(SystemCoreClock / 1000000) + " MHz"); + Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("Timer Frequency = ")); Serial.print(SystemCoreClock / 1000000); Serial.println(F(" MHz")); // Interval in microsecs uint32_t curMillis = millis(); diff --git a/examples/Change_Interval/Change_Interval.ino b/examples/Change_Interval/Change_Interval.ino index 946e986..5be5d98 100644 --- a/examples/Change_Interval/Change_Interval.ino +++ b/examples/Change_Interval/Change_Interval.ino @@ -1,30 +1,31 @@ /**************************************************************************************************************************** - Change_Interval.ino - For SAM DUE boards - Written by Khoi Hoang + Change_Interval.ino + For SAM DUE boards + Written by Khoi Hoang - Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt - Licensed under MIT license + Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt + Licensed under MIT license - Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by - unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. - The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers - Therefore, their executions are not blocked by bad-behaving functions / tasks. - This important feature is absolutely necessary for mission-critical tasks. + Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by + unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. + The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers + Therefore, their executions are not blocked by bad-behaving functions / tasks. + This important feature is absolutely necessary for mission-critical tasks. - Based on SimpleTimer - A timer library for Arduino. - Author: mromani@ottotecnica.com - Copyright (c) 2010 OTTOTECNICA Italy + Based on SimpleTimer - A timer library for Arduino. + Author: mromani@ottotecnica.com + Copyright (c) 2010 OTTOTECNICA Italy - Based on BlynkTimer.h - Author: Volodymyr Shymanskyy + Based on BlynkTimer.h + Author: Volodymyr Shymanskyy - Version: 1.1.1 + Version: 1.2.0 - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.1 K Hoang 06/11/2020 Initial coding - 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.1 K Hoang 06/11/2020 Initial coding + 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + 1.2.0 K.Hoang 10/01/2021 Add better debug feature. Optimize code and examples to reduce RAM usage *****************************************************************************************************************************/ /* @@ -43,9 +44,12 @@ #error This code is designed to run on SAM DUE board / platform! Please check your Tools->Board setting. #endif -// These define's must be placed at the beginning before #include "SAMDTimerInterrupt.h" -// Don't define SAMDUE_TIMER_INTERRUPT_DEBUG > 0. Only for special ISR debugging only. Can hang the system. -#define SAMDUE_TIMER_INTERRUPT_DEBUG 1 +// These define's must be placed at the beginning before #include "SAMDUETimerInterrupt.h" +// _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 +// Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. +// Don't define TIMER_INTERRUPT_DEBUG > 2. Only for special ISR debugging only. Can hang the system. +#define TIMER_INTERRUPT_DEBUG 0 +#define _TIMERINTERRUPT_LOGLEVEL_ 0 #include "SAMDUETimerInterrupt.h" @@ -66,13 +70,14 @@ volatile uint32_t Timer0Count = 0; volatile uint32_t Timer1Count = 0; - void printResult(uint32_t currTime) { - Serial.println("Time = " + String(currTime) + ", Timer0Count = " + String(Timer0Count) + ", Timer1Count = " + String(Timer1Count)); + Serial.print(F("Time = ")); Serial.print(currTime); + Serial.print(F(", Timer0Count = ")); Serial.print(Timer0Count); + Serial.print(F(", Timer1Count = ")); Serial.println(Timer1Count); } -void TimerHandler0(void) +void TimerHandler0() { static bool toggle0 = false; @@ -84,7 +89,7 @@ void TimerHandler0(void) toggle0 = !toggle0; } -void TimerHandler1(void) +void TimerHandler1() { static bool toggle1 = false; @@ -107,10 +112,7 @@ uint16_t attachDueInterrupt(double microseconds, timerCallback callback, const c uint16_t timerNumber = dueTimerInterrupt.getTimerNumber(); - Serial.print(TimerName); - Serial.print(" attached to Timer("); - Serial.print(timerNumber); - Serial.println(")"); + Serial.print(TimerName); Serial.print(F(" attached to Timer(")); Serial.print(timerNumber); Serial.println(F(")")); return timerNumber; } @@ -123,10 +125,7 @@ uint16_t updateTimerInterval(uint16_t timerNumberInput, double microseconds, tim uint16_t timerNumber = dueTimerInterrupt.getTimerNumber(); - Serial.print(TimerName); - Serial.print(" attached to Timer("); - Serial.print(timerNumber); - Serial.println(")"); + Serial.print(TimerName); Serial.print(F(" attached to Timer(")); Serial.print(timerNumber); Serial.println(F(")")); return timerNumber; } @@ -140,11 +139,11 @@ void setup() while (!Serial); delay(100); - - Serial.println("\nStarting Change_Interval on " + String(BOARD_NAME)); + + Serial.print(F("\nStarting Change_Interval on ")); Serial.println(BOARD_NAME); Serial.println(SAMDUE_TIMER_INTERRUPT_VERSION); - Serial.println("CPU Frequency = " + String(F_CPU / 1000000) + " MHz"); - Serial.println("Timer Frequency = " + String(SystemCoreClock / 1000000) + " MHz"); + Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("Timer Frequency = ")); Serial.print(SystemCoreClock / 1000000); Serial.println(F(" MHz")); // Interval in microsecs timerNumber0 = attachDueInterrupt(TIMER0_INTERVAL_MS * 1000, TimerHandler0, "ITimer0"); @@ -175,9 +174,9 @@ void loop() updateTimerInterval(timerNumber0, TIMER0_INTERVAL_MS * 1000 * (multFactor + 1), TimerHandler0, "ITimer0"); updateTimerInterval(timerNumber1, TIMER1_INTERVAL_MS * 1000 * (multFactor + 1), TimerHandler1, "ITimer1"); - - Serial.println("Changing Interval, Timer0 = " + String(TIMER0_INTERVAL_MS * (multFactor + 1)) + - ", Timer1 = " + String(TIMER1_INTERVAL_MS * (multFactor + 1))); + + Serial.print(F("Changing Interval, Timer0 = ")); Serial.print(TIMER0_INTERVAL_MS * (multFactor + 1)); + Serial.print(F(", Timer1 = ")); Serial.println(TIMER1_INTERVAL_MS * (multFactor + 1)); lastChangeTime = currTime; } diff --git a/examples/ISR_16_Timers_Array/ISR_16_Timers_Array.ino b/examples/ISR_16_Timers_Array/ISR_16_Timers_Array.ino index dd4e45e..f3673c8 100644 --- a/examples/ISR_16_Timers_Array/ISR_16_Timers_Array.ino +++ b/examples/ISR_16_Timers_Array/ISR_16_Timers_Array.ino @@ -1,30 +1,31 @@ /**************************************************************************************************************************** - ISR_16_Timers_Array.ino - For SAM DUE boards - Written by Khoi Hoang + ISR_16_Timers_Array.ino + For SAM DUE boards + Written by Khoi Hoang - Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt - Licensed under MIT license + Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt + Licensed under MIT license - Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by - unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. - The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers - Therefore, their executions are not blocked by bad-behaving functions / tasks. - This important feature is absolutely necessary for mission-critical tasks. + Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by + unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. + The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers + Therefore, their executions are not blocked by bad-behaving functions / tasks. + This important feature is absolutely necessary for mission-critical tasks. - Based on SimpleTimer - A timer library for Arduino. - Author: mromani@ottotecnica.com - Copyright (c) 2010 OTTOTECNICA Italy + Based on SimpleTimer - A timer library for Arduino. + Author: mromani@ottotecnica.com + Copyright (c) 2010 OTTOTECNICA Italy - Based on BlynkTimer.h - Author: Volodymyr Shymanskyy + Based on BlynkTimer.h + Author: Volodymyr Shymanskyy - Version: 1.1.1 + Version: 1.2.0 - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.1 K Hoang 06/11/2020 Initial coding - 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.1 K Hoang 06/11/2020 Initial coding + 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + 1.2.0 K.Hoang 10/01/2021 Add better debug feature. Optimize code and examples to reduce RAM usage *****************************************************************************************************************************/ /* Notes: @@ -59,9 +60,12 @@ #error This code is designed to run on SAM DUE board / platform! Please check your Tools->Board setting. #endif -// These define's must be placed at the beginning before #include "SAMDTimerInterrupt.h" -// Don't define SAMDUE_TIMER_INTERRUPT_DEBUG > 0. Only for special ISR debugging only. Can hang the system. -#define SAMDUE_TIMER_INTERRUPT_DEBUG 1 +// These define's must be placed at the beginning before #include "SAMDUETimerInterrupt.h" +// _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 +// Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. +// Don't define TIMER_INTERRUPT_DEBUG > 2. Only for special ISR debugging only. Can hang the system. +#define TIMER_INTERRUPT_DEBUG 0 +#define _TIMERINTERRUPT_LOGLEVEL_ 0 #include "SAMDUETimerInterrupt.h" #include "SAMDUE_ISR_Timer.h" @@ -91,7 +95,7 @@ SAMDUE_ISR_Timer ISR_Timer; #define LED_TOGGLE_INTERVAL_MS 500L -void TimerHandler(void) +void TimerHandler() { static bool toggle = false; static bool started = false; @@ -125,16 +129,13 @@ uint32_t TimerInterval[NUMBER_ISR_TIMERS] = 9000L, 10000L, 11000L, 12000L, 13000L, 14000L, 15000L, 16000L }; -typedef void (*irqCallback) (void); +typedef void (*irqCallback) (); -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 0) +#if (TIMER_INTERRUPT_DEBUG > 0) void printStatus(uint16_t index, unsigned long deltaMillis, unsigned long currentMillis) -{ - Serial.print(TimerInterval[index]/1000); - Serial.print("s: Delta ms = "); - Serial.print(deltaMillis); - Serial.print(", ms = "); - Serial.println(currentMillis); +{ + Serial.print(TimerInterval[index] / 1000); Serial.print("s: Delta ms = "); Serial.print(deltaMillis); + Serial.print(", ms = "); Serial.println(currentMillis); } #endif @@ -143,143 +144,143 @@ void printStatus(uint16_t index, unsigned long deltaMillis, unsigned long curren // Or you can get this run-time error / crash void doingSomething0() { -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 0) +#if (TIMER_INTERRUPT_DEBUG > 0) static unsigned long previousMillis = startMillis; unsigned long currentMillis = millis(); unsigned long deltaMillis = currentMillis - previousMillis; - + printStatus(0, deltaMillis, currentMillis); - + previousMillis = currentMillis; #endif } void doingSomething1() { -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 1) +#if (TIMER_INTERRUPT_DEBUG > 1) static unsigned long previousMillis = startMillis; unsigned long currentMillis = millis(); unsigned long deltaMillis = currentMillis - previousMillis; - + printStatus(1, deltaMillis, currentMillis); - + previousMillis = currentMillis; #endif } void doingSomething2() { -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 1) +#if (TIMER_INTERRUPT_DEBUG > 1) static unsigned long previousMillis = startMillis; unsigned long currentMillis = millis(); unsigned long deltaMillis = currentMillis - previousMillis; - + printStatus(2, deltaMillis, currentMillis); - + previousMillis = currentMillis; #endif } void doingSomething3() { -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 1) +#if (TIMER_INTERRUPT_DEBUG > 1) static unsigned long previousMillis = startMillis; unsigned long currentMillis = millis(); unsigned long deltaMillis = currentMillis - previousMillis; - + printStatus(3, deltaMillis, currentMillis); - + previousMillis = currentMillis; #endif } void doingSomething4() { -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 1) +#if (TIMER_INTERRUPT_DEBUG > 1) static unsigned long previousMillis = startMillis; unsigned long currentMillis = millis(); unsigned long deltaMillis = currentMillis - previousMillis; - + printStatus(4, deltaMillis, currentMillis); - + previousMillis = currentMillis; #endif } void doingSomething5() { -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 1) +#if (TIMER_INTERRUPT_DEBUG > 1) static unsigned long previousMillis = startMillis; unsigned long currentMillis = millis(); unsigned long deltaMillis = currentMillis - previousMillis; - + printStatus(5, deltaMillis, currentMillis); - + previousMillis = currentMillis; #endif } void doingSomething6() { -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 1) +#if (TIMER_INTERRUPT_DEBUG > 1) static unsigned long previousMillis = startMillis; unsigned long currentMillis = millis(); unsigned long deltaMillis = currentMillis - previousMillis; - + printStatus(6, deltaMillis, currentMillis); - + previousMillis = currentMillis; #endif } void doingSomething7() { -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 1) +#if (TIMER_INTERRUPT_DEBUG > 1) static unsigned long previousMillis = startMillis; unsigned long currentMillis = millis(); unsigned long deltaMillis = currentMillis - previousMillis; - + printStatus(7, deltaMillis, currentMillis); - + previousMillis = currentMillis; #endif } void doingSomething8() { -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 1) +#if (TIMER_INTERRUPT_DEBUG > 1) static unsigned long previousMillis = startMillis; unsigned long currentMillis = millis(); unsigned long deltaMillis = currentMillis - previousMillis; - + printStatus(8, deltaMillis, currentMillis); - + previousMillis = currentMillis; #endif } void doingSomething9() { -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 1) +#if (TIMER_INTERRUPT_DEBUG > 1) static unsigned long previousMillis = startMillis; unsigned long currentMillis = millis(); unsigned long deltaMillis = currentMillis - previousMillis; - + printStatus(9, deltaMillis, currentMillis); - + previousMillis = currentMillis; #endif } void doingSomething10() { -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 1) +#if (TIMER_INTERRUPT_DEBUG > 1) static unsigned long previousMillis = startMillis; unsigned long currentMillis = millis(); unsigned long deltaMillis = currentMillis - previousMillis; - + printStatus(10, deltaMillis, currentMillis); - + previousMillis = currentMillis; #endif } @@ -289,13 +290,13 @@ void doingSomething10() // Or you can get this run-time error / crash void doingSomething11() { -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 1) +#if (TIMER_INTERRUPT_DEBUG > 1) static unsigned long previousMillis = startMillis; unsigned long currentMillis = millis(); unsigned long deltaMillis = currentMillis - previousMillis; - + printStatus(11, deltaMillis, currentMillis); - + previousMillis = currentMillis; #endif } @@ -305,52 +306,52 @@ void doingSomething11() // Or you can get this run-time error / crash void doingSomething12() { -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 1) +#if (TIMER_INTERRUPT_DEBUG > 1) static unsigned long previousMillis = startMillis; unsigned long currentMillis = millis(); unsigned long deltaMillis = currentMillis - previousMillis; - + printStatus(12, deltaMillis, currentMillis); - + previousMillis = currentMillis; #endif } void doingSomething13() { -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 1) +#if (TIMER_INTERRUPT_DEBUG > 1) static unsigned long previousMillis = startMillis; unsigned long currentMillis = millis(); unsigned long deltaMillis = currentMillis - previousMillis; - + printStatus(13, deltaMillis, currentMillis); - + previousMillis = currentMillis; #endif } void doingSomething14() { -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 1) +#if (TIMER_INTERRUPT_DEBUG > 1) static unsigned long previousMillis = startMillis; unsigned long currentMillis = millis(); unsigned long deltaMillis = currentMillis - previousMillis; - + printStatus(14, deltaMillis, currentMillis); - + previousMillis = currentMillis; #endif } void doingSomething15() { -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 1) +#if (TIMER_INTERRUPT_DEBUG > 1) static unsigned long previousMillis = startMillis; unsigned long currentMillis = millis(); unsigned long deltaMillis = currentMillis - previousMillis; - + printStatus(15, deltaMillis, currentMillis); - + previousMillis = currentMillis; #endif } @@ -379,12 +380,10 @@ void simpleTimerDoingSomething2s() { static unsigned long previousMillis = startMillis; unsigned long currMillis = millis(); - - Serial.print("simpleTimer2s: Dms="); - Serial.print(SIMPLE_TIMER_MS); - Serial.print(", actual="); - Serial.println(currMillis - previousMillis); - + + Serial.print(F("simpleTimer2s: Dms=")); Serial.print(SIMPLE_TIMER_MS); + Serial.print(F(", actual=")); Serial.println(currMillis - previousMillis); + previousMillis = currMillis; } @@ -396,10 +395,7 @@ uint16_t attachDueInterrupt(double microseconds, timerCallback callback, const c uint16_t timerNumber = dueTimerInterrupt.getTimerNumber(); - Serial.print(TimerName); - Serial.print(" attached to Timer("); - Serial.print(timerNumber); - Serial.println(")"); + Serial.print(TimerName); Serial.print(F(" attached to Timer(")); Serial.print(timerNumber); Serial.println(F(")")); return timerNumber; } @@ -408,11 +404,13 @@ void setup() { Serial.begin(115200); while (!Serial); + + delay(100); - Serial.println("\nStarting ISR_16_Timers_Array on " + String(BOARD_NAME)); + Serial.print(F("\nStarting ISR_16_Timers_Array on ")); Serial.println(BOARD_NAME); Serial.println(SAMDUE_TIMER_INTERRUPT_VERSION); - Serial.println("CPU Frequency = " + String(F_CPU / 1000000) + " MHz"); - Serial.println("Timer Frequency = " + String(SystemCoreClock / 1000000) + " MHz"); + Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("Timer Frequency = ")); Serial.print(SystemCoreClock / 1000000); Serial.println(F(" MHz")); // Interval in microsecs attachDueInterrupt(HW_TIMER_INTERVAL_US, TimerHandler, "ITimer"); diff --git a/examples/ISR_16_Timers_Array_Complex/ISR_16_Timers_Array_Complex.ino b/examples/ISR_16_Timers_Array_Complex/ISR_16_Timers_Array_Complex.ino index 9a6062e..231fedb 100644 --- a/examples/ISR_16_Timers_Array_Complex/ISR_16_Timers_Array_Complex.ino +++ b/examples/ISR_16_Timers_Array_Complex/ISR_16_Timers_Array_Complex.ino @@ -1,30 +1,31 @@ /**************************************************************************************************************************** - ISR_16_Timers_Array.ino - For SAM DUE boards - Written by Khoi Hoang + ISR_16_Timers_Array.ino + For SAM DUE boards + Written by Khoi Hoang - Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt - Licensed under MIT license + Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt + Licensed under MIT license - Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by - unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. - The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers - Therefore, their executions are not blocked by bad-behaving functions / tasks. - This important feature is absolutely necessary for mission-critical tasks. + Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by + unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. + The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers + Therefore, their executions are not blocked by bad-behaving functions / tasks. + This important feature is absolutely necessary for mission-critical tasks. - Based on SimpleTimer - A timer library for Arduino. - Author: mromani@ottotecnica.com - Copyright (c) 2010 OTTOTECNICA Italy + Based on SimpleTimer - A timer library for Arduino. + Author: mromani@ottotecnica.com + Copyright (c) 2010 OTTOTECNICA Italy - Based on BlynkTimer.h - Author: Volodymyr Shymanskyy + Based on BlynkTimer.h + Author: Volodymyr Shymanskyy - Version: 1.1.1 + Version: 1.2.0 - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.1 K Hoang 06/11/2020 Initial coding - 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.1 K Hoang 06/11/2020 Initial coding + 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + 1.2.0 K.Hoang 10/01/2021 Add better debug feature. Optimize code and examples to reduce RAM usage *****************************************************************************************************************************/ /* Notes: @@ -50,9 +51,12 @@ #error This code is designed to run on SAM DUE board / platform! Please check your Tools->Board setting. #endif -// These define's must be placed at the beginning before #include "SAMDTimerInterrupt.h" -// Don't define SAMDUE_TIMER_INTERRUPT_DEBUG > 0. Only for special ISR debugging only. Can hang the system. -#define SAMDUE_TIMER_INTERRUPT_DEBUG 1 +// These define's must be placed at the beginning before #include "SAMDUETimerInterrupt.h" +// _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 +// Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. +// Don't define TIMER_INTERRUPT_DEBUG > 2. Only for special ISR debugging only. Can hang the system. +#define TIMER_INTERRUPT_DEBUG 0 +#define _TIMERINTERRUPT_LOGLEVEL_ 0 #include "SAMDUETimerInterrupt.h" #include "SAMDUE_ISR_Timer.h" @@ -81,7 +85,7 @@ SAMDUE_ISR_Timer ISR_Timer; #define LED_TOGGLE_INTERVAL_MS 2000L -void TimerHandler(void) +void TimerHandler() { static bool toggle = false; static int timeRun = 0; @@ -103,7 +107,7 @@ void TimerHandler(void) #define NUMBER_ISR_TIMERS 16 -typedef void (*irqCallback) (void); +typedef void (*irqCallback) (); ///////////////////////////////////////////////// @@ -290,17 +294,20 @@ void simpleTimerDoingSomething2s() unsigned long currMillis = millis(); - Serial.println("SimpleTimer : " + String(SIMPLE_TIMER_MS / 1000) + ", ms = " + String(currMillis) - + ", Dms : " + String(currMillis - previousMillis)); + Serial.print(F("SimpleTimer : "));Serial.print(SIMPLE_TIMER_MS / 1000); + Serial.print(F(", ms : ")); Serial.print(currMillis); + Serial.print(F(", Dms : ")); Serial.println(currMillis - previousMillis); - for (int i = 0; i < NUMBER_ISR_TIMERS; i++) + for (uint16_t i = 0; i < NUMBER_ISR_TIMERS; i++) { #if USE_COMPLEX_STRUCT - Serial.println("Timer : " + String(i) + ", programmed : " + String(curISRTimerData[i].TimerInterval) - + ", actual : " + String(curISRTimerData[i].deltaMillis)); + Serial.print(F("Timer : ")); Serial.print(i); + Serial.print(F(", programmed : ")); Serial.print(curISRTimerData[i].TimerInterval); + Serial.print(F(", actual : ")); Serial.println(curISRTimerData[i].deltaMillis); #else - Serial.println("Timer : " + String(i) + ", programmed : " + String(TimerInterval[i]) - + ", actual : " + String(deltaMillis[i])); + Serial.print(F("Timer : ")); Serial.print(i); + Serial.print(F(", programmed : ")); Serial.print(TimerInterval[i]); + Serial.print(F(", actual : ")); Serial.println(deltaMillis[i]); #endif } @@ -315,10 +322,7 @@ uint16_t attachDueInterrupt(double microseconds, timerCallback callback, const c uint16_t timerNumber = dueTimerInterrupt.getTimerNumber(); - Serial.print(TimerName); - Serial.print(" attached to Timer("); - Serial.print(timerNumber); - Serial.println(")"); + Serial.print(TimerName); Serial.print(F(" attached to Timer(")); Serial.print(timerNumber); Serial.println(F(")")); return timerNumber; } @@ -330,10 +334,12 @@ void setup() Serial.begin(115200); while (!Serial); - Serial.println("\nStarting ISR_16_Timers_Array_Complex on " + String(BOARD_NAME)); + delay(100); + + Serial.print(F("\nStarting ISR_16_Timers_Array_Complex on ")); Serial.println(BOARD_NAME); Serial.println(SAMDUE_TIMER_INTERRUPT_VERSION); - Serial.println("CPU Frequency = " + String(F_CPU / 1000000) + " MHz"); - Serial.println("Timer Frequency = " + String(SystemCoreClock / 1000000) + " MHz"); + Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("Timer Frequency = ")); Serial.print(SystemCoreClock / 1000000); Serial.println(F(" MHz")); // Interval in microsecs attachDueInterrupt(HW_TIMER_INTERVAL_US, TimerHandler, "ITimer"); @@ -342,7 +348,7 @@ void setup() // Just to demonstrate, don't use too many ISR Timers if not absolutely necessary // You can use up to 16 timer for each ISR_Timer - for (int i = 0; i < NUMBER_ISR_TIMERS; i++) + for (uint8_t i = 0; i < NUMBER_ISR_TIMERS; i++) { #if USE_COMPLEX_STRUCT curISRTimerData[i].previousMillis = startMillis; diff --git a/examples/ISR_RPM_Measure/ISR_RPM_Measure.ino b/examples/ISR_RPM_Measure/ISR_RPM_Measure.ino index 4c2d79d..2a59ba2 100644 --- a/examples/ISR_RPM_Measure/ISR_RPM_Measure.ino +++ b/examples/ISR_RPM_Measure/ISR_RPM_Measure.ino @@ -1,30 +1,31 @@ /**************************************************************************************************************************** - ISR_RPM_Measure.ino - For SAM DUE boards - Written by Khoi Hoang + ISR_RPM_Measure.ino + For SAM DUE boards + Written by Khoi Hoang - Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt - Licensed under MIT license + Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt + Licensed under MIT license - Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by - unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. - The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers - Therefore, their executions are not blocked by bad-behaving functions / tasks. - This important feature is absolutely necessary for mission-critical tasks. + Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by + unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. + The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers + Therefore, their executions are not blocked by bad-behaving functions / tasks. + This important feature is absolutely necessary for mission-critical tasks. - Based on SimpleTimer - A timer library for Arduino. - Author: mromani@ottotecnica.com - Copyright (c) 2010 OTTOTECNICA Italy + Based on SimpleTimer - A timer library for Arduino. + Author: mromani@ottotecnica.com + Copyright (c) 2010 OTTOTECNICA Italy - Based on BlynkTimer.h - Author: Volodymyr Shymanskyy + Based on BlynkTimer.h + Author: Volodymyr Shymanskyy - Version: 1.1.1 + Version: 1.2.0 - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.1 K Hoang 06/11/2020 Initial coding - 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.1 K Hoang 06/11/2020 Initial coding + 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + 1.2.0 K.Hoang 10/01/2021 Add better debug feature. Optimize code and examples to reduce RAM usage *****************************************************************************************************************************/ /* Notes: @@ -52,9 +53,12 @@ #error This code is designed to run on SAM DUE board / platform! Please check your Tools->Board setting. #endif -// These define's must be placed at the beginning before #include "SAMDTimerInterrupt.h" -// Don't define SAMDUE_TIMER_INTERRUPT_DEBUG > 0. Only for special ISR debugging only. Can hang the system. -#define SAMDUE_TIMER_INTERRUPT_DEBUG 1 +// These define's must be placed at the beginning before #include "SAMDUETimerInterrupt.h" +// _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 +// Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. +// Don't define TIMER_INTERRUPT_DEBUG > 2. Only for special ISR debugging only. Can hang the system. +#define TIMER_INTERRUPT_DEBUG 0 +#define _TIMERINTERRUPT_LOGLEVEL_ 0 #include "SAMDUETimerInterrupt.h" @@ -85,15 +89,13 @@ volatile int debounceCounter; volatile bool activeState = false; -void detectRotation(void) +void detectRotation() { activeState = true; } void TimerHandler1() { - static bool started = false; - if ( activeState ) { // Reset to prepare for next round of interrupt @@ -107,7 +109,10 @@ void TimerHandler1() avgRPM = ( 2 * avgRPM + RPM) / 3, - Serial.println("RPM = " + String(avgRPM) + ", rotationTime ms = " + String(rotationTime * TIMER1_INTERVAL_MS) ); +#if (TIMER_INTERRUPT_DEBUG > 1) + Serial.print("RPM = "); Serial.print(avgRPM); + Serial.print(", rotationTime ms = "); Serial.println(rotationTime * TIMER1_INTERVAL_MS); +#endif rotationTime = 0; debounceCounter = 0; @@ -124,7 +129,11 @@ void TimerHandler1() { // If idle, set RPM to 0, don't increase rotationTime RPM = 0; - Serial.println("RPM = " + String(RPM) + ", rotationTime = " + String(rotationTime) ); + +#if (TIMER_INTERRUPT_DEBUG > 1) + Serial.print("RPM = "); Serial.print(RPM); Serial.print(", rotationTime = "); Serial.println(rotationTime); +#endif + rotationTime = 0; } else @@ -140,11 +149,7 @@ uint16_t attachDueInterrupt(double microseconds, timerCallback callback, const c dueTimerInterrupt.attachInterruptInterval(microseconds, callback); uint16_t timerNumber = dueTimerInterrupt.getTimerNumber(); - - Serial.print(TimerName); - Serial.print(" attached to Timer("); - Serial.print(timerNumber); - Serial.println(")"); + Serial.print(TimerName); Serial.print(F(" attached to Timer(")); Serial.print(timerNumber); Serial.println(F(")")); return timerNumber; } @@ -155,11 +160,13 @@ void setup() Serial.begin(115200); while (!Serial); + + delay(100); - Serial.println("\nStarting ISR_RPM_Measure on " + String(BOARD_NAME)); + Serial.print(F("\nStarting ISR_RPM_Measure on ")); Serial.println(BOARD_NAME); Serial.println(SAMDUE_TIMER_INTERRUPT_VERSION); - Serial.println("CPU Frequency = " + String(F_CPU / 1000000) + " MHz"); - Serial.println("Timer Frequency = " + String(SystemCoreClock / 1000000) + " MHz"); + Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("Timer Frequency = ")); Serial.print(SystemCoreClock / 1000000); Serial.println(F(" MHz")); // Interval in microsecs attachDueInterrupt(TIMER1_INTERVAL_MS * 1000, TimerHandler1, "ITimer1"); diff --git a/examples/ISR_Timer_Complex_Ethernet/ISR_Timer_Complex_Ethernet.ino b/examples/ISR_Timer_Complex_Ethernet/ISR_Timer_Complex_Ethernet.ino index 97b6db1..02bfb79 100644 --- a/examples/ISR_Timer_Complex_Ethernet/ISR_Timer_Complex_Ethernet.ino +++ b/examples/ISR_Timer_Complex_Ethernet/ISR_Timer_Complex_Ethernet.ino @@ -1,30 +1,31 @@ /**************************************************************************************************************************** - ISR_Timer_Complex_Ethernet.ino - For SAM DUE boards - Written by Khoi Hoang + ISR_Timer_Complex_Ethernet.ino + For SAM DUE boards + Written by Khoi Hoang - Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt - Licensed under MIT license + Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt + Licensed under MIT license - Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by - unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. - The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers - Therefore, their executions are not blocked by bad-behaving functions / tasks. - This important feature is absolutely necessary for mission-critical tasks. + Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by + unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. + The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers + Therefore, their executions are not blocked by bad-behaving functions / tasks. + This important feature is absolutely necessary for mission-critical tasks. - Based on SimpleTimer - A timer library for Arduino. - Author: mromani@ottotecnica.com - Copyright (c) 2010 OTTOTECNICA Italy + Based on SimpleTimer - A timer library for Arduino. + Author: mromani@ottotecnica.com + Copyright (c) 2010 OTTOTECNICA Italy - Based on BlynkTimer.h - Author: Volodymyr Shymanskyy + Based on BlynkTimer.h + Author: Volodymyr Shymanskyy - Version: 1.1.1 + Version: 1.2.0 - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.1 K Hoang 06/11/2020 Initial coding - 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.1 K Hoang 06/11/2020 Initial coding + 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + 1.2.0 K.Hoang 10/01/2021 Add better debug feature. Optimize code and examples to reduce RAM usage *****************************************************************************************************************************/ /* Notes: @@ -59,9 +60,12 @@ #error This code is designed to run on SAM DUE board / platform! Please check your Tools->Board setting. #endif -// These define's must be placed at the beginning before #include "SAMDTimerInterrupt.h" -// Don't define > 0. Only for special ISR debugging only. Can hang the system. -#define SAMDUE_TIMER_INTERRUPT_DEBUG 1 +// These define's must be placed at the beginning before #include "SAMDUETimerInterrupt.h" +// _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 +// Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. +// Don't define TIMER_INTERRUPT_DEBUG > 2. Only for special ISR debugging only. Can hang the system. +#define TIMER_INTERRUPT_DEBUG 0 +#define _TIMERINTERRUPT_LOGLEVEL_ 0 #define BLYNK_PRINT Serial @@ -135,7 +139,7 @@ BlynkTimer blynkTimer; #define TIMER_INTERVAL_11S 11000L #define TIMER_INTERVAL_101S 101000L -void TimerHandler(void) +void TimerHandler() { static bool toggle = false; static bool started = false; @@ -160,80 +164,80 @@ void TimerHandler(void) } } -// In SAMD, avoid doing something fancy in ISR, for example complex Serial.print with String() argument +// In SAM_DUE, avoid doing something fancy in ISR, for example complex Serial.print with String() argument // The pure simple Serial.prints here are just for demonstration and testing. Must be eliminate in working environment // Or you can get this run-time error / crash void doingSomething2s() { +#if (TIMER_INTERRUPT_DEBUG > 0) static unsigned long previousMillis = lastMillis; unsigned long deltaMillis = millis() - previousMillis; -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 0) + if (previousMillis > TIMER_INTERVAL_2S) { - Serial.print("2s: Delta ms = "); - Serial.println(deltaMillis); + Serial.print("2s: Delta ms = "); Serial.println(deltaMillis); } -#endif previousMillis = millis(); +#endif } -// In SAMD, avoid doing something fancy in ISR, for example complex Serial.print with String() argument +// In SAM_DUE, avoid doing something fancy in ISR, for example complex Serial.print with String() argument // The pure simple Serial.prints here are just for demonstration and testing. Must be eliminate in working environment // Or you can get this run-time error / crash void doingSomething5s() { +#if (TIMER_INTERRUPT_DEBUG > 0) static unsigned long previousMillis = lastMillis; unsigned long deltaMillis = millis() - previousMillis; -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 0) + if (previousMillis > TIMER_INTERVAL_5S) { - Serial.print("5s: Delta ms = "); - Serial.println(deltaMillis); + Serial.print("5s: Delta ms = "); Serial.println(deltaMillis); } -#endif previousMillis = millis(); +#endif } -// In SAMD, avoid doing something fancy in ISR, for example complex Serial.print with String() argument +// In SAM_DUE, avoid doing something fancy in ISR, for example complex Serial.print with String() argument // The pure simple Serial.prints here are just for demonstration and testing. Must be eliminate in working environment // Or you can get this run-time error / crash void doingSomething11s() { +#if (TIMER_INTERRUPT_DEBUG > 0) static unsigned long previousMillis = lastMillis; unsigned long deltaMillis = millis() - previousMillis; -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 0) + if (previousMillis > TIMER_INTERVAL_11S) { - Serial.print("11s: Delta ms = "); - Serial.println(deltaMillis); + Serial.print("11s: Delta ms = "); Serial.println(deltaMillis); } -#endif previousMillis = millis(); +#endif } -// In SAMD, avoid doing something fancy in ISR, for example complex Serial.print with String() argument +// In SAM_DUE, avoid doing something fancy in ISR, for example complex Serial.print with String() argument // The pure simple Serial.prints here are just for demonstration and testing. Must be eliminate in working environment // Or you can get this run-time error / crash void doingSomething101s() { +#if (TIMER_INTERRUPT_DEBUG > 0) static unsigned long previousMillis = lastMillis; unsigned long deltaMillis = millis() - previousMillis; -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 0) + if (previousMillis > TIMER_INTERVAL_101S) { - Serial.print("101s: Delta ms = "); - Serial.println(deltaMillis); + Serial.print("101s: Delta ms = "); Serial.println(deltaMillis); } -#endif previousMillis = millis(); +#endif } #define BLYNK_TIMER_MS 2000L @@ -245,7 +249,10 @@ void doingSomething101s() void blynkDoingSomething2s() { static unsigned long previousMillis = lastMillis; - Serial.println("blynkDoingSomething2s: Delta programmed ms = " + String(BLYNK_TIMER_MS) + ", actual = " + String(millis() - previousMillis)); + + Serial.print(F("blynkDoingSomething2s: Delta programmed ms = ")); Serial.print(BLYNK_TIMER_MS); + Serial.print(F(", actual = ")); Serial.println(millis() - previousMillis); + previousMillis = millis(); } @@ -257,10 +264,7 @@ uint16_t attachDueInterrupt(double microseconds, timerCallback callback, const c uint16_t timerNumber = dueTimerInterrupt.getTimerNumber(); - Serial.print(TimerName); - Serial.print(" attached to Timer("); - Serial.print(timerNumber); - Serial.println(")"); + Serial.print(TimerName); Serial.print(F(" attached to Timer(")); Serial.print(timerNumber); Serial.println(F(")")); return timerNumber; } @@ -269,12 +273,14 @@ void setup() { Serial.begin(115200); while (!Serial); + + delay(100); - Serial.println("\nStarting ISR_Timer_Complex_Ethernet on " + String(BOARD_NAME)); + Serial.print(F("\nStarting ISR_Timer_Complex_Ethernet on ")); Serial.println(BOARD_NAME); Serial.println(SAMDUE_TIMER_INTERRUPT_VERSION); - Serial.println("CPU Frequency = " + String(F_CPU / 1000000) + " MHz"); - Serial.println("Timer Frequency = " + String(SystemCoreClock / 1000000) + " MHz"); - + Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("Timer Frequency = ")); Serial.print(SystemCoreClock / 1000000); Serial.println(F(" MHz")); + // You need this timer for non-critical tasks. Avoid abusing ISR if not absolutely necessary. blynkTimer.setInterval(BLYNK_TIMER_MS, blynkDoingSomething2s); @@ -302,8 +308,7 @@ void setup() if (Blynk.connected()) { - Serial.print(F("IP = ")); - Serial.println(Ethernet.localIP()); + Serial.print(F("IP = ")); Serial.println(Ethernet.localIP()); } } diff --git a/examples/RPM_Measure/RPM_Measure.ino b/examples/RPM_Measure/RPM_Measure.ino index 2022a5d..160eedf 100644 --- a/examples/RPM_Measure/RPM_Measure.ino +++ b/examples/RPM_Measure/RPM_Measure.ino @@ -1,30 +1,31 @@ /**************************************************************************************************************************** - RPM_Measure.ino - For SAM DUE boards - Written by Khoi Hoang + RPM_Measure.ino + For SAM DUE boards + Written by Khoi Hoang - Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt - Licensed under MIT license + Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt + Licensed under MIT license - Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by - unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. - The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers - Therefore, their executions are not blocked by bad-behaving functions / tasks. - This important feature is absolutely necessary for mission-critical tasks. + Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by + unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. + The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers + Therefore, their executions are not blocked by bad-behaving functions / tasks. + This important feature is absolutely necessary for mission-critical tasks. - Based on SimpleTimer - A timer library for Arduino. - Author: mromani@ottotecnica.com - Copyright (c) 2010 OTTOTECNICA Italy + Based on SimpleTimer - A timer library for Arduino. + Author: mromani@ottotecnica.com + Copyright (c) 2010 OTTOTECNICA Italy - Based on BlynkTimer.h - Author: Volodymyr Shymanskyy + Based on BlynkTimer.h + Author: Volodymyr Shymanskyy - Version: 1.1.1 + Version: 1.2.0 - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.1 K Hoang 06/11/2020 Initial coding - 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.1 K Hoang 06/11/2020 Initial coding + 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + 1.2.0 K.Hoang 10/01/2021 Add better debug feature. Optimize code and examples to reduce RAM usage *****************************************************************************************************************************/ /* Notes: @@ -60,9 +61,12 @@ #error This code is designed to run on SAM DUE board / platform! Please check your Tools->Board setting. #endif -// These define's must be placed at the beginning before #include "SAMDTimerInterrupt.h" -// Don't define SAMDUE_TIMER_INTERRUPT_DEBUG > 0. Only for special ISR debugging only. Can hang the system. -#define SAMDUE_TIMER_INTERRUPT_DEBUG 1 +// These define's must be placed at the beginning before #include "SAMDUETimerInterrupt.h" +// _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 +// Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. +// Don't define TIMER_INTERRUPT_DEBUG > 2. Only for special ISR debugging only. Can hang the system. +#define TIMER_INTERRUPT_DEBUG 0 +#define _TIMERINTERRUPT_LOGLEVEL_ 0 #include "SAMDUETimerInterrupt.h" @@ -108,7 +112,10 @@ void TimerHandler() avgRPM = ( 2 * avgRPM + RPM) / 3, - Serial.println("RPM = " + String(avgRPM) + ", rotationTime ms = " + String(rotationTime * TIMER0_INTERVAL_MS) ); +#if (TIMER_INTERRUPT_DEBUG > 1) + Serial.print("RPM = "); Serial.print(avgRPM); + Serial.print(", rotationTime ms = "); Serial.println(rotationTime * TIMER1_INTERVAL_MS); +#endif rotationTime = 0; debounceCounter = 0; @@ -122,7 +129,11 @@ void TimerHandler() { // If idle, set RPM to 0, don't increase rotationTime RPM = 0; - Serial.println("RPM = " + String(RPM) + ", rotationTime = " + String(rotationTime) ); + +#if (TIMER_INTERRUPT_DEBUG > 1) + Serial.print("RPM = "); Serial.print(RPM); Serial.print(", rotationTime = "); Serial.println(rotationTime); +#endif + rotationTime = 0; } else @@ -139,10 +150,7 @@ uint16_t attachDueInterrupt(double microseconds, timerCallback callback, const c uint16_t timerNumber = dueTimerInterrupt.getTimerNumber(); - Serial.print(TimerName); - Serial.print(" attached to Timer("); - Serial.print(timerNumber); - Serial.println(")"); + Serial.print(TimerName); Serial.print(F(" attached to Timer(")); Serial.print(timerNumber); Serial.println(F(")")); return timerNumber; } @@ -151,11 +159,13 @@ void setup() { Serial.begin(115200); while (!Serial); + + delay(100); - Serial.println("\nStarting RPM_Measure on " + String(BOARD_NAME)); + Serial.print(F("\nStarting RPM_Measure on ")); Serial.println(BOARD_NAME); Serial.println(SAMDUE_TIMER_INTERRUPT_VERSION); - Serial.println("CPU Frequency = " + String(F_CPU / 1000000) + " MHz"); - Serial.println("Timer Frequency = " + String(SystemCoreClock / 1000000) + " MHz"); + Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("Timer Frequency = ")); Serial.print(SystemCoreClock / 1000000); Serial.println(F(" MHz")); // Interval in microsecs attachDueInterrupt(TIMER0_INTERVAL_MS * 1000, TimerHandler, "ITimer"); diff --git a/examples/SwitchDebounce/SwitchDebounce.ino b/examples/SwitchDebounce/SwitchDebounce.ino index e1fd9bb..6e9a3c6 100644 --- a/examples/SwitchDebounce/SwitchDebounce.ino +++ b/examples/SwitchDebounce/SwitchDebounce.ino @@ -1,30 +1,31 @@ /**************************************************************************************************************************** - SwitchDebounce.ino - For SAM DUE boards - Written by Khoi Hoang + SwitchDebounce.ino + For SAM DUE boards + Written by Khoi Hoang - Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt - Licensed under MIT license + Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt + Licensed under MIT license - Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by - unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. - The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers - Therefore, their executions are not blocked by bad-behaving functions / tasks. - This important feature is absolutely necessary for mission-critical tasks. + Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by + unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. + The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers + Therefore, their executions are not blocked by bad-behaving functions / tasks. + This important feature is absolutely necessary for mission-critical tasks. - Based on SimpleTimer - A timer library for Arduino. - Author: mromani@ottotecnica.com - Copyright (c) 2010 OTTOTECNICA Italy + Based on SimpleTimer - A timer library for Arduino. + Author: mromani@ottotecnica.com + Copyright (c) 2010 OTTOTECNICA Italy - Based on BlynkTimer.h - Author: Volodymyr Shymanskyy + Based on BlynkTimer.h + Author: Volodymyr Shymanskyy - Version: 1.1.1 + Version: 1.2.0 - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.1 K Hoang 06/11/2020 Initial coding - 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.1 K Hoang 06/11/2020 Initial coding + 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + 1.2.0 K.Hoang 10/01/2021 Add better debug feature. Optimize code and examples to reduce RAM usage *****************************************************************************************************************************/ /* Notes: @@ -48,9 +49,12 @@ #error This code is designed to run on SAM DUE board / platform! Please check your Tools->Board setting. #endif -// These define's must be placed at the beginning before #include "SAMDTimerInterrupt.h" -// Don't define SAMDUE_TIMER_INTERRUPT_DEBUG > 0. Only for special ISR debugging only. Can hang the system. -#define SAMDUE_TIMER_INTERRUPT_DEBUG 1 +// These define's must be placed at the beginning before #include "SAMDUETimerInterrupt.h" +// _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 +// Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. +// Don't define TIMER_INTERRUPT_DEBUG > 2. Only for special ISR debugging only. Can hang the system. +#define TIMER_INTERRUPT_DEBUG 0 +#define _TIMERINTERRUPT_LOGLEVEL_ 0 #include "SAMDUETimerInterrupt.h" @@ -75,14 +79,18 @@ unsigned int SWPin = 7; volatile bool SWPressed = false; volatile bool SWLongPressed = false; -void TimerHandler(void) +void TimerHandler() { static unsigned int debounceCountSWPressed = 0; static unsigned int debounceCountSWReleased = 0; +#if (TIMER_INTERRUPT_DEBUG > 1) static unsigned long SWPressedTime; static unsigned long SWReleasedTime; + unsigned long currentMillis = millis(); +#endif + static bool started = false; if (!started) @@ -101,10 +109,10 @@ void TimerHandler(void) // Call and flag SWPressed if (!SWPressed) { - SWPressedTime = millis(); - -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 0) - Serial.println("SW Press, from millis() = " + String(SWPressedTime - DEBOUNCING_INTERVAL_MS)); +#if (TIMER_INTERRUPT_DEBUG > 1) + SWPressedTime = currentMillis; + + Serial.print("SW Press, from millis() = "); Serial.println(SWPressedTime - DEBOUNCING_INTERVAL_MS); #endif SWPressed = true; @@ -118,10 +126,11 @@ void TimerHandler(void) // Call and flag SWLongPressed if (!SWLongPressed) { -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 0) - Serial.println("SW Long Pressed, total time ms = " + String(millis()) + " - " + String(SWPressedTime - DEBOUNCING_INTERVAL_MS) - + " = " + String(millis() - SWPressedTime + DEBOUNCING_INTERVAL_MS) ); -#endif +#if (TIMER_INTERRUPT_DEBUG > 1) + Serial.print("SW Long Pressed, total time ms = "); Serial.print(currentMillis); + Serial.print(" - "); Serial.print(SWPressedTime - DEBOUNCING_INTERVAL_MS); + Serial.print(" = "); Serial.println(currentMillis - SWPressedTime + DEBOUNCING_INTERVAL_MS); +#endif SWLongPressed = true; // Do something for SWLongPressed here in ISR @@ -136,11 +145,11 @@ void TimerHandler(void) // Start debouncing counting debounceCountSWReleased and clear debounceCountSWPressed if ( SWPressed && (++debounceCountSWReleased >= DEBOUNCING_INTERVAL_MS / TIMER1_INTERVAL_MS)) { - SWReleasedTime = millis(); +#if (TIMER_INTERRUPT_DEBUG > 1) + SWReleasedTime = currentMillis; // Call and flag SWPressed -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 0) - Serial.println("SW Released, from millis() = " + String(SWReleasedTime)); + Serial.print("SW Released, from millis() = "); Serial.println(SWReleasedTime); #endif SWPressed = false; @@ -151,8 +160,8 @@ void TimerHandler(void) //Your_Response_To_Release(); // Call and flag SWPressed -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 0) - Serial.println("SW Pressed total time ms = " + String(SWReleasedTime - SWPressedTime)); +#if (TIMER_INTERRUPT_DEBUG > 1) + Serial.print("SW Pressed total time ms = "); Serial.println(SWReleasedTime - SWPressedTime); #endif debounceCountSWPressed = 0; @@ -168,10 +177,7 @@ uint16_t attachDueInterrupt(double microseconds, timerCallback callback, const c uint16_t timerNumber = dueTimerInterrupt.getTimerNumber(); - Serial.print(TimerName); - Serial.print(" attached to Timer("); - Serial.print(timerNumber); - Serial.println(")"); + Serial.print(TimerName); Serial.print(F(" attached to Timer(")); Serial.print(timerNumber); Serial.println(F(")")); return timerNumber; } @@ -183,10 +189,10 @@ void setup() delay(100); - Serial.println("\nStarting SwitchDebounce on " + String(BOARD_NAME)); + Serial.print(F("\nStarting SwitchDebounce on ")); Serial.println(BOARD_NAME); Serial.println(SAMDUE_TIMER_INTERRUPT_VERSION); - Serial.println("CPU Frequency = " + String(F_CPU / 1000000) + " MHz"); - Serial.println("Timer Frequency = " + String(SystemCoreClock / 1000000) + " MHz"); + Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("Timer Frequency = ")); Serial.print(SystemCoreClock / 1000000); Serial.println(F(" MHz")); // Interval in microsecs attachDueInterrupt(TIMER1_INTERVAL_MS * 1000, TimerHandler, "ITimer"); diff --git a/examples/TimerInterruptLEDDemo/TimerInterruptLEDDemo.ino b/examples/TimerInterruptLEDDemo/TimerInterruptLEDDemo.ino index 4b0d60c..ef5738f 100644 --- a/examples/TimerInterruptLEDDemo/TimerInterruptLEDDemo.ino +++ b/examples/TimerInterruptLEDDemo/TimerInterruptLEDDemo.ino @@ -1,30 +1,31 @@ /**************************************************************************************************************************** - TimerInterruptLEDDemo.ino - For SAM DUE boards - Written by Khoi Hoang + TimerInterruptLEDDemo.ino + For SAM DUE boards + Written by Khoi Hoang - Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt - Licensed under MIT license + Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt + Licensed under MIT license - Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by - unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. - The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers - Therefore, their executions are not blocked by bad-behaving functions / tasks. - This important feature is absolutely necessary for mission-critical tasks. + Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by + unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. + The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers + Therefore, their executions are not blocked by bad-behaving functions / tasks. + This important feature is absolutely necessary for mission-critical tasks. - Based on SimpleTimer - A timer library for Arduino. - Author: mromani@ottotecnica.com - Copyright (c) 2010 OTTOTECNICA Italy + Based on SimpleTimer - A timer library for Arduino. + Author: mromani@ottotecnica.com + Copyright (c) 2010 OTTOTECNICA Italy - Based on BlynkTimer.h - Author: Volodymyr Shymanskyy + Based on BlynkTimer.h + Author: Volodymyr Shymanskyy - Version: 1.1.1 + Version: 1.2.0 - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.1 K Hoang 06/11/2020 Initial coding - 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.1 K Hoang 06/11/2020 Initial coding + 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + 1.2.0 K.Hoang 10/01/2021 Add better debug feature. Optimize code and examples to reduce RAM usage *****************************************************************************************************************************/ /* @@ -43,9 +44,12 @@ #error This code is designed to run on SAM DUE board / platform! Please check your Tools->Board setting. #endif -// These define's must be placed at the beginning before #include "SAMDTimerInterrupt.h" -// Don't define SAMDUE_TIMER_INTERRUPT_DEBUG > 0. Only for special ISR debugging only. Can hang the system. -#define SAMDUE_TIMER_INTERRUPT_DEBUG 1 +// These define's must be placed at the beginning before #include "SAMDUETimerInterrupt.h" +// _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 +// Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. +// Don't define TIMER_INTERRUPT_DEBUG > 2. Only for special ISR debugging only. Can hang the system. +#define TIMER_INTERRUPT_DEBUG 0 +#define _TIMERINTERRUPT_LOGLEVEL_ 0 #include "SAMDUETimerInterrupt.h" #include "SAMDUE_ISR_Timer.h" @@ -72,29 +76,38 @@ SAMDUE_ISR_Timer ISR_Timer; #define TIMER_INTERVAL_2S 2000L #define TIMER_INTERVAL_5S 5000L -void TimerHandler(void) +void TimerHandler() { ISR_Timer.run(); } -// In SAMD, avoid doing something fancy in ISR, for example complex Serial.print with String() argument +// In SAM-DUE, avoid doing something fancy in ISR, for example complex Serial.print with String() argument // The pure simple Serial.prints here are just for demonstration and testing. Must be eliminate in working environment // Or you can get this run-time error / crash void doingSomething1() { digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); + +#if (TIMER_INTERRUPT_DEBUG > 0) Serial.println("G"); +#endif } void doingSomething2() { digitalWrite(LED_BLUE, !digitalRead(LED_BLUE)); + +#if (TIMER_INTERRUPT_DEBUG > 0) Serial.println("B"); +#endif } void doingSomething3() { digitalWrite(LED_RED, !digitalRead(LED_RED)); + +#if (TIMER_INTERRUPT_DEBUG > 0) Serial.println("R"); +#endif } uint16_t attachDueInterrupt(double microseconds, timerCallback callback, const char* TimerName) @@ -105,10 +118,7 @@ uint16_t attachDueInterrupt(double microseconds, timerCallback callback, const c uint16_t timerNumber = dueTimerInterrupt.getTimerNumber(); - Serial.print(TimerName); - Serial.print(" attached to Timer("); - Serial.print(timerNumber); - Serial.println(")"); + Serial.print(TimerName); Serial.print(F(" attached to Timer(")); Serial.print(timerNumber); Serial.println(F(")")); return timerNumber; } @@ -118,10 +128,12 @@ void setup() Serial.begin(115200); while (!Serial); - Serial.println("\nTimerInterruptLEDDemo on " + String(BOARD_NAME)); + delay(100); + + Serial.print(F("\nStarting TimerInterruptLEDDemo on ")); Serial.println(BOARD_NAME); Serial.println(SAMDUE_TIMER_INTERRUPT_VERSION); - Serial.println("CPU Frequency = " + String(F_CPU / 1000000) + " MHz"); - Serial.println("Timer Frequency = " + String(SystemCoreClock / 1000000) + " MHz"); + Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("Timer Frequency = ")); Serial.print(SystemCoreClock / 1000000); Serial.println(F(" MHz")); // Instantiate HardwareTimer object. Thanks to 'new' instanciation, HardwareTimer is not destructed when setup() function is finished. //HardwareTimer *MyTim = new HardwareTimer(Instance); diff --git a/examples/TimerInterruptTest/TimerInterruptTest.ino b/examples/TimerInterruptTest/TimerInterruptTest.ino index 95a1948..931a87a 100644 --- a/examples/TimerInterruptTest/TimerInterruptTest.ino +++ b/examples/TimerInterruptTest/TimerInterruptTest.ino @@ -1,30 +1,31 @@ /**************************************************************************************************************************** - TimerInterruptTest.ino - For SAM DUE boards - Written by Khoi Hoang + TimerInterruptTest.ino + For SAM DUE boards + Written by Khoi Hoang - Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt - Licensed under MIT license + Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt + Licensed under MIT license - Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by - unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. - The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers - Therefore, their executions are not blocked by bad-behaving functions / tasks. - This important feature is absolutely necessary for mission-critical tasks. + Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by + unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. + The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers + Therefore, their executions are not blocked by bad-behaving functions / tasks. + This important feature is absolutely necessary for mission-critical tasks. - Based on SimpleTimer - A timer library for Arduino. - Author: mromani@ottotecnica.com - Copyright (c) 2010 OTTOTECNICA Italy + Based on SimpleTimer - A timer library for Arduino. + Author: mromani@ottotecnica.com + Copyright (c) 2010 OTTOTECNICA Italy - Based on BlynkTimer.h - Author: Volodymyr Shymanskyy + Based on BlynkTimer.h + Author: Volodymyr Shymanskyy - Version: 1.1.1 + Version: 1.2.0 - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.1 K Hoang 06/11/2020 Initial coding - 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.1 K Hoang 06/11/2020 Initial coding + 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + 1.2.0 K.Hoang 10/01/2021 Add better debug feature. Optimize code and examples to reduce RAM usage *****************************************************************************************************************************/ /* Notes: @@ -42,9 +43,12 @@ #error This code is designed to run on SAM DUE board / platform! Please check your Tools->Board setting. #endif -// These define's must be placed at the beginning before #include "SAMDTimerInterrupt.h" -// Don't define SAMDUE_TIMER_INTERRUPT_DEBUG > 0. Only for special ISR debugging only. Can hang the system. -#define SAMDUE_TIMER_INTERRUPT_DEBUG 1 +// These define's must be placed at the beginning before #include "SAMDUETimerInterrupt.h" +// _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 +// Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. +// Don't define TIMER_INTERRUPT_DEBUG > 2. Only for special ISR debugging only. Can hang the system. +#define TIMER_INTERRUPT_DEBUG 0 +#define _TIMERINTERRUPT_LOGLEVEL_ 0 #include "SAMDUETimerInterrupt.h" @@ -75,7 +79,7 @@ uint16_t Timer1_Index = 0; volatile uint32_t preMillisTimer0 = 0; volatile uint32_t preMillisTimer1 = 0; -void TimerHandler0(void) +void TimerHandler0() { static bool toggle0 = false; static bool started = false; @@ -87,14 +91,15 @@ void TimerHandler0(void) pinMode(LED_BUILTIN, OUTPUT); } -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 0) +#if (TIMER_INTERRUPT_DEBUG > 0) static uint32_t curMillis = 0; curMillis = millis(); if (curMillis > TIMER0_INTERVAL_MS) { - Serial.println("ITimer0: millis() = " + String(curMillis) + ", delta = " + String(curMillis - preMillisTimer0)); + Serial.print("ITimer0: millis() = "); Serial.print(curMillis); + Serial.print(", delta = "); Serial.println(curMillis - preMillisTimer0); } preMillisTimer0 = curMillis; @@ -105,7 +110,7 @@ void TimerHandler0(void) toggle0 = !toggle0; } -void TimerHandler1(void) +void TimerHandler1() { static bool toggle1 = false; static bool started = false; @@ -116,14 +121,15 @@ void TimerHandler1(void) pinMode(LED_BLUE, OUTPUT); } -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 0) +#if (TIMER_INTERRUPT_DEBUG > 0) static uint32_t curMillis = 0; curMillis = millis(); if (curMillis > TIMER1_INTERVAL_MS) { - Serial.println("ITimer1: millis() = " + String(curMillis) + ", delta = " + String(curMillis - preMillisTimer1)); + Serial.print("ITimer1: millis() = "); Serial.print(curMillis); + Serial.print(", delta = "); Serial.println(curMillis - preMillisTimer1); } preMillisTimer1 = curMillis; @@ -142,10 +148,7 @@ uint16_t attachDueInterrupt(double microseconds, timerCallback callback, const c uint16_t timerNumber = dueTimerInterrupt.getTimerNumber(); - Serial.print(TimerName); - Serial.print(" attached to Timer("); - Serial.print(timerNumber); - Serial.println(")"); + Serial.print(TimerName); Serial.print(F(" attached to Timer(")); Serial.print(timerNumber); Serial.println(F(")")); return timerNumber; } @@ -157,11 +160,11 @@ void setup() delay(100); - Serial.println("\nStarting TimerInterruptTest on " + String(BOARD_NAME)); + Serial.print(F("\nStarting TimerInterruptTest on ")); Serial.println(BOARD_NAME); Serial.println(SAMDUE_TIMER_INTERRUPT_VERSION); - Serial.println("CPU Frequency = " + String(F_CPU / 1000000) + " MHz"); - Serial.println("Timer Frequency = " + String(SystemCoreClock / 1000000) + " MHz"); - + Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("Timer Frequency = ")); Serial.print(SystemCoreClock / 1000000); Serial.println(F(" MHz")); + // Interval in microsecs Timer0_Index = attachDueInterrupt(TIMER0_INTERVAL_MS * 1000, TimerHandler0, "ITimer0"); @@ -182,12 +185,15 @@ void loop() if (timer0Stopped) { preMillisTimer0 = millis(); - Serial.println("Start ITimer0, millis() = " + String(preMillisTimer0)); + + Serial.print(F("Start ITimer0, millis() = ")); Serial.println(preMillisTimer0); + DueTimerPtr[Timer0_Index].restartTimer(); } else { - Serial.println("Stop ITimer0, millis() = " + String(millis())); + Serial.print(F("Stop ITimer0, millis() = ")); Serial.println(millis()); + DueTimerPtr[Timer0_Index].stopTimer(); } timer0Stopped = !timer0Stopped; @@ -203,12 +209,15 @@ void loop() if (timer1Stopped) { preMillisTimer1 = millis(); - Serial.println("Start ITimer1, millis() = " + String(preMillisTimer1)); + + Serial.print(F("Start ITimer1, millis() = ")); Serial.println(preMillisTimer1); + DueTimerPtr[Timer1_Index].restartTimer(); } else { - Serial.println("Stop ITimer1, millis() = " + String(millis())); + Serial.print(F("Stop ITimer1, millis() = ")); Serial.println(millis()); + DueTimerPtr[Timer1_Index].stopTimer(); } diff --git a/library.json b/library.json index 239a4ea..e07ac1f 100644 --- a/library.json +++ b/library.json @@ -1,8 +1,8 @@ { "name": "SAMDUE_TimerInterrupt", - "version": "1.1.1", - "keywords": "timing,device,control,timer,interrupt,hardware,due,sam-due,mission-critical,precise,non-blocking,isr", - "description": "This library enables you to use Interrupt from Hardware Timers on an SAM DUE-based board. These hardware timers, using interrupt, still work even if other functions are blocking. Moreover, they are much more precise (certainly depending on clock frequency accuracy) than other software timers using millis() or micros(). That's necessary if you need to measure some data requiring better accuracy.", + "version": "1.2.0", + "keywords": "timing,device,control,timer,interrupt,hardware,isr,isr-based,hardware-timer,mission-critical,accuracy,precise,non-blocking,due,sam-due", + "description": "This library enables you to use Interrupt from Hardware Timers on a SAM-DUE board. It now supports 16 ISR-based timers, while consuming only 1 Hardware Timer. Timers' interval is very long (ulong millisecs). The most important feature is they're ISR-based timers. Therefore, their executions are not blocked by bad-behaving functions or tasks. This important feature is absolutely necessary for mission-critical tasks. These hardware timers, using interrupt, still work even if other functions are blocking. Moreover, they are much more precise (certainly depending on clock frequency accuracy) than other software timers using millis() or micros(). That's necessary if you need to measure some data requiring better accuracy.", "authors": { "name": "Khoi Hoang", diff --git a/library.properties b/library.properties index 34b3bf0..7e33f61 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SAMDUE_TimerInterrupt -version=1.1.1 +version=1.2.0 author=Khoi Hoang maintainer=Khoi Hoang sentence=This library enables you to use Interrupt from Hardware Timers on an SAM-DUE-based board diff --git a/src/SAMDUETimerInterrupt.h b/src/SAMDUETimerInterrupt.h index 7e787e4..8cfe73f 100644 --- a/src/SAMDUETimerInterrupt.h +++ b/src/SAMDUETimerInterrupt.h @@ -1,34 +1,38 @@ /**************************************************************************************************************************** - SAMDUETimerInterrupt.h - For SAM DUE boards - Written by Khoi Hoang + SAMDUETimerInterrupt.h + For SAM DUE boards + Written by Khoi Hoang - Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt - Licensed under MIT license + Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt + Licensed under MIT license - Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by - unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. - The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers - Therefore, their executions are not blocked by bad-behaving functions / tasks. - This important feature is absolutely necessary for mission-critical tasks. + Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by + unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. + The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers + Therefore, their executions are not blocked by bad-behaving functions / tasks. + This important feature is absolutely necessary for mission-critical tasks. - Based on SimpleTimer - A timer library for Arduino. - Author: mromani@ottotecnica.com - Copyright (c) 2010 OTTOTECNICA Italy + Based on SimpleTimer - A timer library for Arduino. + Author: mromani@ottotecnica.com + Copyright (c) 2010 OTTOTECNICA Italy - Based on BlynkTimer.h - Author: Volodymyr Shymanskyy + Based on BlynkTimer.h + Author: Volodymyr Shymanskyy - Version: 1.1.1 + Version: 1.2.0 - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.1 K Hoang 06/11/2020 Initial coding - 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.1 K Hoang 06/11/2020 Initial coding + 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + 1.2.0 K.Hoang 10/01/2021 Add better debug feature. Optimize code and examples to reduce RAM usage *****************************************************************************************************************************/ #pragma once +#ifndef SAMDUETIMERINTERRUPT_H +#define SAMDUETIMERINTERRUPT_H + #if !( defined(ARDUINO_SAM_DUE) || defined(__SAM3X8E__) ) #error This code is designed to run on SAM DUE board / platform! Please check your Tools->Board setting. #endif @@ -36,17 +40,19 @@ #include "Arduino.h" #include -#define SAMDUE_TIMER_INTERRUPT_VERSION "SAMDUETimerInterrupt v1.1.1" - -#ifndef SAMDUE_TIMER_INTERRUPT_DEBUG - #define SAMDUE_TIMER_INTERRUPT_DEBUG 0 +#ifndef SAMDUE_TIMER_INTERRUPT_VERSION + #define SAMDUE_TIMER_INTERRUPT_VERSION "SAMDUETimerInterrupt v1.2.0" #endif +#include "TimerInterrupt_Generic_Debug.h" + #ifdef BOARD_NAME #undef BOARD_NAME #endif -#define BOARD_NAME "SAM DUE" +#ifndef BOARD_NAME + #define BOARD_NAME "SAM DUE" +#endif /* This fixes compatibility for Arduino Servo Library. @@ -152,17 +158,9 @@ class DueTimerInterrupt { if (!_callbacks[i]) { -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 0) - // Get data from TimersInfo[NUM_TIMERS] - Serial.print("Using Timer("); - Serial.print(i); - Serial.print(") = "); - Serial.print(TimersInfo[i].tc); - Serial.print(", channel = "); - Serial.print(TimersInfo[i].channel); - Serial.print(", IRQ = "); - Serial.println(TimersInfo[i].irq); -#endif + TISR_LOGWARN3(F("Using Timer("), i, F(") ="), TimersInfo[i].tc); + TISR_LOGWARN3(F("Channel ="), TimersInfo[i].channel, F(", IRQ ="), TimersInfo[i].irq); + return DueTimerInterrupt(i); } } @@ -606,3 +604,5 @@ void TC8_Handler() DueTimerInterrupt::_callbacks[8](); } #endif + +#endif // SAMDUETIMERINTERRUPT_H diff --git a/src/SAMDUE_ISR_Timer-Impl.h b/src/SAMDUE_ISR_Timer-Impl.h index 46c3be8..d8d4fb3 100644 --- a/src/SAMDUE_ISR_Timer-Impl.h +++ b/src/SAMDUE_ISR_Timer-Impl.h @@ -1,34 +1,38 @@ /**************************************************************************************************************************** - SAMDUE_ISR_Timer-Impl.h - For SAM DUE boards - Written by Khoi Hoang + SAMDUE_ISR_Timer-Impl.h + For SAM DUE boards + Written by Khoi Hoang - Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt - Licensed under MIT license + Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt + Licensed under MIT license - Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by - unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. - The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers - Therefore, their executions are not blocked by bad-behaving functions / tasks. - This important feature is absolutely necessary for mission-critical tasks. + Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by + unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. + The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers + Therefore, their executions are not blocked by bad-behaving functions / tasks. + This important feature is absolutely necessary for mission-critical tasks. - Based on SimpleTimer - A timer library for Arduino. - Author: mromani@ottotecnica.com - Copyright (c) 2010 OTTOTECNICA Italy + Based on SimpleTimer - A timer library for Arduino. + Author: mromani@ottotecnica.com + Copyright (c) 2010 OTTOTECNICA Italy - Based on BlynkTimer.h - Author: Volodymyr Shymanskyy + Based on BlynkTimer.h + Author: Volodymyr Shymanskyy - Version: 1.1.1 + Version: 1.2.0 - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.1 K Hoang 06/11/2020 Initial coding - 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.1 K Hoang 06/11/2020 Initial coding + 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + 1.2.0 K.Hoang 10/01/2021 Add better debug feature. Optimize code and examples to reduce RAM usage *****************************************************************************************************************************/ #pragma once +#ifndef ISR_TIMER_GENERIC_IMPL_H +#define ISR_TIMER_GENERIC_IMPL_H + //#include "SAMDUE_ISR_Timer.h" #include @@ -41,7 +45,7 @@ void SAMDUE_ISR_Timer::init() { unsigned long current_millis = millis(); //elapsed(); - for (int i = 0; i < MAX_NUMBER_TIMERS; i++) + for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++) { memset((void*) &timer[i], 0, sizeof (timer_t)); timer[i].prev_millis = current_millis; @@ -52,7 +56,7 @@ void SAMDUE_ISR_Timer::init() void SAMDUE_ISR_Timer::run() { - int i; + uint8_t i; unsigned long current_millis; // get current time @@ -130,7 +134,7 @@ int SAMDUE_ISR_Timer::findFirstFreeSlot() } // return the first slot with no callback (i.e. free) - for (int i = 0; i < MAX_NUMBER_TIMERS; i++) + for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++) { if (timer[i].callback == NULL) { @@ -299,7 +303,7 @@ void SAMDUE_ISR_Timer::enableAll() { // Enable all timers with a callback assigned (used) - for (int i = 0; i < MAX_NUMBER_TIMERS; i++) + for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++) { if (timer[i].callback != NULL && timer[i].numRuns == TIMER_RUN_FOREVER) { @@ -312,7 +316,7 @@ void SAMDUE_ISR_Timer::disableAll() { // Disable all timers with a callback assigned (used) - for (int i = 0; i < MAX_NUMBER_TIMERS; i++) + for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++) { if (timer[i].callback != NULL && timer[i].numRuns == TIMER_RUN_FOREVER) { @@ -336,3 +340,5 @@ unsigned SAMDUE_ISR_Timer::getNumTimers() { return numTimers; } + +#endif // ISR_TIMER_GENERIC_IMPL_H diff --git a/src/SAMDUE_ISR_Timer.h b/src/SAMDUE_ISR_Timer.h index e6ce269..939d988 100644 --- a/src/SAMDUE_ISR_Timer.h +++ b/src/SAMDUE_ISR_Timer.h @@ -1,38 +1,48 @@ /**************************************************************************************************************************** - SAMDUE_ISR_Timer.h - For SAM DUE boards - Written by Khoi Hoang + SAMDUE_ISR_Timer.h + For SAM DUE boards + Written by Khoi Hoang - Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt - Licensed under MIT license + Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt + Licensed under MIT license - Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by - unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. - The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers - Therefore, their executions are not blocked by bad-behaving functions / tasks. - This important feature is absolutely necessary for mission-critical tasks. + Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by + unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. + The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers + Therefore, their executions are not blocked by bad-behaving functions / tasks. + This important feature is absolutely necessary for mission-critical tasks. - Based on SimpleTimer - A timer library for Arduino. - Author: mromani@ottotecnica.com - Copyright (c) 2010 OTTOTECNICA Italy + Based on SimpleTimer - A timer library for Arduino. + Author: mromani@ottotecnica.com + Copyright (c) 2010 OTTOTECNICA Italy - Based on BlynkTimer.h - Author: Volodymyr Shymanskyy + Based on BlynkTimer.h + Author: Volodymyr Shymanskyy - Version: 1.1.1 + Version: 1.2.0 - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.1 K Hoang 06/11/2020 Initial coding - 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.1 K Hoang 06/11/2020 Initial coding + 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + 1.2.0 K.Hoang 10/01/2021 Add better debug feature. Optimize code and examples to reduce RAM usage *****************************************************************************************************************************/ #pragma once +#ifndef ISR_TIMER_GENERIC_H +#define ISR_TIMER_GENERIC_H + #if !( defined(ARDUINO_SAM_DUE) || defined(__SAM3X8E__) ) #error This code is designed to run on SAM DUE board / platform! Please check your Tools->Board setting. #endif +#ifndef SAMDUE_TIMER_INTERRUPT_VERSION + #define SAMDUE_TIMER_INTERRUPT_VERSION "SAMDUETimerInterrupt v1.2.0" +#endif + +#include "TimerInterrupt_Generic_Debug.h" + #include #include @@ -169,3 +179,4 @@ class SAMDUE_ISR_Timer #include "SAMDUE_ISR_Timer-Impl.h" +#endif // ISR_TIMER_GENERIC_H diff --git a/src/TimerInterrupt_Generic_Debug.h b/src/TimerInterrupt_Generic_Debug.h new file mode 100644 index 0000000..d44fea4 --- /dev/null +++ b/src/TimerInterrupt_Generic_Debug.h @@ -0,0 +1,77 @@ +/**************************************************************************************************************************** + TimerInterrupt_Generic_Debug.h + For SAM DUE boards + Written by Khoi Hoang + + Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt + Licensed under MIT license + + Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by + unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. + The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers + Therefore, their executions are not blocked by bad-behaving functions / tasks. + This important feature is absolutely necessary for mission-critical tasks. + + Based on SimpleTimer - A timer library for Arduino. + Author: mromani@ottotecnica.com + Copyright (c) 2010 OTTOTECNICA Italy + + Based on BlynkTimer.h + Author: Volodymyr Shymanskyy + + Version: 1.2.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.1 K Hoang 06/11/2020 Initial coding + 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + 1.2.0 K.Hoang 10/01/2021 Add better debug feature. Optimize code and examples to reduce RAM usage + *****************************************************************************************************************************/ + +#pragma once + +#ifndef TIMERINTERRUPT_GENERIC_DEBUG_H +#define TIMERINTERRUPT_GENERIC_DEBUG_H + +#ifdef TIMERINTERRUPT_DEBUG_PORT + #define TISR_DBG_PORT TIMERINTERRUPT_DEBUG_PORT +#else + #define TISR_DBG_PORT Serial +#endif + +// Change _TIMERINTERRUPT_LOGLEVEL_ to set tracing and logging verbosity +// 0: DISABLED: no logging +// 1: ERROR: errors +// 2: WARN: errors and warnings +// 3: INFO: errors, warnings and informational (default) +// 4: DEBUG: errors, warnings, informational and debug + +#ifndef _TIMERINTERRUPT_LOGLEVEL_ + #define _TIMERINTERRUPT_LOGLEVEL_ 1 +#endif + +#define TISR_LOGERROR(x) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.println(x); } +#define TISR_LOGERROR0(x) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_DBG_PORT.print(x); } +#define TISR_LOGERROR1(x,y) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(y); } +#define TISR_LOGERROR2(x,y,z) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(z); } +#define TISR_LOGERROR3(x,y,z,w) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(z); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(w); } + +#define TISR_LOGWARN(x) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.println(x); } +#define TISR_LOGWARN0(x) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_DBG_PORT.print(x); } +#define TISR_LOGWARN1(x,y) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(y); } +#define TISR_LOGWARN2(x,y,z) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(z); } +#define TISR_LOGWARN3(x,y,z,w) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(z); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(w); } + +#define TISR_LOGINFO(x) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.println(x); } +#define TISR_LOGINFO0(x) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_DBG_PORT.print(x); } +#define TISR_LOGINFO1(x,y) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(y); } +#define TISR_LOGINFO2(x,y,z) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(z); } +#define TISR_LOGINFO3(x,y,z,w) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(z); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(w); } + +#define TISR_LOGDEBUG(x) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.println(x); } +#define TISR_LOGDEBUG0(x) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_DBG_PORT.print(x); } +#define TISR_LOGDEBUG1(x,y) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(y); } +#define TISR_LOGDEBUG2(x,y,z) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(z); } +#define TISR_LOGDEBUG3(x,y,z,w) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(z); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(w); } + +#endif //TIMERINTERRUPT_GENERIC_DEBUG_H diff --git a/src_cpp/SAMDUETimerInterrupt.h b/src_cpp/SAMDUETimerInterrupt.h index 7e787e4..8cfe73f 100644 --- a/src_cpp/SAMDUETimerInterrupt.h +++ b/src_cpp/SAMDUETimerInterrupt.h @@ -1,34 +1,38 @@ /**************************************************************************************************************************** - SAMDUETimerInterrupt.h - For SAM DUE boards - Written by Khoi Hoang + SAMDUETimerInterrupt.h + For SAM DUE boards + Written by Khoi Hoang - Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt - Licensed under MIT license + Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt + Licensed under MIT license - Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by - unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. - The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers - Therefore, their executions are not blocked by bad-behaving functions / tasks. - This important feature is absolutely necessary for mission-critical tasks. + Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by + unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. + The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers + Therefore, their executions are not blocked by bad-behaving functions / tasks. + This important feature is absolutely necessary for mission-critical tasks. - Based on SimpleTimer - A timer library for Arduino. - Author: mromani@ottotecnica.com - Copyright (c) 2010 OTTOTECNICA Italy + Based on SimpleTimer - A timer library for Arduino. + Author: mromani@ottotecnica.com + Copyright (c) 2010 OTTOTECNICA Italy - Based on BlynkTimer.h - Author: Volodymyr Shymanskyy + Based on BlynkTimer.h + Author: Volodymyr Shymanskyy - Version: 1.1.1 + Version: 1.2.0 - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.1 K Hoang 06/11/2020 Initial coding - 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.1 K Hoang 06/11/2020 Initial coding + 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + 1.2.0 K.Hoang 10/01/2021 Add better debug feature. Optimize code and examples to reduce RAM usage *****************************************************************************************************************************/ #pragma once +#ifndef SAMDUETIMERINTERRUPT_H +#define SAMDUETIMERINTERRUPT_H + #if !( defined(ARDUINO_SAM_DUE) || defined(__SAM3X8E__) ) #error This code is designed to run on SAM DUE board / platform! Please check your Tools->Board setting. #endif @@ -36,17 +40,19 @@ #include "Arduino.h" #include -#define SAMDUE_TIMER_INTERRUPT_VERSION "SAMDUETimerInterrupt v1.1.1" - -#ifndef SAMDUE_TIMER_INTERRUPT_DEBUG - #define SAMDUE_TIMER_INTERRUPT_DEBUG 0 +#ifndef SAMDUE_TIMER_INTERRUPT_VERSION + #define SAMDUE_TIMER_INTERRUPT_VERSION "SAMDUETimerInterrupt v1.2.0" #endif +#include "TimerInterrupt_Generic_Debug.h" + #ifdef BOARD_NAME #undef BOARD_NAME #endif -#define BOARD_NAME "SAM DUE" +#ifndef BOARD_NAME + #define BOARD_NAME "SAM DUE" +#endif /* This fixes compatibility for Arduino Servo Library. @@ -152,17 +158,9 @@ class DueTimerInterrupt { if (!_callbacks[i]) { -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 0) - // Get data from TimersInfo[NUM_TIMERS] - Serial.print("Using Timer("); - Serial.print(i); - Serial.print(") = "); - Serial.print(TimersInfo[i].tc); - Serial.print(", channel = "); - Serial.print(TimersInfo[i].channel); - Serial.print(", IRQ = "); - Serial.println(TimersInfo[i].irq); -#endif + TISR_LOGWARN3(F("Using Timer("), i, F(") ="), TimersInfo[i].tc); + TISR_LOGWARN3(F("Channel ="), TimersInfo[i].channel, F(", IRQ ="), TimersInfo[i].irq); + return DueTimerInterrupt(i); } } @@ -606,3 +604,5 @@ void TC8_Handler() DueTimerInterrupt::_callbacks[8](); } #endif + +#endif // SAMDUETIMERINTERRUPT_H diff --git a/src_cpp/SAMDUE_ISR_Timer.cpp b/src_cpp/SAMDUE_ISR_Timer.cpp index e796afc..5c761f5 100644 --- a/src_cpp/SAMDUE_ISR_Timer.cpp +++ b/src_cpp/SAMDUE_ISR_Timer.cpp @@ -1,30 +1,31 @@ /**************************************************************************************************************************** - SAMDUE_ISR_Timer.cpp - For SAM DUE boards - Written by Khoi Hoang + SAMDUE_ISR_Timer.cpp + For SAM DUE boards + Written by Khoi Hoang - Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt - Licensed under MIT license + Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt + Licensed under MIT license - Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by - unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. - The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers - Therefore, their executions are not blocked by bad-behaving functions / tasks. - This important feature is absolutely necessary for mission-critical tasks. + Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by + unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. + The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers + Therefore, their executions are not blocked by bad-behaving functions / tasks. + This important feature is absolutely necessary for mission-critical tasks. - Based on SimpleTimer - A timer library for Arduino. - Author: mromani@ottotecnica.com - Copyright (c) 2010 OTTOTECNICA Italy + Based on SimpleTimer - A timer library for Arduino. + Author: mromani@ottotecnica.com + Copyright (c) 2010 OTTOTECNICA Italy - Based on BlynkTimer.h - Author: Volodymyr Shymanskyy + Based on BlynkTimer.h + Author: Volodymyr Shymanskyy - Version: 1.1.1 + Version: 1.2.0 - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.1 K Hoang 06/11/2020 Initial coding - 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.1 K Hoang 06/11/2020 Initial coding + 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + 1.2.0 K.Hoang 10/01/2021 Add better debug feature. Optimize code and examples to reduce RAM usage *****************************************************************************************************************************/ #include "SAMDUE_ISR_Timer.h" @@ -39,7 +40,7 @@ void SAMDUE_ISR_Timer::init() { unsigned long current_millis = millis(); //elapsed(); - for (int i = 0; i < MAX_NUMBER_TIMERS; i++) + for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++) { memset((void*) &timer[i], 0, sizeof (timer_t)); timer[i].prev_millis = current_millis; @@ -50,7 +51,7 @@ void SAMDUE_ISR_Timer::init() void SAMDUE_ISR_Timer::run() { - int i; + uint8_t i; unsigned long current_millis; // get current time @@ -128,7 +129,7 @@ int SAMDUE_ISR_Timer::findFirstFreeSlot() } // return the first slot with no callback (i.e. free) - for (int i = 0; i < MAX_NUMBER_TIMERS; i++) + for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++) { if (timer[i].callback == NULL) { @@ -297,7 +298,7 @@ void SAMDUE_ISR_Timer::enableAll() { // Enable all timers with a callback assigned (used) - for (int i = 0; i < MAX_NUMBER_TIMERS; i++) + for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++) { if (timer[i].callback != NULL && timer[i].numRuns == TIMER_RUN_FOREVER) { @@ -310,7 +311,7 @@ void SAMDUE_ISR_Timer::disableAll() { // Disable all timers with a callback assigned (used) - for (int i = 0; i < MAX_NUMBER_TIMERS; i++) + for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++) { if (timer[i].callback != NULL && timer[i].numRuns == TIMER_RUN_FOREVER) { @@ -334,3 +335,4 @@ unsigned SAMDUE_ISR_Timer::getNumTimers() { return numTimers; } + diff --git a/src_cpp/SAMDUE_ISR_Timer.h b/src_cpp/SAMDUE_ISR_Timer.h index 8d933e7..4016bce 100644 --- a/src_cpp/SAMDUE_ISR_Timer.h +++ b/src_cpp/SAMDUE_ISR_Timer.h @@ -1,38 +1,49 @@ /**************************************************************************************************************************** - SAMDUE_ISR_Timer.h - For SAM DUE boards - Written by Khoi Hoang + SAMDUE_ISR_Timer.h + For SAM DUE boards + Written by Khoi Hoang - Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt - Licensed under MIT license + Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt + Licensed under MIT license - Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by - unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. - The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers - Therefore, their executions are not blocked by bad-behaving functions / tasks. - This important feature is absolutely necessary for mission-critical tasks. + Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by + unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. + The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers + Therefore, their executions are not blocked by bad-behaving functions / tasks. + This important feature is absolutely necessary for mission-critical tasks. - Based on SimpleTimer - A timer library for Arduino. - Author: mromani@ottotecnica.com - Copyright (c) 2010 OTTOTECNICA Italy + Based on SimpleTimer - A timer library for Arduino. + Author: mromani@ottotecnica.com + Copyright (c) 2010 OTTOTECNICA Italy - Based on BlynkTimer.h - Author: Volodymyr Shymanskyy + Based on BlynkTimer.h + Author: Volodymyr Shymanskyy - Version: 1.1.1 + Version: 1.2.0 - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.1 K Hoang 06/11/2020 Initial coding - 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.1 K Hoang 06/11/2020 Initial coding + 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + 1.2.0 K.Hoang 10/01/2021 Add better debug feature. Optimize code and examples to reduce RAM usage *****************************************************************************************************************************/ #pragma once +#ifndef ISR_TIMER_GENERIC_H +#define ISR_TIMER_GENERIC_H + #if !( defined(ARDUINO_SAM_DUE) || defined(__SAM3X8E__) ) #error This code is designed to run on SAM DUE board / platform! Please check your Tools->Board setting. #endif +#ifndef SAMDUE_TIMER_INTERRUPT_VERSION + #define SAMDUE_TIMER_INTERRUPT_VERSION "SAMDUETimerInterrupt v1.2.0" +#endif + +#include "TimerInterrupt_Generic_Debug.h" + + #include #include @@ -166,4 +177,4 @@ class SAMDUE_ISR_Timer volatile int numTimers; }; - +#endif // ISR_TIMER_GENERIC_H diff --git a/src_cpp/TimerInterrupt_Generic_Debug.h b/src_cpp/TimerInterrupt_Generic_Debug.h new file mode 100644 index 0000000..d44fea4 --- /dev/null +++ b/src_cpp/TimerInterrupt_Generic_Debug.h @@ -0,0 +1,77 @@ +/**************************************************************************************************************************** + TimerInterrupt_Generic_Debug.h + For SAM DUE boards + Written by Khoi Hoang + + Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt + Licensed under MIT license + + Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by + unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. + The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers + Therefore, their executions are not blocked by bad-behaving functions / tasks. + This important feature is absolutely necessary for mission-critical tasks. + + Based on SimpleTimer - A timer library for Arduino. + Author: mromani@ottotecnica.com + Copyright (c) 2010 OTTOTECNICA Italy + + Based on BlynkTimer.h + Author: Volodymyr Shymanskyy + + Version: 1.2.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.1 K Hoang 06/11/2020 Initial coding + 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + 1.2.0 K.Hoang 10/01/2021 Add better debug feature. Optimize code and examples to reduce RAM usage + *****************************************************************************************************************************/ + +#pragma once + +#ifndef TIMERINTERRUPT_GENERIC_DEBUG_H +#define TIMERINTERRUPT_GENERIC_DEBUG_H + +#ifdef TIMERINTERRUPT_DEBUG_PORT + #define TISR_DBG_PORT TIMERINTERRUPT_DEBUG_PORT +#else + #define TISR_DBG_PORT Serial +#endif + +// Change _TIMERINTERRUPT_LOGLEVEL_ to set tracing and logging verbosity +// 0: DISABLED: no logging +// 1: ERROR: errors +// 2: WARN: errors and warnings +// 3: INFO: errors, warnings and informational (default) +// 4: DEBUG: errors, warnings, informational and debug + +#ifndef _TIMERINTERRUPT_LOGLEVEL_ + #define _TIMERINTERRUPT_LOGLEVEL_ 1 +#endif + +#define TISR_LOGERROR(x) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.println(x); } +#define TISR_LOGERROR0(x) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_DBG_PORT.print(x); } +#define TISR_LOGERROR1(x,y) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(y); } +#define TISR_LOGERROR2(x,y,z) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(z); } +#define TISR_LOGERROR3(x,y,z,w) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(z); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(w); } + +#define TISR_LOGWARN(x) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.println(x); } +#define TISR_LOGWARN0(x) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_DBG_PORT.print(x); } +#define TISR_LOGWARN1(x,y) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(y); } +#define TISR_LOGWARN2(x,y,z) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(z); } +#define TISR_LOGWARN3(x,y,z,w) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(z); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(w); } + +#define TISR_LOGINFO(x) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.println(x); } +#define TISR_LOGINFO0(x) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_DBG_PORT.print(x); } +#define TISR_LOGINFO1(x,y) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(y); } +#define TISR_LOGINFO2(x,y,z) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(z); } +#define TISR_LOGINFO3(x,y,z,w) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(z); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(w); } + +#define TISR_LOGDEBUG(x) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.println(x); } +#define TISR_LOGDEBUG0(x) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_DBG_PORT.print(x); } +#define TISR_LOGDEBUG1(x,y) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(y); } +#define TISR_LOGDEBUG2(x,y,z) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(z); } +#define TISR_LOGDEBUG3(x,y,z,w) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(z); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(w); } + +#endif //TIMERINTERRUPT_GENERIC_DEBUG_H diff --git a/src_h/SAMDUETimerInterrupt.h b/src_h/SAMDUETimerInterrupt.h index 7e787e4..6a183c8 100644 --- a/src_h/SAMDUETimerInterrupt.h +++ b/src_h/SAMDUETimerInterrupt.h @@ -1,30 +1,31 @@ /**************************************************************************************************************************** - SAMDUETimerInterrupt.h - For SAM DUE boards - Written by Khoi Hoang + SAMDUETimerInterrupt.h + For SAM DUE boards + Written by Khoi Hoang - Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt - Licensed under MIT license + Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt + Licensed under MIT license - Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by - unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. - The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers - Therefore, their executions are not blocked by bad-behaving functions / tasks. - This important feature is absolutely necessary for mission-critical tasks. + Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by + unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. + The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers + Therefore, their executions are not blocked by bad-behaving functions / tasks. + This important feature is absolutely necessary for mission-critical tasks. - Based on SimpleTimer - A timer library for Arduino. - Author: mromani@ottotecnica.com - Copyright (c) 2010 OTTOTECNICA Italy + Based on SimpleTimer - A timer library for Arduino. + Author: mromani@ottotecnica.com + Copyright (c) 2010 OTTOTECNICA Italy - Based on BlynkTimer.h - Author: Volodymyr Shymanskyy + Based on BlynkTimer.h + Author: Volodymyr Shymanskyy - Version: 1.1.1 + Version: 1.2.0 - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.1 K Hoang 06/11/2020 Initial coding - 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.1 K Hoang 06/11/2020 Initial coding + 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + 1.2.0 K.Hoang 10/01/2021 Add better debug feature. Optimize code and examples to reduce RAM usage *****************************************************************************************************************************/ #pragma once @@ -36,17 +37,19 @@ #include "Arduino.h" #include -#define SAMDUE_TIMER_INTERRUPT_VERSION "SAMDUETimerInterrupt v1.1.1" - -#ifndef SAMDUE_TIMER_INTERRUPT_DEBUG - #define SAMDUE_TIMER_INTERRUPT_DEBUG 0 +#ifndef SAMDUE_TIMER_INTERRUPT_VERSION + #define SAMDUE_TIMER_INTERRUPT_VERSION "SAMDUETimerInterrupt v1.2.0" #endif +#include "TimerInterrupt_Generic_Debug.h" + #ifdef BOARD_NAME #undef BOARD_NAME #endif -#define BOARD_NAME "SAM DUE" +#ifndef BOARD_NAME + #define BOARD_NAME "SAM DUE" +#endif /* This fixes compatibility for Arduino Servo Library. @@ -152,17 +155,9 @@ class DueTimerInterrupt { if (!_callbacks[i]) { -#if (SAMDUE_TIMER_INTERRUPT_DEBUG > 0) - // Get data from TimersInfo[NUM_TIMERS] - Serial.print("Using Timer("); - Serial.print(i); - Serial.print(") = "); - Serial.print(TimersInfo[i].tc); - Serial.print(", channel = "); - Serial.print(TimersInfo[i].channel); - Serial.print(", IRQ = "); - Serial.println(TimersInfo[i].irq); -#endif + TISR_LOGWARN3(F("Using Timer("), i, F(") ="), TimersInfo[i].tc); + TISR_LOGWARN3(F("Channel ="), TimersInfo[i].channel, F(", IRQ ="), TimersInfo[i].irq); + return DueTimerInterrupt(i); } } diff --git a/src_h/SAMDUE_ISR_Timer-Impl.h b/src_h/SAMDUE_ISR_Timer-Impl.h index 46c3be8..d8d4fb3 100644 --- a/src_h/SAMDUE_ISR_Timer-Impl.h +++ b/src_h/SAMDUE_ISR_Timer-Impl.h @@ -1,34 +1,38 @@ /**************************************************************************************************************************** - SAMDUE_ISR_Timer-Impl.h - For SAM DUE boards - Written by Khoi Hoang + SAMDUE_ISR_Timer-Impl.h + For SAM DUE boards + Written by Khoi Hoang - Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt - Licensed under MIT license + Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt + Licensed under MIT license - Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by - unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. - The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers - Therefore, their executions are not blocked by bad-behaving functions / tasks. - This important feature is absolutely necessary for mission-critical tasks. + Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by + unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. + The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers + Therefore, their executions are not blocked by bad-behaving functions / tasks. + This important feature is absolutely necessary for mission-critical tasks. - Based on SimpleTimer - A timer library for Arduino. - Author: mromani@ottotecnica.com - Copyright (c) 2010 OTTOTECNICA Italy + Based on SimpleTimer - A timer library for Arduino. + Author: mromani@ottotecnica.com + Copyright (c) 2010 OTTOTECNICA Italy - Based on BlynkTimer.h - Author: Volodymyr Shymanskyy + Based on BlynkTimer.h + Author: Volodymyr Shymanskyy - Version: 1.1.1 + Version: 1.2.0 - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.1 K Hoang 06/11/2020 Initial coding - 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.1 K Hoang 06/11/2020 Initial coding + 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + 1.2.0 K.Hoang 10/01/2021 Add better debug feature. Optimize code and examples to reduce RAM usage *****************************************************************************************************************************/ #pragma once +#ifndef ISR_TIMER_GENERIC_IMPL_H +#define ISR_TIMER_GENERIC_IMPL_H + //#include "SAMDUE_ISR_Timer.h" #include @@ -41,7 +45,7 @@ void SAMDUE_ISR_Timer::init() { unsigned long current_millis = millis(); //elapsed(); - for (int i = 0; i < MAX_NUMBER_TIMERS; i++) + for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++) { memset((void*) &timer[i], 0, sizeof (timer_t)); timer[i].prev_millis = current_millis; @@ -52,7 +56,7 @@ void SAMDUE_ISR_Timer::init() void SAMDUE_ISR_Timer::run() { - int i; + uint8_t i; unsigned long current_millis; // get current time @@ -130,7 +134,7 @@ int SAMDUE_ISR_Timer::findFirstFreeSlot() } // return the first slot with no callback (i.e. free) - for (int i = 0; i < MAX_NUMBER_TIMERS; i++) + for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++) { if (timer[i].callback == NULL) { @@ -299,7 +303,7 @@ void SAMDUE_ISR_Timer::enableAll() { // Enable all timers with a callback assigned (used) - for (int i = 0; i < MAX_NUMBER_TIMERS; i++) + for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++) { if (timer[i].callback != NULL && timer[i].numRuns == TIMER_RUN_FOREVER) { @@ -312,7 +316,7 @@ void SAMDUE_ISR_Timer::disableAll() { // Disable all timers with a callback assigned (used) - for (int i = 0; i < MAX_NUMBER_TIMERS; i++) + for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++) { if (timer[i].callback != NULL && timer[i].numRuns == TIMER_RUN_FOREVER) { @@ -336,3 +340,5 @@ unsigned SAMDUE_ISR_Timer::getNumTimers() { return numTimers; } + +#endif // ISR_TIMER_GENERIC_IMPL_H diff --git a/src_h/SAMDUE_ISR_Timer.h b/src_h/SAMDUE_ISR_Timer.h index e6ce269..939d988 100644 --- a/src_h/SAMDUE_ISR_Timer.h +++ b/src_h/SAMDUE_ISR_Timer.h @@ -1,38 +1,48 @@ /**************************************************************************************************************************** - SAMDUE_ISR_Timer.h - For SAM DUE boards - Written by Khoi Hoang + SAMDUE_ISR_Timer.h + For SAM DUE boards + Written by Khoi Hoang - Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt - Licensed under MIT license + Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt + Licensed under MIT license - Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by - unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. - The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers - Therefore, their executions are not blocked by bad-behaving functions / tasks. - This important feature is absolutely necessary for mission-critical tasks. + Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by + unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. + The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers + Therefore, their executions are not blocked by bad-behaving functions / tasks. + This important feature is absolutely necessary for mission-critical tasks. - Based on SimpleTimer - A timer library for Arduino. - Author: mromani@ottotecnica.com - Copyright (c) 2010 OTTOTECNICA Italy + Based on SimpleTimer - A timer library for Arduino. + Author: mromani@ottotecnica.com + Copyright (c) 2010 OTTOTECNICA Italy - Based on BlynkTimer.h - Author: Volodymyr Shymanskyy + Based on BlynkTimer.h + Author: Volodymyr Shymanskyy - Version: 1.1.1 + Version: 1.2.0 - Version Modified By Date Comments - ------- ----------- ---------- ----------- - 1.0.1 K Hoang 06/11/2020 Initial coding - 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.1 K Hoang 06/11/2020 Initial coding + 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + 1.2.0 K.Hoang 10/01/2021 Add better debug feature. Optimize code and examples to reduce RAM usage *****************************************************************************************************************************/ #pragma once +#ifndef ISR_TIMER_GENERIC_H +#define ISR_TIMER_GENERIC_H + #if !( defined(ARDUINO_SAM_DUE) || defined(__SAM3X8E__) ) #error This code is designed to run on SAM DUE board / platform! Please check your Tools->Board setting. #endif +#ifndef SAMDUE_TIMER_INTERRUPT_VERSION + #define SAMDUE_TIMER_INTERRUPT_VERSION "SAMDUETimerInterrupt v1.2.0" +#endif + +#include "TimerInterrupt_Generic_Debug.h" + #include #include @@ -169,3 +179,4 @@ class SAMDUE_ISR_Timer #include "SAMDUE_ISR_Timer-Impl.h" +#endif // ISR_TIMER_GENERIC_H diff --git a/src_h/TimerInterrupt_Generic_Debug.h b/src_h/TimerInterrupt_Generic_Debug.h new file mode 100644 index 0000000..d44fea4 --- /dev/null +++ b/src_h/TimerInterrupt_Generic_Debug.h @@ -0,0 +1,77 @@ +/**************************************************************************************************************************** + TimerInterrupt_Generic_Debug.h + For SAM DUE boards + Written by Khoi Hoang + + Built by Khoi Hoang https://github.com/khoih-prog/SAMDUE_TimerInterrupt + Licensed under MIT license + + Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by + unsigned long miliseconds), you just consume only one SAM DUE timer and avoid conflicting with other cores' tasks. + The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers + Therefore, their executions are not blocked by bad-behaving functions / tasks. + This important feature is absolutely necessary for mission-critical tasks. + + Based on SimpleTimer - A timer library for Arduino. + Author: mromani@ottotecnica.com + Copyright (c) 2010 OTTOTECNICA Italy + + Based on BlynkTimer.h + Author: Volodymyr Shymanskyy + + Version: 1.2.0 + + Version Modified By Date Comments + ------- ----------- ---------- ----------- + 1.0.1 K Hoang 06/11/2020 Initial coding + 1.1.1 K.Hoang 06/12/2020 Add Change_Interval example. Bump up version to sync with other TimerInterrupt Libraries + 1.2.0 K.Hoang 10/01/2021 Add better debug feature. Optimize code and examples to reduce RAM usage + *****************************************************************************************************************************/ + +#pragma once + +#ifndef TIMERINTERRUPT_GENERIC_DEBUG_H +#define TIMERINTERRUPT_GENERIC_DEBUG_H + +#ifdef TIMERINTERRUPT_DEBUG_PORT + #define TISR_DBG_PORT TIMERINTERRUPT_DEBUG_PORT +#else + #define TISR_DBG_PORT Serial +#endif + +// Change _TIMERINTERRUPT_LOGLEVEL_ to set tracing and logging verbosity +// 0: DISABLED: no logging +// 1: ERROR: errors +// 2: WARN: errors and warnings +// 3: INFO: errors, warnings and informational (default) +// 4: DEBUG: errors, warnings, informational and debug + +#ifndef _TIMERINTERRUPT_LOGLEVEL_ + #define _TIMERINTERRUPT_LOGLEVEL_ 1 +#endif + +#define TISR_LOGERROR(x) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.println(x); } +#define TISR_LOGERROR0(x) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_DBG_PORT.print(x); } +#define TISR_LOGERROR1(x,y) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(y); } +#define TISR_LOGERROR2(x,y,z) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(z); } +#define TISR_LOGERROR3(x,y,z,w) if(_TIMERINTERRUPT_LOGLEVEL_>0) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(z); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(w); } + +#define TISR_LOGWARN(x) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.println(x); } +#define TISR_LOGWARN0(x) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_DBG_PORT.print(x); } +#define TISR_LOGWARN1(x,y) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(y); } +#define TISR_LOGWARN2(x,y,z) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(z); } +#define TISR_LOGWARN3(x,y,z,w) if(_TIMERINTERRUPT_LOGLEVEL_>1) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(z); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(w); } + +#define TISR_LOGINFO(x) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.println(x); } +#define TISR_LOGINFO0(x) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_DBG_PORT.print(x); } +#define TISR_LOGINFO1(x,y) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(y); } +#define TISR_LOGINFO2(x,y,z) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(z); } +#define TISR_LOGINFO3(x,y,z,w) if(_TIMERINTERRUPT_LOGLEVEL_>2) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(z); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(w); } + +#define TISR_LOGDEBUG(x) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.println(x); } +#define TISR_LOGDEBUG0(x) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_DBG_PORT.print(x); } +#define TISR_LOGDEBUG1(x,y) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(y); } +#define TISR_LOGDEBUG2(x,y,z) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(z); } +#define TISR_LOGDEBUG3(x,y,z,w) if(_TIMERINTERRUPT_LOGLEVEL_>3) { TISR_DBG_PORT.print("[TISR] "); TISR_DBG_PORT.print(x); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(y); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.print(z); TISR_DBG_PORT.print(" "); TISR_DBG_PORT.println(w); } + +#endif //TIMERINTERRUPT_GENERIC_DEBUG_H