├── .arduino-ci.yaml
├── .github
├── FUNDING.yml
└── workflows
│ ├── arduino-lint.yaml
│ └── arduino_ci.yaml
├── .travis.yml
├── LICENSE
├── README.md
├── contributors.txt
├── examples
├── uTimerLib_setInterval_s_example_led
│ ├── .zero.test.skip
│ └── uTimerLib_setInterval_s_example_led.ino
├── uTimerLib_setInterval_s_example_serial
│ ├── .zero.test.skip
│ └── uTimerLib_setInterval_s_example_serial.ino
├── uTimerLib_setInterval_us_example_led
│ ├── .zero.test.skip
│ └── uTimerLib_setInterval_us_example_led.ino
├── uTimerLib_setInterval_us_example_serial
│ ├── .zero.test.skip
│ └── uTimerLib_setInterval_us_example_serial.ino
├── uTimerLib_setTimeout_s_example_led
│ ├── .zero.test.skip
│ └── uTimerLib_setTimeout_s_example_led.ino
├── uTimerLib_setTimeout_s_example_serial
│ ├── .zero.test.skip
│ └── uTimerLib_setTimeout_s_example_serial.ino
├── uTimerLib_setTimeout_us_example_led
│ ├── .zero.test.skip
│ └── uTimerLib_setTimeout_us_example_led.ino
└── uTimerLib_setTimeout_us_example_serial
│ ├── .zero.test.skip
│ └── uTimerLib_setTimeout_us_example_serial.ino
├── library.properties
└── src
├── hardware
├── uTimerLib.ATTINY.cpp
├── uTimerLib.AVR.cpp
├── uTimerLib.DIGISPARK_AVR.cpp
├── uTimerLib.ESP32.cpp
├── uTimerLib.ESP8266.cpp
├── uTimerLib.SAM.cpp
├── uTimerLib.SAMD21.cpp
├── uTimerLib.SAMD51.cpp
├── uTimerLib.STM32.cpp
└── uTimerLib.UNSUPPORTED.cpp
├── uTimerLib.cpp
└── uTimerLib.h
/.arduino-ci.yaml:
--------------------------------------------------------------------------------
1 | compile:
2 | platforms:
3 | - uno
4 | - due
5 | - zero
6 | - leonardo
7 | - m4
8 | - esp32
9 | #- esp8266
10 | - mega2560
11 | - nano_every
12 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: Naguissa
2 | custom: https://www.paypal.me/foroelectro
3 |
--------------------------------------------------------------------------------
/.github/workflows/arduino-lint.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | name: arduino-lint
3 |
4 | on: [push, pull_request]
5 |
6 | jobs:
7 | lint:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - uses: actions/checkout@v4
11 | # https://github.com/actions/checkout
12 | - uses: arduino/arduino-lint-action@v1
13 | # https://github.com/arduino/arduino-lint-action
14 | with:
15 | library-manager: update
16 | compliance: strict
17 |
--------------------------------------------------------------------------------
/.github/workflows/arduino_ci.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | name: arduino_ci
3 |
4 | on: [push, pull_request]
5 |
6 | jobs:
7 | arduino_ci:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - uses: actions/checkout@v4
11 | # https://github.com/actions/checkout
12 | - uses: Arduino-CI/action@stable-1.x
13 | # https://github.com/marketplace/actions/arduino_ci
14 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: c
2 | sudo: false
3 | cache:
4 | directories:
5 | - ~/arduino_ide
6 | - ~/.arduino15/packages/
7 | git:
8 | depth: false
9 | quiet: true
10 | env:
11 | global:
12 | # You can uncomment this to explicitly choose an (old) version of the Arduino IDE
13 | #- ARDUINO_IDE_VERSION="1.8.7"
14 | before_install:
15 | - source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/install.sh)
16 | install:
17 | # Note that every library should be installed in a seperate command
18 | - arduino --install-boards arduino:sam
19 | #- arduino --install-library "Adafruit SleepyDog Library"
20 | #- arduino --install-library "Adafruit FONA Library"
21 | script:
22 | - build_main_platforms
23 | notifications:
24 | email:
25 | on_success: change
26 | on_failure: change
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
167 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Arduino tiny and cross-device compatible timer library - uTimerLib #
2 |
3 | Master status: [](https://travis-ci.org/Naguissa/uTimerLib)
4 |
5 | ## What is this repository for? ##
6 |
7 | Tiny and cross-device compatible timer-driven timed function calls library.
8 |
9 | Supports Arduino AVR, SAM, STM32, ESP8266, ESP32 and SAMD21 microcontrollers.
10 |
11 |
12 | ## Current status ##
13 |
14 | Currently suported architectures:
15 | - Atmel ATtiny, Experimental - https://github.com/damellis/attiny and https://github.com/SpenceKonde/Disgispark AVRCore (25, 45 and 85)
16 | - DisgiSpark AVR, Experimental - https://github.com/digistump/DigistumpArduino
17 | - Atmel AVR 32U4
18 | - Atmel AVR, general
19 | - STM32 (both Roger Clark and ST cores)
20 | - SAM (Due)
21 | - ESP8266
22 | - ESP32
23 | - SAMD21 (Arduino Zero and Zero MKR; experimental support)
24 | - SAMD51 (Adafruit Feather M4, Adafruit Metro M4; work in progress, not functional -need for a SAMD51 board...)
25 |
26 | ## Device timer usage ##
27 |
28 | Depending on wich architecture this library uses one or another device timer. Take in mind this because can caause conflicts with other libraries:
29 | - Atmel ATtiny: Timer1 (2nd timer).
30 | - DisgiSpark AVR: Timer0 (1st timer).
31 | - Atmel AVR 32U4: Timer3 (4rd timer).
32 | - Atmel AVR other: Timer2 (3rd timer).
33 | - STM32: Timer3 (3rd timer).
34 | - SAM (Due): TC3 (Timer1, channel 0).
35 | - ESP8266: OS Timer, one slot of seven available (Software timer provided by Arduino because ESP8266 has only two hardware timers and one is needed by it normal operation).
36 | - ESP32: OS Hardware Timer.
37 | - SAMD21: Timer 4, CC0 (TC3).
38 | - SAMD51: Timer 2 (TC1), 16 bits mode.
39 |
40 | *Note*: On ESP8266 this library uses "ticker" to manage timer, so it's maximum resolution is miliseconds. On "_us" functions times will be rounded to miliseconds.
41 |
42 | ## Usage ##
43 |
44 | This library defines a global variable when included called "TimerLib".
45 |
46 | You have these methods:
47 | - *TimerLib.setInterval_us(callback_function, microseconds);* : callback_function will be called each microseconds.
48 | - *TimerLib.setInterval_s(callback_function, seconds);* : callback_function will be called each seconds.
49 | - *TimerLib.setTimeout_us(callback_function, microseconds);* : callback_function will be called once when microseconds have passed.
50 | - *TimerLib.setTimeout_s(callback_function, seconds);* : callback_function will be called once when seconds have passed.
51 | - *TimerLib.clearTimer();* : will clear any timed function if exists.
52 |
53 | It only manages one function at a time, if you call any setXXX method it will cancel any running timed function and process new one.
54 |
55 | An attached functions broker could be implemented, but then this would not be (micro)TimerLib. Maybe in other project.....
56 |
57 | ## How do I get set up? ##
58 |
59 | You can get it from Arduino libraries directly, searching by uTimerLib.
60 |
61 | For manual installation:
62 |
63 | * Get the ZIP from releases link: https://github.com/Naguissa/uTimerLib/releases
64 | * Rename to uTimerLib.zip
65 | * Install library on Arduino
66 |
67 | ## Documentation and extras ##
68 |
69 | You can find all documentation and extras in this repository: https://github.com/Naguissa/uTimerLib_doc_and_extras
70 |
71 | You can read documentation online here: https://naguissa.github.io/uTimerLib_doc_and_extras/
72 |
73 |
74 |
75 | ## Examples ##
76 |
77 | Included on example folder, available on Arduino IDE.
78 |
79 |
80 | ## Extra ##
81 |
82 | Look in extras folder for datasheets and extra info
83 |
84 |
85 | ## Who do I talk to? ##
86 |
87 | * [Naguissa](https://github.com/Naguissa)
88 | * https://www.foroelectro.net/electronica-digital-microcontroladores-f8/utimerlib-libreria-arduino-para-eventos-temporizad-t191.html
89 | * https://www.naguissa.com
90 |
91 |
92 | ## Contribute ##
93 |
94 | Any code contribution, report or comment are always welcome. Don't hesitate to use GitHub for that.
95 |
96 |
97 | * You can sponsor this project using GitHub's Sponsor button: https://github.com/Naguissa/uTimerLib
98 | * You can make a donation via PayPal: https://paypal.me/foroelectro
99 |
100 |
101 | Thanks for your support.
102 |
103 |
104 | Contributors hall of fame: https://www.foroelectro.net/hall-of-fame-f32/contributors-contribuyentes-t271.html
105 |
--------------------------------------------------------------------------------
/contributors.txt:
--------------------------------------------------------------------------------
1 | Naguissa - https://github.com/Naguissa
2 | svlPanelMaker - https://github.com/svlPanelMaker - SAMD21 timing issue fix
3 | Raf (Raffaele Rialdi) - https://github.com/raffaeler - ESP32 hardware timer (better precission than ticker library)
4 | Daniel Mohr - https://github.com/daniel-mohr - SAMD21 timing issue fix
5 |
--------------------------------------------------------------------------------
/examples/uTimerLib_setInterval_s_example_led/.zero.test.skip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Naguissa/uTimerLib/10c259fabb25de1eab07ca0302af9f782f971291/examples/uTimerLib_setInterval_s_example_led/.zero.test.skip
--------------------------------------------------------------------------------
/examples/uTimerLib_setInterval_s_example_led/uTimerLib_setInterval_s_example_led.ino:
--------------------------------------------------------------------------------
1 | /**
2 | * uTimerLib example
3 | *
4 | * @author Naguissa
5 | * @url https://www.github.com/Naguissa/uTimerLib
6 | * @url https://www.foroelectro.net
7 | */
8 |
9 | #include "Arduino.h"
10 | #include "uTimerLib.h"
11 |
12 | #ifndef LED_BUILTIN
13 | // change to fit your needs
14 | // Use 0 or 1 to use DigiSpark AVR internal LED (depending revision, mine is 1)
15 | #define LED_BUILTIN 13
16 | #endif
17 |
18 | volatile bool status = 0;
19 |
20 | void timed_function() {
21 | status = !status;
22 | }
23 |
24 | void setup() {
25 | pinMode(LED_BUILTIN, OUTPUT);
26 | TimerLib.setInterval_s(timed_function, 2);
27 | }
28 |
29 | void loop() {
30 | digitalWrite(LED_BUILTIN, status);
31 | }
32 |
--------------------------------------------------------------------------------
/examples/uTimerLib_setInterval_s_example_serial/.zero.test.skip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Naguissa/uTimerLib/10c259fabb25de1eab07ca0302af9f782f971291/examples/uTimerLib_setInterval_s_example_serial/.zero.test.skip
--------------------------------------------------------------------------------
/examples/uTimerLib_setInterval_s_example_serial/uTimerLib_setInterval_s_example_serial.ino:
--------------------------------------------------------------------------------
1 | /**
2 | * uTimerLib example
3 | *
4 | * @author Naguissa
5 | * @url https://www.github.com/Naguissa/uTimerLib
6 | * @url https://www.foroelectro.net
7 | */
8 |
9 | #include "Arduino.h"
10 | #include "uTimerLib.h"
11 |
12 | volatile unsigned long int prevMillis = 0;
13 | volatile unsigned long int actMillis = 0;
14 | volatile bool trigger = false;
15 |
16 | void timed_function() {
17 | trigger = true;
18 | }
19 |
20 | void setup() {
21 | Serial.begin(57600);
22 | TimerLib.setInterval_s(timed_function, 2);
23 | prevMillis = millis();
24 | }
25 |
26 | void loop() {
27 | if (trigger) {
28 | trigger = false;
29 | Serial.println(actMillis - prevMillis);
30 | prevMillis = actMillis;
31 | }
32 | actMillis = millis();
33 | }
34 |
--------------------------------------------------------------------------------
/examples/uTimerLib_setInterval_us_example_led/.zero.test.skip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Naguissa/uTimerLib/10c259fabb25de1eab07ca0302af9f782f971291/examples/uTimerLib_setInterval_us_example_led/.zero.test.skip
--------------------------------------------------------------------------------
/examples/uTimerLib_setInterval_us_example_led/uTimerLib_setInterval_us_example_led.ino:
--------------------------------------------------------------------------------
1 | /**
2 | * uTimerLib example
3 | *
4 | * @author Naguissa
5 | * @url https://www.github.com/Naguissa/uTimerLib
6 | * @url https://www.foroelectro.net
7 | */
8 |
9 | #include "Arduino.h"
10 | #include "uTimerLib.h"
11 |
12 | #ifndef LED_BUILTIN
13 | // change to fit your needs
14 | // Use 0 or 1 to use DigiSpark AVR internal LED (depending revision, mine is 1)
15 | #define LED_BUILTIN 13
16 | #endif
17 |
18 | volatile bool status = 0;
19 |
20 | void timed_function() {
21 | status = !status;
22 | }
23 |
24 | void setup() {
25 | pinMode(LED_BUILTIN, OUTPUT);
26 | TimerLib.setInterval_us(timed_function, 1000000);
27 | }
28 |
29 | void loop() {
30 | digitalWrite(LED_BUILTIN, status);
31 | }
32 |
--------------------------------------------------------------------------------
/examples/uTimerLib_setInterval_us_example_serial/.zero.test.skip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Naguissa/uTimerLib/10c259fabb25de1eab07ca0302af9f782f971291/examples/uTimerLib_setInterval_us_example_serial/.zero.test.skip
--------------------------------------------------------------------------------
/examples/uTimerLib_setInterval_us_example_serial/uTimerLib_setInterval_us_example_serial.ino:
--------------------------------------------------------------------------------
1 | /**
2 | * uTimerLib example
3 | *
4 | * @author Naguissa
5 | * @url https://www.github.com/Naguissa/uTimerLib
6 | * @url https://www.foroelectro.net
7 | */
8 |
9 | #include "Arduino.h"
10 | #include "uTimerLib.h"
11 |
12 | volatile unsigned long int prevMillis = 0;
13 | volatile unsigned long int actMillis = 0;
14 | volatile bool trigger = false;
15 |
16 | void timed_function() {
17 | trigger = true;
18 | }
19 |
20 | void setup() {
21 | Serial.begin(57600);
22 | TimerLib.setInterval_us(timed_function, 200000);
23 | prevMillis = millis();
24 | }
25 |
26 | void loop() {
27 | if (trigger) {
28 | trigger = false;
29 | Serial.println(actMillis - prevMillis);
30 | prevMillis = actMillis;
31 | }
32 | actMillis = millis();
33 | }
34 |
--------------------------------------------------------------------------------
/examples/uTimerLib_setTimeout_s_example_led/.zero.test.skip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Naguissa/uTimerLib/10c259fabb25de1eab07ca0302af9f782f971291/examples/uTimerLib_setTimeout_s_example_led/.zero.test.skip
--------------------------------------------------------------------------------
/examples/uTimerLib_setTimeout_s_example_led/uTimerLib_setTimeout_s_example_led.ino:
--------------------------------------------------------------------------------
1 | /**
2 | * uTimerLib example
3 | *
4 | * @author Naguissa
5 | * @url https://www.github.com/Naguissa/uTimerLib
6 | * @url https://www.foroelectro.net
7 | */
8 |
9 | #include "Arduino.h"
10 | #include "uTimerLib.h"
11 |
12 | #ifndef LED_BUILTIN
13 | // change to fit your needs
14 | // Use 0 or 1 to use DigiSpark AVR internal LED (depending revision, mine is 1)
15 | #define LED_BUILTIN 13
16 | #endif
17 |
18 | volatile bool status = 0;
19 |
20 | void timed_function() {
21 | status = !status;
22 | if (status) {
23 | TimerLib.setTimeout_s(timed_function, 2);
24 | }
25 | }
26 |
27 |
28 | void setup() {
29 | pinMode(LED_BUILTIN, OUTPUT);
30 | TimerLib.setTimeout_s(timed_function, 2);
31 | }
32 |
33 |
34 | void loop() {
35 | digitalWrite(LED_BUILTIN, status);
36 | }
37 |
38 |
--------------------------------------------------------------------------------
/examples/uTimerLib_setTimeout_s_example_serial/.zero.test.skip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Naguissa/uTimerLib/10c259fabb25de1eab07ca0302af9f782f971291/examples/uTimerLib_setTimeout_s_example_serial/.zero.test.skip
--------------------------------------------------------------------------------
/examples/uTimerLib_setTimeout_s_example_serial/uTimerLib_setTimeout_s_example_serial.ino:
--------------------------------------------------------------------------------
1 | /**
2 | * uTimerLib example
3 | *
4 | * @author Naguissa
5 | * @url https://www.github.com/Naguissa/uTimerLib
6 | * @url https://www.foroelectro.net
7 | */
8 |
9 | #include "Arduino.h"
10 | #include "uTimerLib.h"
11 |
12 | volatile unsigned long int prevMillis = 0;
13 | volatile unsigned long int actMillis = 0;
14 | volatile bool trigger = false;
15 |
16 | void timed_function() {
17 | trigger = true;
18 | }
19 |
20 | void setup() {
21 | Serial.begin(57600);
22 | TimerLib.setTimeout_s(timed_function, 2);
23 | prevMillis = millis();
24 | }
25 |
26 | void loop() {
27 | if (trigger) {
28 | trigger = false;
29 | Serial.println(actMillis - prevMillis);
30 | prevMillis = actMillis;
31 | }
32 | actMillis = millis();
33 | }
34 |
--------------------------------------------------------------------------------
/examples/uTimerLib_setTimeout_us_example_led/.zero.test.skip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Naguissa/uTimerLib/10c259fabb25de1eab07ca0302af9f782f971291/examples/uTimerLib_setTimeout_us_example_led/.zero.test.skip
--------------------------------------------------------------------------------
/examples/uTimerLib_setTimeout_us_example_led/uTimerLib_setTimeout_us_example_led.ino:
--------------------------------------------------------------------------------
1 | /**
2 | * uTimerLib example
3 | *
4 | * @author Naguissa
5 | * @url https://www.github.com/Naguissa/uTimerLib
6 | * @url https://www.foroelectro.net
7 | */
8 |
9 | #include "Arduino.h"
10 | #include "uTimerLib.h"
11 |
12 | #ifndef LED_BUILTIN
13 | // change to fit your needs
14 | // Use 0 or 1 to use DigiSpark AVR internal LED (depending revision, mine is 1)
15 | #define LED_BUILTIN 13
16 | #endif
17 |
18 | volatile bool status = 0;
19 |
20 | void timed_function() {
21 | status = !status;
22 | if (status) {
23 | TimerLib.setTimeout_us(timed_function, 1000000);
24 | }
25 | }
26 |
27 |
28 | void setup() {
29 | pinMode(LED_BUILTIN, OUTPUT);
30 | TimerLib.setTimeout_us(timed_function, 1000000);
31 | }
32 |
33 |
34 | void loop() {
35 | digitalWrite(LED_BUILTIN, status);
36 | }
37 |
38 |
--------------------------------------------------------------------------------
/examples/uTimerLib_setTimeout_us_example_serial/.zero.test.skip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Naguissa/uTimerLib/10c259fabb25de1eab07ca0302af9f782f971291/examples/uTimerLib_setTimeout_us_example_serial/.zero.test.skip
--------------------------------------------------------------------------------
/examples/uTimerLib_setTimeout_us_example_serial/uTimerLib_setTimeout_us_example_serial.ino:
--------------------------------------------------------------------------------
1 | /**
2 | * uTimerLib example
3 | *
4 | * @author Naguissa
5 | * @url https://www.github.com/Naguissa/uTimerLib
6 | * @url https://www.foroelectro.net
7 | */
8 |
9 | #include "Arduino.h"
10 | #include "uTimerLib.h"
11 |
12 | volatile unsigned long int prevMillis = 0;
13 | volatile unsigned long int actMillis = 0;
14 | volatile bool trigger = false;
15 |
16 | void timed_function() {
17 | trigger = true;
18 | }
19 |
20 | void setup() {
21 | Serial.begin(57600);
22 | TimerLib.setTimeout_us(timed_function, 200000);
23 | prevMillis = millis();
24 | }
25 |
26 | void loop() {
27 | if (trigger) {
28 | trigger = false;
29 | Serial.println(actMillis - prevMillis);
30 | prevMillis = actMillis;
31 | }
32 | actMillis = millis();
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/library.properties:
--------------------------------------------------------------------------------
1 | name=uTimerLib
2 | version=1.7.5
3 | author=Naguissa
4 | maintainer=Naguissa
5 | sentence=Tiny and cross-device compatible timer library
6 | paragraph=Supports Arduino AVR, SAM, STM32, ESP8266, ESP32 and SAMD21 microcontrollers
7 | category=Timing
8 | url=https://github.com/Naguissa/uTimerLib
9 | architectures=*
10 | includes=uTimerLib.h
11 |
12 |
--------------------------------------------------------------------------------
/src/hardware/uTimerLib.ATTINY.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * \class uTimerLib
3 | * \brief Arduino tiny and cross-device compatible timer library.
4 | *
5 | * Timers used by each microcontroller:
6 | * * Atmel ATtiny: Timer1 (2nd timer) - https://github.com/damellis/attiny and https://github.com/SpenceKonde/Disgispark AVRCore (25, 45 and 85)
7 | * * DisgiSpark AVR: Timer0 (1st timer) - https://github.com/digistump/DigistumpArduino
8 | * * Atmel AVR 32U4: Timer3 (4rd timer)
9 | * * Atmel AVR other: Timer2 (3rd timer)
10 | * * STM32: Timer3 (3rd timer)
11 | * * SAM (Due): TC3 (Timer1, channel 0)
12 | * * ESP8266: OS Timer, one slot of seven available (Software timer provided by Arduino because ESP8266 has only two hardware timers and one is needed by it normal operation)
13 | * * ESP32: OS Hardware Timer.
14 | * * SAMD21: Timer 4, CC0 (TC3). See http://ww1.microchip.com/downloads/en/DeviceDoc/40001882A.pdf
15 | * * SAMD51: Timer 2 (TC1), 16 bits mode (See http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
16 | *
17 | * You have public TimerLib variable with following methods:
18 | * * TimerLib.setInterval_us(callback_function, microseconds);* : callback_function will be called each microseconds.
19 | * * TimerLib.setInterval_s(callback_function, seconds);* : callback_function will be called each seconds.
20 | * * TimerLib.setTimeout_us(callback_function, microseconds);* : callback_function will be called once when microseconds have passed.
21 | * * TimerLib.setTimeout_s(callback_function, seconds);* : callback_function will be called once when seconds have passed.
22 | * * TimerLib.clearTimer();* : will clear any timed function if exists.
23 | *
24 | * @file hardware/uTimerLib.ATTINY.cpp
25 | * @copyright Naguissa
26 | * @author Naguissa
27 | * @see https://github.com/Naguissa/uTimerLib
28 | * @see https://www.foroelectro.net/librerias-arduino-ide-f29/utimerlib-libreria-arduino-para-eventos-temporizad-t191.html
29 | * @see naguissa@foroelectro.net
30 | * @version 1.7.5
31 | */
32 |
33 | #if (defined(ARDUINO_ARCH_AVR) && (defined(ARDUINO_attiny) || defined(ARDUINO_AVR_ATTINYX4) || defined(ARDUINO_AVR_ATTINYX5) || defined(ARDUINO_AVR_ATTINYX7) || defined(ARDUINO_AVR_ATTINYX8) || defined(ARDUINO_AVR_ATTINYX61) || defined(ARDUINO_AVR_ATTINY43) || defined(ARDUINO_AVR_ATTINY828) || defined(ARDUINO_AVR_ATTINY1634) || defined(ARDUINO_AVR_ATTINYX313))) && defined(UTIMERLIB_HW_COMPILE)
34 | #if !defined(_uTimerLib_IMP_) && defined(_uTimerLib_cpp_)
35 | #define _uTimerLib_IMP_
36 | #include "uTimerLib.cpp"
37 |
38 |
39 | #ifndef TCCR1A
40 | #define TCCR1A GTCCR
41 | #endif
42 |
43 |
44 | /**
45 | * \brief Sets up the timer, calculation variables and interrupts for desired ms microseconds
46 | *
47 | * Note: This is device-dependant
48 | *
49 | * @param us Desired timing in microseconds
50 | */
51 | void uTimerLib::_attachInterrupt_us(unsigned long int us) {
52 | if (us == 0) { // Not valid
53 | return;
54 | }
55 |
56 | unsigned char CSMask = 0;
57 | // For this notes, we asume 16MHz CPU. We recalculate 'us' if not:
58 | if (F_CPU != 16000000) {
59 | us = (F_CPU / 1000) * us / 16000;
60 | }
61 | TIMSK &= ~((1 << TOIE1) | (1 << OCIE1A)); // Disable overflow interruption when 0 + Disable interrupt on compare match
62 | cli();
63 | // ATTiny, using Timer1. Counts at 16MHz (it other speed is used we recalculate us before)
64 | /*
65 | Prescaler: TCCR1; 4 last bits, CS10, CS11, CS12 and CS13
66 |
67 | CS13 CS12 CS11 CS10 Freq Divisor Base Delay Overflow delay
68 | 0 0 0 0 stopped - - -
69 | 0 0 0 1 16MHz 1 0.0625us 16us
70 | 0 0 1 0 16MHz 2 0.125us 32us
71 | 0 0 1 1 16MHz 4 0.25us 64us
72 | 0 1 0 0 16MHz 8 0.5us 128us
73 | 0 1 0 1 16MHz 16 1us 256us
74 | 0 1 1 0 16MHz 32 2us 512us
75 | 0 1 1 1 16MHz 64 4us 1024us
76 | 1 0 0 0 16MHz 128 8us 2048us
77 | 1 0 0 1 16MHz 256 16us 4096us
78 | 1 0 1 0 16MHz 512 32us 8192us
79 | 1 0 1 1 16MHz 1024 64us 16384us
80 | 1 1 0 0 16MHz 2048 128us 32768us
81 | 1 1 0 1 16MHz 4096 256us 65536us
82 | 1 1 1 0 16MHz 8192 512us 131072us
83 | 1 1 1 1 16MHz 16384 1024us 262144us
84 | */
85 | if (us >= 262144) {
86 | CSMask = (1<= 131072) {
91 | CSMask = (1<= 65536) {
94 | CSMask = (1<= 32768) {
97 | CSMask = (1<= 16384) {
100 | CSMask = (1<= 8192) {
103 | CSMask = (1<= 4096) {
106 | CSMask = (1<= 2048) {
109 | CSMask = (1<= 1024) {
112 | CSMask = (1<= 512) {
115 | CSMask = (1<= 256) {
118 | CSMask = (1<= 128) {
121 | CSMask = (1<= 64) {
124 | CSMask = (1<= 32) {
127 | CSMask = (1<= 16) {
130 | CSMask = (1< 0) {
236 | _overflows--;
237 | }
238 | if (_overflows == 0 && _remaining > 0) {
239 | // Load remaining count to counter
240 | _loadRemaining();
241 | // And clear remaining count
242 | _remaining = 0;
243 | } else if (_overflows == 0 && _remaining == 0) {
244 | if (_type == UTIMERLIB_TYPE_TIMEOUT) {
245 | clearTimer();
246 | } else if (_type == UTIMERLIB_TYPE_INTERVAL) {
247 | if (__overflows == 0) {
248 | _remaining = __remaining;
249 | _loadRemaining();
250 | _remaining = 0;
251 | } else {
252 | _overflows = __overflows;
253 | _remaining = __remaining;
254 | }
255 | }
256 | _cb();
257 | }
258 | }
259 |
260 |
261 | /**
262 | * \brief Preinstantiate Object
263 | *
264 | * Now you can use al functionality calling Timerlib.function
265 | */
266 | uTimerLib TimerLib = uTimerLib();
267 |
268 |
269 |
270 |
271 | /**
272 | * \brief Attach Interrupts using internal functionality
273 | *
274 | * Note: This is device-dependant
275 | */
276 | ISR(TIMER1_OVF_vect) {
277 | TimerLib._interrupt();
278 | }
279 |
280 | #endif
281 | #endif
282 |
--------------------------------------------------------------------------------
/src/hardware/uTimerLib.AVR.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * \class uTimerLib
3 | * \brief Arduino tiny and cross-device compatible timer library.
4 | *
5 | * Timers used by each microcontroller:
6 | * * Atmel ATtiny: Timer1 (2nd timer) - https://github.com/damellis/attiny and https://github.com/SpenceKonde/Disgispark AVRCore (25, 45 and 85)
7 | * * DisgiSpark AVR: Timer0 (1st timer) - https://github.com/digistump/DigistumpArduino
8 | * * Atmel AVR 32U4: Timer3 (4rd timer)
9 | * * Atmel AVR other: Timer2 (3rd timer)
10 | * * STM32: Timer3 (3rd timer)
11 | * * SAM (Due): TC3 (Timer1, channel 0)
12 | * * ESP8266: OS Timer, one slot of seven available (Software timer provided by Arduino because ESP8266 has only two hardware timers and one is needed by it normal operation)
13 | * * ESP32: OS Hardware Timer.
14 | * * SAMD21: Timer 4, CC0 (TC3). See http://ww1.microchip.com/downloads/en/DeviceDoc/40001882A.pdf
15 | * * SAMD51: Timer 2 (TC1), 16 bits mode (See http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
16 | *
17 | * You have public TimerLib variable with following methods:
18 | * * TimerLib.setInterval_us(callback_function, microseconds);* : callback_function will be called each microseconds.
19 | * * TimerLib.setInterval_s(callback_function, seconds);* : callback_function will be called each seconds.
20 | * * TimerLib.setTimeout_us(callback_function, microseconds);* : callback_function will be called once when microseconds have passed.
21 | * * TimerLib.setTimeout_s(callback_function, seconds);* : callback_function will be called once when seconds have passed.
22 | * * TimerLib.clearTimer();* : will clear any timed function if exists.
23 | *
24 | * @file hardware/uTimerLib.ATTINY.cpp
25 | * @copyright Naguissa
26 | * @author Naguissa
27 | * @see https://github.com/Naguissa/uTimerLib
28 | * @see https://www.foroelectro.net/librerias-arduino-ide-f29/utimerlib-libreria-arduino-para-eventos-temporizad-t191.html
29 | * @see naguissa@foroelectro.net
30 | * @version 1.7.5
31 | */
32 |
33 | #if (defined(__AVR_ATmega32U4__) || defined(ARDUINO_ARCH_AVR)) && !defined(ARDUINO_attiny) && defined(UTIMERLIB_HW_COMPILE)
34 | #if !defined(_uTimerLib_IMP_) && defined(_uTimerLib_cpp_)
35 | #define _uTimerLib_IMP_
36 | #include "uTimerLib.cpp"
37 |
38 |
39 | /**
40 | * \brief Sets up the timer, calculation variables and interrupts for desired ms microseconds
41 | *
42 | * Note: This is device-dependant
43 | *
44 | * @param us Desired timing in microseconds
45 | */
46 | void uTimerLib::_attachInterrupt_us(unsigned long int us) {
47 | if (us == 0) { // Not valid
48 | return;
49 | }
50 |
51 | unsigned char CSMask = 0;
52 | // For this notes, we asume 16MHz CPU. We recalculate 'us' if not:
53 | if (F_CPU != 16000000) {
54 | us = (F_CPU / 1000) * us / 16000;
55 | }
56 |
57 | // Leonardo and other 32U4 boards
58 | #ifdef __AVR_ATmega32U4__
59 | TIMSK3 &= ~((1 << TOIE3) | (1 << OCIE3A)); // Disable overflow interruption when 0 + Disable interrupt on compare match
60 | cli();
61 | // 32U4, using Timer3. Counts at 16MHz
62 | /*
63 | Prescaler: TCCR3B; 3 last bits, CS30, CS31 and CS32
64 |
65 | CS32 CS31 CS30 Freq Divisor Base Delay Overflow delay
66 | 0 0 0 stopped - - -
67 | 0 0 1 16MHz 1 0.0625us 16us
68 | 0 1 0 2MHz 8 0.5us 128us
69 | 0 1 1 250KHz 64 4us 1024us
70 | 1 0 0 62.5KHz 256 16us 4096us
71 | 1 0 1 15.625KHz 1024 64us 16384us
72 | */
73 | if (us >= 16384) {
74 | CSMask = (1<= 4096) {
79 | CSMask = (1<= 2048) {
82 | CSMask = (1<= 512) {
85 | CSMask = (1<= 16) {
88 | CSMask = (1<= 16384) {
125 | CSMask = (1<= 4096) {
130 | CSMask = (1<= 2048) {
133 | CSMask = (1<= 1024) {
136 | CSMask = (1<= 512) {
139 | CSMask = (1<= 128) {
142 | CSMask = (1<= 16) {
145 | CSMask = (1< 500000) {
198 | _overflows = s / 16384 * 1000000;
199 | } else {
200 | _overflows = s * 1000000 / 16384;
201 | }
202 | // Original: _remaining = 256 - round(((us * 1000000) % 16384) / 64);
203 | // Anti-Overflow trick:
204 | if (s > 16384) {
205 | unsigned long int temp = floor(s / 16384) * 16384;
206 | _remaining = 256 - ((((s - temp) * 1000000) % 16384) / 64 + 0.5); // + 0.5 is round for positive numbers
207 | } else {
208 | _remaining = 256 - (((s * 1000000) % 16384) / 64 + 0.5); // + 0.5 is round for positive numbers
209 | }
210 |
211 | __overflows = _overflows;
212 | __remaining = _remaining;
213 | _overflows += 1;
214 |
215 | //ASSR &= ~(1< 500000) {
236 | _overflows = s / 16384 * 1000000;
237 | } else {
238 | _overflows = s * 1000000 / 16384;
239 | }
240 | // Original: _remaining = 256 - round(((us * 1000000) % 16384) / 64);
241 | // Anti-Overflow trick:
242 | if (s > 16384) {
243 | unsigned long int temp = floor(s / 16384) * 16384;
244 | _remaining = 256 - ((((s - temp) * 1000000) % 16384) / 64 + 0.5); // + 0.5 is round for positive numbers
245 | } else {
246 | _remaining = 256 - (((s * 1000000) % 16384) / 64 + 0.5); // + 0.5 is round for positive numbers
247 | }
248 |
249 | __overflows = _overflows;
250 | __remaining = _remaining;
251 | _overflows += 1;
252 |
253 | ASSR &= ~(1< 0) {
308 | _overflows--;
309 | }
310 | if (_overflows == 0 && _remaining > 0) {
311 | // Load remaining count to counter
312 | _loadRemaining();
313 | // And clear remaining count
314 | _remaining = 0;
315 | } else if (_overflows == 0 && _remaining == 0) {
316 | if (_type == UTIMERLIB_TYPE_TIMEOUT) {
317 | clearTimer();
318 | } else if (_type == UTIMERLIB_TYPE_INTERVAL) {
319 | if (__overflows == 0) {
320 | _remaining = __remaining;
321 | _loadRemaining();
322 | _remaining = 0;
323 | } else {
324 | _overflows = __overflows;
325 | _remaining = __remaining;
326 | }
327 | }
328 | _cb();
329 | }
330 | }
331 |
332 |
333 | /**
334 | * \brief Preinstantiate Object
335 | *
336 | * Now you can use al functionality calling Timerlib.function
337 | */
338 | uTimerLib TimerLib = uTimerLib();
339 |
340 |
341 |
342 |
343 |
344 | /**
345 | * \brief Attach Interrupts using internal functionality
346 | *
347 | * Note: This is device-dependant
348 | */
349 | #ifdef __AVR_ATmega32U4__
350 | // Arduino AVR
351 | ISR(TIMER3_OVF_vect) {
352 | TimerLib._interrupt();
353 | }
354 | #else
355 | // Arduino AVR
356 | ISR(TIMER2_OVF_vect) {
357 | TimerLib._interrupt();
358 | }
359 | #endif
360 |
361 | #endif
362 | #endif
363 |
--------------------------------------------------------------------------------
/src/hardware/uTimerLib.DIGISPARK_AVR.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * \class uTimerLib
3 | * \brief Arduino tiny and cross-device compatible timer library.
4 | *
5 | * Timers used by each microcontroller:
6 | * * Atmel ATtiny: Timer1 (2nd timer) - https://github.com/damellis/attiny and https://github.com/SpenceKonde/Disgispark AVRCore (25, 45 and 85)
7 | * * DisgiSpark AVR: Timer0 (1st timer) - https://github.com/digistump/DigistumpArduino
8 | * * Atmel AVR 32U4: Timer3 (4rd timer)
9 | * * Atmel AVR other: Timer2 (3rd timer)
10 | * * STM32: Timer3 (3rd timer)
11 | * * SAM (Due): TC3 (Timer1, channel 0)
12 | * * ESP8266: OS Timer, one slot of seven available (Software timer provided by Arduino because ESP8266 has only two hardware timers and one is needed by it normal operation)
13 | * * ESP32: OS Hardware Timer.
14 | * * SAMD21: Timer 4, CC0 (TC3). See http://ww1.microchip.com/downloads/en/DeviceDoc/40001882A.pdf
15 | * * SAMD51: Timer 2 (TC1), 16 bits mode (See http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
16 | *
17 | * You have public TimerLib variable with following methods:
18 | * * TimerLib.setInterval_us(callback_function, microseconds);* : callback_function will be called each microseconds.
19 | * * TimerLib.setInterval_s(callback_function, seconds);* : callback_function will be called each seconds.
20 | * * TimerLib.setTimeout_us(callback_function, microseconds);* : callback_function will be called once when microseconds have passed.
21 | * * TimerLib.setTimeout_s(callback_function, seconds);* : callback_function will be called once when seconds have passed.
22 | * * TimerLib.clearTimer();* : will clear any timed function if exists.
23 | *
24 | * @file hardware/uTimerLib.ATTINY.cpp
25 | * @copyright Naguissa
26 | * @author Naguissa
27 | * @see https://github.com/Naguissa/uTimerLib
28 | * @see https://www.foroelectro.net/librerias-arduino-ide-f29/utimerlib-libreria-arduino-para-eventos-temporizad-t191.html
29 | * @see naguissa@foroelectro.net
30 | * @version 1.7.5
31 | */
32 |
33 | #if defined(ARDUINO_ARCH_AVR) && defined(ARDUINO_AVR_DIGISPARK) && defined(UTIMERLIB_HW_COMPILE)
34 | #if !defined(_uTimerLib_IMP_) && defined(_uTimerLib_cpp_)
35 | #define _uTimerLib_IMP_
36 | #include "uTimerLib.cpp"
37 |
38 | /**
39 | * \brief Sets up the timer, calculation variables and interrupts for desired ms microseconds
40 | *
41 | * Note: This is device-dependant
42 | *
43 | * @param us Desired timing in microseconds
44 | */
45 | void uTimerLib::_attachInterrupt_us(unsigned long int us) {
46 | if (us == 0) { // Not valid
47 | return;
48 | }
49 |
50 | unsigned char CSMask = 0;
51 | // For this notes, we asume 16MHz CPU. We recalculate 'us' if not:
52 | if (F_CPU != 16000000) {
53 | us = (F_CPU / 1000) * us / 16000;
54 | }
55 | TIMSK &= ~((1 << TOIE0) | (1 << OCIE1A)); // Disable overflow interruption when 0 + Disable interrupt on compare match
56 | cli();
57 | // Disgispark AVR, using Timer0. Counts at 16MHz (it other speed is used we recalculate us before)
58 | /*
59 | Prescaler: TCCR0B; 3 last bits, CS00, CS01 and CS02
60 |
61 | CS02 CS01 CS00 Freq Divisor Base Delay Overflow delay
62 | 0 0 0 stopped - - -
63 | 0 0 1 16MHz 1 0.0625us 16us
64 | 0 1 0 16MHz 8 0.5us 128us
65 | 0 1 1 16MHz 64 4us 1024us
66 | 1 0 0 16MHz 256 16us 4096us
67 | 1 0 1 16MHz 1024 64us 16384us
68 | */
69 | if (us >= 16384) {
70 | CSMask = (1<= 4096) {
75 | CSMask = (1<= 1024) {
78 | CSMask = (1<= 128) {
81 | CSMask = (1<= 16) {
84 | CSMask = (1< 0) {
188 | _overflows--;
189 | }
190 | if (_overflows == 0 && _remaining > 0) {
191 | // Load remaining count to counter
192 | _loadRemaining();
193 | // And clear remaining count
194 | _remaining = 0;
195 | } else if (_overflows == 0 && _remaining == 0) {
196 | if (_type == UTIMERLIB_TYPE_TIMEOUT) {
197 | clearTimer();
198 | } else if (_type == UTIMERLIB_TYPE_INTERVAL) {
199 | if (__overflows == 0) {
200 | _remaining = __remaining;
201 | _loadRemaining();
202 | _remaining = 0;
203 | } else {
204 | _overflows = __overflows;
205 | _remaining = __remaining;
206 | }
207 | }
208 | _cb();
209 | }
210 | }
211 |
212 |
213 | /**
214 | * \brief Preinstantiate Object
215 | *
216 | * Now you can use al functionality calling Timerlib.function
217 | */
218 | uTimerLib TimerLib = uTimerLib();
219 |
220 |
221 |
222 |
223 | /**
224 | * \brief Attach Interrupts using internal functionality
225 | *
226 | * Note: This is device-dependant
227 | */
228 | ISR(TIMER0_OVF_vect) {
229 | TimerLib._interrupt();
230 | }
231 |
232 | #endif
233 | #endif
234 |
--------------------------------------------------------------------------------
/src/hardware/uTimerLib.ESP32.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * \class uTimerLib
3 | * \brief Arduino tiny and cross-device compatible timer library.
4 | *
5 | * Timers used by each microcontroller:
6 | * * Atmel ATtiny: Timer1 (2nd timer) - https://github.com/damellis/attiny and https://github.com/SpenceKonde/Disgispark AVRCore (25, 45 and 85)
7 | * * DisgiSpark AVR: Timer0 (1st timer) - https://github.com/digistump/DigistumpArduino
8 | * * Atmel AVR 32U4: Timer3 (4rd timer)
9 | * * Atmel AVR other: Timer2 (3rd timer)
10 | * * STM32: Timer3 (3rd timer)
11 | * * SAM (Due): TC3 (Timer1, channel 0)
12 | * * ESP8266: OS Timer, one slot of seven available (Software timer provided by Arduino because ESP8266 has only two hardware timers and one is needed by it normal operation)
13 | * * ESP32: OS Hardware Timer.
14 | * * SAMD21: Timer 4, CC0 (TC3). See http://ww1.microchip.com/downloads/en/DeviceDoc/40001882A.pdf
15 | * * SAMD51: Timer 2 (TC1), 16 bits mode (See http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
16 | *
17 | * You have public TimerLib variable with following methods:
18 | * * TimerLib.setInterval_us(callback_function, microseconds);* : callback_function will be called each microseconds.
19 | * * TimerLib.setInterval_s(callback_function, seconds);* : callback_function will be called each seconds.
20 | * * TimerLib.setTimeout_us(callback_function, microseconds);* : callback_function will be called once when microseconds have passed.
21 | * * TimerLib.setTimeout_s(callback_function, seconds);* : callback_function will be called once when seconds have passed.
22 | * * TimerLib.clearTimer();* : will clear any timed function if exists.
23 | *
24 | * @file hardware/uTimerLib.ATTINY.cpp
25 | * @copyright Naguissa
26 | * @author Naguissa
27 | * @see https://github.com/Naguissa/uTimerLib
28 | * @see https://www.foroelectro.net/librerias-arduino-ide-f29/utimerlib-libreria-arduino-para-eventos-temporizad-t191.html
29 | * @see naguissa@foroelectro.net
30 | * @version 1.7.5
31 | */
32 | #if (defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)) && defined(UTIMERLIB_HW_COMPILE)
33 | #if !defined(_uTimerLib_IMP_) && defined(_uTimerLib_cpp_)
34 | #define _uTimerLib_IMP_
35 | #include "uTimerLib.cpp"
36 |
37 | /**
38 | * \brief Sets up the timer, calculation variables and interrupts for desired ms microseconds
39 | *
40 | * Note: This is device-dependant
41 | *
42 | * @param us Desired timing in microseconds
43 | */
44 | void uTimerLib::_attachInterrupt_us(unsigned long int us) {
45 | if (us == 0) { // Not valid
46 | return;
47 | }
48 | clearTimer();
49 | __overflows = _overflows = __remaining = _remaining = 0;
50 | const esp_timer_create_args_t timer_args = {
51 | .callback = (esp_timer_cb_t) &uTimerLib::interrupt
52 | };
53 | esp_timer_create(&timer_args, &_timer);
54 | esp_timer_start_periodic(_timer, us);
55 | }
56 |
57 |
58 | /**
59 | * \brief Sets up the timer, calculation variables and interrupts for desired s seconds
60 | *
61 | * Note: This is device-dependant
62 | *
63 | * @param s Desired timing in seconds
64 | */
65 | void uTimerLib::_attachInterrupt_s(unsigned long int s) {
66 | if (s == 0) { // Not valid
67 | return;
68 | }
69 | clearTimer();
70 | __overflows = _overflows = __remaining = _remaining = 0;
71 | const esp_timer_create_args_t timer_args = {
72 | .callback = (esp_timer_cb_t) &uTimerLib::interrupt
73 | };
74 | esp_timer_create(&timer_args, &_timer);
75 | esp_timer_start_periodic(_timer, s * 1000000);
76 | }
77 |
78 |
79 |
80 | /**
81 | * \brief Loads last bit of time needed to precisely count until desired time (non complete loop)
82 | *
83 | * Note: This is device-dependant
84 | */
85 | void uTimerLib::_loadRemaining() { }
86 |
87 | /**
88 | * \brief Clear timer interrupts
89 | *
90 | * Note: This is device-dependant
91 | */
92 | void uTimerLib::clearTimer() {
93 | if (_timer) {
94 | esp_timer_stop(_timer);
95 | esp_timer_delete(_timer);
96 | _type = UTIMERLIB_TYPE_OFF;
97 | _timer = NULL;
98 | }
99 | }
100 | /**
101 | * \brief Internal intermediate function to control timer interrupts
102 | *
103 | * As timers doesn't give us enougth flexibility for large timings,
104 | * this function implements oferflow control to offer user desired timings.
105 | */
106 | void uTimerLib::_interrupt() {
107 | if (_type == UTIMERLIB_TYPE_OFF) { // Should not happen
108 | return;
109 | }
110 | if (_type == UTIMERLIB_TYPE_TIMEOUT) {
111 | clearTimer();
112 | }
113 | _cb();
114 | }
115 |
116 |
117 | /**
118 | * \brief Preinstantiate Object
119 | *
120 | * Now you can use al functionality calling Timerlib.function
121 | */
122 | uTimerLib TimerLib = uTimerLib();
123 |
124 |
125 | /**
126 | * \brief Attach Interrupts using internal functionality
127 | *
128 | * Note: This is device-dependant
129 | */
130 | void uTimerLib::interrupt(void* arg) {
131 | TimerLib._interrupt();
132 | }
133 |
134 | #endif
135 | #endif
136 |
--------------------------------------------------------------------------------
/src/hardware/uTimerLib.ESP8266.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * \class uTimerLib
3 | * \brief Arduino tiny and cross-device compatible timer library.
4 | *
5 | * Timers used by each microcontroller:
6 | * * Atmel ATtiny: Timer1 (2nd timer) - https://github.com/damellis/attiny and https://github.com/SpenceKonde/Disgispark AVRCore (25, 45 and 85)
7 | * * DisgiSpark AVR: Timer0 (1st timer) - https://github.com/digistump/DigistumpArduino
8 | * * Atmel AVR 32U4: Timer3 (4rd timer)
9 | * * Atmel AVR other: Timer2 (3rd timer)
10 | * * STM32: Timer3 (3rd timer)
11 | * * SAM (Due): TC3 (Timer1, channel 0)
12 | * * ESP8266: OS Timer, one slot of seven available (Software timer provided by Arduino because ESP8266 has only two hardware timers and one is needed by it normal operation)
13 | * * ESP32: OS Hardware Timer.
14 | * * SAMD21: Timer 4, CC0 (TC3). See http://ww1.microchip.com/downloads/en/DeviceDoc/40001882A.pdf
15 | * * SAMD51: Timer 2 (TC1), 16 bits mode (See http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
16 | *
17 | * You have public TimerLib variable with following methods:
18 | * * TimerLib.setInterval_us(callback_function, microseconds);* : callback_function will be called each microseconds.
19 | * * TimerLib.setInterval_s(callback_function, seconds);* : callback_function will be called each seconds.
20 | * * TimerLib.setTimeout_us(callback_function, microseconds);* : callback_function will be called once when microseconds have passed.
21 | * * TimerLib.setTimeout_s(callback_function, seconds);* : callback_function will be called once when seconds have passed.
22 | * * TimerLib.clearTimer();* : will clear any timed function if exists.
23 | *
24 | * @file hardware/uTimerLib.ATTINY.cpp
25 | * @copyright Naguissa
26 | * @author Naguissa
27 | * @see https://github.com/Naguissa/uTimerLib
28 | * @see https://www.foroelectro.net/librerias-arduino-ide-f29/utimerlib-libreria-arduino-para-eventos-temporizad-t191.html
29 | * @see naguissa@foroelectro.net
30 | * @version 1.7.5
31 | */
32 | #if (defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)) && defined(UTIMERLIB_HW_COMPILE)
33 | #if !defined(_uTimerLib_IMP_) && defined(_uTimerLib_cpp_)
34 | #define _uTimerLib_IMP_
35 | #include "uTimerLib.cpp"
36 |
37 |
38 | /**
39 | * \brief Sets up the timer, calculation variables and interrupts for desired ms microseconds
40 | *
41 | * Note: This is device-dependant
42 | *
43 | * @param us Desired timing in microseconds
44 | */
45 | void uTimerLib::_attachInterrupt_us(unsigned long int us) {
46 | if (us == 0) { // Not valid
47 | return;
48 | }
49 | unsigned long int ms = (us / 1000) + 0.5;
50 | if (ms == 0) {
51 | ms = 1;
52 | }
53 | __overflows = _overflows = __remaining = _remaining = 0;
54 | _ticker.attach_ms(ms, uTimerLib::interrupt);
55 | }
56 |
57 |
58 | /**
59 | * \brief Sets up the timer, calculation variables and interrupts for desired s seconds
60 | *
61 | * Note: This is device-dependant
62 | *
63 | * @param s Desired timing in seconds
64 | */
65 | void uTimerLib::_attachInterrupt_s(unsigned long int s) {
66 | if (s == 0) { // Not valid
67 | return;
68 | }
69 |
70 | __overflows = _overflows = __remaining = _remaining = 0;
71 | _ticker.attach(s, uTimerLib::interrupt);
72 | }
73 |
74 |
75 |
76 | /**
77 | * \brief Loads last bit of time needed to precisely count until desired time (non complete loop)
78 | *
79 | * Note: This is device-dependant
80 | */
81 | void uTimerLib::_loadRemaining() { }
82 |
83 | /**
84 | * \brief Clear timer interrupts
85 | *
86 | * Note: This is device-dependant
87 | */
88 | void uTimerLib::clearTimer() {
89 | _ticker.detach();
90 | }
91 |
92 | /**
93 | * \brief Internal intermediate function to control timer interrupts
94 | *
95 | * As timers doesn't give us enougth flexibility for large timings,
96 | * this function implements oferflow control to offer user desired timings.
97 | */
98 | void uTimerLib::_interrupt() {
99 | if (_type == UTIMERLIB_TYPE_OFF) { // Should not happen
100 | return;
101 | }
102 | if (_type == UTIMERLIB_TYPE_TIMEOUT) {
103 | clearTimer();
104 | }
105 | _cb();
106 | }
107 |
108 |
109 | /**
110 | * \brief Preinstantiate Object
111 | *
112 | * Now you can use al functionality calling Timerlib.function
113 | */
114 | uTimerLib TimerLib = uTimerLib();
115 |
116 |
117 | /**
118 | * \brief Attach Interrupts using internal functionality
119 | *
120 | * Note: This is device-dependant
121 | */
122 | void uTimerLib::interrupt() {
123 | TimerLib._interrupt();
124 | }
125 |
126 | #endif
127 | #endif
128 |
--------------------------------------------------------------------------------
/src/hardware/uTimerLib.SAM.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * \class uTimerLib
3 | * \brief Arduino tiny and cross-device compatible timer library.
4 | *
5 | * Timers used by each microcontroller:
6 | * * Atmel ATtiny: Timer1 (2nd timer) - https://github.com/damellis/attiny and https://github.com/SpenceKonde/Disgispark AVRCore (25, 45 and 85)
7 | * * DisgiSpark AVR: Timer0 (1st timer) - https://github.com/digistump/DigistumpArduino
8 | * * Atmel AVR 32U4: Timer3 (4rd timer)
9 | * * Atmel AVR other: Timer2 (3rd timer)
10 | * * STM32: Timer3 (3rd timer)
11 | * * SAM (Due): TC3 (Timer1, channel 0)
12 | * * ESP8266: OS Timer, one slot of seven available (Software timer provided by Arduino because ESP8266 has only two hardware timers and one is needed by it normal operation)
13 | * * ESP32: OS Hardware Timer.
14 | * * SAMD21: Timer 4, CC0 (TC3). See http://ww1.microchip.com/downloads/en/DeviceDoc/40001882A.pdf
15 | * * SAMD51: Timer 2 (TC1), 16 bits mode (See http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
16 | *
17 | * You have public TimerLib variable with following methods:
18 | * * TimerLib.setInterval_us(callback_function, microseconds);* : callback_function will be called each microseconds.
19 | * * TimerLib.setInterval_s(callback_function, seconds);* : callback_function will be called each seconds.
20 | * * TimerLib.setTimeout_us(callback_function, microseconds);* : callback_function will be called once when microseconds have passed.
21 | * * TimerLib.setTimeout_s(callback_function, seconds);* : callback_function will be called once when seconds have passed.
22 | * * TimerLib.clearTimer();* : will clear any timed function if exists.
23 | *
24 | * @file hardware/uTimerLib.ATTINY.cpp
25 | * @copyright Naguissa
26 | * @author Naguissa
27 | * @see https://github.com/Naguissa/uTimerLib
28 | * @see https://www.foroelectro.net/librerias-arduino-ide-f29/utimerlib-libreria-arduino-para-eventos-temporizad-t191.html
29 | * @see naguissa@foroelectro.net
30 | * @version 1.7.5
31 | */
32 | #if defined(ARDUINO_ARCH_SAM) && defined(UTIMERLIB_HW_COMPILE)
33 | #if !defined(_uTimerLib_IMP_) && defined(_uTimerLib_cpp_)
34 | #define _uTimerLib_IMP_
35 | #include "uTimerLib.cpp"
36 |
37 |
38 |
39 |
40 |
41 | /**
42 | * \brief Sets up the timer, calculation variables and interrupts for desired ms microseconds
43 | *
44 | * Note: This is device-dependant
45 | *
46 | * @param us Desired timing in microseconds
47 | */
48 | void uTimerLib::_attachInterrupt_us(unsigned long int us) {
49 | if (us == 0) { // Not valid
50 | return;
51 | }
52 |
53 | /*
54 | Prescalers: MCK/2, MCK/8, MCK/32, MCK/128
55 | Base frequency: 84MHz
56 |
57 | Available Timers:
58 | ISR/IRQ TC Channel Due pins
59 | TC0 TC0 0 2, 13
60 | TC1 TC0 1 60, 61
61 | TC2 TC0 2 58
62 | TC3 TC1 0 none
63 | TC4 TC1 1 none
64 | TC5 TC1 2 none
65 | TC6 TC2 0 4, 5
66 | TC7 TC2 1 3, 10
67 | TC8 TC2 2 11, 12
68 |
69 | We will use TC1, as it has no associated pins. We will choose Channel 0, so ISR is TC3
70 |
71 | REMEMBER! 32 bit counter!!!
72 |
73 |
74 | Name Prescaler Freq Base Delay Overflow delay
75 | TC_CMR_TCCLKS_TIMER_CLOCK1 2 42MHz 0,023809524us 102261126,913327104us, 102,261126913327104s
76 | TC_CMR_TCCLKS_TIMER_CLOCK2 8 10.5MHz 0,095238095us 409044503,35834112us, 409,04450335834112s
77 | TC_CMR_TCCLKS_TIMER_CLOCK3 32 2.625MHz 0,380952381us 1636178017,523809524us, 1636,178017523809524s
78 | TC_CMR_TCCLKS_TIMER_CLOCK4 128 656.25KHz 1,523809524us 6544712070,913327104us, 6544,712070913327104s
79 |
80 | For simplify things, we'll use always TC_CMR_TCCLKS_TIMER_CLOCK32,as has enougth resolution for us.
81 | */
82 |
83 | if (us > 1636178017) {
84 | __overflows = _overflows = us / 1636178017.523809524;
85 | __remaining = _remaining = (us - (1636178017.523809524 * _overflows)) / 0.380952381 + 0.5; // +0.5 is same as round
86 | } else {
87 | __overflows = _overflows = 0;
88 | __remaining = _remaining = (us / 0.380952381 + 0.5); // +0.5 is same as round
89 | }
90 | pmc_set_writeprotect(false); // Enable write
91 | pmc_enable_periph_clk(ID_TC3); // Enable TC1 - channel 0 peripheral
92 | TC_Configure(TC1, 0, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK3); // Configure clock; prescaler = 32
93 |
94 | if (__overflows == 0) {
95 | _loadRemaining();
96 | _remaining = 0;
97 | } else {
98 | TC_SetRC(TC1, 0, 4294967295); // Int on last number
99 | }
100 |
101 | TC_Start(TC1, 0);
102 | TC1->TC_CHANNEL[0].TC_IER = TC_IER_CPCS;
103 | TC1->TC_CHANNEL[0].TC_IDR = ~TC_IER_CPCS;
104 | NVIC_EnableIRQ(TC3_IRQn);
105 | }
106 |
107 |
108 | /**
109 | * \brief Sets up the timer, calculation variables and interrupts for desired s seconds
110 | *
111 | * Note: This is device-dependant
112 | *
113 | * @param s Desired timing in seconds
114 | */
115 | void uTimerLib::_attachInterrupt_s(unsigned long int s) {
116 | if (s == 0) { // Not valid
117 | return;
118 | }
119 |
120 | /*
121 | See _ms functions for detailed info; here only selected points
122 |
123 | Name Prescaler Freq Base Delay Overflow delay
124 | TC_CMR_TCCLKS_TIMER_CLOCK4 128 656.25KHz 1,523809524us 6544712070,913327104us, 6544,712070913327104s
125 |
126 | For simplify things, we'll use always TC_CMR_TCCLKS_TIMER_CLOCK32,as has enougth resolution for us.
127 | */
128 | if (s > 6544) {
129 | __overflows = _overflows = s / 6544.712070913327104;
130 | __remaining = _remaining = (s - (6544.712070913327104 * _overflows) / 0.000001523809524 + 0.5); // +0.5 is same as round
131 | } else {
132 | __overflows = _overflows = 0;
133 | __remaining = _remaining = (s / 0.000001523809524 + 0.5); // +0.5 is same as round
134 | }
135 |
136 | pmc_set_writeprotect(false); // Enable write
137 | //pmc_enable_periph_clk((uint32_t) TC3_IRQn); // Enable TC1 - channel 0 peripheral
138 | pmc_enable_periph_clk(ID_TC3); // Enable TC1 - channel 0 peripheral
139 | TC_Configure(TC1, 0, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK4); // Configure clock; prescaler = 128
140 |
141 | if (__overflows == 0) {
142 | _loadRemaining();
143 | _remaining = 0;
144 | } else {
145 | TC_SetRC(TC1, 0, 4294967295); // Int on last number
146 | }
147 |
148 | TC1->TC_CHANNEL[0].TC_IER=TC_IER_CPCS;
149 | TC1->TC_CHANNEL[0].TC_IDR=~TC_IER_CPCS;
150 | NVIC_EnableIRQ(TC3_IRQn);
151 | TC_Start(TC1, 0);
152 | }
153 |
154 |
155 | /**
156 | * \brief Loads last bit of time needed to precisely count until desired time (non complete loop)
157 | *
158 | * Note: This is device-dependant
159 | */
160 | void uTimerLib::_loadRemaining() {
161 | TC_SetRC(TC1, 0, _remaining);
162 | }
163 |
164 | /**
165 | * \brief Clear timer interrupts
166 | *
167 | * Note: This is device-dependant
168 | */
169 | void uTimerLib::clearTimer() {
170 | _type = UTIMERLIB_TYPE_OFF;
171 |
172 | NVIC_DisableIRQ(TC3_IRQn);
173 | }
174 |
175 | /**
176 | * \brief Internal intermediate function to control timer interrupts
177 | *
178 | * As timers doesn't give us enougth flexibility for large timings,
179 | * this function implements oferflow control to offer user desired timings.
180 | */
181 | void uTimerLib::_interrupt() {
182 | if (_type == UTIMERLIB_TYPE_OFF) { // Should not happen
183 | return;
184 | }
185 |
186 | if (_overflows > 0) {
187 | _overflows--;
188 | }
189 | if (_overflows == 0 && _remaining > 0) {
190 | // Load remaining count to counter
191 | _loadRemaining();
192 | // And clear remaining count
193 | _remaining = 0;
194 | } else if (_overflows == 0 && _remaining == 0) {
195 | if (_type == UTIMERLIB_TYPE_TIMEOUT) {
196 | clearTimer();
197 | } else if (_type == UTIMERLIB_TYPE_INTERVAL) {
198 | if (__overflows == 0) {
199 | _remaining = __remaining;
200 | _loadRemaining();
201 | _remaining = 0;
202 | } else {
203 | _overflows = __overflows;
204 | _remaining = __remaining;
205 |
206 | TC_SetRC(TC1, 0, 4294967295);
207 | }
208 | }
209 | _cb();
210 | } else if (_overflows > 0) { // Reload for SAM
211 | TC_SetRC(TC1, 0, 4294967295);
212 | }
213 | }
214 |
215 |
216 | /**
217 | * \brief Preinstantiate Object
218 | *
219 | * Now you can use al functionality calling Timerlib.function
220 | */
221 | uTimerLib TimerLib = uTimerLib();
222 |
223 |
224 |
225 | /**
226 | * \brief Attach Interrupts using internal functionality
227 | *
228 | * Note: This is device-dependant
229 | */
230 | void TC3_Handler() {
231 | TC_GetStatus(TC1, 0); // reset interrupt
232 | TimerLib._interrupt();
233 | }
234 |
235 | #endif
236 | #endif
237 |
--------------------------------------------------------------------------------
/src/hardware/uTimerLib.SAMD21.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * \class uTimerLib
3 | * \brief Arduino tiny and cross-device compatible timer library.
4 | *
5 | * Timers used by each microcontroller:
6 | * * Atmel ATtiny: Timer1 (2nd timer) - https://github.com/damellis/attiny and https://github.com/SpenceKonde/Disgispark AVRCore (25, 45 and 85)
7 | * * DisgiSpark AVR: Timer0 (1st timer) - https://github.com/digistump/DigistumpArduino
8 | * * Atmel AVR 32U4: Timer3 (4rd timer)
9 | * * Atmel AVR other: Timer2 (3rd timer)
10 | * * STM32: Timer3 (3rd timer)
11 | * * SAM (Due): TC3 (Timer1, channel 0)
12 | * * ESP8266: OS Timer, one slot of seven available (Software timer provided by Arduino because ESP8266 has only two hardware timers and one is needed by it normal operation)
13 | * * ESP32: OS Hardware Timer.
14 | * * SAMD21: Timer 4, CC0 (TC3). See http://ww1.microchip.com/downloads/en/DeviceDoc/40001882A.pdf
15 | * * SAMD51: Timer 2 (TC1), 16 bits mode (See http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
16 | *
17 | * You have public TimerLib variable with following methods:
18 | * * TimerLib.setInterval_us(callback_function, microseconds);* : callback_function will be called each microseconds.
19 | * * TimerLib.setInterval_s(callback_function, seconds);* : callback_function will be called each seconds.
20 | * * TimerLib.setTimeout_us(callback_function, microseconds);* : callback_function will be called once when microseconds have passed.
21 | * * TimerLib.setTimeout_s(callback_function, seconds);* : callback_function will be called once when seconds have passed.
22 | * * TimerLib.clearTimer();* : will clear any timed function if exists.
23 | *
24 | * @file hardware/uTimerLib.ATTINY.cpp
25 | * @copyright Naguissa
26 | * @author Naguissa
27 | * @see https://github.com/Naguissa/uTimerLib
28 | * @see https://www.foroelectro.net/librerias-arduino-ide-f29/utimerlib-libreria-arduino-para-eventos-temporizad-t191.html
29 | * @see naguissa@foroelectro.net
30 | * @version 1.7.5
31 | */
32 | #if defined(_SAMD21_) && defined(UTIMERLIB_HW_COMPILE)
33 | #ifndef _uTimerLib_IMP_
34 | #define _uTimerLib_IMP_
35 | #include "uTimerLib.cpp"
36 |
37 |
38 | /**
39 | * \brief Sets up the timer, calculation variables and interrupts for desired ms microseconds
40 | *
41 | * Note: This is device-dependant
42 | *
43 | * @param us Desired timing in microseconds
44 | */
45 | void uTimerLib::_attachInterrupt_us(unsigned long int us) {
46 | if (us == 0) { // Not valid
47 | return;
48 | }
49 |
50 | /*
51 | 16 bit timer
52 |
53 | Prescaler:
54 | Prescalers: GCLK_TC, GCLK_TC/2, GCLK_TC/4, GCLK_TC/8, GCLK_TC/16, GCLK_TC/64, GCLK_TC/256, GCLK_TC/1024
55 | Base frequency: 48MHz
56 |
57 | We will use TCC2, as there're some models with only 3 timers (regular models have 5 TCs)
58 |
59 | REMEMBER! 16 bit counter!!!
60 |
61 |
62 | Name Prescaler Freq Base Delay Overflow delay
63 | GCLK_TC 1 48MHz ~0,020833333us 1365,3125us; 1,3653125ms
64 | GCLK_TC/2 2 24MHz ~0,041666667us 2730,625us; 2,730625ms
65 | GCLK_TC/4 4 12MHz ~0,083333333us 5461,25us; 5,46125ms
66 | GCLK_TC/8 8 6MHz ~0,166666667us 10922,5us; 10,9225ms
67 | GCLK_TC/16 16 3MHz ~0,333333333us 21845us; 21,845ms
68 | GCLK_TC/64 64 750KHz ~1,333333333us 87380us; 87,380ms
69 | GCLK_TC/256 256 187,5KHz ~5,333333333us 349520us; 349,52ms
70 | GCLK_TC/1024 1024 46.875kHz ~21,333333333us 1398080us; 1398,08ms; 1,39808s
71 |
72 | In general:
73 | freq = 48 MHz / prescaler
74 | base_delay = 1 / freq
75 | overflow_delay = UINT16_MAX * base_delay
76 |
77 | Will be using:
78 | GCLK_TC/16 for us
79 | GCLK_TC/1024 for s
80 |
81 | GCLK_TC/16:
82 | freq = 48 MHz / prescaler = 48 MHz / 16 = 3 MHz
83 | base_delay = 1 / freq = 1 / 3e6 s = 1/3 us ~= 0.333333333 us
84 | overflow_delay = UINT16_MAX * base_delay = 65535 / 3 us = 21845 us
85 |
86 | GCLK_TC/1024:
87 | freq = 48 MHz / prescaler = 48 MHz / 1024 = 46.875 kHz = 46875 Hz
88 | base_delay = 1 / freq = 1 / 46875 s = ~= 21.333333333us
89 | overflow_delay = UINT16_MAX * base_delay = 65535 / 46875 s = 1.39808 s
90 | */
91 |
92 | // Enable clock for TC
93 | REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_TCC2_TC3)) ;
94 | while (GCLK->STATUS.bit.SYNCBUSY == 1); // sync
95 |
96 | // Disable TC
97 | _TC->CTRLA.reg &= ~TC_CTRLA_ENABLE;
98 | while (_TC->STATUS.bit.SYNCBUSY == 1); // sync
99 |
100 | // Set Timer counter Mode to 16 bits + Set TC as normal Match Frq + Prescaler: GCLK_TC/16
101 | _TC->CTRLA.reg |= (TC_CTRLA_MODE_COUNT16 + TC_CTRLA_WAVEGEN_MFRQ + TC_CTRLA_PRESCALER_DIV16);
102 | while (_TC->STATUS.bit.SYNCBUSY == 1); // sync
103 |
104 | if (us > 21845) {
105 | __overflows = _overflows = us / 21845.0;
106 | __remaining = _remaining = (us - (21845 * _overflows)) * 3 - 1;
107 | } else {
108 | __overflows = _overflows = 0;
109 | __remaining = _remaining = us * 3 - 1;
110 | }
111 |
112 | if (__overflows == 0) {
113 | _loadRemaining();
114 | _remaining = 0;
115 | } else {
116 | _TC->CC[0].reg = UINT16_MAX;
117 | _TC->INTENSET.reg = 0; // disable all interrupts
118 | _TC->INTENSET.bit.OVF = 1; // enable overfollow
119 | // Skip: while (_TC->STATUS.bit.SYNCBUSY == 1); // sync
120 | }
121 |
122 | _TC->COUNT.reg = 0; // Reset to 0
123 |
124 | NVIC_EnableIRQ(TC3_IRQn);
125 |
126 | // Enable TC
127 | _TC->CTRLA.reg |= TC_CTRLA_ENABLE;
128 | }
129 |
130 |
131 | /**
132 | * \brief Sets up the timer, calculation variables and interrupts for desired s seconds
133 | *
134 | * Note: This is device-dependant
135 | *
136 | * @param s Desired timing in seconds
137 | */
138 | void uTimerLib::_attachInterrupt_s(unsigned long int s) {
139 | if (s == 0) { // Not valid
140 | return;
141 | }
142 |
143 | /*
144 | GCLK_TC/1024 1024 46.875kHz ~21,333333333us 1398080us; 1398,08ms; 1,39808s
145 | */
146 |
147 | // Enable clock for TC
148 | REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_TCC2_TC3)) ;
149 | while (GCLK->STATUS.bit.SYNCBUSY == 1); // sync
150 |
151 | // Disable TC
152 | _TC->CTRLA.reg &= ~TC_CTRLA_ENABLE;
153 | while (_TC->STATUS.bit.SYNCBUSY == 1); // sync
154 |
155 | // Set Timer counter Mode to 16 bits + Set TC as normal Match Frq + Prescaler: GCLK_TC/1024
156 | _TC->CTRLA.reg |= (TC_CTRLA_MODE_COUNT16 + TC_CTRLA_WAVEGEN_MFRQ + TC_CTRLA_PRESCALER_DIV1024);
157 | while (_TC->STATUS.bit.SYNCBUSY == 1); // sync
158 |
159 | if (s > 1) {
160 | __overflows = _overflows = s / 1.39808;
161 | __remaining = _remaining = ((s * 100000) % 139808) * 480 / 1024 - 1; // for integer s this is always an integer
162 | } else {
163 | __overflows = _overflows = 0;
164 | __remaining = _remaining = s * 46875 - 1;
165 | }
166 |
167 | if (__overflows == 0) {
168 | _loadRemaining();
169 | _remaining = 0;
170 | } else {
171 | _TC->CC[0].reg = UINT16_MAX;
172 | _TC->INTENSET.reg = 0; // disable all interrupts
173 | _TC->INTENSET.bit.OVF = 1; // enable overfollow
174 | // Skip: while (_TC->STATUS.bit.SYNCBUSY == 1); // sync
175 | }
176 |
177 | _TC->COUNT.reg = 0; // Reset to 0
178 |
179 | NVIC_EnableIRQ(TC3_IRQn);
180 |
181 | // Enable TC
182 | _TC->CTRLA.reg |= TC_CTRLA_ENABLE;
183 | }
184 |
185 |
186 | /**
187 | * \brief Loads last bit of time needed to precisely count until desired time (non complete loop)
188 | *
189 | * Note: This is device-dependant
190 | */
191 | void uTimerLib::_loadRemaining() {
192 | _TC->CC[0].reg = _remaining;
193 | _TC->INTENSET.reg = 0; // disable all interrupts
194 | _TC->INTENSET.bit.MC0 = 1; // enable compare match to CC0
195 | while (_TC->STATUS.bit.SYNCBUSY == 1); // sync
196 | }
197 |
198 | /**
199 | * \brief Clear timer interrupts
200 | *
201 | * Note: This is device-dependant
202 | */
203 | void uTimerLib::clearTimer() {
204 | _type = UTIMERLIB_TYPE_OFF;
205 |
206 | // Disable TC
207 | _TC->INTENSET.reg = 0; // disable all interrupts
208 | _TC->CTRLA.reg &= ~TC_CTRLA_ENABLE;
209 | }
210 |
211 | /**
212 | * \brief Internal intermediate function to control timer interrupts
213 | *
214 | * As timers doesn't give us enougth flexibility for large timings,
215 | * this function implements oferflow control to offer user desired timings.
216 | */
217 | void uTimerLib::_interrupt() {
218 | if (_type == UTIMERLIB_TYPE_OFF) { // Should not happen
219 | return;
220 | }
221 |
222 | if (_overflows > 0) {
223 | _overflows--;
224 | }
225 | if (_overflows == 0 && _remaining > 0) {
226 | // Load remaining count to counter
227 | _loadRemaining();
228 | // And clear remaining count
229 | _remaining = 0;
230 | } else if (_overflows == 0 && _remaining == 0) {
231 | if (_type == UTIMERLIB_TYPE_TIMEOUT) {
232 | clearTimer();
233 | } else if (_type == UTIMERLIB_TYPE_INTERVAL) {
234 | if (__overflows != 0) {
235 | _overflows = __overflows;
236 | _remaining = __remaining;
237 |
238 | _TC->INTENSET.reg = 0; // disable all interrupts
239 | _TC->INTENSET.bit.OVF = 0; // enable overfollow
240 | _TC->INTENSET.bit.MC0 = 1; // disable compare match to CC0
241 | _TC->CC[0].reg = UINT16_MAX;
242 | }
243 | }
244 | _cb();
245 | } else if (_overflows > 0) { // Reload for SAMD21
246 | _TC->INTENSET.reg = 0; // disable all interrupts
247 | _TC->INTENSET.bit.OVF = 0; // enable overfollow
248 | _TC->INTENSET.bit.MC0 = 1; // disable compare match to CC0
249 | _TC->CC[0].reg = UINT16_MAX;
250 | }
251 | }
252 |
253 | /**
254 | * \brief Preinstantiate Object
255 | *
256 | * Now you can use al functionality calling Timerlib.function
257 | */
258 | uTimerLib TimerLib = uTimerLib();
259 |
260 |
261 |
262 | /**
263 | * \brief Attach Interrupts using internal functionality
264 | *
265 | * Note: This is device-dependant
266 | */
267 | void TC3_Handler() {
268 | // Overflow - Nothing, we will use compare to max value instead to unify behaviour
269 | if (TimerLib._TC->INTFLAG.bit.OVF == 1) {
270 | TimerLib._TC->INTFLAG.bit.OVF = 1; // Clear flag
271 | TimerLib._interrupt();
272 | }
273 | // Compare
274 | if (TimerLib._TC->INTFLAG.bit.MC0 == 1) {
275 | TimerLib._TC->INTFLAG.bit.MC0 = 1; // Clear flag
276 | TimerLib._interrupt();
277 | }
278 | }
279 |
280 | #endif
281 | #endif
282 |
--------------------------------------------------------------------------------
/src/hardware/uTimerLib.SAMD51.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * \class uTimerLib
3 | * \brief Arduino tiny and cross-device compatible timer library.
4 | *
5 | * Timers used by each microcontroller:
6 | * * Atmel ATtiny: Timer1 (2nd timer) - https://github.com/damellis/attiny and https://github.com/SpenceKonde/Disgispark AVRCore (25, 45 and 85)
7 | * * DisgiSpark AVR: Timer0 (1st timer) - https://github.com/digistump/DigistumpArduino
8 | * * Atmel AVR 32U4: Timer3 (4rd timer)
9 | * * Atmel AVR other: Timer2 (3rd timer)
10 | * * STM32: Timer3 (3rd timer)
11 | * * SAM (Due): TC3 (Timer1, channel 0)
12 | * * ESP8266: OS Timer, one slot of seven available (Software timer provided by Arduino because ESP8266 has only two hardware timers and one is needed by it normal operation)
13 | * * ESP32: OS Hardware Timer.
14 | * * SAMD21: Timer 4, CC0 (TC3). See http://ww1.microchip.com/downloads/en/DeviceDoc/40001882A.pdf
15 | * * SAMD51: Timer 2 (TC1), 16 bits mode (See http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
16 | *
17 | * You have public TimerLib variable with following methods:
18 | * * TimerLib.setInterval_us(callback_function, microseconds);* : callback_function will be called each microseconds.
19 | * * TimerLib.setInterval_s(callback_function, seconds);* : callback_function will be called each seconds.
20 | * * TimerLib.setTimeout_us(callback_function, microseconds);* : callback_function will be called once when microseconds have passed.
21 | * * TimerLib.setTimeout_s(callback_function, seconds);* : callback_function will be called once when seconds have passed.
22 | * * TimerLib.clearTimer();* : will clear any timed function if exists.
23 | *
24 | * @file hardware/uTimerLib.ATTINY.cpp
25 | * @copyright Naguissa
26 | * @author Naguissa
27 | * @see https://github.com/Naguissa/uTimerLib
28 | * @see https://www.foroelectro.net/librerias-arduino-ide-f29/utimerlib-libreria-arduino-para-eventos-temporizad-t191.html
29 | * @see naguissa@foroelectro.net
30 | * @version 1.7.5
31 | */
32 | #if defined(__SAMD51__) && defined(UTIMERLIB_HW_COMPILE)
33 | #if !defined(_uTimerLib_IMP_) && defined(_uTimerLib_cpp_)
34 | #define _uTimerLib_IMP_
35 | #include "uTimerLib.cpp"
36 |
37 | #define UTIMERLIB_WAIT_SYNC() while (TC1->COUNT16.SYNCBUSY.reg)
38 | /**
39 | * \brief Sets up the timer, calculation variables and interrupts for desired ms microseconds
40 | *
41 | * Note: This is device-dependant
42 | *
43 | * @param us Desired timing in microseconds
44 | */
45 | void uTimerLib::_attachInterrupt_us(unsigned long int us) {
46 | if (us == 0) { // Not valid
47 | return;
48 | }
49 | /*
50 | 16 bit timer
51 |
52 | Prescaler:
53 | Prescalers: GCLK_TC, GCLK_TC/2, GCLK_TC/4, GCLK_TC/8, GCLK_TC/16, GCLK_TC/64, GCLK_TC/256, GCLK_TC/1024
54 | Base frequency: 84MHz
55 |
56 | We will use TC1
57 |
58 | REMEMBER! 16 bit counter!!!
59 |
60 | Name Prescaler Freq Base Delay Overflow delay
61 | GCLK_TC 1 120MHz 0,008333333us 546,133333333us; 0,546133333333ms
62 | GCLK_TC/2 2 60MHz 0,016666667us 1092,266666667us; 1,092266666667ms
63 | GCLK_TC/4 4 30MHz 0,033333333us 2184,533333333us; 2,184533333333ms
64 | GCLK_TC/8 8 20MHz 0,066666667us 4369,066666667us; 4,369066666667ms
65 | GCLK_TC/16 16 10MHz 0,133333333us 8738,133333333us; 8,738133333333ms
66 | GCLK_TC/64 64 1,875MHz 0,533333333us 34952,533333333us; 34,952533333333ms
67 | GCLK_TC/256 256 468,75KHz 2,133333333us 139810,133333333us; 139,810133333333ms
68 | GCLK_TC/1024 1024 117,1875Hz 8,533333333us 559240,533333333us; 559,240533333333ms
69 |
70 | Will be using:
71 | GCLK_TC/16 for us
72 | GCLK_TC/1024 for s
73 | */
74 |
75 |
76 | /*
77 | // Enable the TC bus clock
78 | MCLK->APBAMASK.bit.TC1_ = 1;
79 | GCLK->PCHCTRL[TC1_GCLK_ID].bit.GEN = 0;
80 | GCLK->PCHCTRL[TC1_GCLK_ID].bit.CHEN = 1;
81 | */
82 | // Enable the TC bus clock
83 | GCLK->PCHCTRL[TC1_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN;
84 | while(GCLK->SYNCBUSY.reg); // sync
85 |
86 | TC1->COUNT16.CTRLA.bit.ENABLE = 0;
87 | UTIMERLIB_WAIT_SYNC();
88 |
89 | TC1->COUNT16.CTRLA.bit.MODE = TC_CTRLA_MODE_COUNT16_Val;
90 | UTIMERLIB_WAIT_SYNC();
91 |
92 |
93 |
94 | TC1->COUNT16.CTRLA.reg &= ((~(TC_CTRLA_ENABLE)) & (~(TC_CTRLA_PRESCALER_DIV1024)) & (~(TC_CTRLA_PRESCALER_DIV256)) & (~(TC_CTRLA_PRESCALER_DIV64)) & (~(TC_CTRLA_PRESCALER_DIV16)) & (~(TC_CTRLA_PRESCALER_DIV4)) & (~(TC_CTRLA_PRESCALER_DIV2)) & (~(TC_CTRLA_PRESCALER_DIV1)));
95 | UTIMERLIB_WAIT_SYNC();
96 |
97 | TC1->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCALER_DIV16;
98 | UTIMERLIB_WAIT_SYNC();
99 |
100 |
101 | if (us > 8738) {
102 | __overflows = _overflows = us / 8738.133333333;
103 | __remaining = _remaining = (us - (8738.133333333 * _overflows)) / 0.133333333 + 0.5; // +0.5 is same as round
104 | } else {
105 | __overflows = _overflows = 0;
106 | __remaining = _remaining = (us / 0.133333333 + 0.5); // +0.5 is same as round
107 | }
108 |
109 | if (__remaining != 0) {
110 | __remaining = _remaining = (((uint16_t) 0xffff) - __remaining); // Remaining is max value minus remaining
111 | }
112 |
113 | if (__overflows == 0) {
114 | _loadRemaining();
115 | _remaining = 0;
116 | } else {
117 | TC1->COUNT16.COUNT.reg = 0;
118 | }
119 |
120 |
121 | TC1->COUNT16.INTENSET.reg = 0;
122 | TC1->COUNT16.INTENSET.bit.OVF = 1;
123 | // Enable InterruptVector
124 | NVIC_EnableIRQ(TC1_IRQn);
125 |
126 | // Count on event
127 | //TC1->COUNT16.EVCTRL.bit.EVACT = TC_EVCTRL_EVACT_COUNT_Val;
128 |
129 | TC1->COUNT16.CTRLA.bit.ENABLE = 1;
130 | }
131 |
132 |
133 | /**
134 | * \brief Sets up the timer, calculation variables and interrupts for desired s seconds
135 | *
136 | * Note: This is device-dependant
137 | *
138 | * @param s Desired timing in seconds
139 | */
140 | void uTimerLib::_attachInterrupt_s(unsigned long int s) {
141 | if (s == 0) { // Not valid
142 | return;
143 | }
144 |
145 | /*
146 | GCLK_TC/1024 1024 117,1875Hz 8,533333333us 559240,533333333us; 559,240533333333ms
147 | */
148 |
149 |
150 |
151 |
152 | // Enable the TC bus clock
153 | GCLK->PCHCTRL[TC1_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN;
154 | while(GCLK->SYNCBUSY.reg); // sync
155 |
156 | TC1->COUNT16.CTRLA.bit.ENABLE = 0;
157 | UTIMERLIB_WAIT_SYNC();
158 |
159 | TC1->COUNT16.CTRLA.bit.MODE = TC_CTRLA_MODE_COUNT16_Val;
160 | UTIMERLIB_WAIT_SYNC();
161 |
162 |
163 |
164 | TC1->COUNT16.CTRLA.reg &= ((~(TC_CTRLA_ENABLE)) & (~(TC_CTRLA_PRESCALER_DIV1024)) & (~(TC_CTRLA_PRESCALER_DIV256)) & (~(TC_CTRLA_PRESCALER_DIV64)) & (~(TC_CTRLA_PRESCALER_DIV16)) & (~(TC_CTRLA_PRESCALER_DIV4)) & (~(TC_CTRLA_PRESCALER_DIV2)) & (~(TC_CTRLA_PRESCALER_DIV1)));
165 | UTIMERLIB_WAIT_SYNC();
166 |
167 | TC1->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCALER_DIV1024;
168 | UTIMERLIB_WAIT_SYNC();
169 |
170 |
171 | __overflows = _overflows = s / 0.559240533333333;
172 | __remaining = _remaining = (s - (0.559240533333333 * _overflows)) / 0.000008533333333 + 0.5; // +0.5 is same as round
173 |
174 | if (__remaining != 0) {
175 | __remaining = _remaining = (((uint16_t) 0xffff) - __remaining); // Remaining is max value minus remaining
176 | }
177 |
178 | if (__overflows == 0) {
179 | _loadRemaining();
180 | _remaining = 0;
181 | } else {
182 | TC1->COUNT16.COUNT.reg = 0;
183 | }
184 |
185 |
186 | TC1->COUNT16.INTENSET.reg = 0;
187 | TC1->COUNT16.INTENSET.bit.OVF = 1;
188 | // Enable InterruptVector
189 | NVIC_EnableIRQ(TC1_IRQn);
190 |
191 | // Count on event
192 | //TC1->COUNT16.EVCTRL.bit.EVACT = TC_EVCTRL_EVACT_COUNT_Val;
193 |
194 | TC1->COUNT16.CTRLA.bit.ENABLE = 1;
195 | }
196 |
197 |
198 |
199 | /**
200 | * \brief Loads last bit of time needed to precisely count until desired time (non complete loop)
201 | *
202 | * Note: This is device-dependant
203 | */
204 | void uTimerLib::_loadRemaining() {
205 | TC1->COUNT16.COUNT.reg = _remaining;
206 | }
207 |
208 | /**
209 | * \brief Clear timer interrupts
210 | *
211 | * Note: This is device-dependant
212 | */
213 | void uTimerLib::clearTimer() {
214 | _type = UTIMERLIB_TYPE_OFF;
215 |
216 | TC1->COUNT16.INTENSET.reg = 0;
217 | // Disable InterruptVector
218 | NVIC_DisableIRQ(TC1_IRQn);
219 | }
220 |
221 | /**
222 | * \brief Internal intermediate function to control timer interrupts
223 | *
224 | * As timers doesn't give us enougth flexibility for large timings,
225 | * this function implements oferflow control to offer user desired timings.
226 | */
227 | void uTimerLib::_interrupt() {
228 | if (_type == UTIMERLIB_TYPE_OFF) { // Should not happen
229 | return;
230 | }
231 | if (_overflows > 0) {
232 | _overflows--;
233 | }
234 | if (_overflows == 0 && _remaining > 0) {
235 | // Load remaining count to counter
236 | _loadRemaining();
237 | // And clear remaining count
238 | _remaining = 0;
239 | } else if (_overflows == 0 && _remaining == 0) {
240 | if (_type == UTIMERLIB_TYPE_TIMEOUT) {
241 | clearTimer();
242 | } else if (_type == UTIMERLIB_TYPE_INTERVAL) {
243 | if (__overflows == 0) {
244 | _remaining = __remaining;
245 | _loadRemaining();
246 | _remaining = 0;
247 | } else {
248 | _overflows = __overflows;
249 | _remaining = __remaining;
250 | }
251 | }
252 | _cb();
253 | }
254 | }
255 |
256 | /**
257 | * \brief Preinstantiate Object
258 | *
259 | * Now you can use al functionality calling Timerlib.function
260 | */
261 | uTimerLib TimerLib = uTimerLib();
262 |
263 |
264 |
265 |
266 |
267 | /**
268 | * \brief Attach Interrupts using internal functionality
269 | *
270 | * Note: This is device-dependant
271 | */
272 | void TC1_Handler() {
273 | if (TC1->COUNT16.INTFLAG.bit.OVF == 1) {
274 | TC1->COUNT16.INTENSET.bit.OVF = 1; // Clear flag
275 | TimerLib._interrupt();
276 | }
277 | if (TC1->COUNT16.INTFLAG.bit.MC0 == 1) {
278 | TC1->COUNT16.INTENSET.bit.MC0 = 1; // Clear flag
279 | }
280 | }
281 |
282 | #endif
283 | #endif
284 |
--------------------------------------------------------------------------------
/src/hardware/uTimerLib.STM32.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * \class uTimerLib
3 | * \brief Arduino tiny and cross-device compatible timer library.
4 | *
5 | * Timers used by each microcontroller:
6 | * * Atmel ATtiny: Timer1 (2nd timer) - https://github.com/damellis/attiny and https://github.com/SpenceKonde/Disgispark AVRCore (25, 45 and 85)
7 | * * DisgiSpark AVR: Timer0 (1st timer) - https://github.com/digistump/DigistumpArduino
8 | * * Atmel AVR 32U4: Timer3 (4rd timer)
9 | * * Atmel AVR other: Timer2 (3rd timer)
10 | * * STM32: Timer3 (3rd timer)
11 | * * SAM (Due): TC3 (Timer1, channel 0)
12 | * * ESP8266: OS Timer, one slot of seven available (Software timer provided by Arduino because ESP8266 has only two hardware timers and one is needed by it normal operation)
13 | * * ESP32: OS Hardware Timer.
14 | * * SAMD21: Timer 4, CC0 (TC3). See http://ww1.microchip.com/downloads/en/DeviceDoc/40001882A.pdf
15 | * * SAMD51: Timer 2 (TC1), 16 bits mode (See http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
16 | *
17 | * You have public TimerLib variable with following methods:
18 | * * TimerLib.setInterval_us(callback_function, microseconds);* : callback_function will be called each microseconds.
19 | * * TimerLib.setInterval_s(callback_function, seconds);* : callback_function will be called each seconds.
20 | * * TimerLib.setTimeout_us(callback_function, microseconds);* : callback_function will be called once when microseconds have passed.
21 | * * TimerLib.setTimeout_s(callback_function, seconds);* : callback_function will be called once when seconds have passed.
22 | * * TimerLib.clearTimer();* : will clear any timed function if exists.
23 | *
24 | * @file hardware/uTimerLib.ATTINY.cpp
25 | * @copyright Naguissa
26 | * @author Naguissa
27 | * @see https://github.com/Naguissa/uTimerLib
28 | * @see https://www.foroelectro.net/librerias-arduino-ide-f29/utimerlib-libreria-arduino-para-eventos-temporizad-t191.html
29 | * @see naguissa@foroelectro.net
30 | * @version 1.7.5
31 | */
32 | #if (defined(_VARIANT_ARDUINO_STM32_) || defined(ARDUINO_ARCH_STM32)) && defined(UTIMERLIB_HW_COMPILE)
33 | #ifndef _uTimerLib_IMP_
34 | #define _uTimerLib_IMP_
35 | #include "uTimerLib.cpp"
36 |
37 | volatile unsigned long int uTimerLib::_overflows = 0;
38 | volatile unsigned long int uTimerLib::__overflows = 0;
39 | volatile unsigned long int uTimerLib::_remaining = 0;
40 | volatile unsigned long int uTimerLib::__remaining = 0;
41 | volatile unsigned char uTimerLib::_type = UTIMERLIB_TYPE_OFF;
42 |
43 | void (*uTimerLib::_cb)() = NULL;
44 |
45 | /**
46 | * \brief Sets up the timer, calculation variables and interrupts for desired ms microseconds
47 | *
48 | * Note: This is device-dependant
49 | *
50 | * @param us Desired timing in microseconds
51 | */
52 | void uTimerLib::_attachInterrupt_us(unsigned long int us) {
53 | if (us == 0) { // Not valid
54 | return;
55 | }
56 |
57 | uTimerLib::__overflows = uTimerLib::_overflows = uTimerLib::__remaining = uTimerLib::_remaining = 0;
58 |
59 | // STM32, all variants - Max us is: uint32 max / CYCLES_PER_MICROSECOND
60 | // ST's Arduino Core STM32, https://github.com/stm32duino/Arduino_Core_STM32
61 | #ifdef BOARD_NAME
62 | Timer3->setMode(1, TIMER_OUTPUT_COMPARE);
63 | Timer3->setOverflow(us, MICROSEC_FORMAT);
64 | Timer3->setCaptureCompare(1, us - 1, MICROSEC_COMPARE_FORMAT);
65 | if (_toInit) {
66 | _toInit = false;
67 | Timer3->attachInterrupt(1, _instance->_interrupt);
68 | }
69 | Timer3->resume();
70 |
71 | // Roger Clark Arduino STM32, https://github.com/rogerclarkmelbourne/Arduino_STM32
72 | #else
73 | Timer3.setMode(TIMER_CH1, TIMER_OUTPUTCOMPARE);
74 | uint16_t timerOverflow = Timer3.setPeriod(us);
75 | Timer3.setCompare(TIMER_CH1, timerOverflow);
76 | if (_toInit) {
77 | _toInit = false;
78 | Timer3.attachInterrupt(TIMER_CH1, []() -> void { _instance->_interrupt(); });
79 | }
80 | Timer3.refresh();
81 | Timer3.resume();
82 | #endif
83 | }
84 |
85 |
86 | /**
87 | * \brief Sets up the timer, calculation variables and interrupts for desired s seconds
88 | *
89 | * Note: This is device-dependant
90 | *
91 | * @param s Desired timing in seconds
92 | */
93 | void uTimerLib::_attachInterrupt_s(unsigned long int s) {
94 | if (s == 0) { // Not valid
95 | return;
96 | }
97 |
98 | uTimerLib::__overflows = uTimerLib::_overflows = s;
99 | uTimerLib::__remaining = uTimerLib::_remaining = 0;
100 |
101 | // ST's Arduino Core STM32, https://github.com/stm32duino/Arduino_Core_STM32
102 | #ifdef BOARD_NAME
103 | Timer3->setMode(1, TIMER_OUTPUT_COMPARE);
104 | Timer3->setOverflow((unsigned long int) 1000000, MICROSEC_FORMAT);
105 | Timer3->setCaptureCompare(1, (unsigned long int) 1000000, MICROSEC_COMPARE_FORMAT);
106 | if (_toInit) {
107 | _toInit = false;
108 | Timer3->attachInterrupt((uint32_t) 1, []() -> void { uTimerLib::_interrupt(); });
109 | }
110 | Timer3->resume();
111 |
112 | // Roger Clark Arduino STM32, https://github.com/rogerclarkmelbourne/Arduino_STM32
113 | #else
114 | Timer3.setMode(TIMER_CH1, TIMER_OUTPUTCOMPARE);
115 | Timer3.setPeriod((uint32) 1000000);
116 | Timer3.setCompare(TIMER_CH1, 0);
117 | Timer3.setCount(1);
118 | if (_toInit) {
119 | _toInit = false;
120 | Timer3.attachInterrupt(TIMER_CH1, []() -> void { uTimerLib::_interrupt(); });
121 | }
122 | Timer3.refresh();
123 | Timer3.resume();
124 | #endif
125 | }
126 |
127 |
128 |
129 | /**
130 | * \brief Loads last bit of time needed to precisely count until desired time (non complete loop)
131 | *
132 | * Note: This is device-dependant
133 | */
134 | void uTimerLib::_loadRemaining() { }
135 |
136 | /**
137 | * \brief Clear timer interrupts
138 | *
139 | * Note: This is device-dependant
140 | */
141 | void uTimerLib::clearTimer() {
142 | uTimerLib::_type = UTIMERLIB_TYPE_OFF;
143 |
144 | // ST's Arduino Core STM32, https://github.com/stm32duino/Arduino_Core_STM32
145 | #ifdef BOARD_NAME
146 | Timer3->pause();
147 |
148 | // Roger Clark Arduino STM32, https://github.com/rogerclarkmelbourne/Arduino_STM32
149 | #else
150 | Timer3.pause();
151 | #endif
152 | }
153 |
154 | /**
155 | * \brief Internal intermediate function to control timer interrupts
156 | *
157 | * As timers doesn't give us enougth flexibility for large timings,
158 | * this function implements oferflow control to offer user desired timings.
159 | */
160 | // ST's Arduino Core STM32, https://github.com/stm32duino/Arduino_Core_STM32
161 | void uTimerLib::_interrupt() {
162 | if (uTimerLib::_type == UTIMERLIB_TYPE_OFF) { // Should not happen
163 | return;
164 | }
165 | // We are making X overflows, as much as seconds (none on us). So wee compare upper than 1
166 | if (uTimerLib::_overflows > 1) {
167 | --uTimerLib::_overflows;
168 | } else {
169 | uTimerLib::_overflows = uTimerLib::__overflows;
170 | if (uTimerLib::_type == UTIMERLIB_TYPE_TIMEOUT) {
171 | _instance->clearTimer();
172 | }
173 | uTimerLib::_cb();
174 | }
175 | }
176 |
177 |
178 | /**
179 | * \brief Preinstantiate Object
180 | *
181 | * Now you can use al functionality calling Timerlib.function
182 | */
183 | uTimerLib TimerLib = uTimerLib();
184 |
185 |
186 | #endif
187 | #endif
188 |
--------------------------------------------------------------------------------
/src/hardware/uTimerLib.UNSUPPORTED.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * \class uTimerLib
3 | * \brief Arduino tiny and cross-device compatible timer library.
4 | *
5 | * Timers used by each microcontroller:
6 | * * Atmel ATtiny: Timer1 (2nd timer) - https://github.com/damellis/attiny and https://github.com/SpenceKonde/Disgispark AVRCore (25, 45 and 85)
7 | * * DisgiSpark AVR: Timer0 (1st timer) - https://github.com/digistump/DigistumpArduino
8 | * * Atmel AVR 32U4: Timer3 (4rd timer)
9 | * * Atmel AVR other: Timer2 (3rd timer)
10 | * * STM32: Timer3 (3rd timer)
11 | * * SAM (Due): TC3 (Timer1, channel 0)
12 | * * ESP8266: OS Timer, one slot of seven available (Software timer provided by Arduino because ESP8266 has only two hardware timers and one is needed by it normal operation)
13 | * * ESP32: OS Hardware Timer.
14 | * * SAMD21: Timer 4, CC0 (TC3). See http://ww1.microchip.com/downloads/en/DeviceDoc/40001882A.pdf
15 | * * SAMD51: Timer 2 (TC1), 16 bits mode (See http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
16 | *
17 | * You have public TimerLib variable with following methods:
18 | * * TimerLib.setInterval_us(callback_function, microseconds);* : callback_function will be called each microseconds.
19 | * * TimerLib.setInterval_s(callback_function, seconds);* : callback_function will be called each seconds.
20 | * * TimerLib.setTimeout_us(callback_function, microseconds);* : callback_function will be called once when microseconds have passed.
21 | * * TimerLib.setTimeout_s(callback_function, seconds);* : callback_function will be called once when seconds have passed.
22 | * * TimerLib.clearTimer();* : will clear any timed function if exists.
23 | *
24 | * @file hardware/uTimerLib.ATTINY.cpp
25 | * @copyright Naguissa
26 | * @author Naguissa
27 | * @see https://github.com/Naguissa/uTimerLib
28 | * @see https://www.foroelectro.net/librerias-arduino-ide-f29/utimerlib-libreria-arduino-para-eventos-temporizad-t191.html
29 | * @see naguissa@foroelectro.net
30 | * @version 1.7.5
31 | */
32 | #if (!defined(__AVR_ATmega32U4__) && !defined(ARDUINO_ARCH_AVR) && !defined(_VARIANT_ARDUINO_STM32_) && !defined(ARDUINO_ARCH_STM32) && !defined(ARDUINO_ARCH_ESP8266) && !defined(ARDUINO_ARCH_ESP32) && !defined(ARDUINO_ARCH_SAM) && !defined(_SAMD21_) && !defined(__SAMD51__) && !defined(ARDUINO_attiny) && !defined(ARDUINO_AVR_ATTINYX5) && defined(UTIMERLIB_HW_COMPILE))
33 | #ifndef _uTimerLib_IMP_
34 | #define _uTimerLib_IMP_
35 | #include "uTimerLib.cpp"
36 |
37 | /**
38 | * \brief Sets up the timer, calculation variables and interrupts for desired ms microseconds
39 | *
40 | * Note: This is device-dependant
41 | *
42 | * @param us Desired timing in microseconds
43 | */
44 | void uTimerLib::_attachInterrupt_us(unsigned long int us) { }
45 |
46 |
47 | /**
48 | * \brief Sets up the timer, calculation variables and interrupts for desired s seconds
49 | *
50 | * Note: This is device-dependant
51 | *
52 | * @param s Desired timing in seconds
53 | */
54 | void uTimerLib::_attachInterrupt_s(unsigned long int s) { }
55 |
56 |
57 |
58 | /**
59 | * \brief Loads last bit of time needed to precisely count until desired time (non complete loop)
60 | *
61 | * Note: This is device-dependant
62 | */
63 | void uTimerLib::_loadRemaining() { }
64 |
65 | /**
66 | * \brief Clear timer interrupts
67 | *
68 | * Note: This is device-dependant
69 | */
70 | void uTimerLib::clearTimer() { }
71 |
72 | /**
73 | * \brief Internal intermediate function to control timer interrupts
74 | *
75 | * As timers doesn't give us enougth flexibility for large timings,
76 | * this function implements oferflow control to offer user desired timings.
77 | */
78 | void uTimerLib::_interrupt() {
79 | #pragma message "This board is unsupported. Please, report it on https://github.com/Naguissa/uTimerLib/issues"
80 | }
81 |
82 |
83 | /**
84 | * \brief Preinstantiate Object
85 | *
86 | * Now you can use al functionality calling Timerlib.function
87 | */
88 | uTimerLib TimerLib = uTimerLib();
89 |
90 | #endif
91 | #endif
92 |
--------------------------------------------------------------------------------
/src/uTimerLib.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * \class uTimerLib
3 | * \brief Arduino tiny and cross-device compatible timer library.
4 | *
5 | * Timers used by each microcontroller:
6 | * * Atmel ATtiny: Timer1 (2nd timer) - https://github.com/damellis/attiny and https://github.com/SpenceKonde/Disgispark AVRCore (25, 45 and 85)
7 | * * DisgiSpark AVR: Timer0 (1st timer) - https://github.com/digistump/DigistumpArduino
8 | * * Atmel AVR 32U4: Timer3 (4rd timer)
9 | * * Atmel AVR other: Timer2 (3rd timer)
10 | * * STM32: Timer3 (3rd timer)
11 | * * SAM (Due): TC3 (Timer1, channel 0)
12 | * * ESP8266: OS Timer, one slot of seven available (Software timer provided by Arduino because ESP8266 has only two hardware timers and one is needed by it normal operation)
13 | * * ESP32: OS Hardware Timer.
14 | * * SAMD21: Timer 4, CC0 (TC3). See http://ww1.microchip.com/downloads/en/DeviceDoc/40001882A.pdf
15 | * * SAMD51: Timer 2 (TC1), 16 bits mode (See http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
16 | *
17 | * You have public TimerLib variable with following methods:
18 | * * TimerLib.setInterval_us(callback_function, microseconds);* : callback_function will be called each microseconds.
19 | * * TimerLib.setInterval_s(callback_function, seconds);* : callback_function will be called each seconds.
20 | * * TimerLib.setTimeout_us(callback_function, microseconds);* : callback_function will be called once when microseconds have passed.
21 | * * TimerLib.setTimeout_s(callback_function, seconds);* : callback_function will be called once when seconds have passed.
22 | * * TimerLib.clearTimer();* : will clear any timed function if exists.
23 | *
24 | * @file hardware/uTimerLib.ATTINY.cpp
25 | * @copyright Naguissa
26 | * @author Naguissa
27 | * @see https://github.com/Naguissa/uTimerLib
28 | * @see https://www.foroelectro.net/librerias-arduino-ide-f29/utimerlib-libreria-arduino-para-eventos-temporizad-t191.html
29 | * @see naguissa@foroelectro.net
30 | * @version 1.7.5
31 | */
32 |
33 | // # if !defined(_uTimerLib_cpp_) && defined(_uTimerLib_IMP_)
34 | #ifndef _uTimerLib_cpp_
35 | #define _uTimerLib_cpp_
36 | #include "uTimerLib.h"
37 |
38 | // extern uTimerLib TimerLib;
39 |
40 | #if defined(_VARIANT_ARDUINO_STM32_) || defined(ARDUINO_ARCH_STM32)
41 | uTimerLib *uTimerLib::_instance = NULL;
42 | #endif
43 |
44 | /**
45 | * \brief Constructor
46 | */
47 | uTimerLib::uTimerLib() {}
48 |
49 | /**
50 | * \brief Attaches a callback function to be executed each us microseconds
51 | *
52 | * @param cb Callback function to be called
53 | * @param us Interval in microseconds
54 | */
55 | void uTimerLib::setInterval_us(void (* cb)(), unsigned long int us) {
56 | clearTimer();
57 | #if defined(_VARIANT_ARDUINO_STM32_) || defined(ARDUINO_ARCH_STM32)
58 | uTimerLib::_cb = cb;
59 | uTimerLib::_type = UTIMERLIB_TYPE_INTERVAL;
60 | #else
61 | _cb = cb;
62 | _type = UTIMERLIB_TYPE_INTERVAL;
63 | #endif
64 | _attachInterrupt_us(us);
65 | }
66 |
67 |
68 | /**
69 | * \brief Attaches a callback function to be executed once when us microseconds have passed
70 | *
71 | * @param cb Callback function to be called
72 | * @param us Timeout in microseconds
73 | */
74 | void uTimerLib::setTimeout_us(void (* cb)(), unsigned long int us) {
75 | clearTimer();
76 | #if defined(_VARIANT_ARDUINO_STM32_) || defined(ARDUINO_ARCH_STM32)
77 | uTimerLib::_cb = cb;
78 | uTimerLib::_type = UTIMERLIB_TYPE_TIMEOUT;
79 | #else
80 | _cb = cb;
81 | _type = UTIMERLIB_TYPE_TIMEOUT;
82 | #endif
83 | _attachInterrupt_us(us);
84 | }
85 |
86 |
87 | /**
88 | * \brief Attaches a callback function to be executed each s seconds
89 | *
90 | * @param cb Callback function to be called
91 | * @param s Interval in seconds
92 | */
93 | void uTimerLib::setInterval_s(void (* cb)(), unsigned long int s) {
94 | clearTimer();
95 | #if defined(_VARIANT_ARDUINO_STM32_) || defined(ARDUINO_ARCH_STM32)
96 | uTimerLib::_cb = cb;
97 | uTimerLib::_type = UTIMERLIB_TYPE_INTERVAL;
98 | #else
99 | _cb = cb;
100 | _type = UTIMERLIB_TYPE_INTERVAL;
101 | #endif
102 | _attachInterrupt_s(s);
103 | }
104 |
105 |
106 | /**
107 | * \brief Attaches a callback function to be executed once when s seconds have passed
108 | *
109 | * @param cb Callback function to be called
110 | * @param s Timeout in seconds
111 | */
112 | void uTimerLib::setTimeout_s(void (* cb)(), unsigned long int s) {
113 | clearTimer();
114 | #if defined(_VARIANT_ARDUINO_STM32_) || defined(ARDUINO_ARCH_STM32)
115 | uTimerLib::_cb = cb;
116 | uTimerLib::_type = UTIMERLIB_TYPE_TIMEOUT;
117 | #else
118 | _cb = cb;
119 | _type = UTIMERLIB_TYPE_TIMEOUT;
120 | #endif
121 | _attachInterrupt_s(s);
122 | }
123 |
124 | #define UTIMERLIB_HW_COMPILE
125 |
126 | // Now load each hardware variation support:
127 |
128 | #if (defined(__AVR_ATmega32U4__) || defined(ARDUINO_ARCH_AVR)) && !defined(ARDUINO_attiny) && !defined(ARDUINO_AVR_ATTINYX4) && !defined(ARDUINO_AVR_ATTINYX5) && !defined(ARDUINO_AVR_ATTINYX7) && !defined(ARDUINO_AVR_ATTINYX8) && !defined(ARDUINO_AVR_ATTINYX61) && !defined(ARDUINO_AVR_ATTINY43) && !defined(ARDUINO_AVR_ATTINY828) && !defined(ARDUINO_AVR_ATTINY1634) && !defined(ARDUINO_AVR_ATTINYX313) && !defined(ARDUINO_AVR_DIGISPARK)
129 | #include "hardware/uTimerLib.AVR.cpp"
130 | #endif
131 |
132 | #if defined(ARDUINO_ARCH_AVR) && (defined(ARDUINO_attiny) || defined(ARDUINO_AVR_ATTINYX4) || defined(ARDUINO_AVR_ATTINYX5) || defined(ARDUINO_AVR_ATTINYX7) || defined(ARDUINO_AVR_ATTINYX8) || defined(ARDUINO_AVR_ATTINYX61) || defined(ARDUINO_AVR_ATTINY43) || defined(ARDUINO_AVR_ATTINY828) || defined(ARDUINO_AVR_ATTINY1634) || defined(ARDUINO_AVR_ATTINYX313))
133 | #include "hardware/uTimerLib.ATTINY.cpp"
134 | #endif
135 |
136 | #if defined(ARDUINO_ARCH_AVR) && defined(ARDUINO_AVR_DIGISPARK)
137 | #include "hardware/uTimerLib.DIGISPARK_AVR.cpp"
138 | #endif
139 |
140 |
141 | #if defined(_VARIANT_ARDUINO_STM32_) || defined(ARDUINO_ARCH_STM32)
142 | #include "hardware/uTimerLib.STM32.cpp"
143 | #endif
144 |
145 | #if defined(ARDUINO_ARCH_ESP32)
146 | #include "hardware/uTimerLib.ESP32.cpp"
147 | #endif
148 |
149 | #if defined(ARDUINO_ARCH_ESP8266)
150 | #include "hardware/uTimerLib.ESP8266.cpp"
151 | #endif
152 |
153 | #ifdef ARDUINO_ARCH_SAM
154 | #include "hardware/uTimerLib.SAM.cpp"
155 | #endif
156 | #ifdef _SAMD21_
157 | #include "hardware/uTimerLib.SAMD21.cpp"
158 | #endif
159 | #ifdef __SAMD51__
160 | #include "hardware/uTimerLib.SAMD51.cpp"
161 | #endif
162 |
163 |
164 | #if !defined(__AVR_ATmega32U4__) && !defined(ARDUINO_ARCH_AVR) && !defined(_VARIANT_ARDUINO_STM32_) && !defined(ARDUINO_ARCH_STM32) && !defined(ARDUINO_ARCH_ESP8266) && !defined(ARDUINO_ARCH_ESP32) && !defined(ARDUINO_ARCH_SAM) && !defined(_SAMD21_) && !defined(__SAMD51__) && !defined(ARDUINO_attiny) && !defined(ARDUINO_AVR_ATTINYX5) && !defined(ARDUINO_AVR_DIGISPARK)
165 | #include "hardware/uTimerLib.UNSUPPORTED.cpp"
166 | #endif
167 |
168 | #endif
169 |
--------------------------------------------------------------------------------
/src/uTimerLib.h:
--------------------------------------------------------------------------------
1 | /**
2 | * \mainpage
3 | * \brief Arduino tiny and cross-device compatible timer library.
4 | *
5 | * Timers used by each microcontroller:
6 | * * Atmel ATtiny: Timer1 (2nd timer) - https://github.com/damellis/attiny and https://github.com/SpenceKonde/Disgispark AVRCore (25, 45 and 85)
7 | * * DisgiSpark AVR: Timer0 (1st timer) - https://github.com/digistump/DigistumpArduino
8 | * * Atmel AVR 32U4: Timer3 (4rd timer)
9 | * * Atmel AVR other: Timer2 (3rd timer)
10 | * * STM32: Timer3 (3rd timer)
11 | * * SAM (Due): TC3 (Timer1, channel 0)
12 | * * ESP8266: OS Timer, one slot of seven available (Software timer provided by Arduino because ESP8266 has only two hardware timers and one is needed by it normal operation)
13 | * * ESP32: OS Hardware Timer.
14 | * * SAMD21: Timer 4, CC0 (TC3). See http://ww1.microchip.com/downloads/en/DeviceDoc/40001882A.pdf
15 | * * SAMD51: Timer 2 (TC1), 16 bits mode (See http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
16 | *
17 | * You have public TimerLib variable with following methods:
18 | * * TimerLib.setInterval_us(callback_function, microseconds);* : callback_function will be called each microseconds.
19 | * * TimerLib.setInterval_s(callback_function, seconds);* : callback_function will be called each seconds.
20 | * * TimerLib.setTimeout_us(callback_function, microseconds);* : callback_function will be called once when microseconds have passed.
21 | * * TimerLib.setTimeout_s(callback_function, seconds);* : callback_function will be called once when seconds have passed.
22 | * * TimerLib.clearTimer();* : will clear any timed function if exists.
23 | *
24 | * @file hardware/uTimerLib.ATTINY.cpp
25 | * @copyright Naguissa
26 | * @author Naguissa
27 | * @see https://github.com/Naguissa/uTimerLib
28 | * @see https://www.foroelectro.net/librerias-arduino-ide-f29/utimerlib-libreria-arduino-para-eventos-temporizad-t191.html
29 | * @see naguissa@foroelectro.net
30 | * @version 1.7.5
31 | */
32 | /** \file uTimerLib.h
33 | * \brief uTimerLib header file
34 | */
35 | #ifndef _uTimerLib_
36 | /**
37 | * \brief Prevent multiple inclussion
38 | */
39 | #define _uTimerLib_
40 |
41 | #include "Arduino.h"
42 |
43 | #if defined(ARDUINO_ARCH_ESP8266)
44 | #include //Ticker Library
45 | #endif
46 |
47 | #if defined(ARDUINO_ARCH_ESP32)
48 | #include "esp_timer.h"
49 | #endif
50 |
51 | // Operation modes
52 | /**
53 | * \brief Internal status
54 | */
55 | #define UTIMERLIB_TYPE_OFF 0
56 | /**
57 | * \brief Internal status
58 | */
59 | #define UTIMERLIB_TYPE_TIMEOUT 1
60 | /**
61 | * \brief Internal status
62 | */
63 | #define UTIMERLIB_TYPE_INTERVAL 2
64 |
65 | #if defined(_VARIANT_ARDUINO_STM32_) || defined(ARDUINO_ARCH_STM32)
66 | #include "HardwareTimer.h"
67 |
68 | // ST's Arduino Core STM32, https://github.com/stm32duino/Arduino_Core_STM32
69 | #ifdef BOARD_NAME
70 | // Private member
71 |
72 | // Roger Clark Arduino STM32, https://github.com/rogerclarkmelbourne/Arduino_STM32
73 | #else
74 | extern HardwareTimer Timer3;
75 | #endif
76 | #endif
77 |
78 | class uTimerLib {
79 | public:
80 | uTimerLib();
81 | void setInterval_us(void (*) (), unsigned long int);
82 | void setInterval_s(void (*) (), unsigned long int);
83 | void setTimeout_us(void (*) (), unsigned long int);
84 | void setTimeout_s(void (*) (), unsigned long int);
85 |
86 | /**
87 | * \brief Loads last bit of time needed to precisely count until desired time (non complete loop)
88 | *
89 | * Note: This is device-dependant
90 | */
91 | void clearTimer();
92 |
93 |
94 | #if defined(_VARIANT_ARDUINO_STM32_) || defined(ARDUINO_ARCH_STM32)
95 | volatile static unsigned long int _overflows;
96 | volatile static unsigned long int __overflows;
97 | volatile static unsigned long int _remaining;
98 | volatile static unsigned long int __remaining;
99 | static void (*_cb)();
100 | static void _interrupt();
101 | volatile static unsigned char _type;
102 | #else
103 | /**
104 | * \brief Internal intermediate function to control timer interrupts
105 | *
106 | * As timers doesn't give us enougth flexibility for large timings,
107 | * this function implements oferflow control to offer user desired timings.
108 | */
109 | void _interrupt();
110 | #endif
111 |
112 | #if defined(ARDUINO_ARCH_ESP32)
113 | static void interrupt(void* arg);
114 | #endif
115 |
116 | #if defined(ARDUINO_ARCH_ESP8266)
117 | #pragma message "ESP8266 can only reach a ms resolution so any us interrupt will be rounded to that"
118 | static void interrupt();
119 | #endif
120 |
121 | #ifdef _SAMD21_
122 | TcCount16* _TC = (TcCount16*) TC3;
123 | #endif
124 |
125 | #ifdef __SAMD51__
126 | #pragma message "SAMD51 support is still experimental"
127 | #endif
128 |
129 | private:
130 | static uTimerLib *_instance;
131 |
132 | #if defined(_VARIANT_ARDUINO_STM32_) || defined(ARDUINO_ARCH_STM32)
133 | bool _toInit = true;
134 |
135 | // ST's Arduino Core STM32, https://github.com/stm32duino/Arduino_Core_STM32
136 | #ifdef BOARD_NAME
137 | HardwareTimer *Timer3 = new HardwareTimer(TIM3);
138 | #endif
139 | #else
140 | volatile unsigned long int _overflows = 0;
141 | volatile unsigned long int __overflows = 0;
142 | #ifdef ARDUINO_ARCH_AVR
143 | volatile unsigned char _remaining = 0;
144 | volatile unsigned char __remaining = 0;
145 | #else
146 | volatile unsigned long int _remaining = 0;
147 | volatile unsigned long int __remaining = 0;
148 | #endif
149 | void (*_cb)() = NULL;
150 | volatile unsigned char _type = UTIMERLIB_TYPE_OFF;
151 | #endif
152 |
153 | void _loadRemaining();
154 |
155 | void _attachInterrupt_us(unsigned long int);
156 | void _attachInterrupt_s(unsigned long int);
157 |
158 |
159 | #if defined(ARDUINO_ARCH_ESP32)
160 | esp_timer_handle_t _timer;
161 | #endif
162 |
163 | #if defined(ARDUINO_ARCH_ESP8266)
164 | Ticker _ticker;
165 | #endif
166 |
167 | };
168 |
169 | /**
170 | * \brief Declares TimerLib variable to access this library's methods
171 | */
172 | extern uTimerLib TimerLib;
173 |
174 | #endif
175 |
176 |
--------------------------------------------------------------------------------