From dfdae9b81b2383e5fdd210faecaad71a72df6f24 Mon Sep 17 00:00:00 2001 From: Khoi Hoang <57012152+khoih-prog@users.noreply.github.com> Date: Sat, 17 Apr 2021 01:36:27 -0400 Subject: [PATCH] v1.2.0 ### Release v1.2.0 1. Selectable **TCB Clock 16MHz, 8MHz or 250KHz** depending on necessary accuracy 2. Add BOARD_NAME definition --- README.md | 312 +++++++++++++++++- .../Argument_Complex/Argument_Complex.ino | 25 +- examples/Argument_None/Argument_None.ino | 25 +- examples/Argument_Simple/Argument_Simple.ino | 25 +- examples/Change_Interval/Change_Interval.ino | 25 +- examples/FakeAnalogWrite/FakeAnalogWrite.ino | 25 +- .../ISR_16_Timers_Array_Complex.ino | 26 +- examples/ISR_RPM_Measure/ISR_RPM_Measure.ino | 25 +- examples/ISR_Switch/ISR_Switch.ino | 25 +- .../ISR_Timer_Complex/ISR_Timer_Complex.ino | 25 +- .../ISR_Timer_Switch/ISR_Timer_Switch.ino | 25 +- .../ISR_Timer_Switches/ISR_Timer_Switches.ino | 25 +- .../ISR_Timers_Array_Simple.ino | 25 +- examples/RPM_Measure/RPM_Measure.ino | 25 +- examples/SwitchDebounce/SwitchDebounce.ino | 25 +- examples/TimerDuration/TimerDuration.ino | 25 +- .../TimerInterruptTest/TimerInterruptTest.ino | 25 +- library.json | 4 +- library.properties | 2 +- src/TimerInterrupt_Generic_Debug.h | 9 +- src/megaAVR_ISR_Timer-Impl.h | 3 +- src/megaAVR_ISR_Timer.h | 15 +- src/megaAVR_TimerInterrupt-Impl.h | 72 +++- src/megaAVR_TimerInterrupt.h | 19 +- src_cpp/TimerInterrupt_Generic_Debug.h | 9 +- src_cpp/megaAVR_ISR_Timer.cpp | 3 +- src_cpp/megaAVR_ISR_Timer.h | 16 +- src_cpp/megaAVR_TimerInterrupt.cpp | 72 +++- src_cpp/megaAVR_TimerInterrupt.h | 19 +- src_h/TimerInterrupt_Generic_Debug.h | 9 +- src_h/megaAVR_ISR_Timer-Impl.h | 3 +- src_h/megaAVR_ISR_Timer.h | 15 +- src_h/megaAVR_TimerInterrupt-Impl.h | 72 +++- src_h/megaAVR_TimerInterrupt.h | 19 +- 34 files changed, 920 insertions(+), 154 deletions(-) diff --git a/README.md b/README.md index e7ac931..c48a32a 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ * [Important Notes about ISR](#important-notes-about-isr) * [Currently supported Boards](#currently-supported-boards) * [Changelog](#changelog) + * [Release v1.2.0](#release-v120) * [Release v1.1.0](#release-v110) * [Initial Release v1.0.0](#initial-release-v100) * [Prerequisites](#prerequisites) @@ -53,8 +54,12 @@ * [ 16. TimerInterruptTest](examples/TimerInterruptTest) * [Example ISR_16_Timers_Array_Complex](#example-isr_16_timers_array_complex) * [Debug Terminal Output Samples](#debug-terminal-output-samples) - * [1. ISR_16_Timers_Array_Complex on Arduino megaAVR UNO WiFi Rev2](#1-isr_16_timers_array_complex-arduino-megaavr-uno-wifi-rev2) - * [2. Change_Interval on Arduino megaAVR UNO WiFi Rev2](#2-change_interval-on-arduino-megaavr-uno-wifi-rev2) + * [1. ISR_16_Timers_Array_Complex on Arduino megaAVR Nano Every](#1-isr_16_timers_array_complex-on-arduino-megaavr-nano-every) + * [2. Change_Interval on Arduino megaAVR Nano Every](#2-change_interval-on-arduino-megaavr-nano-every) + * [3. ISR_16_Timers_Array_Complex on Arduino megaAVR Nano Every to show accuracy difference](#3-isr_16_timers_array_complex-on-arduino-megaavr-nano-every-to-show-accuracy-difference) + * [3.1 TCB Clock Frequency 16MHz for highest accuracy](#31-tcb-clock-frequency-16mhz-for-highest-accuracy) + * [3.2 TCB Clock Frequency 8MHz for very high accuracy](#32-tcb-clock-frequency-8mhz-for-very-high-accuracy) + * [3.3 TCB Clock Frequency 250KHz for lower accuracy but longer time](#33-tcb-clock-frequency-250khz-for-lower-accuracy-but-longer-time) * [Debug](#debug) * [Troubleshooting](#troubleshooting) * [Releases](#releases) @@ -124,6 +129,11 @@ The catch is your function is now part of an ISR (Interrupt Service Routine), an ## Changelog +### Release v1.2.0 + +1. Selectable **TCB Clock 16MHz, 8MHz or 250KHz** depending on necessary accuracy +2. Add BOARD_NAME definition + ### Release v1.1.0 1. Fix bug. Don't use v1.0.0 @@ -219,6 +229,14 @@ Before using any Timer, you have to make sure the Timer has not been used by any ### 1.1 Init Hardware Timer ``` +// Select USING_16MHZ == true for 16MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_8MHZ == true for 8MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_250KHZ == true for 250KHz to Timer TCBx => shorter timer, but better accuracy +// Not select for default 250KHz to Timer TCBx => longer timer, but worse accuracy +#define USING_16MHZ true +#define USING_8MHZ false +#define USING_250KHZ false + // Select the timers you're using, here ITimer1 #define USE_TIMER_0 false #define USE_TIMER_1 true @@ -319,6 +337,14 @@ The 16 ISR_based Timers, designed for long timer intervals, only support using * ### 2.2 Init Hardware Timer and ISR-based Timer ``` +// Select USING_16MHZ == true for 16MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_8MHZ == true for 8MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_250KHZ == true for 250KHz to Timer TCBx => shorter timer, but better accuracy +// Not select for default 250KHz to Timer TCBx => longer timer, but worse accuracy +#define USING_16MHZ true +#define USING_8MHZ false +#define USING_250KHZ false + #define USE_TIMER_0 false #define USE_TIMER_1 true #define USE_TIMER_2 false @@ -422,6 +448,15 @@ void setup() #define TIMER_INTERRUPT_DEBUG 0 #define _TIMERINTERRUPT_LOGLEVEL_ 0 +// Select USING_16MHZ == true for 16MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_8MHZ == true for 8MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_250KHZ == true for 250KHz to Timer TCBx => shorter timer, but better accuracy +// Not select for default 250KHz to Timer TCBx => longer timer, but worse accuracy +#define USING_16MHZ true +#define USING_8MHZ false +#define USING_250KHZ false + + #define USE_TIMER_0 false #define USE_TIMER_1 true #define USE_TIMER_2 true @@ -684,10 +719,21 @@ void setup() Serial.begin(115200); while (!Serial); - Serial.println(F("\nStarting ISR_16_Timers_Array_Complex on AVR")); + Serial.print(F("\nStarting ISR_16_Timers_Array_Complex on ")); + Serial.println(BOARD_NAME); Serial.println(MEGA_AVR_TIMER_INTERRUPT_VERSION); Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("TCB Clock Frequency = ")); + +#if USING_16MHZ + Serial.println(F("16MHz for highest accuracy")); +#elif USING_8MHZ + Serial.println(F("8MHz for very high accuracy")); +#else + Serial.println(F("250KHz for lower accuracy but longer time")); +#endif + ITimer1.init(); if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS, TimerHandler1)) @@ -746,9 +792,10 @@ While software timer, **programmed for 2s, is activated after more than 10.000s ``` -Starting ISR_16_Timers_Array_Complex on megaAVR -megaAVR_TimerInterrupt v1.1.0 +Starting ISR_16_Timers_Array_Complex on megaAVR Nano Every +megaAVR_TimerInterrupt v1.2.0 CPU Frequency = 16 MHz +TCB Clock Frequency = 250KHz for lower accuracy but longer time Starting ITimer1 OK, millis() = 6 SimpleTimer : 2, ms : 10006, Dms : 10006 Timer : 0, programmed : 5000, actual : 5006 @@ -897,9 +944,10 @@ Timer : 15, programmed : 80000, actual : 80016 The following is the sample terminal output when running example [Change_Interval](examples/Change_Interval) on **Arduino megaAVR Nano Every** to demonstrate how to change Timer Interval on-the-fly ``` -Starting Change_Interval on megaAVR -megaAVR_TimerInterrupt v1.1.0 +Starting Change_Interval on megaAVR Nano Every +megaAVR_TimerInterrupt v1.2.0 CPU Frequency = 16 MHz +TCB Clock Frequency = 250KHz for lower accuracy but longer time Starting ITimer1 OK, millis() = 1 Starting ITimer2 OK, millis() = 4 Time = 10001, Timer1Count = 97, Timer2Count = 49 @@ -916,6 +964,250 @@ Time = 80009, Timer1Count = 588, Timer2Count = 296 Changing Interval, Timer1 = 100, Timer2 = 200 ``` +--- + +### 3. ISR_16_Timers_Array_Complex on Arduino megaAVR Nano Every to show accuracy difference. + + +### 3.1. TCB Clock Frequency 16MHz for highest accuracy + + +``` +Starting ISR_16_Timers_Array_Complex on megaAVR Nano Every +megaAVR_TimerInterrupt v1.2.0 +CPU Frequency = 16 MHz +TCB Clock Frequency = 16MHz for highest accuracy +Starting ITimer1 OK, millis() = 6 +SimpleTimer : 2, ms : 10007, Dms : 10007 +Timer : 0, programmed : 5000, actual : 5000 +Timer : 1, programmed : 10000, actual : 10006 +Timer : 2, programmed : 15000, actual : 0 +Timer : 3, programmed : 20000, actual : 0 +Timer : 4, programmed : 25000, actual : 0 +Timer : 5, programmed : 30000, actual : 0 +Timer : 6, programmed : 35000, actual : 0 +Timer : 7, programmed : 40000, actual : 0 +Timer : 8, programmed : 45000, actual : 0 +Timer : 9, programmed : 50000, actual : 0 +Timer : 10, programmed : 55000, actual : 0 +Timer : 11, programmed : 60000, actual : 0 +Timer : 12, programmed : 65000, actual : 0 +Timer : 13, programmed : 70000, actual : 0 +Timer : 14, programmed : 75000, actual : 0 +Timer : 15, programmed : 80000, actual : 0 +SimpleTimer : 2, ms : 20066, Dms : 10059 +Timer : 0, programmed : 5000, actual : 5000 +Timer : 1, programmed : 10000, actual : 10000 +Timer : 2, programmed : 15000, actual : 15006 +Timer : 3, programmed : 20000, actual : 20006 +Timer : 4, programmed : 25000, actual : 0 +Timer : 5, programmed : 30000, actual : 0 +Timer : 6, programmed : 35000, actual : 0 +Timer : 7, programmed : 40000, actual : 0 +Timer : 8, programmed : 45000, actual : 0 +Timer : 9, programmed : 50000, actual : 0 +Timer : 10, programmed : 55000, actual : 0 +Timer : 11, programmed : 60000, actual : 0 +Timer : 12, programmed : 65000, actual : 0 +Timer : 13, programmed : 70000, actual : 0 +Timer : 14, programmed : 75000, actual : 0 +Timer : 15, programmed : 80000, actual : 0 + +... + + +SimpleTimer : 2, ms : 211269, Dms : 10064 +Timer : 0, programmed : 5000, actual : 5000 <========== Very accurate @ clock 16MHz +Timer : 1, programmed : 10000, actual : 10000 +Timer : 2, programmed : 15000, actual : 15000 +Timer : 3, programmed : 20000, actual : 20000 +Timer : 4, programmed : 25000, actual : 25000 +Timer : 5, programmed : 30000, actual : 30000 +Timer : 6, programmed : 35000, actual : 35000 +Timer : 7, programmed : 40000, actual : 40000 +Timer : 8, programmed : 45000, actual : 45000 +Timer : 9, programmed : 50000, actual : 50000 +Timer : 10, programmed : 55000, actual : 55000 +Timer : 11, programmed : 60000, actual : 60000 +Timer : 12, programmed : 65000, actual : 65000 +Timer : 13, programmed : 70000, actual : 70000 +Timer : 14, programmed : 75000, actual : 75000 +Timer : 15, programmed : 80000, actual : 80000 +SimpleTimer : 2, ms : 221333, Dms : 10064 +Timer : 0, programmed : 5000, actual : 5000 +Timer : 1, programmed : 10000, actual : 10000 +Timer : 2, programmed : 15000, actual : 15000 +Timer : 3, programmed : 20000, actual : 20000 +Timer : 4, programmed : 25000, actual : 25000 +Timer : 5, programmed : 30000, actual : 30000 +Timer : 6, programmed : 35000, actual : 35000 +Timer : 7, programmed : 40000, actual : 40000 +Timer : 8, programmed : 45000, actual : 45000 +Timer : 9, programmed : 50000, actual : 50000 +Timer : 10, programmed : 55000, actual : 55000 +Timer : 11, programmed : 60000, actual : 60000 +Timer : 12, programmed : 65000, actual : 65000 +Timer : 13, programmed : 70000, actual : 70000 +Timer : 14, programmed : 75000, actual : 75000 +Timer : 15, programmed : 80000, actual : 80000 + +``` + +--- + +### 3.2. TCB Clock Frequency 8MHz for very high accuracy + +``` + +Starting ISR_16_Timers_Array_Complex on megaAVR Nano Every +megaAVR_TimerInterrupt v1.2.0 +CPU Frequency = 16 MHz +TCB Clock Frequency = 8MHz for very high accuracy +Starting ITimer1 OK, millis() = 10 +SimpleTimer : 2, ms : 10011, Dms : 10011 +Timer : 0, programmed : 5000, actual : 5000 +Timer : 1, programmed : 10000, actual : 10011 +Timer : 2, programmed : 15000, actual : 0 +Timer : 3, programmed : 20000, actual : 0 +Timer : 4, programmed : 25000, actual : 0 +Timer : 5, programmed : 30000, actual : 0 +Timer : 6, programmed : 35000, actual : 0 +Timer : 7, programmed : 40000, actual : 0 +Timer : 8, programmed : 45000, actual : 0 +Timer : 9, programmed : 50000, actual : 0 +Timer : 10, programmed : 55000, actual : 0 +Timer : 11, programmed : 60000, actual : 0 +Timer : 12, programmed : 65000, actual : 0 +Timer : 13, programmed : 70000, actual : 0 +Timer : 14, programmed : 75000, actual : 0 +Timer : 15, programmed : 80000, actual : 0 + +... + + +SimpleTimer : 2, ms : 160949, Dms : 10064 +Timer : 0, programmed : 5000, actual : 5000 <========== Very accurate @ clock 8MHz +Timer : 1, programmed : 10000, actual : 10000 +Timer : 2, programmed : 15000, actual : 15000 +Timer : 3, programmed : 20000, actual : 20000 +Timer : 4, programmed : 25000, actual : 25000 +Timer : 5, programmed : 30000, actual : 30000 +Timer : 6, programmed : 35000, actual : 35000 +Timer : 7, programmed : 40000, actual : 40000 +Timer : 8, programmed : 45000, actual : 45000 +Timer : 9, programmed : 50000, actual : 50000 +Timer : 10, programmed : 55000, actual : 55000 +Timer : 11, programmed : 60000, actual : 60000 +Timer : 12, programmed : 65000, actual : 65000 +Timer : 13, programmed : 70000, actual : 70000 +Timer : 14, programmed : 75000, actual : 75000 +Timer : 15, programmed : 80000, actual : 80000 +SimpleTimer : 2, ms : 171013, Dms : 10064 +Timer : 0, programmed : 5000, actual : 5000 +Timer : 1, programmed : 10000, actual : 10000 +Timer : 2, programmed : 15000, actual : 15000 +Timer : 3, programmed : 20000, actual : 20000 +Timer : 4, programmed : 25000, actual : 25000 +Timer : 5, programmed : 30000, actual : 30000 +Timer : 6, programmed : 35000, actual : 35000 +Timer : 7, programmed : 40000, actual : 40000 +Timer : 8, programmed : 45000, actual : 45000 +Timer : 9, programmed : 50000, actual : 50000 +Timer : 10, programmed : 55000, actual : 55000 +Timer : 11, programmed : 60000, actual : 60000 +Timer : 12, programmed : 65000, actual : 65000 +Timer : 13, programmed : 70000, actual : 70000 +Timer : 14, programmed : 75000, actual : 75000 +Timer : 15, programmed : 80000, actual : 80000 + +``` + +--- + +### 3.3. TCB Clock Frequency 250KHz for lower accuracy but longer time + +``` +Starting ISR_16_Timers_Array_Complex on megaAVR Nano Every +megaAVR_TimerInterrupt v1.2.0 +CPU Frequency = 16 MHz +TCB Clock Frequency = 250KHz for lower accuracy but longer time +Starting ITimer1 OK, millis() = 11 +SimpleTimer : 2, ms : 10012, Dms : 10012 +Timer : 0, programmed : 5000, actual : 5021 +Timer : 1, programmed : 10000, actual : 10015 +Timer : 2, programmed : 15000, actual : 0 +Timer : 3, programmed : 20000, actual : 0 +Timer : 4, programmed : 25000, actual : 0 +Timer : 5, programmed : 30000, actual : 0 +Timer : 6, programmed : 35000, actual : 0 +Timer : 7, programmed : 40000, actual : 0 +Timer : 8, programmed : 45000, actual : 0 +Timer : 9, programmed : 50000, actual : 0 +Timer : 10, programmed : 55000, actual : 0 +Timer : 11, programmed : 60000, actual : 0 +Timer : 12, programmed : 65000, actual : 0 +Timer : 13, programmed : 70000, actual : 0 +Timer : 14, programmed : 75000, actual : 0 +Timer : 15, programmed : 80000, actual : 0 +SimpleTimer : 2, ms : 20071, Dms : 10059 +Timer : 0, programmed : 5000, actual : 4994 +Timer : 1, programmed : 10000, actual : 9999 +Timer : 2, programmed : 15000, actual : 15020 +Timer : 3, programmed : 20000, actual : 20014 +Timer : 4, programmed : 25000, actual : 0 +Timer : 5, programmed : 30000, actual : 0 +Timer : 6, programmed : 35000, actual : 0 +Timer : 7, programmed : 40000, actual : 0 +Timer : 8, programmed : 45000, actual : 0 +Timer : 9, programmed : 50000, actual : 0 +Timer : 10, programmed : 55000, actual : 0 +Timer : 11, programmed : 60000, actual : 0 +Timer : 12, programmed : 65000, actual : 0 +Timer : 13, programmed : 70000, actual : 0 +Timer : 14, programmed : 75000, actual : 0 +Timer : 15, programmed : 80000, actual : 0 + +... + + +SimpleTimer : 2, ms : 845278, Dms : 10063 +Timer : 0, programmed : 5000, actual : 4994 <========== Less accurate @ clock 250KHz +Timer : 1, programmed : 10000, actual : 9997 +Timer : 2, programmed : 15000, actual : 15001 +Timer : 3, programmed : 20000, actual : 20005 +Timer : 4, programmed : 25000, actual : 25000 +Timer : 5, programmed : 30000, actual : 30004 +Timer : 6, programmed : 35000, actual : 34998 +Timer : 7, programmed : 40000, actual : 40001 +Timer : 8, programmed : 45000, actual : 44995 +Timer : 9, programmed : 50000, actual : 50000 +Timer : 10, programmed : 55000, actual : 55004 +Timer : 11, programmed : 60000, actual : 59998 +Timer : 12, programmed : 65000, actual : 64992 +Timer : 13, programmed : 70000, actual : 70005 +Timer : 14, programmed : 75000, actual : 75000 +Timer : 15, programmed : 80000, actual : 80004 +SimpleTimer : 2, ms : 855342, Dms : 10064 +Timer : 0, programmed : 5000, actual : 5004 +Timer : 1, programmed : 10000, actual : 9999 +Timer : 2, programmed : 15000, actual : 15003 +Timer : 3, programmed : 20000, actual : 20005 +Timer : 4, programmed : 25000, actual : 25000 +Timer : 5, programmed : 30000, actual : 30004 +Timer : 6, programmed : 35000, actual : 34998 +Timer : 7, programmed : 40000, actual : 40001 +Timer : 8, programmed : 45000, actual : 45007 +Timer : 9, programmed : 50000, actual : 50000 +Timer : 10, programmed : 55000, actual : 55004 +Timer : 11, programmed : 60000, actual : 59998 +Timer : 12, programmed : 65000, actual : 64992 +Timer : 13, programmed : 70000, actual : 70005 +Timer : 14, programmed : 75000, actual : 75000 +Timer : 15, programmed : 80000, actual : 80004 +``` + + + --- --- @@ -948,6 +1240,11 @@ Sometimes, the library will only work if you update the board core to the latest ## Releases +### Release v1.2.0 + +1. Selectable **TCB Clock 16MHz, 8MHz or 250KHz** depending on necessary accuracy +2. Add BOARD_NAME definition + ### Release v1.1.0 1. Fix bug. Don't use v1.0.0 @@ -997,6 +1294,7 @@ Submit issues to: [megaAVR_TimerInterrupt issues](https://github.com/khoih-prog/ 5. Add more examples. 6. Similar library for ESP32, ESP8266, SAMD21/SAMD51, nRF52, Mbed-OS Nano-33-BLE, STM32 7. Add support to ATmega4809-based boards, such as **Arduino UNO WiFi Rev2, AVR_NANO_EVERY, etc.** +8. Selectable **TCB Clock 16MHz, 8MHz or 250KHz** depending on necessary accuracy --- --- diff --git a/examples/Argument_Complex/Argument_Complex.ino b/examples/Argument_Complex/Argument_Complex.ino index 5963826..334f382 100644 --- a/examples/Argument_Complex/Argument_Complex.ino +++ b/examples/Argument_Complex/Argument_Complex.ino @@ -12,11 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.0.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) + 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ // These define's must be placed at the beginning before #include "megaAVR_TimerInterrupt.h" @@ -25,6 +27,14 @@ #define TIMER_INTERRUPT_DEBUG 0 #define _TIMERINTERRUPT_LOGLEVEL_ 0 +// Select USING_16MHZ == true for 16MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_8MHZ == true for 8MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_250KHZ == true for 250KHz to Timer TCBx => shorter timer, but better accuracy +// Not select for default 250KHz to Timer TCBx => longer timer, but worse accuracy +#define USING_16MHZ true +#define USING_8MHZ false +#define USING_250KHZ false + #define USE_TIMER_0 false #define USE_TIMER_1 true #define USE_TIMER_2 false @@ -85,10 +95,21 @@ void setup() Serial.begin(115200); while (!Serial); - Serial.println(F("\nStarting Argument_Complex on megaAVR")); + Serial.print(F("\nStarting Argument_Complex on ")); + Serial.println(BOARD_NAME); Serial.println(MEGA_AVR_TIMER_INTERRUPT_VERSION); Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("TCB Clock Frequency = ")); + +#if USING_16MHZ + Serial.println(F("16MHz for highest accuracy")); +#elif USING_8MHZ + Serial.println(F("8MHz for very high accuracy")); +#else + Serial.println(F("250KHz for lower accuracy but longer time")); +#endif + // Timer0 is used for micros(), millis(), delay(), etc and can't be used // Select Timer 1-2 for UNO, 0-5 for MEGA // Timer 2 is 8-bit timer, only for higher frequency diff --git a/examples/Argument_None/Argument_None.ino b/examples/Argument_None/Argument_None.ino index d816629..d7708f9 100644 --- a/examples/Argument_None/Argument_None.ino +++ b/examples/Argument_None/Argument_None.ino @@ -12,11 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.0.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) + 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ // These define's must be placed at the beginning before #include "megaAVR_TimerInterrupt.h" @@ -25,6 +27,14 @@ #define TIMER_INTERRUPT_DEBUG 0 #define _TIMERINTERRUPT_LOGLEVEL_ 0 +// Select USING_16MHZ == true for 16MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_8MHZ == true for 8MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_250KHZ == true for 250KHz to Timer TCBx => shorter timer, but better accuracy +// Not select for default 250KHz to Timer TCBx => longer timer, but worse accuracy +#define USING_16MHZ true +#define USING_8MHZ false +#define USING_250KHZ false + #define USE_TIMER_0 false #define USE_TIMER_1 true #define USE_TIMER_2 false @@ -80,10 +90,21 @@ void setup() Serial.begin(115200); while (!Serial); - Serial.println(F("\nStarting Argument_None on megaAVR")); + Serial.print(F("\nStarting Argument_None on ")); + Serial.println(BOARD_NAME); Serial.println(MEGA_AVR_TIMER_INTERRUPT_VERSION); Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("TCB Clock Frequency = ")); + +#if USING_16MHZ + Serial.println(F("16MHz for highest accuracy")); +#elif USING_8MHZ + Serial.println(F("8MHz for very high accuracy")); +#else + Serial.println(F("250KHz for lower accuracy but longer time")); +#endif + // Select Timer 1-2 for UNO, 0-5 for MEGA // Timer 2 is 8-bit timer, only for higher frequency ITimer1.init(); diff --git a/examples/Argument_Simple/Argument_Simple.ino b/examples/Argument_Simple/Argument_Simple.ino index af6db5a..8a717cb 100644 --- a/examples/Argument_Simple/Argument_Simple.ino +++ b/examples/Argument_Simple/Argument_Simple.ino @@ -12,11 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.0.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) + 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ // These define's must be placed at the beginning before #include "megaAVR_TimerInterrupt.h" @@ -25,6 +27,14 @@ #define TIMER_INTERRUPT_DEBUG 0 #define _TIMERINTERRUPT_LOGLEVEL_ 0 +// Select USING_16MHZ == true for 16MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_8MHZ == true for 8MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_250KHZ == true for 250KHz to Timer TCBx => shorter timer, but better accuracy +// Not select for default 250KHz to Timer TCBx => longer timer, but worse accuracy +#define USING_16MHZ true +#define USING_8MHZ false +#define USING_250KHZ false + #define USE_TIMER_0 false #define USE_TIMER_1 true #define USE_TIMER_2 false @@ -88,10 +98,21 @@ void setup() Serial.begin(115200); while (!Serial); - Serial.println(F("\nStarting Argument_Simple on megaAVR")); + Serial.print(F("\nStarting Argument_Simple on ")); + Serial.println(BOARD_NAME); Serial.println(MEGA_AVR_TIMER_INTERRUPT_VERSION); Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("TCB Clock Frequency = ")); + +#if USING_16MHZ + Serial.println(F("16MHz for highest accuracy")); +#elif USING_8MHZ + Serial.println(F("8MHz for very high accuracy")); +#else + Serial.println(F("250KHz for lower accuracy but longer time")); +#endif + // Timer0 is used for micros(), millis(), delay(), etc and can't be used // Select Timer 1-2 for UNO, 0-5 for MEGA // Timer 2 is 8-bit timer, only for higher frequency diff --git a/examples/Change_Interval/Change_Interval.ino b/examples/Change_Interval/Change_Interval.ino index c41d0d4..4c42dbd 100644 --- a/examples/Change_Interval/Change_Interval.ino +++ b/examples/Change_Interval/Change_Interval.ino @@ -12,11 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.0.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) + 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ /* @@ -37,6 +39,14 @@ #define TIMER_INTERRUPT_DEBUG 0 #define _TIMERINTERRUPT_LOGLEVEL_ 0 +// Select USING_16MHZ == true for 16MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_8MHZ == true for 8MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_250KHZ == true for 250KHz to Timer TCBx => shorter timer, but better accuracy +// Not select for default 250KHz to Timer TCBx => longer timer, but worse accuracy +#define USING_16MHZ true +#define USING_8MHZ false +#define USING_250KHZ false + #define USE_TIMER_0 false #define USE_TIMER_1 true #define USE_TIMER_2 true @@ -102,10 +112,21 @@ void setup() Serial.begin(115200); while (!Serial); - Serial.println(F("\nStarting Change_Interval on megaAVR")); + Serial.print(F("\nStarting Change_Interval on ")); + Serial.println(BOARD_NAME); Serial.println(MEGA_AVR_TIMER_INTERRUPT_VERSION); Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("TCB Clock Frequency = ")); + +#if USING_16MHZ + Serial.println(F("16MHz for highest accuracy")); +#elif USING_8MHZ + Serial.println(F("8MHz for very high accuracy")); +#else + Serial.println(F("250KHz for lower accuracy but longer time")); +#endif + // Select Timer 1-2 for UNO, 0-5 for MEGA // Timer 2 is 8-bit timer, only for higher frequency diff --git a/examples/FakeAnalogWrite/FakeAnalogWrite.ino b/examples/FakeAnalogWrite/FakeAnalogWrite.ino index 53f8014..bfb5c40 100644 --- a/examples/FakeAnalogWrite/FakeAnalogWrite.ino +++ b/examples/FakeAnalogWrite/FakeAnalogWrite.ino @@ -12,11 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.0.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) + 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ /* Notes: @@ -46,6 +48,14 @@ #define LOCAL_DEBUG 1 +// Select USING_16MHZ == true for 16MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_8MHZ == true for 8MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_250KHZ == true for 250KHz to Timer TCBx => shorter timer, but better accuracy +// Not select for default 250KHz to Timer TCBx => longer timer, but worse accuracy +#define USING_16MHZ true +#define USING_8MHZ false +#define USING_250KHZ false + #define USE_TIMER_0 false #define USE_TIMER_1 true #define USE_TIMER_2 false @@ -183,10 +193,21 @@ void setup() Serial.begin(115200); while (!Serial); - Serial.println(F("\nStarting FakeAnalogWrite on megaAVR")); + Serial.print(F("\nStarting FakeAnalogWrite on ")); + Serial.println(BOARD_NAME); Serial.println(MEGA_AVR_TIMER_INTERRUPT_VERSION); Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("TCB Clock Frequency = ")); + +#if USING_16MHZ + Serial.println(F("16MHz for highest accuracy")); +#elif USING_8MHZ + Serial.println(F("8MHz for very high accuracy")); +#else + Serial.println(F("250KHz for lower accuracy but longer time")); +#endif + ITimer1.init(); //if (ITimer1.attachInterruptInterval(TIMER2_INTERVAL_MS, TimerHandler)) 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 e5d1444..4d0f033 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 @@ -12,11 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.0.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) + 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ // These define's must be placed at the beginning before #include "megaAVR_TimerInterrupt.h" @@ -25,6 +27,15 @@ #define TIMER_INTERRUPT_DEBUG 0 #define _TIMERINTERRUPT_LOGLEVEL_ 0 +// Select USING_16MHZ == true for 16MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_8MHZ == true for 8MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_250KHZ == true for 250KHz to Timer TCBx => shorter timer, but better accuracy +// Not select for default 250KHz to Timer TCBx => longer timer, but worse accuracy +#define USING_16MHZ true +#define USING_8MHZ false +#define USING_250KHZ false + + #define USE_TIMER_0 false #define USE_TIMER_1 true #define USE_TIMER_2 true @@ -287,10 +298,21 @@ void setup() Serial.begin(115200); while (!Serial); - Serial.println(F("\nStarting ISR_16_Timers_Array_Complex on megaAVR")); + Serial.print(F("\nStarting ISR_16_Timers_Array_Complex on ")); + Serial.println(BOARD_NAME); Serial.println(MEGA_AVR_TIMER_INTERRUPT_VERSION); Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("TCB Clock Frequency = ")); + +#if USING_16MHZ + Serial.println(F("16MHz for highest accuracy")); +#elif USING_8MHZ + Serial.println(F("8MHz for very high accuracy")); +#else + Serial.println(F("250KHz for lower accuracy but longer time")); +#endif + ITimer1.init(); if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS, TimerHandler1)) diff --git a/examples/ISR_RPM_Measure/ISR_RPM_Measure.ino b/examples/ISR_RPM_Measure/ISR_RPM_Measure.ino index 72323aa..64dce33 100644 --- a/examples/ISR_RPM_Measure/ISR_RPM_Measure.ino +++ b/examples/ISR_RPM_Measure/ISR_RPM_Measure.ino @@ -12,11 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.0.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) + 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ /* RPM Measuring uses high frequency hardware timer 1Hz == 1ms) to measure the time from of one rotation, in ms then convert to RPM. One rotation is detected by reading the state of a magnetic REED SW or IR LED Sensor @@ -35,6 +37,14 @@ #define TIMER_INTERRUPT_DEBUG 0 #define _TIMERINTERRUPT_LOGLEVEL_ 0 +// Select USING_16MHZ == true for 16MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_8MHZ == true for 8MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_250KHZ == true for 250KHz to Timer TCBx => shorter timer, but better accuracy +// Not select for default 250KHz to Timer TCBx => longer timer, but worse accuracy +#define USING_16MHZ true +#define USING_8MHZ false +#define USING_250KHZ false + #define USE_TIMER_0 false #define USE_TIMER_1 true #define USE_TIMER_2 true @@ -122,10 +132,21 @@ void setup() Serial.begin(115200); while (!Serial); - Serial.println(F("\nStarting ISR_RPM_Measure on megaAVR")); + Serial.print(F("\nStarting ISR_RPM_Measure on ")); + Serial.println(BOARD_NAME); Serial.println(MEGA_AVR_TIMER_INTERRUPT_VERSION); Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("TCB Clock Frequency = ")); + +#if USING_16MHZ + Serial.println(F("16MHz for highest accuracy")); +#elif USING_8MHZ + Serial.println(F("8MHz for very high accuracy")); +#else + Serial.println(F("250KHz for lower accuracy but longer time")); +#endif + pinMode(LED_BUILTIN, OUTPUT); pinMode(interruptPin, INPUT_PULLUP); diff --git a/examples/ISR_Switch/ISR_Switch.ino b/examples/ISR_Switch/ISR_Switch.ino index 1a368ca..7f08acd 100644 --- a/examples/ISR_Switch/ISR_Switch.ino +++ b/examples/ISR_Switch/ISR_Switch.ino @@ -12,11 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.0.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) + 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ /**************************************************************************************************************************** ISR_Switch demontrates the use of ISR to avoid being blocked by other CPU-monopolizing task @@ -39,6 +41,14 @@ #define TIMER_INTERRUPT_DEBUG 0 #define _TIMERINTERRUPT_LOGLEVEL_ 0 +// Select USING_16MHZ == true for 16MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_8MHZ == true for 8MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_250KHZ == true for 250KHz to Timer TCBx => shorter timer, but better accuracy +// Not select for default 250KHz to Timer TCBx => longer timer, but worse accuracy +#define USING_16MHZ true +#define USING_8MHZ false +#define USING_250KHZ false + #define USE_TIMER_0 false #define USE_TIMER_1 true #define USE_TIMER_2 true @@ -209,10 +219,21 @@ void setup() Serial.begin(115200); while (!Serial); - Serial.println(F("\nStarting ISR_Switch on megaAVR")); + Serial.print(F("\nStarting ISR_Switch on ")); + Serial.println(BOARD_NAME); Serial.println(MEGA_AVR_TIMER_INTERRUPT_VERSION); Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("TCB Clock Frequency = ")); + +#if USING_16MHZ + Serial.println(F("16MHz for highest accuracy")); +#elif USING_8MHZ + Serial.println(F("8MHz for very high accuracy")); +#else + Serial.println(F("250KHz for lower accuracy but longer time")); +#endif + pinMode(RELAY_PIN, OUTPUT); pinMode(BUTTON_PIN, INPUT_PULLUP); digitalWrite(RELAY_PIN, LOW); diff --git a/examples/ISR_Timer_Complex/ISR_Timer_Complex.ino b/examples/ISR_Timer_Complex/ISR_Timer_Complex.ino index ae6b080..47542af 100644 --- a/examples/ISR_Timer_Complex/ISR_Timer_Complex.ino +++ b/examples/ISR_Timer_Complex/ISR_Timer_Complex.ino @@ -12,11 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.0.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) + 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ /**************************************************************************************************************************** @@ -42,6 +44,14 @@ #define TIMER_INTERRUPT_DEBUG 0 #define _TIMERINTERRUPT_LOGLEVEL_ 0 +// Select USING_16MHZ == true for 16MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_8MHZ == true for 8MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_250KHZ == true for 250KHz to Timer TCBx => shorter timer, but better accuracy +// Not select for default 250KHz to Timer TCBx => longer timer, but worse accuracy +#define USING_16MHZ true +#define USING_8MHZ false +#define USING_250KHZ false + #define USE_TIMER_0 false #define USE_TIMER_1 true #define USE_TIMER_2 true @@ -176,10 +186,21 @@ void setup() Serial.begin(115200); while (!Serial); - Serial.println(F("\nStarting ISR_Timer_Complex on megaAVR")); + Serial.print(F("\nStarting ISR_Timer_Complex on ")); + Serial.println(BOARD_NAME); Serial.println(MEGA_AVR_TIMER_INTERRUPT_VERSION); Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("TCB Clock Frequency = ")); + +#if USING_16MHZ + Serial.println(F("16MHz for highest accuracy")); +#elif USING_8MHZ + Serial.println(F("8MHz for very high accuracy")); +#else + Serial.println(F("250KHz for lower accuracy but longer time")); +#endif + // Select Timer 1-2 for UNO, 0-5 for MEGA // Timer 2 is 8-bit timer, only for higher frequency ITimer1.init(); diff --git a/examples/ISR_Timer_Switch/ISR_Timer_Switch.ino b/examples/ISR_Timer_Switch/ISR_Timer_Switch.ino index d88442e..daa1af6 100644 --- a/examples/ISR_Timer_Switch/ISR_Timer_Switch.ino +++ b/examples/ISR_Timer_Switch/ISR_Timer_Switch.ino @@ -12,11 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.0.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) + 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ /**************************************************************************************************************************** ISR_Timer_Switch demontrates the use of ISR combining with Timer Interrupt to avoid being blocked by @@ -41,6 +43,14 @@ #define TIMER_INTERRUPT_DEBUG 0 #define _TIMERINTERRUPT_LOGLEVEL_ 0 +// Select USING_16MHZ == true for 16MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_8MHZ == true for 8MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_250KHZ == true for 250KHz to Timer TCBx => shorter timer, but better accuracy +// Not select for default 250KHz to Timer TCBx => longer timer, but worse accuracy +#define USING_16MHZ true +#define USING_8MHZ false +#define USING_250KHZ false + #define USE_TIMER_0 false #define USE_TIMER_1 true #define USE_TIMER_2 true @@ -228,10 +238,21 @@ void setup() Serial.begin(115200); while (!Serial); - Serial.println(F("\nStarting ISR_Timer_Switch on megaAVR")); + Serial.print(F("\nStarting ISR_Timer_Switch on ")); + Serial.println(BOARD_NAME); Serial.println(MEGA_AVR_TIMER_INTERRUPT_VERSION); Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("TCB Clock Frequency = ")); + +#if USING_16MHZ + Serial.println(F("16MHz for highest accuracy")); +#elif USING_8MHZ + Serial.println(F("8MHz for very high accuracy")); +#else + Serial.println(F("250KHz for lower accuracy but longer time")); +#endif + pinMode(RELAY_PIN, OUTPUT); pinMode(BUTTON_PIN, INPUT_PULLUP); digitalWrite(RELAY_PIN, LOW); diff --git a/examples/ISR_Timer_Switches/ISR_Timer_Switches.ino b/examples/ISR_Timer_Switches/ISR_Timer_Switches.ino index 7e80cb0..965128c 100644 --- a/examples/ISR_Timer_Switches/ISR_Timer_Switches.ino +++ b/examples/ISR_Timer_Switches/ISR_Timer_Switches.ino @@ -12,11 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.0.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) + 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ /**************************************************************************************************************************** ISR_Timer_Switches demontrates the use of ISR combining with Timer Interrupt to avoid being blocked by @@ -41,6 +43,14 @@ #define TIMER_INTERRUPT_DEBUG 0 #define _TIMERINTERRUPT_LOGLEVEL_ 0 +// Select USING_16MHZ == true for 16MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_8MHZ == true for 8MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_250KHZ == true for 250KHz to Timer TCBx => shorter timer, but better accuracy +// Not select for default 250KHz to Timer TCBx => longer timer, but worse accuracy +#define USING_16MHZ true +#define USING_8MHZ false +#define USING_250KHZ false + #define USE_TIMER_0 false #define USE_TIMER_1 true #define USE_TIMER_2 true @@ -358,10 +368,21 @@ void setup() Serial.begin(115200); while (!Serial); - Serial.println(F("\nStarting ISR_Timer_Switches on megaAVR")); + Serial.print(F("\nStarting ISR_Timer_Switches on ")); + Serial.println(BOARD_NAME); Serial.println(MEGA_AVR_TIMER_INTERRUPT_VERSION); Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("TCB Clock Frequency = ")); + +#if USING_16MHZ + Serial.println(F("16MHz for highest accuracy")); +#elif USING_8MHZ + Serial.println(F("8MHz for very high accuracy")); +#else + Serial.println(F("250KHz for lower accuracy but longer time")); +#endif + LampState = false; // Lamp 1 diff --git a/examples/ISR_Timers_Array_Simple/ISR_Timers_Array_Simple.ino b/examples/ISR_Timers_Array_Simple/ISR_Timers_Array_Simple.ino index 38e555f..30a9a20 100644 --- a/examples/ISR_Timers_Array_Simple/ISR_Timers_Array_Simple.ino +++ b/examples/ISR_Timers_Array_Simple/ISR_Timers_Array_Simple.ino @@ -12,11 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.0.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) + 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ // These define's must be placed at the beginning before #include "megaAVR_TimerInterrupt.h" @@ -25,6 +27,14 @@ #define TIMER_INTERRUPT_DEBUG 0 #define _TIMERINTERRUPT_LOGLEVEL_ 0 +// Select USING_16MHZ == true for 16MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_8MHZ == true for 8MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_250KHZ == true for 250KHz to Timer TCBx => shorter timer, but better accuracy +// Not select for default 250KHz to Timer TCBx => longer timer, but worse accuracy +#define USING_16MHZ true +#define USING_8MHZ false +#define USING_250KHZ false + #define USE_TIMER_0 false #define USE_TIMER_1 true #define USE_TIMER_2 true @@ -126,10 +136,21 @@ void setup() Serial.begin(115200); while (!Serial); - Serial.println(F("\nStarting ISR_Timers_Array_Simple on megaAVR")); + Serial.print(F("\nStarting ISR_Timers_Array_Simple on ")); + Serial.println(BOARD_NAME); Serial.println(MEGA_AVR_TIMER_INTERRUPT_VERSION); Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("TCB Clock Frequency = ")); + +#if USING_16MHZ + Serial.println(F("16MHz for highest accuracy")); +#elif USING_8MHZ + Serial.println(F("8MHz for very high accuracy")); +#else + Serial.println(F("250KHz for lower accuracy but longer time")); +#endif + ITimer1.init(); if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS, TimerHandler1)) diff --git a/examples/RPM_Measure/RPM_Measure.ino b/examples/RPM_Measure/RPM_Measure.ino index d04988e..6a48a83 100644 --- a/examples/RPM_Measure/RPM_Measure.ino +++ b/examples/RPM_Measure/RPM_Measure.ino @@ -12,11 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.0.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) + 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ /* RPM Measuring uses high frequency hardware timer 1Hz == 1ms) to measure the time from of one rotation, in ms then convert to RPM. One rotation is detected by reading the state of a magnetic REED SW or IR LED Sensor @@ -35,6 +37,14 @@ #define TIMER_INTERRUPT_DEBUG 0 #define _TIMERINTERRUPT_LOGLEVEL_ 0 +// Select USING_16MHZ == true for 16MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_8MHZ == true for 8MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_250KHZ == true for 250KHz to Timer TCBx => shorter timer, but better accuracy +// Not select for default 250KHz to Timer TCBx => longer timer, but worse accuracy +#define USING_16MHZ true +#define USING_8MHZ false +#define USING_250KHZ false + #define USE_TIMER_0 false #define USE_TIMER_1 true #define USE_TIMER_2 true @@ -110,10 +120,21 @@ void setup() Serial.begin(115200); while (!Serial); - Serial.println(F("\nStarting RPM_Measure on megaAVR")); + Serial.print(F("\nStarting RPM_Measure on ")); + Serial.println(BOARD_NAME); Serial.println(MEGA_AVR_TIMER_INTERRUPT_VERSION); Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("TCB Clock Frequency = ")); + +#if USING_16MHZ + Serial.println(F("16MHz for highest accuracy")); +#elif USING_8MHZ + Serial.println(F("8MHz for very high accuracy")); +#else + Serial.println(F("250KHz for lower accuracy but longer time")); +#endif + // Timer0 is used for micros(), millis(), delay(), etc and can't be used // Select Timer 1-2 for UNO, 0-5 for MEGA // Timer 2 is 8-bit timer, only for higher frequency diff --git a/examples/SwitchDebounce/SwitchDebounce.ino b/examples/SwitchDebounce/SwitchDebounce.ino index c54ce8a..20cf7a8 100644 --- a/examples/SwitchDebounce/SwitchDebounce.ino +++ b/examples/SwitchDebounce/SwitchDebounce.ino @@ -12,11 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.0.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) + 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ /**************************************************************************************************************************** Switch Debouncing uses high frequency hardware timer 50Hz == 20ms) to measure the time from the SW is pressed, @@ -32,6 +34,14 @@ #define TIMER_INTERRUPT_DEBUG 0 #define _TIMERINTERRUPT_LOGLEVEL_ 0 +// Select USING_16MHZ == true for 16MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_8MHZ == true for 8MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_250KHZ == true for 250KHz to Timer TCBx => shorter timer, but better accuracy +// Not select for default 250KHz to Timer TCBx => longer timer, but worse accuracy +#define USING_16MHZ true +#define USING_8MHZ false +#define USING_250KHZ false + #define USE_TIMER_0 false #define USE_TIMER_1 true #define USE_TIMER_2 true @@ -145,10 +155,21 @@ void setup() Serial.begin(115200); while (!Serial); - Serial.println(F("\nStarting SwitchDebounce on megaAVR")); + Serial.print(F("\nStarting SwitchDebounce on ")); + Serial.println(BOARD_NAME); Serial.println(MEGA_AVR_TIMER_INTERRUPT_VERSION); Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("TCB Clock Frequency = ")); + +#if USING_16MHZ + Serial.println(F("16MHz for highest accuracy")); +#elif USING_8MHZ + Serial.println(F("8MHz for very high accuracy")); +#else + Serial.println(F("250KHz for lower accuracy but longer time")); +#endif + // Timer0 is used for micros(), millis(), delay(), etc and can't be used // Select Timer 1-2 for UNO, 0-5 for MEGA // Timer 2 is 8-bit timer, only for higher frequency diff --git a/examples/TimerDuration/TimerDuration.ino b/examples/TimerDuration/TimerDuration.ino index f8081fe..7c256b0 100644 --- a/examples/TimerDuration/TimerDuration.ino +++ b/examples/TimerDuration/TimerDuration.ino @@ -12,11 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.0.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) + 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ // These define's must be placed at the beginning before #include "megaAVR_TimerInterrupt.h" @@ -25,6 +27,14 @@ #define TIMER_INTERRUPT_DEBUG 4 #define _TIMERINTERRUPT_LOGLEVEL_ 4 +// Select USING_16MHZ == true for 16MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_8MHZ == true for 8MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_250KHZ == true for 250KHz to Timer TCBx => shorter timer, but better accuracy +// Not select for default 250KHz to Timer TCBx => longer timer, but worse accuracy +#define USING_16MHZ true +#define USING_8MHZ false +#define USING_250KHZ false + #define USE_TIMER_0 false #define USE_TIMER_1 true #define USE_TIMER_2 true @@ -95,10 +105,21 @@ void setup() Serial.begin(115200); while (!Serial); - Serial.println(F("\nStarting TimerDuration on megaAVR")); + Serial.print(F("\nStarting TimerDuration on ")); + Serial.println(BOARD_NAME); Serial.println(MEGA_AVR_TIMER_INTERRUPT_VERSION); Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + Serial.print(F("TCB Clock Frequency = ")); + +#if USING_16MHZ + Serial.println(F("16MHz for highest accuracy")); +#elif USING_8MHZ + Serial.println(F("8MHz for very high accuracy")); +#else + Serial.println(F("250KHz for lower accuracy but longer time")); +#endif + // Timer0 is used for micros(), millis(), delay(), etc and can't be used // Select Timer 1-2 for UNO, 0-5 for MEGA // Timer 2 is 8-bit timer, only for higher frequency diff --git a/examples/TimerInterruptTest/TimerInterruptTest.ino b/examples/TimerInterruptTest/TimerInterruptTest.ino index 6a46769..7ebef97 100644 --- a/examples/TimerInterruptTest/TimerInterruptTest.ino +++ b/examples/TimerInterruptTest/TimerInterruptTest.ino @@ -12,11 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.0.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) + 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ // These define's must be placed at the beginning before #include "megaAVR_TimerInterrupt.h" @@ -25,6 +27,14 @@ #define TIMER_INTERRUPT_DEBUG 2 #define _TIMERINTERRUPT_LOGLEVEL_ 4 +// Select USING_16MHZ == true for 16MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_8MHZ == true for 8MHz to Timer TCBx => shorter timer, but better accuracy +// Select USING_250KHZ == true for 250KHz to Timer TCBx => shorter timer, but better accuracy +// Not select for default 250KHz to Timer TCBx => longer timer, but worse accuracy +#define USING_16MHZ true +#define USING_8MHZ false +#define USING_250KHZ false + #define USE_TIMER_0 false #define USE_TIMER_1 true #define USE_TIMER_2 true @@ -97,9 +107,20 @@ void setup() Serial.begin(115200); while (!Serial); - Serial.println(F("\nStarting TimerInterruptTest on megaAVR")); + Serial.print(F("\nStarting TimerInterruptTest on ")); + Serial.println(BOARD_NAME); Serial.println(MEGA_AVR_TIMER_INTERRUPT_VERSION); Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); + + Serial.print(F("TCB Clock Frequency = ")); + +#if USING_16MHZ + Serial.println(F("16MHz for highest accuracy")); +#elif USING_8MHZ + Serial.println(F("8MHz for very high accuracy")); +#else + Serial.println(F("250KHz for lower accuracy but longer time")); +#endif Serial.print(F("CPU ADJUST_FACTOR = ")); Serial.println(ADJUST_FACTOR); diff --git a/library.json b/library.json index f993822..9f7405f 100644 --- a/library.json +++ b/library.json @@ -1,7 +1,7 @@ { "name": "megaAVR_TimerInterrupt", - "version": "1.1.0", - "keywords": "timer, interrupt, hardware, isr, isr-based, hardware-timer, mission-critical, accuracy, precise, megaave, nano, uno, atmega4809", + "version": "1.2.0", + "keywords": "timer, interrupt, hardware, isr, isr-based, timing, control, device, hardware-timer, mission-critical, accuracy, precise, megaavr, mega-avr, nano, uno, atmega4809, nano-every, uno-wifi-rev2, arduino", "description": "This library enables you to use Interrupt from Hardware Timers on an Arduino megaAVR board, such as UNO WiFi Rev2, AVR_NANO_EVERY, etc. 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.", "authors": { diff --git a/library.properties b/library.properties index 7f40287..d0d6120 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=megaAVR_TimerInterrupt -version=1.1.0 +version=1.2.0 author=Khoi Hoang maintainer=Khoi Hoang sentence=This library enables you to use Interrupt from Hardware Timers on an Arduino megaAVR board, such as UNO WiFi Rev2, AVR_NANO_EVERY, etc. diff --git a/src/TimerInterrupt_Generic_Debug.h b/src/TimerInterrupt_Generic_Debug.h index a054696..bf3d59d 100644 --- a/src/TimerInterrupt_Generic_Debug.h +++ b/src/TimerInterrupt_Generic_Debug.h @@ -6,24 +6,19 @@ Built by Khoi Hoang https://github.com/khoih-prog/TimerInterrupt Licensed under MIT license - TCNTx - Timer/Counter Register. The actual timer value is stored here. - OCRx - Output Compare Register - ICRx - Input Capture Register (only for 16bit timer) - TIMSKx - Timer/Counter Interrupt Mask Register. To enable/disable timer interrupts. - TIFRx - Timer/Counter Interrupt Flag Register. Indicates a pending timer interrupt. - Now with we can use these new 16 ISR-based timers, while consuming only 1 hwarware Timer. Their independently-selected, maximum interval is practically unlimited (limited only by unsigned long miliseconds) 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. - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ #pragma once diff --git a/src/megaAVR_ISR_Timer-Impl.h b/src/megaAVR_ISR_Timer-Impl.h index 7bef513..ed17b04 100644 --- a/src/megaAVR_ISR_Timer-Impl.h +++ b/src/megaAVR_ISR_Timer-Impl.h @@ -12,12 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ #pragma once diff --git a/src/megaAVR_ISR_Timer.h b/src/megaAVR_ISR_Timer.h index 04df71a..3f60858 100644 --- a/src/megaAVR_ISR_Timer.h +++ b/src/megaAVR_ISR_Timer.h @@ -12,12 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ #pragma once @@ -26,13 +27,21 @@ #define MEGA_AVR_ISR_TIMER_H #if ( defined(__AVR_ATmega4809__) || defined(ARDUINO_AVR_UNO_WIFI_REV2) || defined(ARDUINO_AVR_NANO_EVERY) ) - + #if !defined(BOARD_NAME) + #if (ARDUINO_AVR_UNO_WIFI_REV2) + #define BOARD_NAME "megaAVR UNO WiFi Rev2" + #elif (ARDUINO_AVR_NANO_EVERY) + #define BOARD_NAME "megaAVR Nano Every" + #else + #define BOARD_NAME "megaAVR Unknown" + #endif + #endif #else #error This is designed only for Arduino megaAVR board! Please check your Tools->Board setting. #endif #ifndef MEGA_AVR_TIMER_INTERRUPT_VERSION - #define MEGA_AVR_TIMER_INTERRUPT_VERSION "megaAVR_TimerInterrupt v1.1.0" + #define MEGA_AVR_TIMER_INTERRUPT_VERSION "megaAVR_TimerInterrupt v1.2.0" #endif #include "TimerInterrupt_Generic_Debug.h" diff --git a/src/megaAVR_TimerInterrupt-Impl.h b/src/megaAVR_TimerInterrupt-Impl.h index b5df6c2..01f192b 100644 --- a/src/megaAVR_TimerInterrupt-Impl.h +++ b/src/megaAVR_TimerInterrupt-Impl.h @@ -12,12 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy ****************************************************************************************************************************/ #pragma once @@ -31,14 +32,60 @@ #define TIMER_INTERRUPT_DEBUG 0 #endif -// From iom4809.h -//#define TCB0 (*(TCB_t *) 0x0A80) /* 16-bit Timer Type B */ -//#define TCB1 (*(TCB_t *) 0x0A90) /* 16-bit Timer Type B */ -//#define TCB2 (*(TCB_t *) 0x0AA0) /* 16-bit Timer Type B */ -//#define TCB3 (*(TCB_t *) 0x0AB0) /* 16-bit Timer Type B */ +/***************************************************************************************** + +// From ~/.arduino15/packages/arduino/7.3.0-atmel3.6.1-arduino5/avr/include/avr/iom4809.h + +//#define TCB0 (*(TCB_t *) 0x0A80) // 16-bit Timer Type B +//#define TCB1 (*(TCB_t *) 0x0A90) // 16-bit Timer Type B +//#define TCB2 (*(TCB_t *) 0x0AA0) // 16-bit Timer Type B +//#define TCB3 (*(TCB_t *) 0x0AB0) // 16-bit Timer Type B + +// +typedef enum TCB_CLKSEL_enum +{ + TCB_CLKSEL_CLKDIV1_gc = (0x00<<1), // CLK_PER (No Prescaling) + TCB_CLKSEL_CLKDIV2_gc = (0x01<<1), // CLK_PER/2 (From Prescaler) + TCB_CLKSEL_CLKTCA_gc = (0x02<<1), // Use Clock from TCA +} TCB_CLKSEL_t; + +// +typedef enum TCB_CNTMODE_enum +{ + TCB_CNTMODE_INT_gc = (0x00<<0), // Periodic Interrupt + TCB_CNTMODE_TIMEOUT_gc = (0x01<<0), // Periodic Timeout + TCB_CNTMODE_CAPT_gc = (0x02<<0), // Input Capture Event + TCB_CNTMODE_FRQ_gc = (0x03<<0), // Input Capture Frequency measurement + TCB_CNTMODE_PW_gc = (0x04<<0), // Input Capture Pulse-Width measurement + TCB_CNTMODE_FRQPW_gc = (0x05<<0), // Input Capture Frequency and Pulse-Width measurement + TCB_CNTMODE_SINGLE_gc = (0x06<<0), // Single Shot + TCB_CNTMODE_PWM8_gc = (0x07<<0), // 8-bit PWM +} TCB_CNTMODE_t; + +*****************************************************************************************/ + TCB_t* TimerTCB[ NUM_HW_TIMERS ] = { &TCB0, &TCB1, &TCB2, &TCB3 }; +// Clock for UNO WiFi Rev2 and Nano Every is 16MHz +#if USING_16MHZ // Use no prescaler (prescaler 1) => 16MHz + #warning Using no prescaler => 16MHz + #define TCB_CLKSEL_VALUE TCB_CLKSEL_CLKDIV1_gc +#elif USING_8MHZ + // Use prescaler 2 => 8MHz + #warning Using prescaler 2 => 8MHz + #define TCB_CLKSEL_VALUE TCB_CLKSEL_CLKDIV2_gc +#elif USING_250KHZ + // Optional, but for clarity + // Use Timer A as clock (prescaler 64) => 250KHz + #warning Using prescaler 64 => 250KHz + #define TCB_CLKSEL_VALUE TCB_CLKSEL_CLKTCA_gc +#else + // Use Timer A as clock (prescaler 64) => 250KHz + #warning Using prescaler 64 => 250KHz + #define TCB_CLKSEL_VALUE TCB_CLKSEL_CLKTCA_gc +#endif + void TimerInterrupt::init(int8_t timer) { // Set timer specific stuff @@ -46,14 +93,13 @@ void TimerInterrupt::init(int8_t timer) // 8 bit timers will require changing prescalar values, // whereas 16 bit timers are set to either ck/1 or ck/64 prescalar - //cli();//stop interrupts noInterrupts(); // 16 bit timer TimerTCB[timer]->CTRLB = TCB_CNTMODE_INT_gc; // Use timer compare mode TimerTCB[timer]->CCMP = MAX_COUNT_16BIT; // Value to compare with. TimerTCB[timer]->INTCTRL &= ~TCB_CAPT_bm; // Disable the interrupt - TimerTCB[timer]->CTRLA = TCB_CLKSEL_CLKTCA_gc | TCB_ENABLE_bm; // Use Timer A as clock, enable timer + TimerTCB[timer]->CTRLA = TCB_CLKSEL_VALUE | TCB_ENABLE_bm; // Use Timer A as clock, enable timer TISR_LOGWARN1(F("TCB"), timer); @@ -67,7 +113,6 @@ void TimerInterrupt::init(int8_t timer) _timer = timer; - //sei();//enable interrupts interrupts(); } @@ -108,8 +153,6 @@ bool TimerInterrupt::setFrequency(float frequency, timer_callback_p callback, ui #define CLK_TCA_FREQ (250000L) - //uint8_t andMask = 0b11111000; - unsigned long CCMPValue; bool isSuccess = false; // Currently using CLK_TCA from TCA0 == 250KHz @@ -148,7 +191,6 @@ bool TimerInterrupt::setFrequency(float frequency, timer_callback_p callback, ui //Timer0-3 are 16 bit timers, meaning it can store a maximum counter value of 65535. - //cli();//stop interrupts noInterrupts(); _frequency = frequency; @@ -168,7 +210,6 @@ bool TimerInterrupt::setFrequency(float frequency, timer_callback_p callback, ui // then turn on the interrupts set_CCMP(); - //sei();//allow interrupts interrupts(); return true; @@ -177,7 +218,6 @@ bool TimerInterrupt::setFrequency(float frequency, timer_callback_p callback, ui void TimerInterrupt::detachInterrupt(void) { - //cli();//stop interrupts noInterrupts(); // Clear interrupt flag @@ -185,14 +225,12 @@ void TimerInterrupt::detachInterrupt(void) TimerTCB[_timer]->INTCTRL &= ~TCB_CAPT_bm; // Disable the interrupt TimerTCB[_timer]->CTRLA &= ~TCB_ENABLE_bm; // Disable timer - //sei();//allow interrupts interrupts(); } // Duration (in milliseconds). Duration = 0 or not specified => run indefinitely void TimerInterrupt::reattachInterrupt(unsigned long duration) { - //cli();//stop interrupts noInterrupts(); // Calculate the toggle count @@ -206,11 +244,9 @@ void TimerInterrupt::reattachInterrupt(unsigned long duration) } // Set interrupt flag - //TimerTCB[_timer]->INTFLAGS = TCB_CAPT_bm; TimerTCB[_timer]->INTCTRL |= TCB_CAPT_bm; // Enable the interrupt TimerTCB[_timer]->CTRLA |= TCB_ENABLE_bm; // Enable timer - //sei();//allow interrupts interrupts(); } diff --git a/src/megaAVR_TimerInterrupt.h b/src/megaAVR_TimerInterrupt.h index 8589165..fa5ef8c 100644 --- a/src/megaAVR_TimerInterrupt.h +++ b/src/megaAVR_TimerInterrupt.h @@ -12,12 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy ****************************************************************************************************************************/ #pragma once @@ -26,7 +27,15 @@ #define MEGA_AVR_TIMERINTERRUPT_H #if ( defined(__AVR_ATmega4809__) || defined(ARDUINO_AVR_UNO_WIFI_REV2) || defined(ARDUINO_AVR_NANO_EVERY) ) - + #if !defined(BOARD_NAME) + #if (ARDUINO_AVR_UNO_WIFI_REV2) + #define BOARD_NAME "megaAVR UNO WiFi Rev2" + #elif (ARDUINO_AVR_NANO_EVERY) + #define BOARD_NAME "megaAVR Nano Every" + #else + #define BOARD_NAME "megaAVR Unknown" + #endif + #endif #else #error This is designed only for Arduino megaAVR board! Please check your Tools->Board setting. #endif @@ -218,12 +227,10 @@ class TimerInterrupt void setCount(long countInput) __attribute__((always_inline)) { - //cli();//stop interrupts //noInterrupts(); _toggle_count = countInput; - //sei();//enable interrupts //interrupts(); }; @@ -239,7 +246,6 @@ class TimerInterrupt void adjust_CCMPValue() //__attribute__((always_inline)) { - //cli();//stop interrupts noInterrupts(); _CCMPValueRemaining -= min(MAX_COUNT_16BIT, _CCMPValueRemaining); @@ -254,13 +260,11 @@ class TimerInterrupt else _timerDone = false; - //sei();//enable interrupts interrupts(); }; void reload_CCMPValue() //__attribute__((always_inline)) { - //cli();//stop interrupts noInterrupts(); // Reset value for next cycle, have to deduct the value already loaded to CCMP register @@ -269,7 +273,6 @@ class TimerInterrupt _timerDone = false; - //sei();//enable interrupts interrupts(); }; diff --git a/src_cpp/TimerInterrupt_Generic_Debug.h b/src_cpp/TimerInterrupt_Generic_Debug.h index a054696..bf3d59d 100644 --- a/src_cpp/TimerInterrupt_Generic_Debug.h +++ b/src_cpp/TimerInterrupt_Generic_Debug.h @@ -6,24 +6,19 @@ Built by Khoi Hoang https://github.com/khoih-prog/TimerInterrupt Licensed under MIT license - TCNTx - Timer/Counter Register. The actual timer value is stored here. - OCRx - Output Compare Register - ICRx - Input Capture Register (only for 16bit timer) - TIMSKx - Timer/Counter Interrupt Mask Register. To enable/disable timer interrupts. - TIFRx - Timer/Counter Interrupt Flag Register. Indicates a pending timer interrupt. - Now with we can use these new 16 ISR-based timers, while consuming only 1 hwarware Timer. Their independently-selected, maximum interval is practically unlimited (limited only by unsigned long miliseconds) 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. - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ #pragma once diff --git a/src_cpp/megaAVR_ISR_Timer.cpp b/src_cpp/megaAVR_ISR_Timer.cpp index 1adc385..a69b898 100644 --- a/src_cpp/megaAVR_ISR_Timer.cpp +++ b/src_cpp/megaAVR_ISR_Timer.cpp @@ -12,12 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ #include "megaAVR_ISR_Timer.h" diff --git a/src_cpp/megaAVR_ISR_Timer.h b/src_cpp/megaAVR_ISR_Timer.h index 0958ce2..bdb1654 100644 --- a/src_cpp/megaAVR_ISR_Timer.h +++ b/src_cpp/megaAVR_ISR_Timer.h @@ -12,12 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ #pragma once @@ -26,13 +27,21 @@ #define MEGA_AVR_ISR_TIMER_H #if ( defined(__AVR_ATmega4809__) || defined(ARDUINO_AVR_UNO_WIFI_REV2) || defined(ARDUINO_AVR_NANO_EVERY) ) - + #if !defined(BOARD_NAME) + #if (ARDUINO_AVR_UNO_WIFI_REV2) + #define BOARD_NAME "megaAVR UNO WiFi Rev2" + #elif (ARDUINO_AVR_NANO_EVERY) + #define BOARD_NAME "megaAVR Nano Every" + #else + #define BOARD_NAME "megaAVR Unknown" + #endif + #endif #else #error This is designed only for Arduino megaAVR board! Please check your Tools->Board setting. #endif #ifndef MEGA_AVR_TIMER_INTERRUPT_VERSION - #define MEGA_AVR_TIMER_INTERRUPT_VERSION "megaAVR_TimerInterrupt v1.1.0" + #define MEGA_AVR_TIMER_INTERRUPT_VERSION "megaAVR_TimerInterrupt v1.2.0" #endif #include "TimerInterrupt_Generic_Debug.h" @@ -170,5 +179,4 @@ class ISR_Timer volatile int numTimers; }; - #endif // MEGA_AVR_ISR_TIMER_H diff --git a/src_cpp/megaAVR_TimerInterrupt.cpp b/src_cpp/megaAVR_TimerInterrupt.cpp index 2392810..b18041a 100644 --- a/src_cpp/megaAVR_TimerInterrupt.cpp +++ b/src_cpp/megaAVR_TimerInterrupt.cpp @@ -12,12 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy ****************************************************************************************************************************/ #include "megaAVR_TimerInterrupt.h" @@ -26,14 +27,60 @@ #define TIMER_INTERRUPT_DEBUG 0 #endif -// From iom4809.h -//#define TCB0 (*(TCB_t *) 0x0A80) /* 16-bit Timer Type B */ -//#define TCB1 (*(TCB_t *) 0x0A90) /* 16-bit Timer Type B */ -//#define TCB2 (*(TCB_t *) 0x0AA0) /* 16-bit Timer Type B */ -//#define TCB3 (*(TCB_t *) 0x0AB0) /* 16-bit Timer Type B */ +/***************************************************************************************** + +// From ~/.arduino15/packages/arduino/7.3.0-atmel3.6.1-arduino5/avr/include/avr/iom4809.h + +//#define TCB0 (*(TCB_t *) 0x0A80) // 16-bit Timer Type B +//#define TCB1 (*(TCB_t *) 0x0A90) // 16-bit Timer Type B +//#define TCB2 (*(TCB_t *) 0x0AA0) // 16-bit Timer Type B +//#define TCB3 (*(TCB_t *) 0x0AB0) // 16-bit Timer Type B + +// +typedef enum TCB_CLKSEL_enum +{ + TCB_CLKSEL_CLKDIV1_gc = (0x00<<1), // CLK_PER (No Prescaling) + TCB_CLKSEL_CLKDIV2_gc = (0x01<<1), // CLK_PER/2 (From Prescaler) + TCB_CLKSEL_CLKTCA_gc = (0x02<<1), // Use Clock from TCA +} TCB_CLKSEL_t; + +// +typedef enum TCB_CNTMODE_enum +{ + TCB_CNTMODE_INT_gc = (0x00<<0), // Periodic Interrupt + TCB_CNTMODE_TIMEOUT_gc = (0x01<<0), // Periodic Timeout + TCB_CNTMODE_CAPT_gc = (0x02<<0), // Input Capture Event + TCB_CNTMODE_FRQ_gc = (0x03<<0), // Input Capture Frequency measurement + TCB_CNTMODE_PW_gc = (0x04<<0), // Input Capture Pulse-Width measurement + TCB_CNTMODE_FRQPW_gc = (0x05<<0), // Input Capture Frequency and Pulse-Width measurement + TCB_CNTMODE_SINGLE_gc = (0x06<<0), // Single Shot + TCB_CNTMODE_PWM8_gc = (0x07<<0), // 8-bit PWM +} TCB_CNTMODE_t; + +*****************************************************************************************/ + TCB_t* TimerTCB[ NUM_HW_TIMERS ] = { &TCB0, &TCB1, &TCB2, &TCB3 }; +// Clock for UNO WiFi Rev2 and Nano Every is 16MHz +#if USING_16MHZ // Use no prescaler (prescaler 1) => 16MHz + #warning Using no prescaler => 16MHz + #define TCB_CLKSEL_VALUE TCB_CLKSEL_CLKDIV1_gc +#elif USING_8MHZ + // Use prescaler 2 => 8MHz + #warning Using prescaler 2 => 8MHz + #define TCB_CLKSEL_VALUE TCB_CLKSEL_CLKDIV2_gc +#elif USING_250KHZ + // Optional, but for clarity + // Use Timer A as clock (prescaler 64) => 250KHz + #warning Using prescaler 64 => 250KHz + #define TCB_CLKSEL_VALUE TCB_CLKSEL_CLKTCA_gc +#else + // Use Timer A as clock (prescaler 64) => 250KHz + #warning Using prescaler 64 => 250KHz + #define TCB_CLKSEL_VALUE TCB_CLKSEL_CLKTCA_gc +#endif + void TimerInterrupt::init(int8_t timer) { // Set timer specific stuff @@ -41,14 +88,13 @@ void TimerInterrupt::init(int8_t timer) // 8 bit timers will require changing prescalar values, // whereas 16 bit timers are set to either ck/1 or ck/64 prescalar - //cli();//stop interrupts noInterrupts(); // 16 bit timer TimerTCB[timer]->CTRLB = TCB_CNTMODE_INT_gc; // Use timer compare mode TimerTCB[timer]->CCMP = MAX_COUNT_16BIT; // Value to compare with. TimerTCB[timer]->INTCTRL &= ~TCB_CAPT_bm; // Disable the interrupt - TimerTCB[timer]->CTRLA = TCB_CLKSEL_CLKTCA_gc | TCB_ENABLE_bm; // Use Timer A as clock, enable timer + TimerTCB[timer]->CTRLA = TCB_CLKSEL_VALUE | TCB_ENABLE_bm; // Use Timer A as clock, enable timer TISR_LOGWARN1(F("TCB"), timer); @@ -62,7 +108,6 @@ void TimerInterrupt::init(int8_t timer) _timer = timer; - //sei();//enable interrupts interrupts(); } @@ -103,8 +148,6 @@ bool TimerInterrupt::setFrequency(float frequency, timer_callback_p callback, ui #define CLK_TCA_FREQ (250000L) - //uint8_t andMask = 0b11111000; - unsigned long CCMPValue; bool isSuccess = false; // Currently using CLK_TCA from TCA0 == 250KHz @@ -143,7 +186,6 @@ bool TimerInterrupt::setFrequency(float frequency, timer_callback_p callback, ui //Timer0-3 are 16 bit timers, meaning it can store a maximum counter value of 65535. - //cli();//stop interrupts noInterrupts(); _frequency = frequency; @@ -163,7 +205,6 @@ bool TimerInterrupt::setFrequency(float frequency, timer_callback_p callback, ui // then turn on the interrupts set_CCMP(); - //sei();//allow interrupts interrupts(); return true; @@ -172,7 +213,6 @@ bool TimerInterrupt::setFrequency(float frequency, timer_callback_p callback, ui void TimerInterrupt::detachInterrupt(void) { - //cli();//stop interrupts noInterrupts(); // Clear interrupt flag @@ -180,14 +220,12 @@ void TimerInterrupt::detachInterrupt(void) TimerTCB[_timer]->INTCTRL &= ~TCB_CAPT_bm; // Disable the interrupt TimerTCB[_timer]->CTRLA &= ~TCB_ENABLE_bm; // Disable timer - //sei();//allow interrupts interrupts(); } // Duration (in milliseconds). Duration = 0 or not specified => run indefinitely void TimerInterrupt::reattachInterrupt(unsigned long duration) { - //cli();//stop interrupts noInterrupts(); // Calculate the toggle count @@ -201,11 +239,9 @@ void TimerInterrupt::reattachInterrupt(unsigned long duration) } // Set interrupt flag - //TimerTCB[_timer]->INTFLAGS = TCB_CAPT_bm; TimerTCB[_timer]->INTCTRL |= TCB_CAPT_bm; // Enable the interrupt TimerTCB[_timer]->CTRLA |= TCB_ENABLE_bm; // Enable timer - //sei();//allow interrupts interrupts(); } diff --git a/src_cpp/megaAVR_TimerInterrupt.h b/src_cpp/megaAVR_TimerInterrupt.h index 07e5271..9cdfc88 100644 --- a/src_cpp/megaAVR_TimerInterrupt.h +++ b/src_cpp/megaAVR_TimerInterrupt.h @@ -12,12 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy ****************************************************************************************************************************/ #pragma once @@ -26,7 +27,15 @@ #define MEGA_AVR_TIMERINTERRUPT_H #if ( defined(__AVR_ATmega4809__) || defined(ARDUINO_AVR_UNO_WIFI_REV2) || defined(ARDUINO_AVR_NANO_EVERY) ) - + #if !defined(BOARD_NAME) + #if (ARDUINO_AVR_UNO_WIFI_REV2) + #define BOARD_NAME "megaAVR UNO WiFi Rev2" + #elif (ARDUINO_AVR_NANO_EVERY) + #define BOARD_NAME "megaAVR Nano Every" + #else + #define BOARD_NAME "megaAVR Unknown" + #endif + #endif #else #error This is designed only for Arduino megaAVR board! Please check your Tools->Board setting. #endif @@ -218,12 +227,10 @@ class TimerInterrupt void setCount(long countInput) __attribute__((always_inline)) { - //cli();//stop interrupts //noInterrupts(); _toggle_count = countInput; - //sei();//enable interrupts //interrupts(); }; @@ -239,7 +246,6 @@ class TimerInterrupt void adjust_CCMPValue() //__attribute__((always_inline)) { - //cli();//stop interrupts noInterrupts(); _CCMPValueRemaining -= min(MAX_COUNT_16BIT, _CCMPValueRemaining); @@ -254,13 +260,11 @@ class TimerInterrupt else _timerDone = false; - //sei();//enable interrupts interrupts(); }; void reload_CCMPValue() //__attribute__((always_inline)) { - //cli();//stop interrupts noInterrupts(); // Reset value for next cycle, have to deduct the value already loaded to CCMP register @@ -269,7 +273,6 @@ class TimerInterrupt _timerDone = false; - //sei();//enable interrupts interrupts(); }; diff --git a/src_h/TimerInterrupt_Generic_Debug.h b/src_h/TimerInterrupt_Generic_Debug.h index a054696..bf3d59d 100644 --- a/src_h/TimerInterrupt_Generic_Debug.h +++ b/src_h/TimerInterrupt_Generic_Debug.h @@ -6,24 +6,19 @@ Built by Khoi Hoang https://github.com/khoih-prog/TimerInterrupt Licensed under MIT license - TCNTx - Timer/Counter Register. The actual timer value is stored here. - OCRx - Output Compare Register - ICRx - Input Capture Register (only for 16bit timer) - TIMSKx - Timer/Counter Interrupt Mask Register. To enable/disable timer interrupts. - TIFRx - Timer/Counter Interrupt Flag Register. Indicates a pending timer interrupt. - Now with we can use these new 16 ISR-based timers, while consuming only 1 hwarware Timer. Their independently-selected, maximum interval is practically unlimited (limited only by unsigned long miliseconds) 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. - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ #pragma once diff --git a/src_h/megaAVR_ISR_Timer-Impl.h b/src_h/megaAVR_ISR_Timer-Impl.h index 7bef513..ed17b04 100644 --- a/src_h/megaAVR_ISR_Timer-Impl.h +++ b/src_h/megaAVR_ISR_Timer-Impl.h @@ -12,12 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ #pragma once diff --git a/src_h/megaAVR_ISR_Timer.h b/src_h/megaAVR_ISR_Timer.h index 04df71a..3f60858 100644 --- a/src_h/megaAVR_ISR_Timer.h +++ b/src_h/megaAVR_ISR_Timer.h @@ -12,12 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy *****************************************************************************************************************************/ #pragma once @@ -26,13 +27,21 @@ #define MEGA_AVR_ISR_TIMER_H #if ( defined(__AVR_ATmega4809__) || defined(ARDUINO_AVR_UNO_WIFI_REV2) || defined(ARDUINO_AVR_NANO_EVERY) ) - + #if !defined(BOARD_NAME) + #if (ARDUINO_AVR_UNO_WIFI_REV2) + #define BOARD_NAME "megaAVR UNO WiFi Rev2" + #elif (ARDUINO_AVR_NANO_EVERY) + #define BOARD_NAME "megaAVR Nano Every" + #else + #define BOARD_NAME "megaAVR Unknown" + #endif + #endif #else #error This is designed only for Arduino megaAVR board! Please check your Tools->Board setting. #endif #ifndef MEGA_AVR_TIMER_INTERRUPT_VERSION - #define MEGA_AVR_TIMER_INTERRUPT_VERSION "megaAVR_TimerInterrupt v1.1.0" + #define MEGA_AVR_TIMER_INTERRUPT_VERSION "megaAVR_TimerInterrupt v1.2.0" #endif #include "TimerInterrupt_Generic_Debug.h" diff --git a/src_h/megaAVR_TimerInterrupt-Impl.h b/src_h/megaAVR_TimerInterrupt-Impl.h index b5df6c2..01f192b 100644 --- a/src_h/megaAVR_TimerInterrupt-Impl.h +++ b/src_h/megaAVR_TimerInterrupt-Impl.h @@ -12,12 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy ****************************************************************************************************************************/ #pragma once @@ -31,14 +32,60 @@ #define TIMER_INTERRUPT_DEBUG 0 #endif -// From iom4809.h -//#define TCB0 (*(TCB_t *) 0x0A80) /* 16-bit Timer Type B */ -//#define TCB1 (*(TCB_t *) 0x0A90) /* 16-bit Timer Type B */ -//#define TCB2 (*(TCB_t *) 0x0AA0) /* 16-bit Timer Type B */ -//#define TCB3 (*(TCB_t *) 0x0AB0) /* 16-bit Timer Type B */ +/***************************************************************************************** + +// From ~/.arduino15/packages/arduino/7.3.0-atmel3.6.1-arduino5/avr/include/avr/iom4809.h + +//#define TCB0 (*(TCB_t *) 0x0A80) // 16-bit Timer Type B +//#define TCB1 (*(TCB_t *) 0x0A90) // 16-bit Timer Type B +//#define TCB2 (*(TCB_t *) 0x0AA0) // 16-bit Timer Type B +//#define TCB3 (*(TCB_t *) 0x0AB0) // 16-bit Timer Type B + +// +typedef enum TCB_CLKSEL_enum +{ + TCB_CLKSEL_CLKDIV1_gc = (0x00<<1), // CLK_PER (No Prescaling) + TCB_CLKSEL_CLKDIV2_gc = (0x01<<1), // CLK_PER/2 (From Prescaler) + TCB_CLKSEL_CLKTCA_gc = (0x02<<1), // Use Clock from TCA +} TCB_CLKSEL_t; + +// +typedef enum TCB_CNTMODE_enum +{ + TCB_CNTMODE_INT_gc = (0x00<<0), // Periodic Interrupt + TCB_CNTMODE_TIMEOUT_gc = (0x01<<0), // Periodic Timeout + TCB_CNTMODE_CAPT_gc = (0x02<<0), // Input Capture Event + TCB_CNTMODE_FRQ_gc = (0x03<<0), // Input Capture Frequency measurement + TCB_CNTMODE_PW_gc = (0x04<<0), // Input Capture Pulse-Width measurement + TCB_CNTMODE_FRQPW_gc = (0x05<<0), // Input Capture Frequency and Pulse-Width measurement + TCB_CNTMODE_SINGLE_gc = (0x06<<0), // Single Shot + TCB_CNTMODE_PWM8_gc = (0x07<<0), // 8-bit PWM +} TCB_CNTMODE_t; + +*****************************************************************************************/ + TCB_t* TimerTCB[ NUM_HW_TIMERS ] = { &TCB0, &TCB1, &TCB2, &TCB3 }; +// Clock for UNO WiFi Rev2 and Nano Every is 16MHz +#if USING_16MHZ // Use no prescaler (prescaler 1) => 16MHz + #warning Using no prescaler => 16MHz + #define TCB_CLKSEL_VALUE TCB_CLKSEL_CLKDIV1_gc +#elif USING_8MHZ + // Use prescaler 2 => 8MHz + #warning Using prescaler 2 => 8MHz + #define TCB_CLKSEL_VALUE TCB_CLKSEL_CLKDIV2_gc +#elif USING_250KHZ + // Optional, but for clarity + // Use Timer A as clock (prescaler 64) => 250KHz + #warning Using prescaler 64 => 250KHz + #define TCB_CLKSEL_VALUE TCB_CLKSEL_CLKTCA_gc +#else + // Use Timer A as clock (prescaler 64) => 250KHz + #warning Using prescaler 64 => 250KHz + #define TCB_CLKSEL_VALUE TCB_CLKSEL_CLKTCA_gc +#endif + void TimerInterrupt::init(int8_t timer) { // Set timer specific stuff @@ -46,14 +93,13 @@ void TimerInterrupt::init(int8_t timer) // 8 bit timers will require changing prescalar values, // whereas 16 bit timers are set to either ck/1 or ck/64 prescalar - //cli();//stop interrupts noInterrupts(); // 16 bit timer TimerTCB[timer]->CTRLB = TCB_CNTMODE_INT_gc; // Use timer compare mode TimerTCB[timer]->CCMP = MAX_COUNT_16BIT; // Value to compare with. TimerTCB[timer]->INTCTRL &= ~TCB_CAPT_bm; // Disable the interrupt - TimerTCB[timer]->CTRLA = TCB_CLKSEL_CLKTCA_gc | TCB_ENABLE_bm; // Use Timer A as clock, enable timer + TimerTCB[timer]->CTRLA = TCB_CLKSEL_VALUE | TCB_ENABLE_bm; // Use Timer A as clock, enable timer TISR_LOGWARN1(F("TCB"), timer); @@ -67,7 +113,6 @@ void TimerInterrupt::init(int8_t timer) _timer = timer; - //sei();//enable interrupts interrupts(); } @@ -108,8 +153,6 @@ bool TimerInterrupt::setFrequency(float frequency, timer_callback_p callback, ui #define CLK_TCA_FREQ (250000L) - //uint8_t andMask = 0b11111000; - unsigned long CCMPValue; bool isSuccess = false; // Currently using CLK_TCA from TCA0 == 250KHz @@ -148,7 +191,6 @@ bool TimerInterrupt::setFrequency(float frequency, timer_callback_p callback, ui //Timer0-3 are 16 bit timers, meaning it can store a maximum counter value of 65535. - //cli();//stop interrupts noInterrupts(); _frequency = frequency; @@ -168,7 +210,6 @@ bool TimerInterrupt::setFrequency(float frequency, timer_callback_p callback, ui // then turn on the interrupts set_CCMP(); - //sei();//allow interrupts interrupts(); return true; @@ -177,7 +218,6 @@ bool TimerInterrupt::setFrequency(float frequency, timer_callback_p callback, ui void TimerInterrupt::detachInterrupt(void) { - //cli();//stop interrupts noInterrupts(); // Clear interrupt flag @@ -185,14 +225,12 @@ void TimerInterrupt::detachInterrupt(void) TimerTCB[_timer]->INTCTRL &= ~TCB_CAPT_bm; // Disable the interrupt TimerTCB[_timer]->CTRLA &= ~TCB_ENABLE_bm; // Disable timer - //sei();//allow interrupts interrupts(); } // Duration (in milliseconds). Duration = 0 or not specified => run indefinitely void TimerInterrupt::reattachInterrupt(unsigned long duration) { - //cli();//stop interrupts noInterrupts(); // Calculate the toggle count @@ -206,11 +244,9 @@ void TimerInterrupt::reattachInterrupt(unsigned long duration) } // Set interrupt flag - //TimerTCB[_timer]->INTFLAGS = TCB_CAPT_bm; TimerTCB[_timer]->INTCTRL |= TCB_CAPT_bm; // Enable the interrupt TimerTCB[_timer]->CTRLA |= TCB_ENABLE_bm; // Enable timer - //sei();//allow interrupts interrupts(); } diff --git a/src_h/megaAVR_TimerInterrupt.h b/src_h/megaAVR_TimerInterrupt.h index 8589165..fa5ef8c 100644 --- a/src_h/megaAVR_TimerInterrupt.h +++ b/src_h/megaAVR_TimerInterrupt.h @@ -12,12 +12,13 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.1.0 + Version: 1.2.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 01/04/2021 Initial coding to support Arduino megaAVR ATmega4809-based boards (UNO WiFi Rev2, etc.) 1.1.0 K.Hoang 14/04/2021 Fix bug. Don't use v1.0.0 + 1.2.0 K.Hoang 17/04/2021 Selectable TCB Clock 16MHz, 8MHz or 250KHz depending on necessary accuracy ****************************************************************************************************************************/ #pragma once @@ -26,7 +27,15 @@ #define MEGA_AVR_TIMERINTERRUPT_H #if ( defined(__AVR_ATmega4809__) || defined(ARDUINO_AVR_UNO_WIFI_REV2) || defined(ARDUINO_AVR_NANO_EVERY) ) - + #if !defined(BOARD_NAME) + #if (ARDUINO_AVR_UNO_WIFI_REV2) + #define BOARD_NAME "megaAVR UNO WiFi Rev2" + #elif (ARDUINO_AVR_NANO_EVERY) + #define BOARD_NAME "megaAVR Nano Every" + #else + #define BOARD_NAME "megaAVR Unknown" + #endif + #endif #else #error This is designed only for Arduino megaAVR board! Please check your Tools->Board setting. #endif @@ -218,12 +227,10 @@ class TimerInterrupt void setCount(long countInput) __attribute__((always_inline)) { - //cli();//stop interrupts //noInterrupts(); _toggle_count = countInput; - //sei();//enable interrupts //interrupts(); }; @@ -239,7 +246,6 @@ class TimerInterrupt void adjust_CCMPValue() //__attribute__((always_inline)) { - //cli();//stop interrupts noInterrupts(); _CCMPValueRemaining -= min(MAX_COUNT_16BIT, _CCMPValueRemaining); @@ -254,13 +260,11 @@ class TimerInterrupt else _timerDone = false; - //sei();//enable interrupts interrupts(); }; void reload_CCMPValue() //__attribute__((always_inline)) { - //cli();//stop interrupts noInterrupts(); // Reset value for next cycle, have to deduct the value already loaded to CCMP register @@ -269,7 +273,6 @@ class TimerInterrupt _timerDone = false; - //sei();//enable interrupts interrupts(); };