@@ -51,7 +51,11 @@ constexpr int32_t MAXIRQTICKSCCYS = microsecondsToClockCycles(10000);
5151// Maximum servicing time for any single IRQ
5252constexpr uint32_t ISRTIMEOUTCCYS = microsecondsToClockCycles(18 );
5353// 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 );
5559
5660// for INFINITE, the NMI proceeds on the waveform without expiry deadline.
5761// 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
251255}
252256
253257static ICACHE_RAM_ATTR void timer1Interrupt () {
254- const bool isCPU2X = CPU2X & 1 ;
255258 const uint32_t isrStartCcy = ESP.getCycleCount ();
259+ int32_t clockDrift = isrStartCcy - waveform.nextEventCcy - DELTAIRQCCYS;
260+ const bool isCPU2X = CPU2X & 1 ;
256261 if ((waveform.toSetBits && !(waveform.enabled & waveform.toSetBits )) || waveform.toDisableBits ) {
257262 // Handle enable/disable requests from main app.
258263 waveform.enabled = (waveform.enabled & ~waveform.toDisableBits ) | waveform.toSetBits ; // Set the requested waveforms on/off
@@ -268,13 +273,9 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
268273 waveform.states &= ~waveform.toSetBits ; // Clear the state of any just started
269274 if (wave.alignPhase >= 0 && waveform.enabled & (1UL << wave.alignPhase )) {
270275 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- }
274276 }
275277 else {
276- wave.nextPeriodCcy = isrStartCcy;
277- waveform.nextEventCcy = wave.nextPeriodCcy ;
278+ wave.nextPeriodCcy = waveform.nextEventCcy ;
278279 }
279280 if (!wave.expiryCcy ) {
280281 wave.mode = WaveformMode::INFINITE;
@@ -294,10 +295,8 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
294295
295296 // Exit the loop if the next event, if any, is sufficiently distant.
296297 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;
301300
302301 uint32_t now = ESP.getCycleCount ();
303302 uint32_t isrNextEventCcy = now;
@@ -315,6 +314,12 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
315314
316315 Waveform& wave = waveform.pins [pin];
317316
317+ if (clockDrift) {
318+ wave.endDutyCcy += clockDrift;
319+ wave.nextPeriodCcy += clockDrift;
320+ wave.expiryCcy += clockDrift;
321+ }
322+
318323 uint32_t waveNextEventCcy = (waveform.states & pinBit) ? wave.endDutyCcy : wave.nextPeriodCcy ;
319324 if (WaveformMode::EXPIRES == wave.mode &&
320325 static_cast <int32_t >(waveNextEventCcy - wave.expiryCcy ) >= 0 &&
@@ -394,29 +399,32 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
394399 }
395400 now = ESP.getCycleCount ();
396401 }
402+ clockDrift = 0 ;
397403 }
398404
399405 int32_t callbackCcys = 0 ;
400406 if (waveform.timer1CB ) {
401407 callbackCcys = scaleCcys (microsecondsToClockCycles (waveform.timer1CB ()), isCPU2X);
402408 }
403409 now = ESP.getCycleCount ();
404- int32_t nextTimerCcys = waveform.nextEventCcy - now;
410+ int32_t nextEventCcys = waveform.nextEventCcy - now;
405411 // 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;
408415 }
409416
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 ;
413420 }
414421
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;
418426 }
419427
420428 // Register access is fast and edge IRQ was configured before.
421- T1L = nextTimerCcys ;
429+ T1L = nextEventCcys ;
422430}
0 commit comments