57
57
// Waveform generator can create tones, PWM, and servos
58
58
typedef struct {
59
59
uint32_t nextServiceCycle ; // ESP cycle timer when a transition required
60
- uint32_t timeLeftCycles ; // For time-limited waveform, how many ESP cycles left
60
+ uint32_t expiryCycle ; // For time-limited waveform, the cycle when this waveform must stop
61
61
uint32_t nextTimeHighCycles ; // Copy over low->high to keep smooth waveform
62
62
uint32_t nextTimeLowCycles ; // Copy over high->low to keep smooth waveform
63
63
} Waveform ;
@@ -86,13 +86,11 @@ static inline ICACHE_RAM_ATTR uint32_t GetCycleCount() {
86
86
// Interrupt on/off control
87
87
static ICACHE_RAM_ATTR void timer1Interrupt ();
88
88
static bool timerRunning = false;
89
- static uint32_t lastCycleCount = 0 ; // Last ESP cycle counter on running the interrupt routine
90
89
91
90
static void initTimer () {
92
91
timer1_disable ();
93
92
ETS_FRC_TIMER1_INTR_ATTACH (NULL , NULL );
94
93
ETS_FRC_TIMER1_NMI_INTR_ATTACH (timer1Interrupt );
95
- lastCycleCount = GetCycleCount ();
96
94
timer1_enable (TIM_DIV1 , TIM_EDGE , TIM_SINGLE );
97
95
timerRunning = true;
98
96
}
@@ -130,7 +128,11 @@ int startWaveform(uint8_t pin, uint32_t timeHighUS, uint32_t timeLowUS, uint32_t
130
128
wave -> nextTimeHighCycles = MicrosecondsToCycles (timeHighUS ) > 280 ? MicrosecondsToCycles (timeHighUS ) - 280 : MicrosecondsToCycles (timeHighUS ); // Take out some time for IRQ codepath
131
129
wave -> nextTimeLowCycles = MicrosecondsToCycles (timeLowUS ) > 280 ? MicrosecondsToCycles (timeLowUS )- 280 : MicrosecondsToCycles (timeLowUS ); // Take out some time for IRQ codepath
132
130
#endif
133
- wave -> timeLeftCycles = MicrosecondsToCycles (runTimeUS );
131
+ wave -> expiryCycle = runTimeUS ? GetCycleCount () + MicrosecondsToCycles (runTimeUS ) : 0 ;
132
+ if (runTimeUS && !wave -> expiryCycle ) {
133
+ wave -> expiryCycle = 1 ; // expiryCycle==0 means no timeout, so avoid setting it
134
+ }
135
+
134
136
uint32_t mask = 1 <<pin ;
135
137
if (!waveformEnabled && mask ) {
136
138
// Actually set the pin high or low in the IRQ service to guarantee times
@@ -193,9 +195,9 @@ int ICACHE_RAM_ATTR stopWaveform(uint8_t pin) {
193
195
static ICACHE_RAM_ATTR void timer1Interrupt () {
194
196
uint32_t nextEventCycles ;
195
197
#if F_CPU == 160000000
196
- uint8_t cnt = 20 ;
198
+ int cnt = 20 ;
197
199
#else
198
- uint8_t cnt = 5 ;
200
+ int cnt = 10 ;
199
201
#endif
200
202
201
203
// Handle enable/disable requests from main app.
@@ -215,10 +217,21 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
215
217
}
216
218
217
219
Waveform * wave = & waveform [i ];
218
- uint32_t now ;
220
+ uint32_t now = GetCycleCountIRQ ();
221
+
222
+ // Disable any waveforms that are done
223
+ if (wave -> expiryCycle ) {
224
+ int32_t expiryToGo = wave -> expiryCycle - now ;
225
+ if (expiryToGo < 0 ) {
226
+ // Done, remove!
227
+ waveformEnabled &= ~mask ;
228
+ if (i == 16 ) GP16O &= ~1 ;
229
+ else ClearGPIO (mask );
230
+ continue ;
231
+ }
232
+ }
219
233
220
234
// Check for toggles
221
- now = GetCycleCountIRQ ();
222
235
int32_t cyclesToGo = wave -> nextServiceCycle - now ;
223
236
if (cyclesToGo < 0 ) {
224
237
waveformState ^= mask ;
@@ -242,28 +255,6 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
242
255
}
243
256
} while (-- cnt && (nextEventCycles < MicrosecondsToCycles (4 )));
244
257
245
- uint32_t curCycleCount = GetCycleCountIRQ ();
246
- uint32_t deltaCycles = curCycleCount - lastCycleCount ;
247
- lastCycleCount = curCycleCount ;
248
-
249
- // Check for timed-out waveforms out of the high-frequency toggle loop
250
- for (size_t i = 0 ; i <= 16 ; i ++ ) {
251
- Waveform * wave = & waveform [i ];
252
- uint32_t mask = 1 <<i ;
253
- if ((waveformEnabled & mask ) && wave -> timeLeftCycles ) {
254
- // Check for unsigned underflow with new > old
255
- if (deltaCycles >= wave -> timeLeftCycles ) {
256
- // Done, remove!
257
- waveformEnabled &= ~mask ;
258
- if (i == 16 ) GP16O &= ~1 ;
259
- else ClearGPIO (mask );
260
- } else {
261
- uint32_t newTimeLeftCycles = wave -> timeLeftCycles - deltaCycles ;
262
- wave -> timeLeftCycles = newTimeLeftCycles ;
263
- }
264
- }
265
- }
266
-
267
258
if (timer1CB ) {
268
259
nextEventCycles = min_u32 (nextEventCycles , timer1CB ());
269
260
}
@@ -284,6 +275,6 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
284
275
#endif
285
276
286
277
// Do it here instead of global function to save time and because we know it's edge-IRQ
287
- T1L = nextEventCycles ; // Already know we're in range by MAXIRQUS
288
278
TEIE |= TEIE1 ; //edge int enable
279
+ T1L = nextEventCycles ; // Already know we're in range by MAXIRQUS
289
280
}
0 commit comments