Skip to content

Commit 07dd886

Browse files
V1.7.02a Updates
- Forgot to commit this
1 parent a1c50cb commit 07dd886

File tree

7 files changed

+2103
-0
lines changed

7 files changed

+2103
-0
lines changed
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
/****************************************************************************************************************************
2+
ESP8266TimerInterrupt.h
3+
For ESP8266 boards
4+
Written by Khoi Hoang
5+
6+
Built by Khoi Hoang https://github.com/khoih-prog/ESP32TimerInterrupt
7+
Licensed under MIT license
8+
Version: 1.0.3
9+
10+
The ESP8266 timers are badly designed, using only 23-bit counter along with maximum 256 prescaler. They're only better than UNO / Mega.
11+
The ESP8266 has two hardware timers, but timer0 has been used for WiFi and it's not advisable to use. Only timer1 is available.
12+
The timer1's 23-bit counter terribly can count only up to 8,388,607. So the timer1 maximum interval is very short.
13+
Using 256 prescaler, maximum timer1 interval is only 26.843542 seconds !!!
14+
15+
Now with these new 16 ISR-based timers, the maximum interval is practically unlimited (limited only by unsigned long miliseconds)
16+
The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers
17+
Therefore, their executions are not blocked by bad-behaving functions / tasks.
18+
This important feature is absolutely necessary for mission-critical tasks.
19+
20+
Based on SimpleTimer - A timer library for Arduino.
21+
Author: mromani@ottotecnica.com
22+
Copyright (c) 2010 OTTOTECNICA Italy
23+
24+
Based on BlynkTimer.h
25+
Author: Volodymyr Shymanskyy
26+
27+
Version Modified By Date Comments
28+
------- ----------- ---------- -----------
29+
1.0.0 K Hoang 23/11/2019 Initial coding
30+
1.0.1 K Hoang 25/11/2019 New release fixing compiler error
31+
1.0.2 K.Hoang 26/11/2019 Permit up to 16 super-long-time, super-accurate ISR-based timers to avoid being blocked
32+
1.0.3 K.Hoang 17/05/2020 Restructure code. Fix example. Enhance README.
33+
*****************************************************************************************************************************/
34+
35+
#ifndef ESP8266TimerInterrupt_h
36+
#define ESP8266TimerInterrupt_h
37+
38+
#if !defined(ESP8266)
39+
#error This code is designed to run on ESP8266 and ESP8266-based boards! Please check your Tools->Board setting.
40+
#endif
41+
42+
#ifndef TIMER_INTERRUPT_DEBUG
43+
#define TIMER_INTERRUPT_DEBUG 0
44+
#endif
45+
46+
#ifndef ESP8266
47+
#error This code is designed to run on ESP8266 platform, not Arduino nor ESP32! Please check your Tools->Board setting.
48+
#endif
49+
50+
/* From /arduino-1.8.10/hardware/esp8266com/esp8266/cores/esp8266/esp8266_peri.h
51+
52+
#define ESP8266_REG(addr) *((volatile uint32_t *)(0x60000000+(addr)))
53+
#define ESP8266_DREG(addr) *((volatile uint32_t *)(0x3FF00000+(addr)))
54+
#define ESP8266_CLOCK 80000000UL
55+
56+
//CPU Register
57+
#define CPU2X ESP8266_DREG(0x14) //when bit 0 is set, F_CPU = 160MHz
58+
*/
59+
60+
/* From /arduino-1.8.10/hardware/esp8266com/esp8266/cores/esp8266/Arduino.h
61+
62+
//timer dividers
63+
enum TIM_DIV_ENUM {
64+
TIM_DIV1 = 0, // 80 / 160 MHz (80 / 160 ticks/us - 104857.588 us max)
65+
TIM_DIV16 = 1, // 5 / 10 MHz (5 / 10 ticks/us - 1677721.4 us max)
66+
TIM_DIV256 = 3 // 312.5 / 625 Khz (1 tick = 3.2 / 1.6 us - 26843542.4 us max)
67+
};
68+
69+
//timer int_types
70+
#define TIM_EDGE 0
71+
#define TIM_LEVEL 1
72+
//timer reload values
73+
#define TIM_SINGLE 0 //on interrupt routine you need to write a new value to start the timer again
74+
#define TIM_LOOP 1 //on interrupt the counter will start with the same value again
75+
76+
*/
77+
78+
// ESP8266 only has one usable timer1, max count is only 8,388,607. So to get longer time, we use max available 256 divider
79+
class ESP8266TimerInterrupt;
80+
81+
typedef ESP8266TimerInterrupt ESP8266Timer;
82+
83+
#define MAX_ESP8266_NUM_TIMERS 1
84+
#define MAX_ESP8266_COUNT 8388607
85+
86+
typedef void (*timer_callback) (void);
87+
88+
89+
class ESP8266TimerInterrupt
90+
{
91+
private:
92+
timer_callback _callback; // pointer to the callback function
93+
float _frequency; // Timer frequency
94+
uint32_t _timerCount; // count to activate timer
95+
96+
public:
97+
98+
ESP8266TimerInterrupt()
99+
{
100+
_frequency = 0;
101+
_timerCount = 0;
102+
_callback = NULL;
103+
};
104+
105+
// frequency (in hertz) and duration (in milliseconds). Duration = 0 or not specified => run indefinitely
106+
// No params and duration now. To be addes in the future by adding similar functions here or to esp32-hal-timer.c
107+
bool setFrequency(float frequency, timer_callback callback)
108+
{
109+
#if (TIMER_INTERRUPT_DEBUG > 0)
110+
Serial.println("setFrequency : freq " + String(frequency, 5));
111+
#endif
112+
bool isOKFlag = true;
113+
114+
// ESP8266 only has one usable timer1, max count is only 8,388,607. So to get longer time, we use max available 256 divider
115+
// Will use later if very low frequency is needed.
116+
_frequency = 80000000 / 256;
117+
#if (TIMER_INTERRUPT_DEBUG > 0)
118+
Serial.println("setFrequency : const freq " + String(_frequency, 5));
119+
#endif
120+
_timerCount = (uint32_t) _frequency / frequency;
121+
#if (TIMER_INTERRUPT_DEBUG > 0)
122+
Serial.println("setFrequency : timercount " + String(_timerCount));
123+
#endif
124+
_callback = callback;
125+
126+
if ( _timerCount > MAX_ESP8266_COUNT)
127+
{
128+
_timerCount = MAX_ESP8266_COUNT;
129+
// Flag error
130+
isOKFlag = false;
131+
}
132+
133+
// count up
134+
#if (TIMER_INTERRUPT_DEBUG > 0)
135+
Serial.println("ESP8266TimerInterrupt: _fre = " + String(_frequency) + ", _count = " + String(_timerCount));
136+
#endif
137+
138+
// Clock to timer (prescaler) is always 80MHz, even F_CPU is 160 MHz
139+
140+
timer1_attachInterrupt(callback);
141+
142+
timer1_write(_timerCount);
143+
144+
// Interrupt on EGDE, autoloop
145+
timer1_enable(TIM_DIV256, TIM_EDGE, TIM_LOOP);
146+
147+
return isOKFlag;
148+
}
149+
150+
// interval (in microseconds) and duration (in milliseconds). Duration = 0 or not specified => run indefinitely
151+
// No params and duration now. To be addes in the future by adding similar functions here or to esp32-hal-timer.c
152+
bool setInterval(unsigned long interval, timer_callback callback)
153+
{
154+
return setFrequency((float) (1000000.0f / interval), callback);
155+
}
156+
157+
bool attachInterrupt(float frequency, timer_callback callback)
158+
{
159+
return setFrequency(frequency, callback);
160+
}
161+
162+
// interval (in microseconds) and duration (in milliseconds). Duration = 0 or not specified => run indefinitely
163+
// No params and duration now. To be addes in the future by adding similar functions here or to esp32-hal-timer.c
164+
bool attachInterruptInterval(unsigned long interval, timer_callback callback)
165+
{
166+
return setFrequency( (float) ( 1000000.0f / interval), callback);
167+
}
168+
169+
void detachInterrupt()
170+
{
171+
timer1_disable();
172+
}
173+
174+
void disableTimer(void)
175+
{
176+
timer1_disable();
177+
}
178+
179+
// Duration (in milliseconds). Duration = 0 or not specified => run indefinitely
180+
void reattachInterrupt()
181+
{
182+
if ( (_frequency != 0) && (_timerCount != 0) && (_callback != NULL) )
183+
setFrequency(_frequency, _callback);
184+
}
185+
186+
// Duration (in milliseconds). Duration = 0 or not specified => run indefinitely
187+
void enableTimer(void)
188+
{
189+
reattachInterrupt();
190+
}
191+
192+
// Just stop clock source, clear the count
193+
void stopTimer(void)
194+
{
195+
timer1_disable();
196+
}
197+
198+
// Just reconnect clock source, start current count from 0
199+
void restartTimer(void)
200+
{
201+
enableTimer();
202+
}
203+
}; // class ESP8266TimerInterrupt
204+
205+
#endif //#ifndef ESP8266TimerInterrupt_h

0 commit comments

Comments
 (0)