From 31ef8911a701540687852c8108e00558d8a7525a Mon Sep 17 00:00:00 2001 From: Khoi Hoang <57012152+khoih-prog@users.noreply.github.com> Date: Fri, 19 Nov 2021 23:06:40 -0500 Subject: [PATCH] v1.4.0 to fix HF bug ### Release v1.4.0 1. Fix TCB Clock bug in high frequencies. Check [Interrupt interval 2X requested interval #1](https://github.com/khoih-prog/megaAVR_TimerInterrupt/issues/1) 2. Add example to demo High Frequency 3. Delete Blynk-related examples 4. Add changelog.md --- CONTRIBUTING.md | 6 +- README.md | 155 +++++++----------- changelog.md | 49 ++++++ .../Argument_Complex/Argument_Complex.ino | 9 - examples/Argument_None/Argument_None.ino | 9 - examples/Argument_Simple/Argument_Simple.ino | 9 - examples/Change_Interval/Change_Interval.ino | 9 - .../Change_Interval_HF/Change_Interval_HF.ino | 143 ++++++++++++++++ examples/FakeAnalogWrite/FakeAnalogWrite.ino | 17 -- .../ISR_16_Timers_Array_Complex.ino | 13 +- examples/ISR_RPM_Measure/ISR_RPM_Measure.ino | 9 - .../ISR_Timers_Array_Simple.ino | 9 - examples/RPM_Measure/RPM_Measure.ino | 9 - examples/SwitchDebounce/SwitchDebounce.ino | 9 - examples/TimerDuration/TimerDuration.ino | 9 - .../TimerInterruptTest/TimerInterruptTest.ino | 9 - library.json | 2 +- library.properties | 2 +- platformio/platformio.ini | 2 +- src/megaAVR_ISR_Timer-Impl.h | 3 +- src/megaAVR_ISR_Timer.h | 7 +- src/megaAVR_TimerInterrupt-Impl.h | 25 +-- src/megaAVR_TimerInterrupt.h | 70 +++++--- src_cpp/megaAVR_ISR_Timer.cpp | 3 +- src_cpp/megaAVR_ISR_Timer.h | 5 +- src_cpp/megaAVR_TimerInterrupt.cpp | 26 +-- src_cpp/megaAVR_TimerInterrupt.h | 70 +++++--- src_h/megaAVR_ISR_Timer-Impl.h | 3 +- src_h/megaAVR_ISR_Timer.h | 7 +- src_h/megaAVR_TimerInterrupt-Impl.h | 25 +-- src_h/megaAVR_TimerInterrupt.h | 70 +++++--- 31 files changed, 449 insertions(+), 344 deletions(-) create mode 100644 changelog.md create mode 100644 examples/Change_Interval_HF/Change_Interval_HF.ino diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6ccb5cf..5eeadc7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,7 +14,7 @@ If you don't find anything, please [open a new issue](https://github.com/khoih-p Please ensure to specify the following: -* Arduino IDE version (e.g. 1.8.13) or Platform.io version +* Arduino IDE version (e.g. 1.8.16) or Platform.io version * `Arduino megaAVR` Core Version (e.g. Arduino megaAVR core v1.8.7) * Contextual information (e.g. what you were trying to achieve) * Simplest possible steps to reproduce @@ -26,10 +26,10 @@ Please ensure to specify the following: ### Example ``` -Arduino IDE version: 1.8.13 +Arduino IDE version: 1.8.16 Arduino megaAVR Core Version 1.8.7 OS: Ubuntu 20.04 LTS -Linux xy-Inspiron-3593 5.4.0-71-generic #79-Ubuntu SMP Wed Mar 24 10:56:57 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux +Linux xy-Inspiron-3593 5.4.0-90-generic #101-Ubuntu SMP Fri Oct 15 20:00:55 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux Context: I encountered a crash while trying to use the Timer Interrupt. diff --git a/README.md b/README.md index c01cd33..dbac23b 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,7 @@ * [Why using ISR-based Hardware Timer Interrupt is better](#why-using-isr-based-hardware-timer-interrupt-is-better) * [Important Notes about ISR](#important-notes-about-isr) * [Currently supported Boards](#currently-supported-boards) -* [Changelog](#changelog) - * [Release v1.3.0](#release-v130) - * [Release v1.2.0](#release-v120) - * [Release v1.1.0](#release-v110) - * [Initial Release v1.0.0](#initial-release-v100) +* [Changelog](changelog.md) * [Prerequisites](#prerequisites) * [Installation](#installation) * [Use Arduino Library Manager](#use-arduino-library-manager) @@ -40,19 +36,16 @@ * [ 1. Argument_Complex](examples/Argument_Complex) * [ 2. Argument_None](examples/Argument_None) * [ 3. Argument_Simple](examples/Argument_Simple) - * [ 4. **Change_Interval**](examples/Change_Interval). - * [ 5. **FakeAnalogWrite**](examples/FakeAnalogWrite). + * [ 4. Change_Interval](examples/Change_Interval) + * [ 5. FakeAnalogWrite](examples/FakeAnalogWrite) * [ 6. **ISR_16_Timers_Array_Complex**](examples/ISR_16_Timers_Array_Complex). * [ 7. ISR_RPM_Measure](examples/ISR_RPM_Measure) - * [ 8. ISR_Switch](examples/ISR_Switch) - * [ 9. ISR_Timer_Complex](examples/ISR_Timer_Complex) - * [ 10. **ISR_Timers_Array_Simple**](examples/ISR_Timers_Array_Simple). - * [ 11. ISR_Timer_Switch](examples/ISR_Timer_Switch) - * [ 12. ISR_Timer_Switches](examples/ISR_Timer_Switches) - * [ 13. RPM_Measure](examples/RPM_Measure) - * [ 14. SwitchDebounce](examples/SwitchDebounce) - * [ 15. TimerDuration](examples/TimerDuration) - * [ 16. TimerInterruptTest](examples/TimerInterruptTest) + * [ 8. **Change_Interval_HF**](examples/Change_Interval_HF) + * [ 9. **ISR_Timers_Array_Simple**](examples/ISR_Timers_Array_Simple). + * [ 10. RPM_Measure](examples/RPM_Measure) + * [ 11. SwitchDebounce](examples/SwitchDebounce) + * [ 12. TimerDuration](examples/TimerDuration) + * [ 13. 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 Nano Every](#1-isr_16_timers_array_complex-on-arduino-megaavr-nano-every) @@ -63,7 +56,6 @@ * [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) * [Issues](#issues) * [TO DO](#to-do) * [DONE](#done) @@ -125,31 +117,6 @@ The catch is your function is now part of an ISR (Interrupt Service Routine), an - **Arduino UNO WiFi Rev2, AVR_NANO_EVERY, etc.** - ATmega4809-based boards. ---- ---- - -## Changelog - -### Release v1.3.0 - -1. Fix TCB Clock bug. Don't use v1.2.0 - - -### 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 - -### Initial Release v1.0.0 - -1. Intial release to support to ATmega4809-based boards, such as **Arduino UNO WiFi Rev2, AVR_NANO_EVERY, etc.** -2. New examples to support Blynk using [**WiFiNINA_Generic**](https://github.com/khoih-prog/WiFiNINA_Generic) and [**Blynk_WiFiNINA_WM**](https://github.com/khoih-prog/Blynk_WiFiNINA_WM) libraries. - - --- --- @@ -429,19 +396,16 @@ void setup() 1. [Argument_Complex](examples/Argument_Complex) 2. [Argument_None](examples/Argument_None) 3. [Argument_Simple](examples/Argument_Simple) - 4. [**Change_Interval**](examples/Change_Interval). - 5. [**FakeAnalogWrite**](examples/FakeAnalogWrite). + 4. [Change_Interval](examples/Change_Interval). + 5. [FakeAnalogWrite](examples/FakeAnalogWrite). 6. [**ISR_16_Timers_Array_Complex**](examples/ISR_16_Timers_Array_Complex). 7. [ISR_RPM_Measure](examples/ISR_RPM_Measure) - 8. [ISR_Switch](examples/ISR_Switch) - 9. [ISR_Timer_Complex](examples/ISR_Timer_Complex) -10. [**ISR_Timers_Array_Simple**](examples/ISR_Timers_Array_Simple). -11. [ISR_Timer_Switch](examples/ISR_Timer_Switch) -12. [ISR_Timer_Switches](examples/ISR_Timer_Switches) -13. [RPM_Measure](examples/RPM_Measure) -14. [SwitchDebounce](examples/SwitchDebounce) -15. [TimerDuration](examples/TimerDuration) -16. [TimerInterruptTest](examples/TimerInterruptTest) + 8. [**Change_Interval_HF**](examples/Change_Interval_HF) + 9. [**ISR_Timers_Array_Simple**](examples/ISR_Timers_Array_Simple). +10. [RPM_Measure](examples/RPM_Measure) +11. [SwitchDebounce](examples/SwitchDebounce) +12. [TimerDuration](examples/TimerDuration) +13. [TimerInterruptTest](examples/TimerInterruptTest) --- @@ -799,7 +763,7 @@ While software timer, **programmed for 2s, is activated after more than 10.000s ``` Starting ISR_16_Timers_Array_Complex on megaAVR Nano Every -megaAVR_TimerInterrupt v1.3.0 +megaAVR_TimerInterrupt v1.4.0 CPU Frequency = 16 MHz TCB Clock Frequency = 250KHz for lower accuracy but longer time Starting ITimer1 OK, millis() = 6 @@ -951,7 +915,7 @@ The following is the sample terminal output when running example [Change_Interva ``` Starting Change_Interval on megaAVR Nano Every -megaAVR_TimerInterrupt v1.3.0 +megaAVR_TimerInterrupt v1.4.0 CPU Frequency = 16 MHz TCB Clock Frequency = 250KHz for lower accuracy but longer time Starting ITimer1 OK, millis() = 1 @@ -980,7 +944,7 @@ Changing Interval, Timer1 = 100, Timer2 = 200 ``` Starting ISR_16_Timers_Array_Complex on megaAVR Nano Every -megaAVR_TimerInterrupt v1.3.0 +megaAVR_TimerInterrupt v1.4.0 CPU Frequency = 16 MHz TCB Clock Frequency = 16MHz for highest accuracy Starting ITimer1 OK, millis() = 6 @@ -1066,7 +1030,7 @@ Timer : 15, programmed : 80000, actual : 80000 ``` Starting ISR_16_Timers_Array_Complex on megaAVR Nano Every -megaAVR_TimerInterrupt v1.3.0 +megaAVR_TimerInterrupt v1.4.0 CPU Frequency = 16 MHz TCB Clock Frequency = 8MHz for very high accuracy Starting ITimer1 OK, millis() = 10 @@ -1134,7 +1098,7 @@ Timer : 15, programmed : 80000, actual : 80000 ``` Starting ISR_16_Timers_Array_Complex on megaAVR Nano Every -megaAVR_TimerInterrupt v1.3.0 +megaAVR_TimerInterrupt v1.4.0 CPU Frequency = 16 MHz TCB Clock Frequency = 250KHz for lower accuracy but longer time Starting ITimer1 OK, millis() = 11 @@ -1212,6 +1176,40 @@ Timer : 14, programmed : 75000, actual : 75000 Timer : 15, programmed : 80000, actual : 80004 ``` +--- + +### 4. Change_Interval_HF on Arduino megaAVR Nano Every + +The following is the sample terminal output when running example [Change_Interval_HF](examples/Change_Interval_HF) on **Arduino megaAVR Nano Every** to demonstrate how to change High Frequency Timer Interval on-the-fly + +``` +Starting Change_Interval_HF on megaAVR Nano Every +megaAVR_TimerInterrupt v1.4.0 +CPU Frequency = 16 MHz +TCB Clock Frequency = 16MHz for highest accuracy +[TISR] TCB 1 +[TISR] ================== +[TISR] Init, Timer = 1 +[TISR] CTRLB = 0 +[TISR] CCMP = 65535 +[TISR] INTCTRL = 0 +[TISR] CTRLA = 1 +[TISR] ================== +[TISR] Frequency = 10000.00 , CLK_TCB_FREQ = 16000000 +[TISR] setFrequency: _CCMPValueRemaining = 1600 +Starting ITimer1 OK, millis() = 12 +Frequency, Timer1 = 10000 +Time = 10001, Timer1Count = 99856 +Time = 20002, Timer1Count = 199807 +[TISR] Frequency = 5000.00 , CLK_TCB_FREQ = 16000000 +[TISR] setFrequency: _CCMPValueRemaining = 3200 +Changing Frequency, Timer1 = 5000 +Time = 30003, Timer1Count = 249792 +Time = 40004, Timer1Count = 299784 +[TISR] Frequency = 10000.00 , CLK_TCB_FREQ = 16000000 +[TISR] setFrequency: _CCMPValueRemaining = 1600 +Changing Frequency, Timer1 = 10000 +``` --- @@ -1241,44 +1239,6 @@ If you get compilation errors, more often than not, you may need to install a ne Sometimes, the library will only work if you update the board core to the latest version because I am using newly added functions. ---- ---- - -## Releases - -### Release v1.3.0 - -1. Fix TCB Clock bug. Don't use v1.2.0 - -### 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 - -### Initial Release v1.0.0 - -1. Intial release to support to ATmega4809-based boards, such as **Arduino UNO WiFi Rev2, AVR_NANO_EVERY, etc.** -2. New examples to support Blynk using [**WiFiNINA_Generic**](https://github.com/khoih-prog/WiFiNINA_Generic) and [**Blynk_WiFiNINA_WM**](https://github.com/khoih-prog/Blynk_WiFiNINA_WM) libraries. - -The [**ISR_Timer_Complex**](examples/ISR_Timer_Complex) example will demonstrate the nearly perfect accuracy compared to software timers by printing the actual elapsed millisecs of each type of timers. -Being ISR-based timers, their executions are not blocked by bad-behaving functions / tasks, such as connecting to WiFi, Internet and Blynk services. You can also have many `(up to 16)` timers to use. - -This non-being-blocked important feature is absolutely necessary for mission-critical tasks. - -You'll see blynkTimer Software is blocked while system is connecting to WiFi / Internet / Blynk, as well as by blocking task -in loop(), using delay() function as an example. The elapsed time then is very unaccurate - ---- - -### Currently supported Boards - -- **Arduino UNO WiFi Rev2, AVR_NANO_EVERY, etc.** -- ATmega4809-based boards. - --- --- @@ -1314,11 +1274,12 @@ Submit issues to: [megaAVR_TimerInterrupt issues](https://github.com/khoih-prog/ Many thanks for everyone for bug reporting, new feature suggesting, testing and contributing to the development of this library. Especially to these people who have directly or indirectly contributed to this [megaAVR_TimerInterrupt library](https://github.com/khoih-prog/megaAVR_TimerInterrupt) 1. Thanks to good work of [Miguel Wisintainer](https://github.com/tcpipchip) for initiating, inspriring, working with, developing, debugging, testing and maintaining. - +2. Thanks to [Bill Wuttke](https://github.com/wcwuttke) to report the issue [Interrupt interval 2X requested interval #1](https://github.com/khoih-prog/megaAVR_TimerInterrupt/issues/1) leading to new release v1.4.0 to fix bug in using higher frequencies than 250Hz. +
tcpipchip
⭐️ Miguel Wisintainer

