@@ -51,7 +51,11 @@ constexpr int32_t MAXIRQTICKSCCYS = microsecondsToClockCycles(10000);
51
51
// Maximum servicing time for any single IRQ
52
52
constexpr uint32_t ISRTIMEOUTCCYS = microsecondsToClockCycles(18 );
53
53
// The latency between in-ISR rearming of the timer and the earliest firing
54
- constexpr int32_t IRQLATENCYCCYS = microsecondsToClockCycles(2 );
54
+ constexpr int32_t IRQLATENCYCCYS = ISCPUFREQ160MHZ ?
55
+ microsecondsToClockCycles (2 ) >> 1 : microsecondsToClockCycles(2 );
56
+ // The SDK and hardware take some time to actually get to our NMI code
57
+ constexpr int32_t DELTAIRQCCYS = ISCPUFREQ160MHZ ?
58
+ microsecondsToClockCycles (2 ) >> 1 : microsecondsToClockCycles(2 );
55
59
56
60
// for INFINITE, the NMI proceeds on the waveform without expiry deadline.
57
61
// for EXPIRES, the NMI expires the waveform automatically on the expiry ccy.
@@ -251,8 +255,9 @@ static inline ICACHE_RAM_ATTR int32_t scaleCcys(const int32_t ccys, const bool i
251
255
}
252
256
253
257
static ICACHE_RAM_ATTR void timer1Interrupt () {
254
- const bool isCPU2X = CPU2X & 1 ;
255
258
const uint32_t isrStartCcy = ESP.getCycleCount ();
259
+ int32_t clockDrift = isrStartCcy - waveform.nextEventCcy - DELTAIRQCCYS;
260
+ const bool isCPU2X = CPU2X & 1 ;
256
261
if ((waveform.toSetBits && !(waveform.enabled & waveform.toSetBits )) || waveform.toDisableBits ) {
257
262
// Handle enable/disable requests from main app.
258
263
waveform.enabled = (waveform.enabled & ~waveform.toDisableBits ) | waveform.toSetBits ; // Set the requested waveforms on/off
@@ -268,13 +273,9 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
268
273
waveform.states &= ~waveform.toSetBits ; // Clear the state of any just started
269
274
if (wave.alignPhase >= 0 && waveform.enabled & (1UL << wave.alignPhase )) {
270
275
wave.nextPeriodCcy = waveform.pins [wave.alignPhase ].nextPeriodCcy + wave.nextPeriodCcy ;
271
- if (static_cast <int32_t >(waveform.nextEventCcy - wave.nextPeriodCcy ) > 0 ) {
272
- waveform.nextEventCcy = wave.nextPeriodCcy ;
273
- }
274
276
}
275
277
else {
276
- wave.nextPeriodCcy = isrStartCcy;
277
- waveform.nextEventCcy = wave.nextPeriodCcy ;
278
+ wave.nextPeriodCcy = waveform.nextEventCcy ;
278
279
}
279
280
if (!wave.expiryCcy ) {
280
281
wave.mode = WaveformMode::INFINITE;
@@ -294,10 +295,8 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
294
295
295
296
// Exit the loop if the next event, if any, is sufficiently distant.
296
297
const uint32_t isrTimeoutCcy = isrStartCcy + ISRTIMEOUTCCYS;
297
- uint32_t busyPins = (static_cast <int32_t >(waveform.nextEventCcy - isrTimeoutCcy) < 0 ) ? waveform.enabled : 0 ;
298
- if (!waveform.enabled || busyPins) {
299
- waveform.nextEventCcy = isrStartCcy + MAXIRQTICKSCCYS;
300
- }
298
+ uint32_t busyPins = waveform.enabled ;
299
+ waveform.nextEventCcy = isrStartCcy + MAXIRQTICKSCCYS;
301
300
302
301
uint32_t now = ESP.getCycleCount ();
303
302
uint32_t isrNextEventCcy = now;
@@ -315,6 +314,12 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
315
314
316
315
Waveform& wave = waveform.pins [pin];
317
316
317
+ if (clockDrift) {
318
+ wave.endDutyCcy += clockDrift;
319
+ wave.nextPeriodCcy += clockDrift;
320
+ wave.expiryCcy += clockDrift;
321
+ }
322
+
318
323
uint32_t waveNextEventCcy = (waveform.states & pinBit) ? wave.endDutyCcy : wave.nextPeriodCcy ;
319
324
if (WaveformMode::EXPIRES == wave.mode &&
320
325
static_cast <int32_t >(waveNextEventCcy - wave.expiryCcy ) >= 0 &&
@@ -394,29 +399,32 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
394
399
}
395
400
now = ESP.getCycleCount ();
396
401
}
402
+ clockDrift = 0 ;
397
403
}
398
404
399
405
int32_t callbackCcys = 0 ;
400
406
if (waveform.timer1CB ) {
401
407
callbackCcys = scaleCcys (microsecondsToClockCycles (waveform.timer1CB ()), isCPU2X);
402
408
}
403
409
now = ESP.getCycleCount ();
404
- int32_t nextTimerCcys = waveform.nextEventCcy - now;
410
+ int32_t nextEventCcys = waveform.nextEventCcy - now;
405
411
// Account for unknown duration of timer1CB().
406
- if (waveform.timer1CB && nextTimerCcys > callbackCcys) {
407
- nextTimerCcys = callbackCcys;
412
+ if (waveform.timer1CB && nextEventCcys > callbackCcys) {
413
+ waveform.nextEventCcy = now + callbackCcys;
414
+ nextEventCcys = callbackCcys;
408
415
}
409
416
410
- // Firing timer too soon, the NMI occurs before ISR has returned .
411
- if (nextTimerCcys < IRQLATENCYCCYS ) {
412
- nextTimerCcys = IRQLATENCYCCYS ;
417
+ // Timer is 80MHz fixed. 160MHz CPU frequency need scaling .
418
+ if (isCPU2X ) {
419
+ nextEventCcys >>= 1 ;
413
420
}
414
421
415
- // Timer is 80MHz fixed. 160MHz CPU frequency need scaling.
416
- if (ISCPUFREQ160MHZ || isCPU2X) {
417
- nextTimerCcys >>= 1 ;
422
+ // Firing timer too soon, the NMI occurs before ISR has returned.
423
+ if (nextEventCcys < IRQLATENCYCCYS) {
424
+ waveform.nextEventCcy = now + IRQLATENCYCCYS;
425
+ nextEventCcys = IRQLATENCYCCYS;
418
426
}
419
427
420
428
// Register access is fast and edge IRQ was configured before.
421
- T1L = nextTimerCcys ;
429
+ T1L = nextEventCcys ;
422
430
}
0 commit comments