├── .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: [![Build Status](https://travis-ci.org/Naguissa/uTimerLib.svg?branch=master)](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 | --------------------------------------------------------------------------------