diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e8b63c0..4c52145 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -15,7 +15,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.19) or Platform.io version
-* `ESP32` Core Version (e.g. ESP32 core v2.0.4)
+* `ESP32` Core Version (e.g. ESP32 core v2.0.5)
* `ESP32-C3` Board type (e.g. ESP32C3_DEV Module, LOLIN_C3_MINI, DFROBOT_BEETLE_ESP32_C3, ADAFRUIT_QTPY_ESP32C3, AirM2M_CORE_ESP32C3, XIAO_ESP32C3, etc.)
* Contextual information (e.g. what you were trying to achieve)
* Simplest possible steps to reproduce
@@ -28,14 +28,13 @@ Please ensure to specify the following:
```
Arduino IDE version: 1.8.19
-ESP32 Core Version v2.0.4
+ESP32 core v2.0.5
ESP32C3_DEV Module
OS: Ubuntu 20.04 LTS
-Linux xy-Inspiron-3593 5.15.0-41-generic #44~20.04.1-Ubuntu SMP Fri Jun 24 13:27:29 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
+Linux xy-Inspiron-3593 5.15.0-52-generic #58~20.04.1-Ubuntu SMP Thu Oct 13 13:09:46 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
Context:
-I encountered a crash while using TimerInterrupt.
-
+I encountered a crash while using this library
Steps to reproduce:
1. ...
2. ...
@@ -43,13 +42,36 @@ Steps to reproduce:
4. ...
```
+### Additional context
+
+Add any other context about the problem here.
+
+---
+
### Sending Feature Requests
Feel free to post feature requests. It's helpful if you can explain exactly why the feature would be useful.
There are usually some outstanding feature requests in the [existing issues list](https://github.com/khoih-prog/ESP32_C3_TimerInterrupt/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement), feel free to add comments to them.
+---
+
### Sending Pull Requests
Pull Requests with changes and fixes are also welcome!
+Please use the `astyle` to reformat the updated library code as follows (demo for Ubuntu Linux)
+
+1. Change directory to the library GitHub
+
+```
+xy@xy-Inspiron-3593:~$ cd Arduino/xy/ESP32_C3_TimerInterrupt_GitHub/
+xy@xy-Inspiron-3593:~/Arduino/xy/ESP32_C3_TimerInterrupt_GitHub$
+```
+
+2. Issue astyle command
+
+```
+xy@xy-Inspiron-3593:~/Arduino/xy/ESP32_C3_TimerInterrupt_GitHub$ bash utils/restyle.sh
+```
+
diff --git a/changelog.md b/changelog.md
index 4478255..5b7cda1 100644
--- a/changelog.md
+++ b/changelog.md
@@ -2,10 +2,14 @@
[![arduino-library-badge](https://www.ardu-badge.com/badge/ESP32_C3_TimerInterrupt.svg?)](https://www.ardu-badge.com/ESP32_C3_TimerInterrupt)
[![GitHub release](https://img.shields.io/github/release/khoih-prog/ESP32_C3_TimerInterrupt.svg)](https://github.com/khoih-prog/ESP32_C3_TimerInterrupt/releases)
-[![GitHub](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/khoih-prog/ESP32_C3_TimerInterrupt/blob/master/LICENSE)
+[![GitHub](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/khoih-prog/ESP32_C3_TimerInterrupt/blob/main/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/ESP32_C3_TimerInterrupt.svg)](http://github.com/khoih-prog/ESP32_C3_TimerInterrupt/issues)
+
+
+
+
---
---
@@ -13,6 +17,7 @@
## Table of Contents
* [Changelog](#changelog)
+ * [Releases v1.8.0](#releases-v180)
* [Releases v1.7.0](#releases-v170)
* [Releases v1.6.0](#releases-v160)
* [Releases v1.5.0](#releases-v150)
@@ -23,11 +28,17 @@
## Changelog
+### Releases v1.8.0
+
+1. Fix doubled time for `ESP32_C3`. Check [Error in the value defined by TIMER0_INTERVAL_MS #28](https://github.com/khoih-prog/ESP32_C3_TimerInterrupt/issues/28)
+2. Modify examples to avoid using `LED_BUILTIN` / `GPIO2`, `GPIO1` as it can cause crash in some boards, such as `ESP32_C3`
+3. Use `allman astyle` and add `utils`
+
### Releases v1.7.0
1. Add support to
- ESP32_C3 : LOLIN_C3_MINI, DFROBOT_BEETLE_ESP32_C3, ADAFRUIT_QTPY_ESP32C3, AirM2M_CORE_ESP32C3, XIAO_ESP32C3
-
+
### Releases v1.6.0
1. Suppress errors and warnings for new ESP32 core v2.0.4+
diff --git a/examples/Argument_None/Argument_None.ino b/examples/Argument_None/Argument_None.ino
index 0762636..5a21ef7 100644
--- a/examples/Argument_None/Argument_None.ino
+++ b/examples/Argument_None/Argument_None.ino
@@ -46,35 +46,34 @@
// Can be included as many times as necessary, without `Multiple Definitions` Linker Error
#include "ESP32_C3_TimerInterrupt.h"
-#ifndef LED_BUILTIN
- #define LED_BUILTIN 2 // Pin D2 mapped to pin GPIO2/ADC12 of ESP32, control on-board LED
-#endif
-
-#define PIN_D1 1 // Pin D1 mapped to pin GPIO1 of ESP32-S2
+// Don't use PIN_D3 in core v2.0.0 and v2.0.1. Check https://github.com/espressif/arduino-esp32/issues/5868
+// Don't use PIN_D2 with ESP32_C3 (crash)
+#define PIN_D39 19 // Pin D19 mapped to pin GPIO9 of ESP32
+#define PIN_D3 3 // Pin D3 mapped to pin GPIO3/RX0 of ESP32
bool IRAM_ATTR TimerHandler0(void * timerNo)
-{
- static bool toggle0 = false;
-
- //timer interrupt toggles pin LED_BUILTIN
- digitalWrite(LED_BUILTIN, toggle0);
- toggle0 = !toggle0;
-
- return true;
+{
+ static bool toggle0 = false;
+
+ //timer interrupt toggles pin PIN_D39
+ digitalWrite(PIN_D39, toggle0);
+ toggle0 = !toggle0;
+
+ return true;
}
bool IRAM_ATTR TimerHandler1(void * timerNo)
{
- static bool toggle1 = false;
+ static bool toggle1 = false;
- //timer interrupt toggles outputPin
- digitalWrite(PIN_D1, toggle1);
- toggle1 = !toggle1;
+ //timer interrupt toggles outputPin
+ digitalWrite(PIN_D3, toggle1);
+ toggle1 = !toggle1;
- return true;
+ return true;
}
-#define TIMER0_INTERVAL_MS 1000
+#define TIMER0_INTERVAL_MS 100 //1000
#define TIMER1_INTERVAL_MS 5000
@@ -84,40 +83,46 @@ ESP32Timer ITimer1(1);
void setup()
{
- pinMode(LED_BUILTIN, OUTPUT);
- pinMode(PIN_D1, OUTPUT);
-
- Serial.begin(115200);
- while (!Serial);
-
- delay(100);
-
- Serial.print(F("\nStarting Argument_None on ")); Serial.println(ARDUINO_BOARD);
- Serial.println(ESP32_C3_TIMER_INTERRUPT_VERSION);
- Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz"));
-
- // Using ESP32 => 80 / 160 / 240MHz CPU clock ,
- // For 64-bit timer counter
- // For 16-bit timer prescaler up to 1024
-
- // Interval in microsecs
- if (ITimer0.attachInterruptInterval(TIMER0_INTERVAL_MS * 1000, TimerHandler0))
- //if (ITimer0.attachInterrupt(1, TimerHandler0))
- {
- Serial.print(F("Starting ITimer0 OK, millis() = ")); Serial.println(millis());
- }
- else
- Serial.println(F("Can't set ITimer0. Select another Timer, freq. or timer"));
-
-
- // Interval in microsecs
- if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS * 1000, TimerHandler1))
- //if (ITimer1.attachInterrupt(2, TimerHandler1))
- {
- Serial.print(F("Starting ITimer1 OK, millis() = ")); Serial.println(millis());
- }
- else
- Serial.println(F("Can't set ITimer1. Select another Timer, freq. or timer"));
+ pinMode(PIN_D39, OUTPUT);
+ pinMode(PIN_D3, OUTPUT);
+
+ Serial.begin(115200);
+
+ while (!Serial && millis() < 5000);
+
+ delay(500);
+
+ Serial.print(F("\nStarting Argument_None on "));
+ Serial.println(ARDUINO_BOARD);
+ Serial.println(ESP32_C3_TIMER_INTERRUPT_VERSION);
+ Serial.print(F("CPU Frequency = "));
+ Serial.print(F_CPU / 1000000);
+ Serial.println(F(" MHz"));
+
+ // Using ESP32 => 80 / 160 / 240MHz CPU clock ,
+ // For 64-bit timer counter
+ // For 16-bit timer prescaler up to 1024
+
+ // Interval in microsecs
+ if (ITimer0.attachInterruptInterval(TIMER0_INTERVAL_MS * 1000, TimerHandler0))
+ //if (ITimer0.attachInterrupt(1, TimerHandler0))
+ {
+ Serial.print(F("Starting ITimer0 OK, millis() = "));
+ Serial.println(millis());
+ }
+ else
+ Serial.println(F("Can't set ITimer0. Select another Timer, freq. or timer"));
+
+
+ // Interval in microsecs
+ if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS * 1000, TimerHandler1))
+ //if (ITimer1.attachInterrupt(2, TimerHandler1))
+ {
+ Serial.print(F("Starting ITimer1 OK, millis() = "));
+ Serial.println(millis());
+ }
+ else
+ Serial.println(F("Can't set ITimer1. Select another Timer, freq. or timer"));
}
void loop()
diff --git a/examples/Change_Interval/Change_Interval.ino b/examples/Change_Interval/Change_Interval.ino
index 88b762a..ed11f20 100644
--- a/examples/Change_Interval/Change_Interval.ino
+++ b/examples/Change_Interval/Change_Interval.ino
@@ -46,48 +46,50 @@
// Can be included as many times as necessary, without `Multiple Definitions` Linker Error
#include "ESP32_C3_TimerInterrupt.h"
-#ifndef LED_BUILTIN
- #define LED_BUILTIN 2 // Pin D2 mapped to pin GPIO2/ADC12 of ESP32, control on-board LED
-#endif
-
-#define PIN_D1 1 // Pin D1 mapped to pin GPIO1 of ESP32-S2
+// Don't use PIN_D3 in core v2.0.0 and v2.0.1. Check https://github.com/espressif/arduino-esp32/issues/5868
+// Don't use PIN_D2 with ESP32_C3 (crash)
+#define PIN_D39 19 // Pin D19 mapped to pin GPIO9 of ESP32
+#define PIN_D3 3 // Pin D3 mapped to pin GPIO3/RX0 of ESP32
volatile uint32_t Timer0Count = 0;
volatile uint32_t Timer1Count = 0;
bool IRAM_ATTR TimerHandler0(void * timerNo)
-{
- static bool toggle0 = false;
+{
+ static bool toggle0 = false;
- // Flag for checking to be sure ISR is working as Serial.print is not OK here in ISR
- Timer0Count++;
+ // Flag for checking to be sure ISR is working as Serial.print is not OK here in ISR
+ Timer0Count++;
- //timer interrupt toggles pin LED_BUILTIN
- digitalWrite(LED_BUILTIN, toggle0);
- toggle0 = !toggle0;
+ //timer interrupt toggles pin PIN_D39
+ digitalWrite(PIN_D39, toggle0);
+ toggle0 = !toggle0;
- return true;
+ return true;
}
bool IRAM_ATTR TimerHandler1(void * timerNo)
{
- static bool toggle1 = false;
+ static bool toggle1 = false;
- // Flag for checking to be sure ISR is working as Serial.print is not OK here in ISR
- Timer1Count++;
+ // Flag for checking to be sure ISR is working as Serial.print is not OK here in ISR
+ Timer1Count++;
- //timer interrupt toggles PIN_D1
- digitalWrite(PIN_D1, toggle1);
- toggle1 = !toggle1;
+ //timer interrupt toggles PIN_D3
+ digitalWrite(PIN_D3, toggle1);
+ toggle1 = !toggle1;
- return true;
+ return true;
}
void printResult(uint32_t currTime)
{
- Serial.print(F("Time = ")); Serial.print(currTime);
- Serial.print(F(", Timer0Count = ")); Serial.print(Timer0Count);
- Serial.print(F(", Timer1Count = ")); Serial.println(Timer1Count);
+ Serial.print(F("Time = "));
+ Serial.print(currTime);
+ Serial.print(F(", Timer0Count = "));
+ Serial.print(Timer0Count);
+ Serial.print(F(", Timer1Count = "));
+ Serial.println(Timer1Count);
}
#define TIMER0_INTERVAL_MS 2000
@@ -100,33 +102,39 @@ ESP32Timer ITimer1(1);
void setup()
{
- pinMode(LED_BUILTIN, OUTPUT);
- pinMode(PIN_D1, OUTPUT);
-
- Serial.begin(115200);
- while (!Serial);
-
- delay(100);
-
- Serial.print(F("\nStarting Change_Interval on ")); Serial.println(ARDUINO_BOARD);
- Serial.println(ESP32_C3_TIMER_INTERRUPT_VERSION);
- Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz"));
-
- // Interval in microsecs
- if (ITimer0.attachInterruptInterval(TIMER0_INTERVAL_MS * 1000, TimerHandler0))
- {
- Serial.print(F("Starting ITimer0 OK, millis() = ")); Serial.println(millis());
- }
- else
- Serial.println(F("Can't set ITimer0. Select another freq. or timer"));
-
- // Interval in microsecs
- if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS * 1000, TimerHandler1))
- {
- Serial.print(F("Starting ITimer1 OK, millis() = ")); Serial.println(millis());
- }
- else
- Serial.println(F("Can't set ITimer1. Select another freq. or timer"));
+ pinMode(PIN_D39, OUTPUT);
+ pinMode(PIN_D3, OUTPUT);
+
+ Serial.begin(115200);
+
+ while (!Serial && millis() < 5000);
+
+ delay(500);
+
+ Serial.print(F("\nStarting Change_Interval on "));
+ Serial.println(ARDUINO_BOARD);
+ Serial.println(ESP32_C3_TIMER_INTERRUPT_VERSION);
+ Serial.print(F("CPU Frequency = "));
+ Serial.print(F_CPU / 1000000);
+ Serial.println(F(" MHz"));
+
+ // Interval in microsecs
+ if (ITimer0.attachInterruptInterval(TIMER0_INTERVAL_MS * 1000, TimerHandler0))
+ {
+ Serial.print(F("Starting ITimer0 OK, millis() = "));
+ Serial.println(millis());
+ }
+ else
+ Serial.println(F("Can't set ITimer0. Select another freq. or timer"));
+
+ // Interval in microsecs
+ if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS * 1000, TimerHandler1))
+ {
+ Serial.print(F("Starting ITimer1 OK, millis() = "));
+ Serial.println(millis());
+ }
+ else
+ Serial.println(F("Can't set ITimer1. Select another freq. or timer"));
}
#define CHECK_INTERVAL_MS 10000L
@@ -134,30 +142,32 @@ void setup()
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;
-
- ITimer0.setInterval(TIMER0_INTERVAL_MS * 1000 * (multFactor + 1), TimerHandler0);
- ITimer1.setInterval(TIMER1_INTERVAL_MS * 1000 * (multFactor + 1), TimerHandler1);
-
- Serial.print(F("Changing Interval, Timer0 = ")); Serial.print(TIMER0_INTERVAL_MS * (multFactor + 1));
- Serial.print(F(", Timer1 = ")); Serial.println(TIMER1_INTERVAL_MS * (multFactor + 1));
-
- lastChangeTime = currTime;
- }
- }
+ 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;
+
+ ITimer0.setInterval(TIMER0_INTERVAL_MS * 1000 * (multFactor + 1), TimerHandler0);
+ ITimer1.setInterval(TIMER1_INTERVAL_MS * 1000 * (multFactor + 1), TimerHandler1);
+
+ Serial.print(F("Changing Interval, Timer0 = "));
+ Serial.print(TIMER0_INTERVAL_MS * (multFactor + 1));
+ Serial.print(F(", Timer1 = "));
+ Serial.println(TIMER1_INTERVAL_MS * (multFactor + 1));
+
+ lastChangeTime = currTime;
+ }
+ }
}
diff --git a/examples/ISR_16_Timers_Array/ISR_16_Timers_Array.ino b/examples/ISR_16_Timers_Array/ISR_16_Timers_Array.ino
index a8da80d..079ae15 100644
--- a/examples/ISR_16_Timers_Array/ISR_16_Timers_Array.ino
+++ b/examples/ISR_16_Timers_Array/ISR_16_Timers_Array.ino
@@ -54,18 +54,18 @@
// Don't use PIN_D1 in core v2.0.0 and v2.0.1. Check https://github.com/espressif/arduino-esp32/issues/5868
-#ifndef LED_BUILTIN
- #define LED_BUILTIN 2
-#endif
-
#ifndef LED_BLUE
- #define LED_BLUE 25
+ #define LED_BLUE 25
#endif
#ifndef LED_RED
- #define LED_RED 27
+ #define LED_RED 27
#endif
+// Don't use PIN_D1 in core v2.0.0 and v2.0.1. Check https://github.com/espressif/arduino-esp32/issues/5868
+// Don't use PIN_D2 with ESP32_C3 (crash)
+#define PIN_D19 19 // Pin D19 mapped to pin GPIO9 of ESP32
+
#define HW_TIMER_INTERVAL_MS 1L
volatile uint32_t startMillis = 0;
@@ -82,30 +82,30 @@ ESP32_ISR_Timer ISR_Timer;
// and you can't use float calculation inside ISR
// Only OK in core v1.0.6-
bool IRAM_ATTR TimerHandler(void * timerNo)
-{
- static bool toggle = false;
- static bool started = false;
- static int timeRun = 0;
-
- ISR_Timer.run();
-
- // Toggle LED every LED_TOGGLE_INTERVAL_MS = 2000ms = 2s
- if (++timeRun == (LED_TOGGLE_INTERVAL_MS / HW_TIMER_INTERVAL_MS) )
- {
- timeRun = 0;
-
- if (!started)
- {
- started = true;
- pinMode(LED_BUILTIN, OUTPUT);
- }
-
- //timer interrupt toggles pin LED_BUILTIN
- digitalWrite(LED_BUILTIN, toggle);
- toggle = !toggle;
- }
-
- return true;
+{
+ static bool toggle = false;
+ static bool started = false;
+ static int timeRun = 0;
+
+ ISR_Timer.run();
+
+ // Toggle LED every LED_TOGGLE_INTERVAL_MS = 2000ms = 2s
+ if (++timeRun == (LED_TOGGLE_INTERVAL_MS / HW_TIMER_INTERVAL_MS) )
+ {
+ timeRun = 0;
+
+ if (!started)
+ {
+ started = true;
+ pinMode(PIN_D19, OUTPUT);
+ }
+
+ //timer interrupt toggles pin PIN_D19
+ digitalWrite(PIN_D19, toggle);
+ toggle = !toggle;
+ }
+
+ return true;
}
#define NUMBER_ISR_TIMERS 16
@@ -113,8 +113,8 @@ bool IRAM_ATTR TimerHandler(void * timerNo)
// You can assign any interval for any timer here, in milliseconds
uint32_t TimerInterval[NUMBER_ISR_TIMERS] =
{
- 1000L, 2000L, 3000L, 4000L, 5000L, 6000L, 7000L, 8000L,
- 9000L, 10000L, 11000L, 12000L, 13000L, 14000L, 15000L, 16000L
+ 1000L, 2000L, 3000L, 4000L, 5000L, 6000L, 7000L, 8000L,
+ 9000L, 10000L, 11000L, 12000L, 13000L, 14000L, 15000L, 16000L
};
typedef void (*irqCallback) ();
@@ -189,10 +189,10 @@ void doingSomething15()
irqCallback irqCallbackFunc[NUMBER_ISR_TIMERS] =
{
- doingSomething0, doingSomething1, doingSomething2, doingSomething3,
- doingSomething4, doingSomething5, doingSomething6, doingSomething7,
- doingSomething8, doingSomething9, doingSomething10, doingSomething11,
- doingSomething12, doingSomething13, doingSomething14, doingSomething15
+ doingSomething0, doingSomething1, doingSomething2, doingSomething3,
+ doingSomething4, doingSomething5, doingSomething6, doingSomething7,
+ doingSomething8, doingSomething9, doingSomething10, doingSomething11,
+ doingSomething12, doingSomething13, doingSomething14, doingSomething15
};
////////////////////////////////////////////////
@@ -209,56 +209,63 @@ SimpleTimer simpleTimer;
// 2. Very long "do", "while", "for" loops without predetermined exit time.
void simpleTimerDoingSomething2s()
{
- static unsigned long previousMillis = startMillis;
-
- Serial.print(F("simpleTimerDoingSomething2s: Delta programmed ms = ")); Serial.print(SIMPLE_TIMER_MS);
- Serial.print(F(", actual = ")); Serial.println(millis() - previousMillis);
-
- previousMillis = millis();
+ static unsigned long previousMillis = startMillis;
+
+ Serial.print(F("simpleTimerDoingSomething2s: Delta programmed ms = "));
+ Serial.print(SIMPLE_TIMER_MS);
+ Serial.print(F(", actual = "));
+ Serial.println(millis() - previousMillis);
+
+ previousMillis = millis();
}
void setup()
{
- Serial.begin(115200);
- while (!Serial);
-
- delay(2000);
-
- Serial.print(F("\nStarting ISR_16_Timers_Array on ")); Serial.println(ARDUINO_BOARD);
- Serial.println(ESP32_C3_TIMER_INTERRUPT_VERSION);
- Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz"));
-
- // Interval in microsecs
- if (ITimer.attachInterruptInterval(HW_TIMER_INTERVAL_MS * 1000, TimerHandler))
- {
- startMillis = millis();
- Serial.print(F("Starting ITimer OK, millis() = ")); Serial.println(startMillis);
- }
- else
- Serial.println(F("Can't set ITimer. Select another freq. or timer"));
-
- // Just to demonstrate, don't use too many ISR Timers if not absolutely necessary
- // You can use up to 16 timer for each ISR_Timer
- for (uint16_t i = 0; i < NUMBER_ISR_TIMERS; i++)
- {
- ISR_Timer.setInterval(TimerInterval[i], irqCallbackFunc[i]);
- }
-
- // You need this timer for non-critical tasks. Avoid abusing ISR if not absolutely necessary.
- simpleTimer.setInterval(SIMPLE_TIMER_MS, simpleTimerDoingSomething2s);
+ Serial.begin(115200);
+
+ while (!Serial && millis() < 5000);
+
+ delay(500);
+
+ Serial.print(F("\nStarting ISR_16_Timers_Array on "));
+ Serial.println(ARDUINO_BOARD);
+ Serial.println(ESP32_C3_TIMER_INTERRUPT_VERSION);
+ Serial.print(F("CPU Frequency = "));
+ Serial.print(F_CPU / 1000000);
+ Serial.println(F(" MHz"));
+
+ // Interval in microsecs
+ if (ITimer.attachInterruptInterval(HW_TIMER_INTERVAL_MS * 1000, TimerHandler))
+ {
+ startMillis = millis();
+ Serial.print(F("Starting ITimer OK, millis() = "));
+ Serial.println(startMillis);
+ }
+ else
+ Serial.println(F("Can't set ITimer. Select another freq. or timer"));
+
+ // Just to demonstrate, don't use too many ISR Timers if not absolutely necessary
+ // You can use up to 16 timer for each ISR_Timer
+ for (uint16_t i = 0; i < NUMBER_ISR_TIMERS; i++)
+ {
+ ISR_Timer.setInterval(TimerInterval[i], irqCallbackFunc[i]);
+ }
+
+ // You need this timer for non-critical tasks. Avoid abusing ISR if not absolutely necessary.
+ simpleTimer.setInterval(SIMPLE_TIMER_MS, simpleTimerDoingSomething2s);
}
#define BLOCKING_TIME_MS 10000L
void loop()
{
- // This unadvised blocking task is used to demonstrate the blocking effects onto the execution and accuracy to Software timer
- // You see the time elapse of ISR_Timer still accurate, whereas very unaccurate for Software Timer
- // The time elapse for 2000ms software timer now becomes 3000ms (BLOCKING_TIME_MS)
- // While that of ISR_Timer is still prefect.
- delay(BLOCKING_TIME_MS);
-
- // You need this Software timer for non-critical tasks. Avoid abusing ISR if not absolutely necessary
- // You don't need to and never call ISR_Timer.run() here in the loop(). It's already handled by ISR timer.
- simpleTimer.run();
+ // This unadvised blocking task is used to demonstrate the blocking effects onto the execution and accuracy to Software timer
+ // You see the time elapse of ISR_Timer still accurate, whereas very unaccurate for Software Timer
+ // The time elapse for 2000ms software timer now becomes 3000ms (BLOCKING_TIME_MS)
+ // While that of ISR_Timer is still prefect.
+ delay(BLOCKING_TIME_MS);
+
+ // You need this Software timer for non-critical tasks. Avoid abusing ISR if not absolutely necessary
+ // You don't need to and never call ISR_Timer.run() here in the loop(). It's already handled by ISR timer.
+ simpleTimer.run();
}
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 11d4d20..fc06adc 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
@@ -52,18 +52,18 @@
#include // https://github.com/jfturcot/SimpleTimer
-#ifndef LED_BUILTIN
- #define LED_BUILTIN 2
-#endif
-
#ifndef LED_BLUE
- #define LED_BLUE 25
+ #define LED_BLUE 25
#endif
#ifndef LED_RED
- #define LED_RED 27
+ #define LED_RED 27
#endif
+// Don't use PIN_D1 in core v2.0.0 and v2.0.1. Check https://github.com/espressif/arduino-esp32/issues/5868
+// Don't use PIN_D2 with ESP32_C3 (crash)
+#define PIN_D19 19 // Pin D19 mapped to pin GPIO9 of ESP32
+
#define HW_TIMER_INTERVAL_US 10000L
volatile uint32_t startMillis = 0;
@@ -77,23 +77,23 @@ ESP32_ISR_Timer ISR_Timer;
#define LED_TOGGLE_INTERVAL_MS 2000L
bool IRAM_ATTR TimerHandler(void * timerNo)
-{
- static bool toggle = false;
- static int timeRun = 0;
+{
+ static bool toggle = false;
+ static int timeRun = 0;
- ISR_Timer.run();
+ ISR_Timer.run();
- // Toggle LED every LED_TOGGLE_INTERVAL_MS = 2000ms = 2s
- if (++timeRun == ((LED_TOGGLE_INTERVAL_MS * 1000) / HW_TIMER_INTERVAL_US) )
- {
- timeRun = 0;
+ // Toggle LED every LED_TOGGLE_INTERVAL_MS = 2000ms = 2s
+ if (++timeRun == ((LED_TOGGLE_INTERVAL_MS * 1000) / HW_TIMER_INTERVAL_US) )
+ {
+ timeRun = 0;
- //timer interrupt toggles pin LED_BUILTIN
- digitalWrite(LED_BUILTIN, toggle);
- toggle = !toggle;
- }
+ //timer interrupt toggles pin PIN_D19
+ digitalWrite(PIN_D19, toggle);
+ toggle = !toggle;
+ }
- return true;
+ return true;
}
/////////////////////////////////////////////////
@@ -110,10 +110,10 @@ typedef void (*irqCallback) ();
typedef struct
{
- irqCallback irqCallbackFunc;
- uint32_t TimerInterval;
- unsigned long deltaMillis;
- unsigned long previousMillis;
+ irqCallback irqCallbackFunc;
+ uint32_t TimerInterval;
+ unsigned long deltaMillis;
+ unsigned long previousMillis;
} ISRTimerData;
// In NRF52, avoid doing something fancy in ISR, for example Serial.print()
@@ -130,16 +130,16 @@ volatile unsigned long previousMillis [NUMBER_ISR_TIMERS] = { 0, 0, 0, 0, 0, 0,
// You can assign any interval for any timer here, in milliseconds
uint32_t TimerInterval[NUMBER_ISR_TIMERS] =
{
- 5000L, 10000L, 15000L, 20000L, 25000L, 30000L, 35000L, 40000L,
- 45000L, 50000L, 55000L, 60000L, 65000L, 70000L, 75000L, 80000L
+ 5000L, 10000L, 15000L, 20000L, 25000L, 30000L, 35000L, 40000L,
+ 45000L, 50000L, 55000L, 60000L, 65000L, 70000L, 75000L, 80000L
};
void doingSomething(int index)
{
- unsigned long currentMillis = millis();
+ unsigned long currentMillis = millis();
- deltaMillis[index] = currentMillis - previousMillis[index];
- previousMillis[index] = currentMillis;
+ deltaMillis[index] = currentMillis - previousMillis[index];
+ previousMillis[index] = currentMillis;
}
#endif
@@ -150,123 +150,123 @@ void doingSomething(int index)
void doingSomething0()
{
- doingSomething(0);
+ doingSomething(0);
}
void doingSomething1()
{
- doingSomething(1);
+ doingSomething(1);
}
void doingSomething2()
{
- doingSomething(2);
+ doingSomething(2);
}
void doingSomething3()
{
- doingSomething(3);
+ doingSomething(3);
}
void doingSomething4()
{
- doingSomething(4);
+ doingSomething(4);
}
void doingSomething5()
{
- doingSomething(5);
+ doingSomething(5);
}
void doingSomething6()
{
- doingSomething(6);
+ doingSomething(6);
}
void doingSomething7()
{
- doingSomething(7);
+ doingSomething(7);
}
void doingSomething8()
{
- doingSomething(8);
+ doingSomething(8);
}
void doingSomething9()
{
- doingSomething(9);
+ doingSomething(9);
}
void doingSomething10()
{
- doingSomething(10);
+ doingSomething(10);
}
void doingSomething11()
{
- doingSomething(11);
+ doingSomething(11);
}
void doingSomething12()
{
- doingSomething(12);
+ doingSomething(12);
}
void doingSomething13()
{
- doingSomething(13);
+ doingSomething(13);
}
void doingSomething14()
{
- doingSomething(14);
+ doingSomething(14);
}
void doingSomething15()
{
- doingSomething(15);
+ doingSomething(15);
}
#if USE_COMPLEX_STRUCT
ISRTimerData curISRTimerData[NUMBER_ISR_TIMERS] =
{
- //irqCallbackFunc, TimerInterval, deltaMillis, previousMillis
- { doingSomething0, 5000L, 0, 0 },
- { doingSomething1, 10000L, 0, 0 },
- { doingSomething2, 15000L, 0, 0 },
- { doingSomething3, 20000L, 0, 0 },
- { doingSomething4, 25000L, 0, 0 },
- { doingSomething5, 30000L, 0, 0 },
- { doingSomething6, 35000L, 0, 0 },
- { doingSomething7, 40000L, 0, 0 },
- { doingSomething8, 45000L, 0, 0 },
- { doingSomething9, 50000L, 0, 0 },
- { doingSomething10, 55000L, 0, 0 },
- { doingSomething11, 60000L, 0, 0 },
- { doingSomething12, 65000L, 0, 0 },
- { doingSomething13, 70000L, 0, 0 },
- { doingSomething14, 75000L, 0, 0 },
- { doingSomething15, 80000L, 0, 0 }
+ //irqCallbackFunc, TimerInterval, deltaMillis, previousMillis
+ { doingSomething0, 5000L, 0, 0 },
+ { doingSomething1, 10000L, 0, 0 },
+ { doingSomething2, 15000L, 0, 0 },
+ { doingSomething3, 20000L, 0, 0 },
+ { doingSomething4, 25000L, 0, 0 },
+ { doingSomething5, 30000L, 0, 0 },
+ { doingSomething6, 35000L, 0, 0 },
+ { doingSomething7, 40000L, 0, 0 },
+ { doingSomething8, 45000L, 0, 0 },
+ { doingSomething9, 50000L, 0, 0 },
+ { doingSomething10, 55000L, 0, 0 },
+ { doingSomething11, 60000L, 0, 0 },
+ { doingSomething12, 65000L, 0, 0 },
+ { doingSomething13, 70000L, 0, 0 },
+ { doingSomething14, 75000L, 0, 0 },
+ { doingSomething15, 80000L, 0, 0 }
};
void doingSomething(int index)
{
- unsigned long currentMillis = millis();
+ unsigned long currentMillis = millis();
- curISRTimerData[index].deltaMillis = currentMillis - curISRTimerData[index].previousMillis;
- curISRTimerData[index].previousMillis = currentMillis;
+ curISRTimerData[index].deltaMillis = currentMillis - curISRTimerData[index].previousMillis;
+ curISRTimerData[index].previousMillis = currentMillis;
}
#else
irqCallback irqCallbackFunc[NUMBER_ISR_TIMERS] =
{
- doingSomething0, doingSomething1, doingSomething2, doingSomething3,
- doingSomething4, doingSomething5, doingSomething6, doingSomething7,
- doingSomething8, doingSomething9, doingSomething10, doingSomething11,
- doingSomething12, doingSomething13, doingSomething14, doingSomething15
+ doingSomething0, doingSomething1, doingSomething2, doingSomething3,
+ doingSomething4, doingSomething5, doingSomething6, doingSomething7,
+ doingSomething8, doingSomething9, doingSomething10, doingSomething11,
+ doingSomething12, doingSomething13, doingSomething14, doingSomething15
};
#endif
@@ -283,82 +283,96 @@ SimpleTimer simpleTimer;
// 2. Very long "do", "while", "for" loops without predetermined exit time.
void simpleTimerDoingSomething2s()
{
- static unsigned long previousMillis = startMillis;
+ static unsigned long previousMillis = startMillis;
- unsigned long currMillis = millis();
+ unsigned long currMillis = millis();
- Serial.print(F("SimpleTimer : ")); Serial.print(SIMPLE_TIMER_MS / 1000);
- Serial.print(F(", ms : ")); Serial.print(currMillis);
- Serial.print(F(", Dms : ")); Serial.println(currMillis - previousMillis);
+ Serial.print(F("SimpleTimer : "));
+ Serial.print(SIMPLE_TIMER_MS / 1000);
+ Serial.print(F(", ms : "));
+ Serial.print(currMillis);
+ Serial.print(F(", Dms : "));
+ Serial.println(currMillis - previousMillis);
- for (uint16_t i = 0; i < NUMBER_ISR_TIMERS; i++)
- {
+ for (uint16_t i = 0; i < NUMBER_ISR_TIMERS; i++)
+ {
#if USE_COMPLEX_STRUCT
- Serial.print(F("Timer : ")); Serial.print(i);
- Serial.print(F(", programmed : ")); Serial.print(curISRTimerData[i].TimerInterval);
- Serial.print(F(", actual : ")); Serial.println(curISRTimerData[i].deltaMillis);
+ Serial.print(F("Timer : "));
+ Serial.print(i);
+ Serial.print(F(", programmed : "));
+ Serial.print(curISRTimerData[i].TimerInterval);
+ Serial.print(F(", actual : "));
+ Serial.println(curISRTimerData[i].deltaMillis);
#else
- Serial.print(F("Timer : ")); Serial.print(i);
- Serial.print(F(", programmed : ")); Serial.print(TimerInterval[i]);
- Serial.print(F(", actual : ")); Serial.println(deltaMillis[i]);
+ Serial.print(F("Timer : "));
+ Serial.print(i);
+ Serial.print(F(", programmed : "));
+ Serial.print(TimerInterval[i]);
+ Serial.print(F(", actual : "));
+ Serial.println(deltaMillis[i]);
#endif
- }
+ }
- previousMillis = currMillis;
+ previousMillis = currMillis;
}
void setup()
{
- pinMode(LED_BUILTIN, OUTPUT);
+ pinMode(PIN_D19, OUTPUT);
+
+ Serial.begin(115200);
- Serial.begin(115200);
- while (!Serial);
+ while (!Serial && millis() < 5000);
delay(2000);
- Serial.print(F("\nStarting ISR_16_Timers_Array_Complex on ")); Serial.println(ARDUINO_BOARD);
- Serial.println(ESP32_C3_TIMER_INTERRUPT_VERSION);
- Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz"));
-
- // Interval in microsecs
- if (ITimer.attachInterruptInterval(HW_TIMER_INTERVAL_US, TimerHandler))
- {
- startMillis = millis();
- Serial.print(F("Starting ITimer OK, millis() = ")); Serial.println(startMillis);
- }
- else
- Serial.println(F("Can't set ITimer. Select another freq. or timer"));
-
- startMillis = millis();
-
- // Just to demonstrate, don't use too many ISR Timers if not absolutely necessary
- // You can use up to 16 timer for each ISR_Timer
- for (uint16_t i = 0; i < NUMBER_ISR_TIMERS; i++)
- {
+ Serial.print(F("\nStarting ISR_16_Timers_Array_Complex on "));
+ Serial.println(ARDUINO_BOARD);
+ Serial.println(ESP32_C3_TIMER_INTERRUPT_VERSION);
+ Serial.print(F("CPU Frequency = "));
+ Serial.print(F_CPU / 1000000);
+ Serial.println(F(" MHz"));
+
+ // Interval in microsecs
+ if (ITimer.attachInterruptInterval(HW_TIMER_INTERVAL_US, TimerHandler))
+ {
+ startMillis = millis();
+ Serial.print(F("Starting ITimer OK, millis() = "));
+ Serial.println(startMillis);
+ }
+ else
+ Serial.println(F("Can't set ITimer. Select another freq. or timer"));
+
+ startMillis = millis();
+
+ // Just to demonstrate, don't use too many ISR Timers if not absolutely necessary
+ // You can use up to 16 timer for each ISR_Timer
+ for (uint16_t i = 0; i < NUMBER_ISR_TIMERS; i++)
+ {
#if USE_COMPLEX_STRUCT
- curISRTimerData[i].previousMillis = startMillis;
- ISR_Timer.setInterval(curISRTimerData[i].TimerInterval, curISRTimerData[i].irqCallbackFunc);
+ curISRTimerData[i].previousMillis = startMillis;
+ ISR_Timer.setInterval(curISRTimerData[i].TimerInterval, curISRTimerData[i].irqCallbackFunc);
#else
- previousMillis[i] = millis();
- ISR_Timer.setInterval(TimerInterval[i], irqCallbackFunc[i]);
+ previousMillis[i] = millis();
+ ISR_Timer.setInterval(TimerInterval[i], irqCallbackFunc[i]);
#endif
- }
+ }
- // You need this timer for non-critical tasks. Avoid abusing ISR if not absolutely necessary.
- simpleTimer.setInterval(SIMPLE_TIMER_MS, simpleTimerDoingSomething2s);
+ // You need this timer for non-critical tasks. Avoid abusing ISR if not absolutely necessary.
+ simpleTimer.setInterval(SIMPLE_TIMER_MS, simpleTimerDoingSomething2s);
}
#define BLOCKING_TIME_MS 10000L
void loop()
{
- // This unadvised blocking task is used to demonstrate the blocking effects onto the execution and accuracy to Software timer
- // You see the time elapse of ISR_Timer still accurate, whereas very unaccurate for Software Timer
- // The time elapse for 2000ms software timer now becomes 3000ms (BLOCKING_TIME_MS)
- // While that of ISR_Timer is still prefect.
- delay(BLOCKING_TIME_MS);
-
- // You need this Software timer for non-critical tasks. Avoid abusing ISR if not absolutely necessary
- // You don't need to and never call ISR_Timer.run() here in the loop(). It's already handled by ISR timer.
- simpleTimer.run();
+ // This unadvised blocking task is used to demonstrate the blocking effects onto the execution and accuracy to Software timer
+ // You see the time elapse of ISR_Timer still accurate, whereas very unaccurate for Software Timer
+ // The time elapse for 2000ms software timer now becomes 3000ms (BLOCKING_TIME_MS)
+ // While that of ISR_Timer is still prefect.
+ delay(BLOCKING_TIME_MS);
+
+ // You need this Software timer for non-critical tasks. Avoid abusing ISR if not absolutely necessary
+ // You don't need to and never call ISR_Timer.run() here in the loop(). It's already handled by ISR timer.
+ simpleTimer.run();
}
diff --git a/examples/RPM_Measure/RPM_Measure.ino b/examples/RPM_Measure/RPM_Measure.ino
index e597f17..657fd5f 100644
--- a/examples/RPM_Measure/RPM_Measure.ino
+++ b/examples/RPM_Measure/RPM_Measure.ino
@@ -47,7 +47,8 @@
#include "ESP32_C3_TimerInterrupt.h"
// Don't use PIN_D1 in core v2.0.0 and v2.0.1. Check https://github.com/espressif/arduino-esp32/issues/5868
-#define PIN_D2 2 // Pin D2 mapped to pin GPIO2/ADC12/TOUCH2/LED_BUILTIN of ESP32
+// Don't use PIN_D2 with ESP32_C3 (crash)
+#define PIN_D19 19 // Pin D19 mapped to pin GPIO9 of ESP32
#define PIN_D3 3 // Pin D3 mapped to pin GPIO3/RX0 of ESP32
#define PIN_D4 4 // Pin D4 mapped to pin GPIO4/ADC10/TOUCH0 of ESP32
@@ -75,76 +76,84 @@ volatile int debounceCounter;
// and you can't use float calculation inside ISR
// Only OK in core v1.0.6-
bool IRAM_ATTR TimerHandler0(void * timerNo)
-{
- if ( !digitalRead(SWPin) && (debounceCounter >= DEBOUNCING_INTERVAL_MS / TIMER0_INTERVAL_MS ) )
- {
- //min time between pulses has passed
- // Using float calculation / vars in core v2.0.0 and core v2.0.1 will cause crash
- // Not using float => using RPM = 100 * real RPM
- RPM = ( 6000000 / ( rotationTime * TIMER0_INTERVAL_MS ) );
-
- avgRPM = ( 2 * avgRPM + RPM) / 3;
-
- rotationTime = 0;
- debounceCounter = 0;
- }
- else
- {
- debounceCounter++;
- }
-
- //if (rotationTime >= 5000)
- if (rotationTime >= 1000)
- {
- // If idle, set RPM to 0, don't increase rotationTime
- RPM = 0;
-
- avgRPM = ( avgRPM + 3 * RPM) / 4;
-
- rotationTime = 0;
- }
- else
- {
- rotationTime++;
- }
-
- return true;
+{
+ if ( !digitalRead(SWPin) && (debounceCounter >= DEBOUNCING_INTERVAL_MS / TIMER0_INTERVAL_MS ) )
+ {
+ //min time between pulses has passed
+ // Using float calculation / vars in core v2.0.0 and core v2.0.1 will cause crash
+ // Not using float => using RPM = 100 * real RPM
+ RPM = ( 6000000 / ( rotationTime * TIMER0_INTERVAL_MS ) );
+
+ avgRPM = ( 2 * avgRPM + RPM) / 3;
+
+ rotationTime = 0;
+ debounceCounter = 0;
+ }
+ else
+ {
+ debounceCounter++;
+ }
+
+ //if (rotationTime >= 5000)
+ if (rotationTime >= 1000)
+ {
+ // If idle, set RPM to 0, don't increase rotationTime
+ RPM = 0;
+
+ avgRPM = ( avgRPM + 3 * RPM) / 4;
+
+ rotationTime = 0;
+ }
+ else
+ {
+ rotationTime++;
+ }
+
+ return true;
}
void setup()
{
- pinMode(SWPin, INPUT_PULLUP);
-
- Serial.begin(115200);
- while (!Serial);
-
- delay(100);
-
- Serial.print(F("\nStarting RPM_Measure on ")); Serial.println(ARDUINO_BOARD);
- Serial.println(ESP32_C3_TIMER_INTERRUPT_VERSION);
- Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz"));
-
- // Using ESP32 => 80 / 160 / 240MHz CPU clock ,
- // For 64-bit timer counter
- // For 16-bit timer prescaler up to 1024
-
- // Interval in microsecs
- if (ITimer0.attachInterruptInterval(TIMER0_INTERVAL_MS * 1000, TimerHandler0))
- {
- Serial.print(F("Starting ITimer0 OK, millis() = ")); Serial.println(millis());
- }
- else
- Serial.println(F("Can't set ITimer0. Select another freq. or timer"));
-
- Serial.flush();
+ pinMode(SWPin, INPUT_PULLUP);
+
+ Serial.begin(115200);
+
+ while (!Serial && millis() < 5000);
+
+ delay(500);
+
+ Serial.print(F("\nStarting RPM_Measure on "));
+ Serial.println(ARDUINO_BOARD);
+ Serial.println(ESP32_C3_TIMER_INTERRUPT_VERSION);
+ Serial.print(F("CPU Frequency = "));
+ Serial.print(F_CPU / 1000000);
+ Serial.println(F(" MHz"));
+
+ // Using ESP32 => 80 / 160 / 240MHz CPU clock ,
+ // For 64-bit timer counter
+ // For 16-bit timer prescaler up to 1024
+
+ // Interval in microsecs
+ if (ITimer0.attachInterruptInterval(TIMER0_INTERVAL_MS * 1000, TimerHandler0))
+ {
+ Serial.print(F("Starting ITimer0 OK, millis() = "));
+ Serial.println(millis());
+ }
+ else
+ Serial.println(F("Can't set ITimer0. Select another freq. or timer"));
+
+ Serial.flush();
}
void loop()
{
- if (avgRPM > 0)
- {
- Serial.print(F("RPM = ")); Serial.print((float) RPM / 100.f); Serial.print(F(", avgRPM = ")); Serial.println((float) avgRPM / 100.f);
- }
-
- delay(1000);
+ if (avgRPM > 0)
+ {
+ Serial.print(F("RPM = "));
+ Serial.print((float) RPM / 100.f);
+ Serial.print(F(", avgRPM = "));
+ Serial.println((float) avgRPM / 100.f);
+ }
+
+ delay(1000);
}
diff --git a/examples/SwitchDebounce/SwitchDebounce.ino b/examples/SwitchDebounce/SwitchDebounce.ino
index 387f414..5ec3c31 100644
--- a/examples/SwitchDebounce/SwitchDebounce.ino
+++ b/examples/SwitchDebounce/SwitchDebounce.ino
@@ -45,7 +45,8 @@
#include "ESP32_C3_TimerInterrupt.h"
// Don't use PIN_D1 in core v2.0.0 and v2.0.1. Check https://github.com/espressif/arduino-esp32/issues/5868
-#define PIN_D2 2 // Pin D2 mapped to pin GPIO2/ADC12/TOUCH2/LED_BUILTIN of ESP32
+// Don't use PIN_D2 with ESP32_C3 (crash)
+#define PIN_D19 19 // Pin D19 mapped to pin GPIO9 of ESP32
#define PIN_D4 4 // Pin D4 mapped to pin GPIO4/ADC10/TOUCH0 of ESP32
unsigned int SWPin = PIN_D4;
@@ -68,114 +69,121 @@ volatile bool lastSWLongPressedNoted = true;
void IRAM_ATTR lastSWPressedMS()
{
- lastSWPressedTime = millis();
- lastSWPressedNoted = false;
+ lastSWPressedTime = millis();
+ lastSWPressedNoted = false;
}
void IRAM_ATTR lastSWLongPressedMS()
{
- lastSWLongPressedTime = millis();
- lastSWLongPressedNoted = false;
+ lastSWLongPressedTime = millis();
+ lastSWLongPressedNoted = false;
}
// With core v2.0.0+, you can't use Serial.print/println in ISR or crash.
// and you can't use float calculation inside ISR
// Only OK in core v1.0.6-
bool IRAM_ATTR TimerHandler1(void * timerNo)
-{
- static unsigned int debounceCountSWPressed = 0;
- static unsigned int debounceCountSWReleased = 0;
-
- if ( (!digitalRead(SWPin)) )
- {
- // Start debouncing counting debounceCountSWPressed and clear debounceCountSWReleased
- debounceCountSWReleased = 0;
-
- if (++debounceCountSWPressed >= DEBOUNCING_INTERVAL_MS / TIMER1_INTERVAL_MS)
- {
- // Call and flag SWPressed
- if (!SWPressed)
- {
- SWPressed = true;
- // Do something for SWPressed here in ISR
- // But it's better to use outside software timer to do your job instead of inside ISR
- //Your_Response_To_Press();
- lastSWPressedMS();
- }
-
- if (debounceCountSWPressed >= LONG_PRESS_INTERVAL_MS / TIMER1_INTERVAL_MS)
- {
- // Call and flag SWLongPressed
- if (!SWLongPressed)
- {
- SWLongPressed = true;
- // Do something for SWLongPressed here in ISR
- // But it's better to use outside software timer to do your job instead of inside ISR
- //Your_Response_To_Long_Press();
- lastSWLongPressedMS();
- }
- }
- }
- }
- else
- {
- // Start debouncing counting debounceCountSWReleased and clear debounceCountSWPressed
- if ( SWPressed && (++debounceCountSWReleased >= DEBOUNCING_INTERVAL_MS / TIMER1_INTERVAL_MS))
- {
- SWPressed = false;
- SWLongPressed = false;
-
- // Do something for !SWPressed here in ISR
- // But it's better to use outside software timer to do your job instead of inside ISR
- //Your_Response_To_Release();
-
- // Call and flag SWPressed
- debounceCountSWPressed = 0;
- }
- }
-
- return true;
+{
+ static unsigned int debounceCountSWPressed = 0;
+ static unsigned int debounceCountSWReleased = 0;
+
+ if ( (!digitalRead(SWPin)) )
+ {
+ // Start debouncing counting debounceCountSWPressed and clear debounceCountSWReleased
+ debounceCountSWReleased = 0;
+
+ if (++debounceCountSWPressed >= DEBOUNCING_INTERVAL_MS / TIMER1_INTERVAL_MS)
+ {
+ // Call and flag SWPressed
+ if (!SWPressed)
+ {
+ SWPressed = true;
+ // Do something for SWPressed here in ISR
+ // But it's better to use outside software timer to do your job instead of inside ISR
+ //Your_Response_To_Press();
+ lastSWPressedMS();
+ }
+
+ if (debounceCountSWPressed >= LONG_PRESS_INTERVAL_MS / TIMER1_INTERVAL_MS)
+ {
+ // Call and flag SWLongPressed
+ if (!SWLongPressed)
+ {
+ SWLongPressed = true;
+ // Do something for SWLongPressed here in ISR
+ // But it's better to use outside software timer to do your job instead of inside ISR
+ //Your_Response_To_Long_Press();
+ lastSWLongPressedMS();
+ }
+ }
+ }
+ }
+ else
+ {
+ // Start debouncing counting debounceCountSWReleased and clear debounceCountSWPressed
+ if ( SWPressed && (++debounceCountSWReleased >= DEBOUNCING_INTERVAL_MS / TIMER1_INTERVAL_MS))
+ {
+ SWPressed = false;
+ SWLongPressed = false;
+
+ // Do something for !SWPressed here in ISR
+ // But it's better to use outside software timer to do your job instead of inside ISR
+ //Your_Response_To_Release();
+
+ // Call and flag SWPressed
+ debounceCountSWPressed = 0;
+ }
+ }
+
+ return true;
}
void setup()
{
- pinMode(SWPin, INPUT_PULLUP);
-
- Serial.begin(115200);
- while (!Serial);
-
- delay(100);
-
- Serial.print(F("\nStarting SwitchDebounce on ")); Serial.println(ARDUINO_BOARD);
- Serial.println(ESP32_C3_TIMER_INTERRUPT_VERSION);
- Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz"));
-
- // Using ESP32 => 80 / 160 / 240MHz CPU clock ,
- // For 64-bit timer counter
- // For 16-bit timer prescaler up to 1024
-
- // Interval in microsecs
- if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS * 1000, TimerHandler1))
- {
- Serial.print(F("Starting ITimer1 OK, millis() = ")); Serial.println(millis());
- }
- else
- Serial.println(F("Can't set ITimer1. Select another freq. or timer"));
+ pinMode(SWPin, INPUT_PULLUP);
+
+ Serial.begin(115200);
+
+ while (!Serial && millis() < 5000);
+
+ delay(500);
+
+ Serial.print(F("\nStarting SwitchDebounce on "));
+ Serial.println(ARDUINO_BOARD);
+ Serial.println(ESP32_C3_TIMER_INTERRUPT_VERSION);
+ Serial.print(F("CPU Frequency = "));
+ Serial.print(F_CPU / 1000000);
+ Serial.println(F(" MHz"));
+
+ // Using ESP32 => 80 / 160 / 240MHz CPU clock ,
+ // For 64-bit timer counter
+ // For 16-bit timer prescaler up to 1024
+
+ // Interval in microsecs
+ if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS * 1000, TimerHandler1))
+ {
+ Serial.print(F("Starting ITimer1 OK, millis() = "));
+ Serial.println(millis());
+ }
+ else
+ Serial.println(F("Can't set ITimer1. Select another freq. or timer"));
}
void loop()
{
- if (!lastSWPressedNoted)
- {
- lastSWPressedNoted = true;
- Serial.print(F("lastSWPressed @ millis() = ")); Serial.println(lastSWPressedTime);
- }
-
- if (!lastSWLongPressedNoted)
- {
- lastSWLongPressedNoted = true;
- Serial.print(F("lastSWLongPressed @ millis() = ")); Serial.println(lastSWLongPressedTime);
- }
-
- delay(500);
+ if (!lastSWPressedNoted)
+ {
+ lastSWPressedNoted = true;
+ Serial.print(F("lastSWPressed @ millis() = "));
+ Serial.println(lastSWPressedTime);
+ }
+
+ if (!lastSWLongPressedNoted)
+ {
+ lastSWLongPressedNoted = true;
+ Serial.print(F("lastSWLongPressed @ millis() = "));
+ Serial.println(lastSWLongPressedTime);
+ }
+
+ delay(500);
}
diff --git a/examples/TimerInterruptTest/TimerInterruptTest.ino b/examples/TimerInterruptTest/TimerInterruptTest.ino
index a492163..912ac86 100644
--- a/examples/TimerInterruptTest/TimerInterruptTest.ino
+++ b/examples/TimerInterruptTest/TimerInterruptTest.ino
@@ -46,37 +46,34 @@
// Can be included as many times as necessary, without `Multiple Definitions` Linker Error
#include "ESP32_C3_TimerInterrupt.h"
-#ifndef LED_BUILTIN
- #define LED_BUILTIN 2 // Pin D2 mapped to pin GPIO2/ADC12 of ESP32, control on-board LED
-#endif
-
// Don't use PIN_D1 in core v2.0.0 and v2.0.1. Check https://github.com/espressif/arduino-esp32/issues/5868
-#define PIN_D2 2 // Pin D2 mapped to pin GPIO2/ADC12/TOUCH2/LED_BUILTIN of ESP32
+// Don't use PIN_D2 with ESP32_C3 (crash)
+#define PIN_D19 19 // Pin D19 mapped to pin GPIO9 of ESP32
#define PIN_D3 3 // Pin D3 mapped to pin GPIO3/RX0 of ESP32
// With core v2.0.0+, you can't use Serial.print/println in ISR or crash.
// and you can't use float calculation inside ISR
// Only OK in core v1.0.6-
bool IRAM_ATTR TimerHandler0(void * timerNo)
-{
- static bool toggle0 = false;
+{
+ static bool toggle0 = false;
- //timer interrupt toggles pin LED_BUILTIN
- digitalWrite(LED_BUILTIN, toggle0);
- toggle0 = !toggle0;
+ //timer interrupt toggles pin PIN_D19
+ digitalWrite(PIN_D19, toggle0);
+ toggle0 = !toggle0;
- return true;
+ return true;
}
bool IRAM_ATTR TimerHandler1(void * timerNo)
-{
- static bool toggle1 = false;
+{
+ static bool toggle1 = false;
- //timer interrupt toggles outputPin
- digitalWrite(PIN_D3, toggle1);
- toggle1 = !toggle1;
+ //timer interrupt toggles outputPin
+ digitalWrite(PIN_D3, toggle1);
+ toggle1 = !toggle1;
- return true;
+ return true;
}
#define TIMER0_INTERVAL_MS 1000
@@ -91,81 +88,92 @@ ESP32Timer ITimer1(1);
void setup()
{
- pinMode(LED_BUILTIN, OUTPUT);
- pinMode(PIN_D3, OUTPUT);
-
- Serial.begin(115200);
- while (!Serial);
-
- delay(100);
-
- Serial.print(F("\nStarting TimerInterruptTest on ")); Serial.println(ARDUINO_BOARD);
- Serial.println(ESP32_C3_TIMER_INTERRUPT_VERSION);
- Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz"));
-
- // Using ESP32 => 80 / 160 / 240MHz CPU clock ,
- // For 64-bit timer counter
- // For 16-bit timer prescaler up to 1024
-
- // Interval in microsecs
- if (ITimer0.attachInterruptInterval(TIMER0_INTERVAL_MS * 1000, TimerHandler0))
- {
- Serial.print(F("Starting ITimer0 OK, millis() = ")); Serial.println(millis());
- }
- else
- Serial.println(F("Can't set ITimer0. Select another freq. or timer"));
-
- // Interval in microsecs
- if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS * 1000, TimerHandler1))
- {
- Serial.print(F("Starting ITimer1 OK, millis() = ")); Serial.println(millis());
- }
- else
- Serial.println(F("Can't set ITimer1. Select another freq. or timer"));
-
- Serial.flush();
+ pinMode(PIN_D19, OUTPUT);
+ pinMode(PIN_D3, OUTPUT);
+
+ Serial.begin(115200);
+
+ while (!Serial && millis() < 5000);
+
+ delay(500);
+
+ Serial.print(F("\nStarting TimerInterruptTest on "));
+ Serial.println(ARDUINO_BOARD);
+ Serial.println(ESP32_C3_TIMER_INTERRUPT_VERSION);
+ Serial.print(F("CPU Frequency = "));
+ Serial.print(F_CPU / 1000000);
+ Serial.println(F(" MHz"));
+
+ // Using ESP32 => 80 / 160 / 240MHz CPU clock ,
+ // For 64-bit timer counter
+ // For 16-bit timer prescaler up to 1024
+
+ // Interval in microsecs
+ if (ITimer0.attachInterruptInterval(TIMER0_INTERVAL_MS * 1000, TimerHandler0))
+ {
+ Serial.print(F("Starting ITimer0 OK, millis() = "));
+ Serial.println(millis());
+ }
+ else
+ Serial.println(F("Can't set ITimer0. Select another freq. or timer"));
+
+ // Interval in microsecs
+ if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS * 1000, TimerHandler1))
+ {
+ Serial.print(F("Starting ITimer1 OK, millis() = "));
+ Serial.println(millis());
+ }
+ else
+ Serial.println(F("Can't set ITimer1. Select another freq. or timer"));
+
+ Serial.flush();
}
void loop()
{
- static unsigned long lastTimer0 = 0;
- static unsigned long lastTimer1 = 0;
-
- static bool timer0Stopped = false;
- static bool timer1Stopped = false;
-
- if (millis() - lastTimer0 > TIMER0_DURATION_MS)
- {
- lastTimer0 = millis();
-
- if (timer0Stopped)
- {
- Serial.print(F("Start ITimer0, millis() = ")); Serial.println(millis());
- ITimer0.restartTimer();
- }
- else
- {
- Serial.print(F("Stop ITimer0, millis() = ")); Serial.println(millis());
- ITimer0.stopTimer();
- }
- timer0Stopped = !timer0Stopped;
- }
-
- if (millis() - lastTimer1 > TIMER1_DURATION_MS)
- {
- lastTimer1 = millis();
-
- if (timer1Stopped)
- {
- Serial.print(F("Start ITimer1, millis() = ")); Serial.println(millis());
- ITimer1.restartTimer();
- }
- else
- {
- Serial.print(F("Stop ITimer1, millis() = ")); Serial.println(millis());
- ITimer1.stopTimer();
- }
-
- timer1Stopped = !timer1Stopped;
- }
+ static unsigned long lastTimer0 = 0;
+ static unsigned long lastTimer1 = 0;
+
+ static bool timer0Stopped = false;
+ static bool timer1Stopped = false;
+
+ if (millis() - lastTimer0 > TIMER0_DURATION_MS)
+ {
+ lastTimer0 = millis();
+
+ if (timer0Stopped)
+ {
+ Serial.print(F("Start ITimer0, millis() = "));
+ Serial.println(millis());
+ ITimer0.restartTimer();
+ }
+ else
+ {
+ Serial.print(F("Stop ITimer0, millis() = "));
+ Serial.println(millis());
+ ITimer0.stopTimer();
+ }
+
+ timer0Stopped = !timer0Stopped;
+ }
+
+ if (millis() - lastTimer1 > TIMER1_DURATION_MS)
+ {
+ lastTimer1 = millis();
+
+ if (timer1Stopped)
+ {
+ Serial.print(F("Start ITimer1, millis() = "));
+ Serial.println(millis());
+ ITimer1.restartTimer();
+ }
+ else
+ {
+ Serial.print(F("Stop ITimer1, millis() = "));
+ Serial.println(millis());
+ ITimer1.stopTimer();
+ }
+
+ timer1Stopped = !timer1Stopped;
+ }
}
diff --git a/examples/multiFileProject/multiFileProject.ino b/examples/multiFileProject/multiFileProject.ino
index 607ca3d..65cade2 100644
--- a/examples/multiFileProject/multiFileProject.ino
+++ b/examples/multiFileProject/multiFileProject.ino
@@ -28,12 +28,12 @@
// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include "ESP32_C3_ISR_Timer.h"
-void setup()
+void setup()
{
- // put your setup code here, to run once:
+ // put your setup code here, to run once:
}
-void loop()
+void loop()
{
- // put your main code here, to run repeatedly:
+ // put your main code here, to run repeatedly:
}
diff --git a/library.json b/library.json
index 2fa52ae..613e5a9 100644
--- a/library.json
+++ b/library.json
@@ -1,6 +1,6 @@
{
"name": "ESP32_C3_TimerInterrupt",
- "version": "1.7.0",
+ "version": "1.8.0",
"keywords": "timing, device, control, timer, interrupt, timer-interrupt, hardware, isr, isr-based, hardware-timer, isr-timer, isr-based-timer, mission-critical, accuracy, precise, non-blocking, esp32, esp32-c3",
"description": "This library enables you to use Interrupt from Hardware Timers on an ESP32-C3-based board. It now supports 16 ISR-based timers, while consuming only 1 Hardware Timer. Timers' interval is very long (ulong millisecs). The most important feature is they're ISR-based timers. Therefore, their executions are not blocked by bad-behaving functions or tasks. This important feature is absolutely necessary for mission-critical tasks. These hardware timers, using interrupt, still work even if other functions are blocking. Moreover, they are much more precise (certainly depending on clock frequency accuracy) than other software timers using millis() or micros(). That's necessary if you need to measure some data requiring better accuracy.",
"authors":
diff --git a/library.properties b/library.properties
index b3ad20c..457dbf3 100644
--- a/library.properties
+++ b/library.properties
@@ -1,5 +1,5 @@
name=ESP32_C3_TimerInterrupt
-version=1.7.0
+version=1.8.0
author=Khoi Hoang
maintainer=Khoi Hoang
sentence=This library enables you to use Interrupt from Hardware Timers on an ESP32-C3-based board
diff --git a/src/ESP32_C3_ISR_Timer-Impl.h b/src/ESP32_C3_ISR_Timer-Impl.h
index 9f458fa..e5b7bd7 100644
--- a/src/ESP32_C3_ISR_Timer-Impl.h
+++ b/src/ESP32_C3_ISR_Timer-Impl.h
@@ -24,7 +24,7 @@
Based on BlynkTimer.h
Author: Volodymyr Shymanskyy
- Version: 1.7.0
+ Version: 1.8.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -32,6 +32,7 @@
1.5.0 K.Hoang 23/01/2022 Avoid deprecated functions. Fix `multiple-definitions` linker error
1.6.0 K Hoang 10/08/2022 Suppress errors and warnings for new ESP32 core
1.7.0 K Hoang 11/08/2022 Suppress warnings and add support for more ESP32_C3 boards
+ 1.8.0 K Hoang 16/11/2022 Fix doubled time for ESP32_C3
*****************************************************************************************************************************/
#pragma once
@@ -46,11 +47,11 @@ ESP32_ISR_Timer::ESP32_ISR_Timer()
{
}
-void ESP32_ISR_Timer::init()
+void ESP32_ISR_Timer::init()
{
unsigned long current_millis = millis(); //elapsed();
- for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++)
+ for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++)
{
memset((void*) &timer[i], 0, sizeof (timer_t));
timer[i].prev_millis = current_millis;
@@ -62,7 +63,7 @@ void ESP32_ISR_Timer::init()
timerMux = portMUX_INITIALIZER_UNLOCKED;
}
-void IRAM_ATTR ESP32_ISR_Timer::run()
+void IRAM_ATTR ESP32_ISR_Timer::run()
{
uint8_t i;
unsigned long current_millis;
@@ -73,42 +74,42 @@ void IRAM_ATTR ESP32_ISR_Timer::run()
// ESP32 is a multi core / multi processing chip. It is mandatory to disable task switches during ISR
portENTER_CRITICAL_ISR(&timerMux);
- for (i = 0; i < MAX_NUMBER_TIMERS; i++)
+ for (i = 0; i < MAX_NUMBER_TIMERS; i++)
{
timer[i].toBeCalled = TIMER_DEFCALL_DONTRUN;
// no callback == no timer, i.e. jump over empty slots
- if (timer[i].callback != NULL)
+ if (timer[i].callback != NULL)
{
// is it time to process this timer ?
// see http://arduino.cc/forum/index.php/topic,124048.msg932592.html#msg932592
- if ((current_millis - timer[i].prev_millis) >= timer[i].delay)
+ if ((current_millis - timer[i].prev_millis) >= timer[i].delay)
{
unsigned long skipTimes = (current_millis - timer[i].prev_millis) / timer[i].delay;
-
+
// update time
timer[i].prev_millis += timer[i].delay * skipTimes;
// check if the timer callback has to be executed
- if (timer[i].enabled)
+ if (timer[i].enabled)
{
// "run forever" timers must always be executed
- if (timer[i].maxNumRuns == TIMER_RUN_FOREVER)
+ if (timer[i].maxNumRuns == TIMER_RUN_FOREVER)
{
timer[i].toBeCalled = TIMER_DEFCALL_RUNONLY;
}
// other timers get executed the specified number of times
- else if (timer[i].numRuns < timer[i].maxNumRuns)
+ else if (timer[i].numRuns < timer[i].maxNumRuns)
{
timer[i].toBeCalled = TIMER_DEFCALL_RUNONLY;
timer[i].numRuns++;
// after the last run, delete the timer
- if (timer[i].numRuns >= timer[i].maxNumRuns)
+ if (timer[i].numRuns >= timer[i].maxNumRuns)
{
timer[i].toBeCalled = TIMER_DEFCALL_RUNANDDEL;
}
@@ -118,7 +119,7 @@ void IRAM_ATTR ESP32_ISR_Timer::run()
}
}
- for (i = 0; i < MAX_NUMBER_TIMERS; i++)
+ for (i = 0; i < MAX_NUMBER_TIMERS; i++)
{
if (timer[i].toBeCalled == TIMER_DEFCALL_DONTRUN)
continue;
@@ -140,18 +141,18 @@ void IRAM_ATTR ESP32_ISR_Timer::run()
// find the first available slot
// return -1 if none found
-int ESP32_ISR_Timer::findFirstFreeSlot()
+int ESP32_ISR_Timer::findFirstFreeSlot()
{
// all slots are used
- if (numTimers >= MAX_NUMBER_TIMERS)
+ if (numTimers >= MAX_NUMBER_TIMERS)
{
return -1;
}
// return the first slot with no callback (i.e. free)
- for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++)
+ for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++)
{
- if (timer[i].callback == NULL)
+ if (timer[i].callback == NULL)
{
return i;
}
@@ -162,22 +163,23 @@ int ESP32_ISR_Timer::findFirstFreeSlot()
}
-int ESP32_ISR_Timer::setupTimer(const unsigned long& d, void* f, void* p, bool h, const unsigned& n)
+int ESP32_ISR_Timer::setupTimer(const unsigned long& d, void* f, void* p, bool h, const unsigned& n)
{
int freeTimer;
- if (numTimers < 0)
+ if (numTimers < 0)
{
init();
}
freeTimer = findFirstFreeSlot();
- if (freeTimer < 0)
+
+ if (freeTimer < 0)
{
return -1;
}
- if (f == NULL)
+ if (f == NULL)
{
return -1;
}
@@ -196,45 +198,45 @@ int ESP32_ISR_Timer::setupTimer(const unsigned long& d, void* f, void* p, bool h
}
-int ESP32_ISR_Timer::setTimer(const unsigned long& d, timer_callback f, const unsigned& n)
+int ESP32_ISR_Timer::setTimer(const unsigned long& d, timer_callback f, const unsigned& n)
{
return setupTimer(d, (void *)f, NULL, false, n);
}
-int ESP32_ISR_Timer::setTimer(const unsigned long& d, timer_callback_p f, void* p, const unsigned& n)
+int ESP32_ISR_Timer::setTimer(const unsigned long& d, timer_callback_p f, void* p, const unsigned& n)
{
return setupTimer(d, (void *)f, p, true, n);
}
-int ESP32_ISR_Timer::setInterval(const unsigned long& d, timer_callback f)
+int ESP32_ISR_Timer::setInterval(const unsigned long& d, timer_callback f)
{
return setupTimer(d, (void *)f, NULL, false, TIMER_RUN_FOREVER);
}
-int ESP32_ISR_Timer::setInterval(const unsigned long& d, timer_callback_p f, void* p)
+int ESP32_ISR_Timer::setInterval(const unsigned long& d, timer_callback_p f, void* p)
{
return setupTimer(d, (void *)f, p, true, TIMER_RUN_FOREVER);
}
-int ESP32_ISR_Timer::setTimeout(const unsigned long& d, timer_callback f)
+int ESP32_ISR_Timer::setTimeout(const unsigned long& d, timer_callback f)
{
return setupTimer(d, (void *)f, NULL, false, TIMER_RUN_ONCE);
}
-int ESP32_ISR_Timer::setTimeout(const unsigned long& d, timer_callback_p f, void* p)
+int ESP32_ISR_Timer::setTimeout(const unsigned long& d, timer_callback_p f, void* p)
{
return setupTimer(d, (void *)f, p, true, TIMER_RUN_ONCE);
}
-bool IRAM_ATTR ESP32_ISR_Timer::changeInterval(const unsigned& numTimer, const unsigned long& d)
+bool IRAM_ATTR ESP32_ISR_Timer::changeInterval(const unsigned& numTimer, const unsigned long& d)
{
- if (numTimer >= MAX_NUMBER_TIMERS)
+ if (numTimer >= MAX_NUMBER_TIMERS)
{
return false;
}
// Updates interval of existing specified timer
- if (timer[numTimer].callback != NULL)
+ if (timer[numTimer].callback != NULL)
{
// ESP32 is a multi core / multi processing chip. It is mandatory to disable task switches during modifying shared vars
portENTER_CRITICAL(&timerMux);
@@ -247,26 +249,26 @@ bool IRAM_ATTR ESP32_ISR_Timer::changeInterval(const unsigned& numTimer, const u
return true;
}
-
+
// false return for non-used numTimer, no callback
return false;
}
-void ESP32_ISR_Timer::deleteTimer(const unsigned& timerId)
+void ESP32_ISR_Timer::deleteTimer(const unsigned& timerId)
{
- if (timerId >= MAX_NUMBER_TIMERS)
+ if (timerId >= MAX_NUMBER_TIMERS)
{
return;
}
// nothing to delete if no timers are in use
- if (numTimers == 0)
+ if (numTimers == 0)
{
return;
}
// don't decrease the number of timers if the specified slot is already empty
- if (timer[timerId].callback != NULL)
+ if (timer[timerId].callback != NULL)
{
// ESP32 is a multi core / multi processing chip. It is mandatory to disable task switches during modifying shared vars
portENTER_CRITICAL(&timerMux);
@@ -284,9 +286,9 @@ void ESP32_ISR_Timer::deleteTimer(const unsigned& timerId)
}
// function contributed by code@rowansimms.com
-void ESP32_ISR_Timer::restartTimer(const unsigned& numTimer)
+void ESP32_ISR_Timer::restartTimer(const unsigned& numTimer)
{
- if (numTimer >= MAX_NUMBER_TIMERS)
+ if (numTimer >= MAX_NUMBER_TIMERS)
{
return;
}
@@ -301,9 +303,9 @@ void ESP32_ISR_Timer::restartTimer(const unsigned& numTimer)
}
-bool ESP32_ISR_Timer::isEnabled(const unsigned& numTimer)
+bool ESP32_ISR_Timer::isEnabled(const unsigned& numTimer)
{
- if (numTimer >= MAX_NUMBER_TIMERS)
+ if (numTimer >= MAX_NUMBER_TIMERS)
{
return false;
}
@@ -312,9 +314,9 @@ bool ESP32_ISR_Timer::isEnabled(const unsigned& numTimer)
}
-void ESP32_ISR_Timer::enable(const unsigned& numTimer)
+void ESP32_ISR_Timer::enable(const unsigned& numTimer)
{
- if (numTimer >= MAX_NUMBER_TIMERS)
+ if (numTimer >= MAX_NUMBER_TIMERS)
{
return;
}
@@ -323,9 +325,9 @@ void ESP32_ISR_Timer::enable(const unsigned& numTimer)
}
-void ESP32_ISR_Timer::disable(const unsigned& numTimer)
+void ESP32_ISR_Timer::disable(const unsigned& numTimer)
{
- if (numTimer >= MAX_NUMBER_TIMERS)
+ if (numTimer >= MAX_NUMBER_TIMERS)
{
return;
}
@@ -333,16 +335,16 @@ void ESP32_ISR_Timer::disable(const unsigned& numTimer)
timer[numTimer].enabled = false;
}
-void ESP32_ISR_Timer::enableAll()
+void ESP32_ISR_Timer::enableAll()
{
// Enable all timers with a callback assigned (used)
// ESP32 is a multi core / multi processing chip. It is mandatory to disable task switches during modifying shared vars
portENTER_CRITICAL(&timerMux);
- for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++)
+ for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++)
{
- if (timer[i].callback != NULL && timer[i].numRuns == TIMER_RUN_FOREVER)
+ if (timer[i].callback != NULL && timer[i].numRuns == TIMER_RUN_FOREVER)
{
timer[i].enabled = true;
}
@@ -352,16 +354,16 @@ void ESP32_ISR_Timer::enableAll()
portEXIT_CRITICAL(&timerMux);
}
-void ESP32_ISR_Timer::disableAll()
+void ESP32_ISR_Timer::disableAll()
{
// Disable all timers with a callback assigned (used)
// ESP32 is a multi core / multi processing chip. It is mandatory to disable task switches during modifying shared vars
portENTER_CRITICAL(&timerMux);
- for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++)
+ for (uint8_t i = 0; i < MAX_NUMBER_TIMERS; i++)
{
- if (timer[i].callback != NULL && timer[i].numRuns == TIMER_RUN_FOREVER)
+ if (timer[i].callback != NULL && timer[i].numRuns == TIMER_RUN_FOREVER)
{
timer[i].enabled = false;
}
@@ -372,9 +374,9 @@ void ESP32_ISR_Timer::disableAll()
}
-void ESP32_ISR_Timer::toggle(const unsigned& numTimer)
+void ESP32_ISR_Timer::toggle(const unsigned& numTimer)
{
- if (numTimer >= MAX_NUMBER_TIMERS)
+ if (numTimer >= MAX_NUMBER_TIMERS)
{
return;
}
@@ -383,7 +385,7 @@ void ESP32_ISR_Timer::toggle(const unsigned& numTimer)
}
-unsigned ESP32_ISR_Timer::getNumTimers()
+unsigned ESP32_ISR_Timer::getNumTimers()
{
return numTimers;
}
diff --git a/src/ESP32_C3_ISR_Timer.h b/src/ESP32_C3_ISR_Timer.h
index d589803..e53356d 100644
--- a/src/ESP32_C3_ISR_Timer.h
+++ b/src/ESP32_C3_ISR_Timer.h
@@ -24,7 +24,7 @@
Based on BlynkTimer.h
Author: Volodymyr Shymanskyy
- Version: 1.7.0
+ Version: 1.8.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -32,6 +32,7 @@
1.5.0 K.Hoang 23/01/2022 Avoid deprecated functions. Fix `multiple-definitions` linker error
1.6.0 K Hoang 10/08/2022 Suppress errors and warnings for new ESP32 core
1.7.0 K Hoang 11/08/2022 Suppress warnings and add support for more ESP32_C3 boards
+ 1.8.0 K Hoang 16/11/2022 Fix doubled time for ESP32_C3
*****************************************************************************************************************************/
#pragma once
diff --git a/src/ESP32_C3_ISR_Timer.hpp b/src/ESP32_C3_ISR_Timer.hpp
index c129b31..6f509c2 100644
--- a/src/ESP32_C3_ISR_Timer.hpp
+++ b/src/ESP32_C3_ISR_Timer.hpp
@@ -24,7 +24,7 @@
Based on BlynkTimer.h
Author: Volodymyr Shymanskyy
- Version: 1.7.0
+ Version: 1.8.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -32,6 +32,7 @@
1.5.0 K.Hoang 23/01/2022 Avoid deprecated functions. Fix `multiple-definitions` linker error
1.6.0 K Hoang 10/08/2022 Suppress errors and warnings for new ESP32 core
1.7.0 K Hoang 11/08/2022 Suppress warnings and add support for more ESP32_C3 boards
+ 1.8.0 K Hoang 16/11/2022 Fix doubled time for ESP32_C3
*****************************************************************************************************************************/
#pragma once
@@ -45,13 +46,13 @@
#endif
#ifndef ESP32_C3_TIMER_INTERRUPT_VERSION
- #define ESP32_C3_TIMER_INTERRUPT_VERSION "ESP32_C3_TimerInterrupt v1.7.0"
+ #define ESP32_C3_TIMER_INTERRUPT_VERSION "ESP32_C3_TimerInterrupt v1.8.0"
#define ESP32_C3_TIMER_INTERRUPT_VERSION_MAJOR 1
- #define ESP32_C3_TIMER_INTERRUPT_VERSION_MINOR 7
+ #define ESP32_C3_TIMER_INTERRUPT_VERSION_MINOR 8
#define ESP32_C3_TIMER_INTERRUPT_VERSION_PATCH 0
- #define ESP32_C3_TIMER_INTERRUPT_VERSION_INT 1007000
+ #define ESP32_C3_TIMER_INTERRUPT_VERSION_INT 1008000
#endif
#include "TimerInterrupt_Generic_Debug.h"
diff --git a/src/ESP32_C3_TimerInterrupt.h b/src/ESP32_C3_TimerInterrupt.h
index 5a7ddac..b4a4c9b 100644
--- a/src/ESP32_C3_TimerInterrupt.h
+++ b/src/ESP32_C3_TimerInterrupt.h
@@ -25,7 +25,7 @@
Based on BlynkTimer.h
Author: Volodymyr Shymanskyy
- Version: 1.7.0
+ Version: 1.8.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -33,6 +33,7 @@
1.5.0 K.Hoang 23/01/2022 Avoid deprecated functions. Fix `multiple-definitions` linker error
1.6.0 K Hoang 10/08/2022 Suppress errors and warnings for new ESP32 core
1.7.0 K Hoang 11/08/2022 Suppress warnings and add support for more ESP32_C3 boards
+ 1.8.0 K Hoang 16/11/2022 Fix doubled time for ESP32_C3
*****************************************************************************************************************************/
#pragma once
@@ -42,19 +43,19 @@
#if !( defined(ARDUINO_ESP32C3_DEV) || defined(ARDUINO_LOLIN_C3_MINI) || defined(ARDUINO_ADAFRUIT_QTPY_ESP32C3) || \
defined(ARDUINO_AirM2M_CORE_ESP32C3) || defined(ARDUINO_XIAO_ESP32C3) )
- #error This code is intended to run on the ESP32-C3 platform! Please check your Tools->Board setting.
+#error This code is intended to run on the ESP32-C3 platform! Please check your Tools->Board setting.
#else
- #define USING_ESP32_C3_TIMER_INTERRUPT true
+#define USING_ESP32_C3_TIMER_INTERRUPT true
#endif
#ifndef ESP32_C3_TIMER_INTERRUPT_VERSION
- #define ESP32_C3_TIMER_INTERRUPT_VERSION "ESP32_C3_TimerInterrupt v1.7.0"
-
+ #define ESP32_C3_TIMER_INTERRUPT_VERSION "ESP32_C3_TimerInterrupt v1.8.0"
+
#define ESP32_C3_TIMER_INTERRUPT_VERSION_MAJOR 1
- #define ESP32_C3_TIMER_INTERRUPT_VERSION_MINOR 7
+ #define ESP32_C3_TIMER_INTERRUPT_VERSION_MINOR 8
#define ESP32_C3_TIMER_INTERRUPT_VERSION_PATCH 0
- #define ESP32_C3_TIMER_INTERRUPT_VERSION_INT 1007000
+ #define ESP32_C3_TIMER_INTERRUPT_VERSION_INT 1008000
#endif
#ifndef TIMER_INTERRUPT_DEBUG
@@ -76,89 +77,89 @@
/*
//ESP32 core v1.0.6, hw_timer_t defined in esp32/tools/sdk/include/driver/driver/timer.h:
- #define TIMER_BASE_CLK (APB_CLK_FREQ) //Frequency of the clock on the input of the timer groups
+ #define TIMER_BASE_CLK (APB_CLK_FREQ) //Frequency of the clock on the input of the timer groups
- //@brief Selects a Timer-Group out of 2 available groups
-
-typedef enum
-{
+ //@brief Selects a Timer-Group out of 2 available groups
+
+ typedef enum
+ {
TIMER_GROUP_0 = 0, // Hw timer group 0
TIMER_GROUP_1 = 1, // Hw timer group 1
TIMER_GROUP_MAX,
-} timer_group_t;
+ } timer_group_t;
- //@brief Select a hardware timer from timer groups
-
-typedef enum
-{
+ //@brief Select a hardware timer from timer groups
+
+ typedef enum
+ {
TIMER_0 = 0, // Select timer0 of GROUPx
TIMER_1 = 1, // Select timer1 of GROUPx
TIMER_MAX,
-} timer_idx_t;
+ } timer_idx_t;
- //@brief Decides the direction of counter
-
-typedef enum
-{
+ //@brief Decides the direction of counter
+
+ typedef enum
+ {
TIMER_COUNT_DOWN = 0, //Descending Count from cnt.high|cnt.low
TIMER_COUNT_UP = 1, //Ascending Count from Zero
TIMER_COUNT_MAX
-} timer_count_dir_t;
+ } timer_count_dir_t;
- //@brief Decides whether timer is on or paused
-
-typedef enum
-{
+ //@brief Decides whether timer is on or paused
+
+ typedef enum
+ {
TIMER_PAUSE = 0, //Pause timer counter
TIMER_START = 1, //Start timer counter
-} timer_start_t;
+ } timer_start_t;
- //@brief Decides whether to enable alarm mode
-
-typedef enum
-{
+ //@brief Decides whether to enable alarm mode
+
+ typedef enum
+ {
TIMER_ALARM_DIS = 0, //Disable timer alarm
TIMER_ALARM_EN = 1, //Enable timer alarm
TIMER_ALARM_MAX
-} timer_alarm_t;
+ } timer_alarm_t;
- //@brief Select interrupt type if running in alarm mode.
-
-typedef enum
-{
+ //@brief Select interrupt type if running in alarm mode.
+
+ typedef enum
+ {
TIMER_INTR_LEVEL = 0, //Interrupt mode: level mode
//TIMER_INTR_EDGE = 1, //Interrupt mode: edge mode, Not supported Now
TIMER_INTR_MAX
-} timer_intr_mode_t;
+ } timer_intr_mode_t;
- //@brief Select if Alarm needs to be loaded by software or automatically reload by hardware.
-
-typedef enum
-{
+ //@brief Select if Alarm needs to be loaded by software or automatically reload by hardware.
+
+ typedef enum
+ {
TIMER_AUTORELOAD_DIS = 0, //Disable auto-reload: hardware will not load counter value after an alarm event
TIMER_AUTORELOAD_EN = 1, //Enable auto-reload: hardware will load counter value after an alarm event
TIMER_AUTORELOAD_MAX,
-} timer_autoreload_t;
+ } timer_autoreload_t;
- //@brief Data structure with timer's configuration settings
-
-typedef struct
-{
- bool alarm_en; //Timer alarm enable
- bool counter_en; //Counter enable
- timer_intr_mode_t intr_type; //Interrupt mode
- timer_count_dir_t counter_dir; //Counter direction
- bool auto_reload; //Timer auto-reload
- uint32_t divider; //Counter clock divider. The divider's range is from from 2 to 65536.
-} timer_config_t;
+ //@brief Data structure with timer's configuration settings
+
+ typedef struct
+ {
+ bool alarm_en; //Timer alarm enable
+ bool counter_en; //Counter enable
+ timer_intr_mode_t intr_type; //Interrupt mode
+ timer_count_dir_t counter_dir; //Counter direction
+ bool auto_reload; //Timer auto-reload
+ uint32_t divider; //Counter clock divider. The divider's range is from from 2 to 65536.
+ } timer_config_t;
*/
@@ -213,11 +214,14 @@ typedef struct
//timer_autoreload_t auto_reload;
} timer_info_t;
+// Warning: TIMER_SRC_CLK_XTAL only good for ESP32
+// Use TIMER_SRC_CLK_APB for ESP32_C3, ESP32_S2 and ESP32_S3
+
class ESP32TimerInterrupt
{
private:
-
- timer_config_t stdConfig =
+
+ timer_config_t stdConfig =
{
.alarm_en = TIMER_ALARM_EN, //enable timer alarm
.counter_en = TIMER_START, //starts counting counter once timer_init called
@@ -226,39 +230,39 @@ class ESP32TimerInterrupt
.auto_reload = TIMER_AUTORELOAD_EN, //reloads counter automatically
.divider = TIMER_DIVIDER,
#if SOC_TIMER_GROUP_SUPPORT_XTAL
- .clk_src = TIMER_SRC_CLK_XTAL //Use XTAL as source clock
-#endif
+ .clk_src = TIMER_SRC_CLK_APB //Use XTAL as source clock
+#endif
};
timer_idx_t _timerIndex;
timer_group_t _timerGroup;
uint32_t interruptFlag; // either TIMER_INTR_T0 or TIMER_INTR_T1
-
+
uint8_t _timerNo;
esp32_timer_callback _callback; // pointer to the callback function
-
+
float TIM_CLOCK_FREQ; // Timer Clock
float _frequency; // Timer frequency
uint64_t _timerCount; // count to activate timer
-
+
//xQueueHandle s_timer_queue;
public:
ESP32TimerInterrupt(const uint8_t& timerNo)
- {
+ {
_callback = NULL;
-
+
if (timerNo < MAX_ESP32_NUM_TIMERS)
{
_timerNo = timerNo;
-
+
// Always using TIMER_INTR_T0
_timerIndex = (timer_idx_t) ( (uint32_t) 0 );
-
+
// timerNo == 0 => Group 0, timerNo == 1 => Group 1
- _timerGroup = (timer_group_t) ( (uint32_t) timerNo);
+ _timerGroup = (timer_group_t) ( (uint32_t) timerNo);
}
else
{
@@ -271,44 +275,45 @@ class ESP32TimerInterrupt
bool setFrequency(const float& frequency, esp32_timer_callback callback)
{
if (_timerNo < MAX_ESP32_NUM_TIMERS)
- {
+ {
// select timer frequency is 1MHz for better accuracy. We don't use 16-bit prescaler for now.
// Will use later if very low frequency is needed.
_frequency = frequency;
TIM_CLOCK_FREQ = TIMER_BASE_CLK / TIMER_DIVIDER; //1000000;
_timerCount = (uint64_t) TIM_CLOCK_FREQ / frequency;
// count up
-
+
TISR_LOGWARN3(F("ESP32_C3_TimerInterrupt: _timerNo = "), _timerNo, F(", TIM_CLOCK_FREQ = "), TIM_CLOCK_FREQ);
TISR_LOGWARN3(F("TIMER_BASE_CLK = "), TIMER_BASE_CLK, F(", TIMER_DIVIDER = "), TIMER_DIVIDER);
TISR_LOGWARN3(F("_timerIndex = "), _timerIndex, F(", _timerGroup = "), _timerGroup);
- TISR_LOGWARN5(F("Timer freq = "), _frequency, F(", _count = "), (uint32_t) (_timerCount >> 32) , F("-"), (uint32_t) (_timerCount));
+ TISR_LOGWARN5(F("Timer freq = "), _frequency, F(", _count = "), (uint32_t) (_timerCount >> 32), F("-"),
+ (uint32_t) (_timerCount));
TISR_LOGWARN1(F("timer_set_alarm_value = "), TIMER_SCALE / frequency);
timer_init(_timerGroup, _timerIndex, &stdConfig);
-
+
// Counter value to 0 => counting up to alarm value as .counter_dir == TIMER_COUNT_UP
- timer_set_counter_value(_timerGroup, _timerIndex , 0x00000000ULL);
-
+ timer_set_counter_value(_timerGroup, _timerIndex, 0x00000000ULL);
+
timer_set_alarm_value(_timerGroup, _timerIndex, TIMER_SCALE / frequency);
-
+
// enable interrupts for _timerGroup, _timerIndex
timer_enable_intr(_timerGroup, _timerIndex);
-
+
_callback = callback;
-
- // Register the ISR handler
+
+ // Register the ISR handler
// If the intr_alloc_flags value ESP_INTR_FLAG_IRAM is set, the handler function must be declared with IRAM_ATTR attribute
// and can only call functions in IRAM or ROM. It cannot call other timer APIs.
- //timer_isr_register(_timerGroup, _timerIndex, _callback, (void *) (uint32_t) _timerNo, ESP_INTR_FLAG_IRAM, NULL);
+ //timer_isr_register(_timerGroup, _timerIndex, _callback, (void *) (uint32_t) _timerNo, ESP_INTR_FLAG_IRAM, NULL);
timer_isr_callback_add(_timerGroup, _timerIndex, _callback, (void *) (uint32_t) _timerNo, 0);
timer_start(_timerGroup, _timerIndex);
-
+
return true;
}
else
- {
+ {
TISR_LOGERROR(F("Error. Timer must be 0-1"));
return false;
@@ -335,24 +340,24 @@ class ESP32TimerInterrupt
}
void detachInterrupt()
- {
+ {
timer_group_intr_disable(_timerGroup, TIMER_INTR_T0);
}
void disableTimer()
- {
+ {
timer_group_intr_disable(_timerGroup, TIMER_INTR_T0);
}
// Duration (in milliseconds). Duration = 0 or not specified => run indefinitely
void reattachInterrupt()
- {
- timer_group_intr_enable(_timerGroup, TIMER_INTR_T0);
+ {
+ timer_group_intr_enable(_timerGroup, TIMER_INTR_T0);
}
// Duration (in milliseconds). Duration = 0 or not specified => run indefinitely
void enableTimer()
- {
+ {
timer_group_intr_enable(_timerGroup, TIMER_INTR_T0);
}
@@ -365,7 +370,7 @@ class ESP32TimerInterrupt
// Just reconnect clock source, start current count from 0
void restartTimer()
{
- timer_set_counter_value(_timerGroup, _timerIndex , 0x00000000ULL);
+ timer_set_counter_value(_timerGroup, _timerIndex, 0x00000000ULL);
timer_start(_timerGroup, _timerIndex);
}
@@ -373,7 +378,7 @@ class ESP32TimerInterrupt
{
return _timerIndex;
};
-
+
int8_t getTimerGroup() __attribute__((always_inline))
{
return _timerGroup;
diff --git a/src/TimerInterrupt_Generic_Debug.h b/src/TimerInterrupt_Generic_Debug.h
index 0df6ed3..740c9f2 100644
--- a/src/TimerInterrupt_Generic_Debug.h
+++ b/src/TimerInterrupt_Generic_Debug.h
@@ -24,7 +24,7 @@
Based on BlynkTimer.h
Author: Volodymyr Shymanskyy
- Version: 1.7.0
+ Version: 1.8.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -32,6 +32,7 @@
1.5.0 K.Hoang 23/01/2022 Avoid deprecated functions. Fix `multiple-definitions` linker error
1.6.0 K Hoang 10/08/2022 Suppress errors and warnings for new ESP32 core
1.7.0 K Hoang 11/08/2022 Suppress warnings and add support for more ESP32_C3 boards
+ 1.8.0 K Hoang 16/11/2022 Fix doubled time for ESP32_C3
*****************************************************************************************************************************/
#pragma once
diff --git a/utils/astyle_library.conf b/utils/astyle_library.conf
new file mode 100644
index 0000000..8a73bc2
--- /dev/null
+++ b/utils/astyle_library.conf
@@ -0,0 +1,70 @@
+# Code formatting rules for Arduino libraries, modified from for KH libraries:
+#
+# https://github.com/arduino/Arduino/blob/master/build/shared/examples_formatter.conf
+#
+
+# astyle --style=allman -s2 -t2 -C -S -xW -Y -M120 -f -p -xg -H -xb -c --xC120 -xL *.h *.cpp *.ino
+
+--mode=c
+--lineend=linux
+--style=allman
+
+# -r or -R
+#--recursive
+
+# -c => Converts tabs into spaces
+convert-tabs
+
+# -s2 => 2 spaces indentation
+--indent=spaces=2
+
+# -t2 => tab =2 spaces
+#--indent=tab=2
+
+# -C
+--indent-classes
+
+# -S
+--indent-switches
+
+# -xW
+--indent-preproc-block
+
+# -Y => indent classes, switches (and cases), comments starting at column 1
+--indent-col1-comments
+
+# -M120 => maximum of 120 spaces to indent a continuation line
+--max-continuation-indent=120
+
+# -xC120 => max‑code‑length will break a line if the code exceeds # characters
+--max-code-length=120
+
+# -f =>
+--break-blocks
+
+# -p => put a space around operators
+--pad-oper
+
+# -xg => Insert space padding after commas
+--pad-comma
+
+# -H => put a space after if/for/while
+pad-header
+
+# -xb => Break one line headers (e.g. if/for/while)
+--break-one-line-headers
+
+# -c => Converts tabs into spaces
+#--convert-tabs
+
+# if you like one-liners, keep them
+#keep-one-line-statements
+
+# -xV
+--attach-closing-while
+
+#unpad-paren
+
+# -xp
+remove-comment-prefix
+
diff --git a/utils/restyle.sh b/utils/restyle.sh
new file mode 100644
index 0000000..bcd846f
--- /dev/null
+++ b/utils/restyle.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+for dir in . ; do
+ find $dir -type f \( -name "*.c" -o -name "*.h" -o -name "*.cpp" -o -name "*.ino" \) -exec astyle --suffix=none --options=./utils/astyle_library.conf \{\} \;
+done
+