wcwuttke
Bill Wuttke

diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000..8bb8a94 --- /dev/null +++ b/changelog.md @@ -0,0 +1,49 @@ +## megaAVR_TimerInterrupt Library + +[![arduino-library-badge](https://www.ardu-badge.com/badge/megaAVR_TimerInterrupt.svg?)](https://www.ardu-badge.com/megaAVR_TimerInterrupt) +[![GitHub release](https://img.shields.io/github/release/khoih-prog/megaAVR_TimerInterrupt.svg)](https://github.com/khoih-prog/megaAVR_TimerInterrupt/releases) +[![GitHub](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/khoih-prog/megaAVR_TimerInterrupt/blob/master/LICENSE) +[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](#Contributing) +[![GitHub issues](https://img.shields.io/github/issues/khoih-prog/megaAVR_TimerInterrupt.svg)](http://github.com/khoih-prog/megaAVR_TimerInterrupt/issues) + +## Table of Contents + +* [Changelog](#changelog) + * [Release v1.4.0](#release-v140) + * [Release v1.3.0](#release-v130) + * [Release v1.2.0](#release-v120) + * [Release v1.1.0](#release-v110) + * [Initial Release v1.0.0](#initial-release-v100) + +--- +--- + +## Changelog + +### Release v1.4.0 + +1. Fix TCB Clock bug in high frequencies. Check [Interrupt interval 2X requested interval #1](https://github.com/khoih-prog/megaAVR_TimerInterrupt/issues/1) +2. Add example to demo High Frequency +3. Delete Blynk-related examples +4. Add changelog.md + +### Release v1.3.0 + +1. Fix TCB Clock bug. Don't use v1.2.0 + + +### 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 + +### Initial Release v1.0.0 + +1. Intial release to support to ATmega4809-based boards, such as **Arduino UNO WiFi Rev2, AVR_NANO_EVERY, etc.** +2. New examples to support Blynk using [**WiFiNINA_Generic**](https://github.com/khoih-prog/WiFiNINA_Generic) and [**Blynk_WiFiNINA_WM**](https://github.com/khoih-prog/Blynk_WiFiNINA_WM) libraries. + + diff --git a/examples/Argument_Complex/Argument_Complex.ino b/examples/Argument_Complex/Argument_Complex.ino index 9efa180..dda7037 100644 --- a/examples/Argument_Complex/Argument_Complex.ino +++ b/examples/Argument_Complex/Argument_Complex.ino @@ -11,15 +11,6 @@ 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.3.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 - 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 *****************************************************************************************************************************/ // These define's must be placed at the beginning before #include "megaAVR_TimerInterrupt.h" diff --git a/examples/Argument_None/Argument_None.ino b/examples/Argument_None/Argument_None.ino index 6cd0608..55af6e8 100644 --- a/examples/Argument_None/Argument_None.ino +++ b/examples/Argument_None/Argument_None.ino @@ -11,15 +11,6 @@ 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.3.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 - 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 *****************************************************************************************************************************/ // These define's must be placed at the beginning before #include "megaAVR_TimerInterrupt.h" diff --git a/examples/Argument_Simple/Argument_Simple.ino b/examples/Argument_Simple/Argument_Simple.ino index a2edcdc..441f12b 100644 --- a/examples/Argument_Simple/Argument_Simple.ino +++ b/examples/Argument_Simple/Argument_Simple.ino @@ -11,15 +11,6 @@ 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.3.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 - 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 *****************************************************************************************************************************/ // These define's must be placed at the beginning before #include "megaAVR_TimerInterrupt.h" diff --git a/examples/Change_Interval/Change_Interval.ino b/examples/Change_Interval/Change_Interval.ino index 7fef400..a39d625 100644 --- a/examples/Change_Interval/Change_Interval.ino +++ b/examples/Change_Interval/Change_Interval.ino @@ -11,15 +11,6 @@ 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.3.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 - 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 *****************************************************************************************************************************/ /* diff --git a/examples/Change_Interval_HF/Change_Interval_HF.ino b/examples/Change_Interval_HF/Change_Interval_HF.ino new file mode 100644 index 0000000..db99edf --- /dev/null +++ b/examples/Change_Interval_HF/Change_Interval_HF.ino @@ -0,0 +1,143 @@ +/**************************************************************************************************************************** + Change_Interval_HF.ino + For Arduino megaAVR ATMEGA4809-based boards (UNO WiFi Rev2, NANO_EVERY, etc. ) + Written by Khoi Hoang + + Built by Khoi Hoang https://github.com/khoih-prog/megaAVR_TimerInterrupt + Licensed under MIT license + + 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. +*****************************************************************************************************************************/ + +/* + Notes: + Special design is necessary to share data between interrupt code and the rest of your program. + Variables usually need to be "volatile" types. Volatile tells the compiler to avoid optimizations that assume + variable can not spontaneously change. Because your function may change variables while your program is using them, + the compiler needs this hint. But volatile alone is often not enough. + When accessing shared variables, usually interrupts must be disabled. Even with volatile, + if the interrupt changes a multi-byte variable between a sequence of instructions, it can be read incorrectly. + If your data is multiple variables, such as an array and a count, usually interrupts need to be disabled + or the entire sequence of your code which accesses the data. +*/ + +// These define's must be placed at the beginning before #include "megaAVR_TimerInterrupt.h" +// _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4 +// Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system. +#define TIMER_INTERRUPT_DEBUG 0 +#define _TIMERINTERRUPT_LOGLEVEL_ 3 + +// 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 +#define USE_TIMER_3 false + +#include "megaAVR_TimerInterrupt.h" + +#if !defined(LED_BUILTIN) + #define LED_BUILTIN 13 +#endif + +#ifndef LED_BLUE + #define LED_BLUE 7 +#endif + +#define TIMER1_FREQUENCY 1000UL + +volatile uint32_t Timer1Count = 0; + +void printResult(uint32_t currTime) +{ + Serial.print(F("Time = ")); Serial.print(currTime); + Serial.print(F(", Timer1Count = ")); Serial.println(Timer1Count); +} + +void TimerHandler1() +{ + Timer1Count++; +} + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + Serial.print(F("\nStarting Change_Interval_HF 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 + + ITimer1.init(); + + // Using ATmega328 used in UNO => 16MHz CPU clock , + // For 16-bit timer 1, 3, 4 and 5, set frequency from 0.2385 to some KHz + // For 8-bit timer 2 (prescaler up to 1024, set frequency from 61.5Hz to some KHz + + if (ITimer1.attachInterrupt(TIMER1_FREQUENCY, TimerHandler1)) + { + Serial.print(F("Starting ITimer1 OK, millis() = ")); Serial.println(millis()); + Serial.print(F("Frequency, Timer1 = ")); Serial.println(TIMER1_FREQUENCY); + } + else + Serial.println(F("Can't set ITimer1. Select another freq. or timer")); +} + +#define CHECK_INTERVAL_MS 10000L +#define CHANGE_INTERVAL_MS 20000L + +void loop() +{ + static uint32_t lastTime = 0; + static uint32_t lastChangeTime = 0; + static uint32_t currTime; + static uint32_t multFactor = 0; + + currTime = millis(); + + if (currTime - lastTime > CHECK_INTERVAL_MS) + { + printResult(currTime); + lastTime = currTime; + + if (currTime - lastChangeTime > CHANGE_INTERVAL_MS) + { + //setInterval(unsigned long interval, timerCallback callback) + multFactor = (multFactor + 1) % 2; + + // interval (in ms) and duration (in milliseconds). Duration = 0 or not specified => run indefinitely + // bool setInterval(unsigned long interval, timer_callback callback, unsigned long duration) + + ITimer1.setFrequency(TIMER1_FREQUENCY / (multFactor + 1), TimerHandler1); + + Serial.print(F("Changing Frequency, Timer1 = ")); Serial.println(TIMER1_FREQUENCY / (multFactor + 1)); + + lastChangeTime = currTime; + } + } +} diff --git a/examples/FakeAnalogWrite/FakeAnalogWrite.ino b/examples/FakeAnalogWrite/FakeAnalogWrite.ino index f33348b..2fafe83 100644 --- a/examples/FakeAnalogWrite/FakeAnalogWrite.ino +++ b/examples/FakeAnalogWrite/FakeAnalogWrite.ino @@ -11,15 +11,6 @@ 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.3.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 - 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 *****************************************************************************************************************************/ /* Notes: @@ -31,14 +22,6 @@ if the interrupt changes a multi-byte variable between a sequence of instructions, it can be read incorrectly. If your data is multiple variables, such as an array and a count, usually interrupts need to be disabled or the entire sequence of your code which accesses the data. - - This example will demonstrate the nearly perfect accuracy compared to software timers by printing the actual elapsed millisecs. - Being ISR-based timers, their executions are not blocked by bad-behaving functions / tasks, such as connecting to WiFi, Internet - and Blynk services. You can also have many (up to 16) timers to use. - This non-being-blocked important feature is absolutely necessary for mission-critical tasks. - You'll see blynkTimer is blocked while connecting to WiFi / Internet / Blynk, and elapsed time is very unaccurate - In this super simple example, you don't see much different after Blynk is connected, because of no competing task is - written */ // These define's must be placed at the beginning before #include "megaAVR_TimerInterrupt.h" 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 b0d7220..92bdcb6 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 @@ -11,15 +11,6 @@ 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.3.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 - 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 *****************************************************************************************************************************/ // These define's must be placed at the beginning before #include "megaAVR_TimerInterrupt.h" @@ -32,9 +23,9 @@ // 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 false +#define USING_16MHZ true #define USING_8MHZ false -#define USING_250KHZ true +#define USING_250KHZ false #define USE_TIMER_0 false diff --git a/examples/ISR_RPM_Measure/ISR_RPM_Measure.ino b/examples/ISR_RPM_Measure/ISR_RPM_Measure.ino index 385ea6e..81d2aa4 100644 --- a/examples/ISR_RPM_Measure/ISR_RPM_Measure.ino +++ b/examples/ISR_RPM_Measure/ISR_RPM_Measure.ino @@ -11,15 +11,6 @@ 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.3.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 - 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 *****************************************************************************************************************************/ /* 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 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 78698da..aa4c29f 100644 --- a/examples/ISR_Timers_Array_Simple/ISR_Timers_Array_Simple.ino +++ b/examples/ISR_Timers_Array_Simple/ISR_Timers_Array_Simple.ino @@ -11,15 +11,6 @@ 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.3.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 - 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 *****************************************************************************************************************************/ // These define's must be placed at the beginning before #include "megaAVR_TimerInterrupt.h" diff --git a/examples/RPM_Measure/RPM_Measure.ino b/examples/RPM_Measure/RPM_Measure.ino index 9f8c5f2..ae19444 100644 --- a/examples/RPM_Measure/RPM_Measure.ino +++ b/examples/RPM_Measure/RPM_Measure.ino @@ -11,15 +11,6 @@ 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.3.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 - 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 *****************************************************************************************************************************/ /* 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 diff --git a/examples/SwitchDebounce/SwitchDebounce.ino b/examples/SwitchDebounce/SwitchDebounce.ino index 8940c78..d21e12e 100644 --- a/examples/SwitchDebounce/SwitchDebounce.ino +++ b/examples/SwitchDebounce/SwitchDebounce.ino @@ -11,15 +11,6 @@ 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.3.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 - 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 *****************************************************************************************************************************/ /**************************************************************************************************************************** Switch Debouncing uses high frequency hardware timer 50Hz == 20ms) to measure the time from the SW is pressed, diff --git a/examples/TimerDuration/TimerDuration.ino b/examples/TimerDuration/TimerDuration.ino index 6588bc7..09a2d1f 100644 --- a/examples/TimerDuration/TimerDuration.ino +++ b/examples/TimerDuration/TimerDuration.ino @@ -11,15 +11,6 @@ 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.3.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 - 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 *****************************************************************************************************************************/ // These define's must be placed at the beginning before #include "megaAVR_TimerInterrupt.h" diff --git a/examples/TimerInterruptTest/TimerInterruptTest.ino b/examples/TimerInterruptTest/TimerInterruptTest.ino index 9779b6b..987e2e6 100644 --- a/examples/TimerInterruptTest/TimerInterruptTest.ino +++ b/examples/TimerInterruptTest/TimerInterruptTest.ino @@ -11,15 +11,6 @@ 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.3.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 - 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 *****************************************************************************************************************************/ // These define's must be placed at the beginning before #include "megaAVR_TimerInterrupt.h" diff --git a/library.json b/library.json index 162e4e0..0cde10a 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "megaAVR_TimerInterrupt", - "version": "1.3.0", + "version": "1.4.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 90377be..c633c32 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=megaAVR_TimerInterrupt -version=1.3.0 +version=1.4.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/platformio/platformio.ini b/platformio/platformio.ini index 4076dd5..7729dc6 100644 --- a/platformio/platformio.ini +++ b/platformio/platformio.ini @@ -46,7 +46,7 @@ framework = arduino ; ============================================================ ;board = uno2018 -;board = nona4809 +;board = nano4809 board = uno_wifi_rev2 ;board = nano_every diff --git a/src/megaAVR_ISR_Timer-Impl.h b/src/megaAVR_ISR_Timer-Impl.h index c0edcd8..3835ac2 100644 --- a/src/megaAVR_ISR_Timer-Impl.h +++ b/src/megaAVR_ISR_Timer-Impl.h @@ -12,7 +12,7 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.3.0 + Version: 1.4.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -20,6 +20,7 @@ 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 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 + 1.4.0 K.Hoang 19/11/2021 Fix TCB Clock bug in high frequencies *****************************************************************************************************************************/ #pragma once diff --git a/src/megaAVR_ISR_Timer.h b/src/megaAVR_ISR_Timer.h index 615679b..ff5c0fd 100644 --- a/src/megaAVR_ISR_Timer.h +++ b/src/megaAVR_ISR_Timer.h @@ -12,7 +12,7 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.3.0 + Version: 1.4.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -20,6 +20,7 @@ 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 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 + 1.4.0 K.Hoang 19/11/2021 Fix TCB Clock bug in high frequencies *****************************************************************************************************************************/ #pragma once @@ -42,7 +43,7 @@ #endif #ifndef MEGA_AVR_TIMER_INTERRUPT_VERSION - #define MEGA_AVR_TIMER_INTERRUPT_VERSION "megaAVR_TimerInterrupt v1.3.0" + #define MEGA_AVR_TIMER_INTERRUPT_VERSION "megaAVR_TimerInterrupt v1.4.0" #endif #include "TimerInterrupt_Generic_Debug.h" @@ -58,7 +59,7 @@ #endif #endif -typedef void (*timer_callback)(void); +typedef void (*timer_callback)(); typedef void (*timer_callback_p)(void *); class ISR_Timer diff --git a/src/megaAVR_TimerInterrupt-Impl.h b/src/megaAVR_TimerInterrupt-Impl.h index f8cb490..df04a3f 100644 --- a/src/megaAVR_TimerInterrupt-Impl.h +++ b/src/megaAVR_TimerInterrupt-Impl.h @@ -12,7 +12,7 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.3.0 + Version: 1.4.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -20,6 +20,7 @@ 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 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 + 1.4.0 K.Hoang 19/11/2021 Fix TCB Clock bug in high frequencies ****************************************************************************************************************************/ #pragma once @@ -138,18 +139,18 @@ void TimerInterrupt::set_CCMP() _CCMPValueToUse = min(MAX_COUNT_16BIT, _CCMPValueRemaining); _CCMPValueRemaining -= _CCMPValueToUse; - TimerTCB[_timer]->CCMP = _CCMPValueToUse; // Value to compare with. + TimerTCB[_timer]->CCMP = _CCMPValueToUse; // Value to compare with. TimerTCB[_timer]->INTCTRL = TCB_CAPT_bm; // Enable the interrupt - TISR_LOGINFO(F("==================")); - TISR_LOGINFO1(F("set_CCMP, Timer ="), _timer); - TISR_LOGINFO1(F("CTRLB ="), TimerTCB[_timer]->CTRLB); - TISR_LOGINFO1(F("CCMP ="), TimerTCB[_timer]->CCMP); - TISR_LOGINFO1(F("INTCTRL ="), TimerTCB[_timer]->INTCTRL); - TISR_LOGINFO1(F("CTRLA ="), TimerTCB[_timer]->CTRLA); TISR_LOGDEBUG(F("==================")); - + TISR_LOGDEBUG1(F("set_CCMP, Timer ="), _timer); + TISR_LOGDEBUG1(F("CTRLB ="), TimerTCB[_timer]->CTRLB); + TISR_LOGDEBUG1(F("CCMP ="), TimerTCB[_timer]->CCMP); + TISR_LOGDEBUG1(F("INTCTRL ="), TimerTCB[_timer]->INTCTRL); + TISR_LOGDEBUG1(F("CTRLA ="), TimerTCB[_timer]->CTRLA); + TISR_LOGDEBUG(F("==================")); + // Flag _CCMPValue == 0 => end of long timer if (_CCMPValueRemaining == 0) _timerDone = true; @@ -220,7 +221,7 @@ bool TimerInterrupt::setFrequency(float frequency, timer_callback_p callback, ui } } -void TimerInterrupt::detachInterrupt(void) +void TimerInterrupt::detachInterrupt() { noInterrupts(); @@ -256,13 +257,13 @@ void TimerInterrupt::reattachInterrupt(unsigned long duration) // Just stop clock source, still keep the count // To fix this. -void TimerInterrupt::pauseTimer(void) +void TimerInterrupt::pauseTimer() { detachInterrupt(); } // Just reconnect clock source, continue from the current count -void TimerInterrupt::resumeTimer(void) +void TimerInterrupt::resumeTimer() { reattachInterrupt(); } diff --git a/src/megaAVR_TimerInterrupt.h b/src/megaAVR_TimerInterrupt.h index c237ce4..3ead651 100644 --- a/src/megaAVR_TimerInterrupt.h +++ b/src/megaAVR_TimerInterrupt.h @@ -12,7 +12,7 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.3.0 + Version: 1.4.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -20,6 +20,7 @@ 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 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 + 1.4.0 K.Hoang 19/11/2021 Fix TCB Clock bug in high frequencies ****************************************************************************************************************************/ #pragma once @@ -48,7 +49,7 @@ #include "TimerInterrupt_Generic_Debug.h" #ifndef MEGA_AVR_TIMER_INTERRUPT_VERSION - #define MEGA_AVR_TIMER_INTERRUPT_VERSION "megaAVR_TimerInterrupt v1.3.0" + #define MEGA_AVR_TIMER_INTERRUPT_VERSION "megaAVR_TimerInterrupt v1.4.0" #endif #include @@ -58,7 +59,7 @@ #define MAX_COUNT_16BIT 65535 -typedef void (*timer_callback)(void); +typedef void (*timer_callback)(); typedef void (*timer_callback_p)(void *); // Count only TCB0-TCB3 @@ -87,7 +88,7 @@ class TimerInterrupt void* _callback; // pointer to the callback function void* _params; // function parameter - void set_CCMP(void); + void set_CCMP(); public: @@ -184,7 +185,7 @@ class TimerInterrupt void detachInterrupt(); - void disableTimer(void) + void disableTimer() { detachInterrupt(); } @@ -199,13 +200,13 @@ class TimerInterrupt } // Just stop clock source, still keep the count - void pauseTimer(void); + void pauseTimer(); // Just reconnect clock source, continue from the current count - void resumeTimer(void); + void resumeTimer(); // Just stop clock source, clear the count - void stopTimer(void) + void stopTimer() { detachInterrupt(); } @@ -248,36 +249,42 @@ class TimerInterrupt void adjust_CCMPValue() //__attribute__((always_inline)) { noInterrupts(); + + if (_CCMPValueRemaining < MAX_COUNT_16BIT) + { + set_CCMP(); + } + + interrupts(); _CCMPValueRemaining -= min(MAX_COUNT_16BIT, _CCMPValueRemaining); - if (_CCMPValueRemaining == 0) + if (_CCMPValueRemaining <= 0) { // Reset value for next cycle _CCMPValueRemaining = _CCMPValue; + TISR_LOGDEBUG1(F("adjust_CCMPValue: reset _CCMPValueRemaining = "), _CCMPValue); _timerDone = true; } else _timerDone = false; - - interrupts(); }; void reload_CCMPValue() //__attribute__((always_inline)) { noInterrupts(); - // Reset value for next cycle, have to deduct the value already loaded to CCMP register - - _CCMPValueRemaining -= min(MAX_COUNT_16BIT, _CCMPValueRemaining); - + // Reset value for next cycle, have to deduct the value already loaded to CCMP register + _CCMPValueRemaining = _CCMPValue; + set_CCMP(); + _timerDone = false; interrupts(); }; - bool checkTimerDone(void) //__attribute__((always_inline)) + bool checkTimerDone() //__attribute__((always_inline)) { return _timerDone; }; @@ -331,8 +338,11 @@ class TimerInterrupt ITimer0.callback(); - // To reload _CCMPValueRemaining as well as _CCMP register to MAX_COUNT_16BIT - ITimer0.reload_CCMPValue(); + if (ITimer0.get_CCMPValue() > MAX_COUNT_16BIT) + { + // To reload _CCMPValueRemaining as well as _CCMP register to MAX_COUNT_16BIT + ITimer0.reload_CCMPValue(); + } if (countLocal > 0) ITimer0.setCount(countLocal - 1); @@ -382,8 +392,11 @@ class TimerInterrupt ITimer1.callback(); - // To reload _CCMPValueRemaining as well as _CCMP register to MAX_COUNT_16BIT if _CCMPValueRemaining > MAX_COUNT_16BIT - ITimer1.reload_CCMPValue(); + if (ITimer1.get_CCMPValue() > MAX_COUNT_16BIT) + { + // To reload _CCMPValueRemaining as well as _CCMP register to MAX_COUNT_16BIT if _CCMPValueRemaining > MAX_COUNT_16BIT + ITimer1.reload_CCMPValue(); + } if (countLocal > 0) ITimer1.setCount(countLocal - 1); @@ -429,8 +442,12 @@ class TimerInterrupt TISR_LOGDEBUG3(("T2 callback, _CCMPValueRemaining ="), ITimer2.get_CCMPValueRemaining(), (", millis ="), millis()); ITimer2.callback(); - // To reload _CCMPValue - ITimer2.reload_CCMPValue(); + + if (ITimer2.get_CCMPValue() > MAX_COUNT_16BIT) + { + // To reload _CCMPValueRemaining as well as _CCMP register to MAX_COUNT_16BIT if _CCMPValueRemaining > MAX_COUNT_16BIT + ITimer2.reload_CCMPValue(); + } if (countLocal > 0) ITimer2.setCount(countLocal - 1); @@ -478,9 +495,12 @@ class TimerInterrupt ITimer3.callback(); - // To reload _CCMPValueRemaining as well as _CCMP register to MAX_COUNT_16BIT - ITimer3.reload_CCMPValue(); - + if (ITimer3.get_CCMPValue() > MAX_COUNT_16BIT) + { + // To reload _CCMPValueRemaining as well as _CCMP register to MAX_COUNT_16BIT if _CCMPValueRemaining > MAX_COUNT_16BIT + ITimer3.reload_CCMPValue(); + } + if (countLocal > 0) ITimer3.setCount(countLocal - 1); } diff --git a/src_cpp/megaAVR_ISR_Timer.cpp b/src_cpp/megaAVR_ISR_Timer.cpp index 34fd8ad..2f213a4 100644 --- a/src_cpp/megaAVR_ISR_Timer.cpp +++ b/src_cpp/megaAVR_ISR_Timer.cpp @@ -12,7 +12,7 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.3.0 + Version: 1.4.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -20,6 +20,7 @@ 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 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 + 1.4.0 K.Hoang 19/11/2021 Fix TCB Clock bug in high frequencies *****************************************************************************************************************************/ #include "megaAVR_ISR_Timer.h" diff --git a/src_cpp/megaAVR_ISR_Timer.h b/src_cpp/megaAVR_ISR_Timer.h index 1a7423e..43517e3 100644 --- a/src_cpp/megaAVR_ISR_Timer.h +++ b/src_cpp/megaAVR_ISR_Timer.h @@ -12,7 +12,7 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.3.0 + Version: 1.4.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -20,6 +20,7 @@ 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 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 + 1.4.0 K.Hoang 19/11/2021 Fix TCB Clock bug in high frequencies *****************************************************************************************************************************/ #pragma once @@ -42,7 +43,7 @@ #endif #ifndef MEGA_AVR_TIMER_INTERRUPT_VERSION - #define MEGA_AVR_TIMER_INTERRUPT_VERSION "megaAVR_TimerInterrupt v1.3.0" + #define MEGA_AVR_TIMER_INTERRUPT_VERSION "megaAVR_TimerInterrupt v1.4.0" #endif #include "TimerInterrupt_Generic_Debug.h" diff --git a/src_cpp/megaAVR_TimerInterrupt.cpp b/src_cpp/megaAVR_TimerInterrupt.cpp index 014f2ce..f2934de 100644 --- a/src_cpp/megaAVR_TimerInterrupt.cpp +++ b/src_cpp/megaAVR_TimerInterrupt.cpp @@ -12,7 +12,7 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.3.0 + Version: 1.4.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -20,6 +20,7 @@ 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 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 + 1.4.0 K.Hoang 19/11/2021 Fix TCB Clock bug in high frequencies ****************************************************************************************************************************/ #include "megaAVR_TimerInterrupt.h" @@ -133,18 +134,18 @@ void TimerInterrupt::set_CCMP() _CCMPValueToUse = min(MAX_COUNT_16BIT, _CCMPValueRemaining); _CCMPValueRemaining -= _CCMPValueToUse; - TimerTCB[_timer]->CCMP = _CCMPValueToUse; // Value to compare with. + TimerTCB[_timer]->CCMP = _CCMPValueToUse; // Value to compare with. TimerTCB[_timer]->INTCTRL = TCB_CAPT_bm; // Enable the interrupt - TISR_LOGINFO(F("==================")); - TISR_LOGINFO1(F("set_CCMP, Timer ="), _timer); - TISR_LOGINFO1(F("CTRLB ="), TimerTCB[_timer]->CTRLB); - TISR_LOGINFO1(F("CCMP ="), TimerTCB[_timer]->CCMP); - TISR_LOGINFO1(F("INTCTRL ="), TimerTCB[_timer]->INTCTRL); - TISR_LOGINFO1(F("CTRLA ="), TimerTCB[_timer]->CTRLA); TISR_LOGDEBUG(F("==================")); - + TISR_LOGDEBUG1(F("set_CCMP, Timer ="), _timer); + TISR_LOGDEBUG1(F("CTRLB ="), TimerTCB[_timer]->CTRLB); + TISR_LOGDEBUG1(F("CCMP ="), TimerTCB[_timer]->CCMP); + TISR_LOGDEBUG1(F("INTCTRL ="), TimerTCB[_timer]->INTCTRL); + TISR_LOGDEBUG1(F("CTRLA ="), TimerTCB[_timer]->CTRLA); + TISR_LOGDEBUG(F("==================")); + // Flag _CCMPValue == 0 => end of long timer if (_CCMPValueRemaining == 0) _timerDone = true; @@ -215,7 +216,7 @@ bool TimerInterrupt::setFrequency(float frequency, timer_callback_p callback, ui } } -void TimerInterrupt::detachInterrupt(void) +void TimerInterrupt::detachInterrupt() { noInterrupts(); @@ -251,15 +252,14 @@ void TimerInterrupt::reattachInterrupt(unsigned long duration) // Just stop clock source, still keep the count // To fix this. -void TimerInterrupt::pauseTimer(void) +void TimerInterrupt::pauseTimer() { detachInterrupt(); } // Just reconnect clock source, continue from the current count -void TimerInterrupt::resumeTimer(void) +void TimerInterrupt::resumeTimer() { reattachInterrupt(); } - diff --git a/src_cpp/megaAVR_TimerInterrupt.h b/src_cpp/megaAVR_TimerInterrupt.h index 2159192..5604288 100644 --- a/src_cpp/megaAVR_TimerInterrupt.h +++ b/src_cpp/megaAVR_TimerInterrupt.h @@ -12,7 +12,7 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.3.0 + Version: 1.4.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -20,6 +20,7 @@ 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 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 + 1.4.0 K.Hoang 19/11/2021 Fix TCB Clock bug in high frequencies ****************************************************************************************************************************/ #pragma once @@ -48,7 +49,7 @@ #include "TimerInterrupt_Generic_Debug.h" #ifndef MEGA_AVR_TIMER_INTERRUPT_VERSION - #define MEGA_AVR_TIMER_INTERRUPT_VERSION "megaAVR_TimerInterrupt v1.3.0" + #define MEGA_AVR_TIMER_INTERRUPT_VERSION "megaAVR_TimerInterrupt v1.4.0" #endif #include @@ -58,7 +59,7 @@ #define MAX_COUNT_16BIT 65535 -typedef void (*timer_callback)(void); +typedef void (*timer_callback)(); typedef void (*timer_callback_p)(void *); // Count only TCB0-TCB3 @@ -87,7 +88,7 @@ class TimerInterrupt void* _callback; // pointer to the callback function void* _params; // function parameter - void set_CCMP(void); + void set_CCMP(); public: @@ -184,7 +185,7 @@ class TimerInterrupt void detachInterrupt(); - void disableTimer(void) + void disableTimer() { detachInterrupt(); } @@ -199,13 +200,13 @@ class TimerInterrupt } // Just stop clock source, still keep the count - void pauseTimer(void); + void pauseTimer(); // Just reconnect clock source, continue from the current count - void resumeTimer(void); + void resumeTimer(); // Just stop clock source, clear the count - void stopTimer(void) + void stopTimer() { detachInterrupt(); } @@ -248,36 +249,42 @@ class TimerInterrupt void adjust_CCMPValue() //__attribute__((always_inline)) { noInterrupts(); + + if (_CCMPValueRemaining < MAX_COUNT_16BIT) + { + set_CCMP(); + } + + interrupts(); _CCMPValueRemaining -= min(MAX_COUNT_16BIT, _CCMPValueRemaining); - if (_CCMPValueRemaining == 0) + if (_CCMPValueRemaining <= 0) { // Reset value for next cycle _CCMPValueRemaining = _CCMPValue; + TISR_LOGDEBUG1(F("adjust_CCMPValue: reset _CCMPValueRemaining = "), _CCMPValue); _timerDone = true; } else _timerDone = false; - - interrupts(); }; void reload_CCMPValue() //__attribute__((always_inline)) { noInterrupts(); - // Reset value for next cycle, have to deduct the value already loaded to CCMP register - - _CCMPValueRemaining -= min(MAX_COUNT_16BIT, _CCMPValueRemaining); - + // Reset value for next cycle, have to deduct the value already loaded to CCMP register + _CCMPValueRemaining = _CCMPValue; + set_CCMP(); + _timerDone = false; interrupts(); }; - bool checkTimerDone(void) //__attribute__((always_inline)) + bool checkTimerDone() //__attribute__((always_inline)) { return _timerDone; }; @@ -331,8 +338,11 @@ class TimerInterrupt ITimer0.callback(); - // To reload _CCMPValueRemaining as well as _CCMP register to MAX_COUNT_16BIT - ITimer0.reload_CCMPValue(); + if (ITimer0.get_CCMPValue() > MAX_COUNT_16BIT) + { + // To reload _CCMPValueRemaining as well as _CCMP register to MAX_COUNT_16BIT + ITimer0.reload_CCMPValue(); + } if (countLocal > 0) ITimer0.setCount(countLocal - 1); @@ -382,8 +392,11 @@ class TimerInterrupt ITimer1.callback(); - // To reload _CCMPValueRemaining as well as _CCMP register to MAX_COUNT_16BIT if _CCMPValueRemaining > MAX_COUNT_16BIT - ITimer1.reload_CCMPValue(); + if (ITimer1.get_CCMPValue() > MAX_COUNT_16BIT) + { + // To reload _CCMPValueRemaining as well as _CCMP register to MAX_COUNT_16BIT if _CCMPValueRemaining > MAX_COUNT_16BIT + ITimer1.reload_CCMPValue(); + } if (countLocal > 0) ITimer1.setCount(countLocal - 1); @@ -429,8 +442,12 @@ class TimerInterrupt TISR_LOGDEBUG3(("T2 callback, _CCMPValueRemaining ="), ITimer2.get_CCMPValueRemaining(), (", millis ="), millis()); ITimer2.callback(); - // To reload _CCMPValue - ITimer2.reload_CCMPValue(); + + if (ITimer2.get_CCMPValue() > MAX_COUNT_16BIT) + { + // To reload _CCMPValueRemaining as well as _CCMP register to MAX_COUNT_16BIT if _CCMPValueRemaining > MAX_COUNT_16BIT + ITimer2.reload_CCMPValue(); + } if (countLocal > 0) ITimer2.setCount(countLocal - 1); @@ -478,9 +495,12 @@ class TimerInterrupt ITimer3.callback(); - // To reload _CCMPValueRemaining as well as _CCMP register to MAX_COUNT_16BIT - ITimer3.reload_CCMPValue(); - + if (ITimer3.get_CCMPValue() > MAX_COUNT_16BIT) + { + // To reload _CCMPValueRemaining as well as _CCMP register to MAX_COUNT_16BIT if _CCMPValueRemaining > MAX_COUNT_16BIT + ITimer3.reload_CCMPValue(); + } + if (countLocal > 0) ITimer3.setCount(countLocal - 1); } diff --git a/src_h/megaAVR_ISR_Timer-Impl.h b/src_h/megaAVR_ISR_Timer-Impl.h index c0edcd8..3835ac2 100644 --- a/src_h/megaAVR_ISR_Timer-Impl.h +++ b/src_h/megaAVR_ISR_Timer-Impl.h @@ -12,7 +12,7 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.3.0 + Version: 1.4.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -20,6 +20,7 @@ 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 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 + 1.4.0 K.Hoang 19/11/2021 Fix TCB Clock bug in high frequencies *****************************************************************************************************************************/ #pragma once diff --git a/src_h/megaAVR_ISR_Timer.h b/src_h/megaAVR_ISR_Timer.h index 615679b..ff5c0fd 100644 --- a/src_h/megaAVR_ISR_Timer.h +++ b/src_h/megaAVR_ISR_Timer.h @@ -12,7 +12,7 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.3.0 + Version: 1.4.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -20,6 +20,7 @@ 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 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 + 1.4.0 K.Hoang 19/11/2021 Fix TCB Clock bug in high frequencies *****************************************************************************************************************************/ #pragma once @@ -42,7 +43,7 @@ #endif #ifndef MEGA_AVR_TIMER_INTERRUPT_VERSION - #define MEGA_AVR_TIMER_INTERRUPT_VERSION "megaAVR_TimerInterrupt v1.3.0" + #define MEGA_AVR_TIMER_INTERRUPT_VERSION "megaAVR_TimerInterrupt v1.4.0" #endif #include "TimerInterrupt_Generic_Debug.h" @@ -58,7 +59,7 @@ #endif #endif -typedef void (*timer_callback)(void); +typedef void (*timer_callback)(); typedef void (*timer_callback_p)(void *); class ISR_Timer diff --git a/src_h/megaAVR_TimerInterrupt-Impl.h b/src_h/megaAVR_TimerInterrupt-Impl.h index f8cb490..df04a3f 100644 --- a/src_h/megaAVR_TimerInterrupt-Impl.h +++ b/src_h/megaAVR_TimerInterrupt-Impl.h @@ -12,7 +12,7 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.3.0 + Version: 1.4.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -20,6 +20,7 @@ 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 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 + 1.4.0 K.Hoang 19/11/2021 Fix TCB Clock bug in high frequencies ****************************************************************************************************************************/ #pragma once @@ -138,18 +139,18 @@ void TimerInterrupt::set_CCMP() _CCMPValueToUse = min(MAX_COUNT_16BIT, _CCMPValueRemaining); _CCMPValueRemaining -= _CCMPValueToUse; - TimerTCB[_timer]->CCMP = _CCMPValueToUse; // Value to compare with. + TimerTCB[_timer]->CCMP = _CCMPValueToUse; // Value to compare with. TimerTCB[_timer]->INTCTRL = TCB_CAPT_bm; // Enable the interrupt - TISR_LOGINFO(F("==================")); - TISR_LOGINFO1(F("set_CCMP, Timer ="), _timer); - TISR_LOGINFO1(F("CTRLB ="), TimerTCB[_timer]->CTRLB); - TISR_LOGINFO1(F("CCMP ="), TimerTCB[_timer]->CCMP); - TISR_LOGINFO1(F("INTCTRL ="), TimerTCB[_timer]->INTCTRL); - TISR_LOGINFO1(F("CTRLA ="), TimerTCB[_timer]->CTRLA); TISR_LOGDEBUG(F("==================")); - + TISR_LOGDEBUG1(F("set_CCMP, Timer ="), _timer); + TISR_LOGDEBUG1(F("CTRLB ="), TimerTCB[_timer]->CTRLB); + TISR_LOGDEBUG1(F("CCMP ="), TimerTCB[_timer]->CCMP); + TISR_LOGDEBUG1(F("INTCTRL ="), TimerTCB[_timer]->INTCTRL); + TISR_LOGDEBUG1(F("CTRLA ="), TimerTCB[_timer]->CTRLA); + TISR_LOGDEBUG(F("==================")); + // Flag _CCMPValue == 0 => end of long timer if (_CCMPValueRemaining == 0) _timerDone = true; @@ -220,7 +221,7 @@ bool TimerInterrupt::setFrequency(float frequency, timer_callback_p callback, ui } } -void TimerInterrupt::detachInterrupt(void) +void TimerInterrupt::detachInterrupt() { noInterrupts(); @@ -256,13 +257,13 @@ void TimerInterrupt::reattachInterrupt(unsigned long duration) // Just stop clock source, still keep the count // To fix this. -void TimerInterrupt::pauseTimer(void) +void TimerInterrupt::pauseTimer() { detachInterrupt(); } // Just reconnect clock source, continue from the current count -void TimerInterrupt::resumeTimer(void) +void TimerInterrupt::resumeTimer() { reattachInterrupt(); } diff --git a/src_h/megaAVR_TimerInterrupt.h b/src_h/megaAVR_TimerInterrupt.h index c237ce4..3ead651 100644 --- a/src_h/megaAVR_TimerInterrupt.h +++ b/src_h/megaAVR_TimerInterrupt.h @@ -12,7 +12,7 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.3.0 + Version: 1.4.0 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -20,6 +20,7 @@ 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 1.3.0 K.Hoang 17/04/2021 Fix TCB Clock bug. Don't use v1.2.0 + 1.4.0 K.Hoang 19/11/2021 Fix TCB Clock bug in high frequencies ****************************************************************************************************************************/ #pragma once @@ -48,7 +49,7 @@ #include "TimerInterrupt_Generic_Debug.h" #ifndef MEGA_AVR_TIMER_INTERRUPT_VERSION - #define MEGA_AVR_TIMER_INTERRUPT_VERSION "megaAVR_TimerInterrupt v1.3.0" + #define MEGA_AVR_TIMER_INTERRUPT_VERSION "megaAVR_TimerInterrupt v1.4.0" #endif #include @@ -58,7 +59,7 @@ #define MAX_COUNT_16BIT 65535 -typedef void (*timer_callback)(void); +typedef void (*timer_callback)(); typedef void (*timer_callback_p)(void *); // Count only TCB0-TCB3 @@ -87,7 +88,7 @@ class TimerInterrupt void* _callback; // pointer to the callback function void* _params; // function parameter - void set_CCMP(void); + void set_CCMP(); public: @@ -184,7 +185,7 @@ class TimerInterrupt void detachInterrupt(); - void disableTimer(void) + void disableTimer() { detachInterrupt(); } @@ -199,13 +200,13 @@ class TimerInterrupt } // Just stop clock source, still keep the count - void pauseTimer(void); + void pauseTimer(); // Just reconnect clock source, continue from the current count - void resumeTimer(void); + void resumeTimer(); // Just stop clock source, clear the count - void stopTimer(void) + void stopTimer() { detachInterrupt(); } @@ -248,36 +249,42 @@ class TimerInterrupt void adjust_CCMPValue() //__attribute__((always_inline)) { noInterrupts(); + + if (_CCMPValueRemaining < MAX_COUNT_16BIT) + { + set_CCMP(); + } + + interrupts(); _CCMPValueRemaining -= min(MAX_COUNT_16BIT, _CCMPValueRemaining); - if (_CCMPValueRemaining == 0) + if (_CCMPValueRemaining <= 0) { // Reset value for next cycle _CCMPValueRemaining = _CCMPValue; + TISR_LOGDEBUG1(F("adjust_CCMPValue: reset _CCMPValueRemaining = "), _CCMPValue); _timerDone = true; } else _timerDone = false; - - interrupts(); }; void reload_CCMPValue() //__attribute__((always_inline)) { noInterrupts(); - // Reset value for next cycle, have to deduct the value already loaded to CCMP register - - _CCMPValueRemaining -= min(MAX_COUNT_16BIT, _CCMPValueRemaining); - + // Reset value for next cycle, have to deduct the value already loaded to CCMP register + _CCMPValueRemaining = _CCMPValue; + set_CCMP(); + _timerDone = false; interrupts(); }; - bool checkTimerDone(void) //__attribute__((always_inline)) + bool checkTimerDone() //__attribute__((always_inline)) { return _timerDone; }; @@ -331,8 +338,11 @@ class TimerInterrupt ITimer0.callback(); - // To reload _CCMPValueRemaining as well as _CCMP register to MAX_COUNT_16BIT - ITimer0.reload_CCMPValue(); + if (ITimer0.get_CCMPValue() > MAX_COUNT_16BIT) + { + // To reload _CCMPValueRemaining as well as _CCMP register to MAX_COUNT_16BIT + ITimer0.reload_CCMPValue(); + } if (countLocal > 0) ITimer0.setCount(countLocal - 1); @@ -382,8 +392,11 @@ class TimerInterrupt ITimer1.callback(); - // To reload _CCMPValueRemaining as well as _CCMP register to MAX_COUNT_16BIT if _CCMPValueRemaining > MAX_COUNT_16BIT - ITimer1.reload_CCMPValue(); + if (ITimer1.get_CCMPValue() > MAX_COUNT_16BIT) + { + // To reload _CCMPValueRemaining as well as _CCMP register to MAX_COUNT_16BIT if _CCMPValueRemaining > MAX_COUNT_16BIT + ITimer1.reload_CCMPValue(); + } if (countLocal > 0) ITimer1.setCount(countLocal - 1); @@ -429,8 +442,12 @@ class TimerInterrupt TISR_LOGDEBUG3(("T2 callback, _CCMPValueRemaining ="), ITimer2.get_CCMPValueRemaining(), (", millis ="), millis()); ITimer2.callback(); - // To reload _CCMPValue - ITimer2.reload_CCMPValue(); + + if (ITimer2.get_CCMPValue() > MAX_COUNT_16BIT) + { + // To reload _CCMPValueRemaining as well as _CCMP register to MAX_COUNT_16BIT if _CCMPValueRemaining > MAX_COUNT_16BIT + ITimer2.reload_CCMPValue(); + } if (countLocal > 0) ITimer2.setCount(countLocal - 1); @@ -478,9 +495,12 @@ class TimerInterrupt ITimer3.callback(); - // To reload _CCMPValueRemaining as well as _CCMP register to MAX_COUNT_16BIT - ITimer3.reload_CCMPValue(); - + if (ITimer3.get_CCMPValue() > MAX_COUNT_16BIT) + { + // To reload _CCMPValueRemaining as well as _CCMP register to MAX_COUNT_16BIT if _CCMPValueRemaining > MAX_COUNT_16BIT + ITimer3.reload_CCMPValue(); + } + if (countLocal > 0) ITimer3.setCount(countLocal - 1); }