@@ -54,7 +54,7 @@ constexpr uint32_t ISRTIMEOUTCCYS = microsecondsToClockCycles(14);
54
54
// decrement the next IRQ's timer value by a bit so we can actually catch the
55
55
// real CPU cycle count we want for the waveforms.
56
56
constexpr int32_t DELTAIRQ = clockCyclesPerMicrosecond() == 160 ?
57
- microsecondsToClockCycles (3 ) >> 1 : microsecondsToClockCycles(3 );
57
+ microsecondsToClockCycles (4 ) >> 1 : microsecondsToClockCycles(4 );
58
58
// The latency between in-ISR rearming of the timer and the earliest firing
59
59
constexpr int32_t IRQLATENCY = clockCyclesPerMicrosecond() == 160 ?
60
60
microsecondsToClockCycles (3 ) >> 1 : microsecondsToClockCycles(3 );
@@ -306,18 +306,16 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
306
306
waveform.enabled ^= 1UL << pin;
307
307
}
308
308
else {
309
+ const uint32_t idleCcys = wave.periodCcys - wave.dutyCcys ;
309
310
// get true accumulated overshoot
310
311
overshootCcys = now - ((waveform.states & (1UL << pin)) ? wave.endDutyCcy : wave.nextPeriodCcy );
311
- const uint32_t idleCcys = wave.periodCcys - wave.dutyCcys ;
312
312
uint32_t fwdPeriods = static_cast <uint32_t >(overshootCcys) >= idleCcys ?
313
313
((overshootCcys + wave.dutyCcys ) / wave.periodCcys ) : 0 ;
314
- if (fwdPeriods && !wave.autoPwm ) {
315
- // for best effort hard timings - allow only limited duty cycle floating
316
- fwdPeriods = 0 ;
317
- overshootCcys = 0 ;
318
- }
319
314
uint32_t nextEdgeCcy;
320
315
if (waveform.states & (1UL << pin)) {
316
+ if (!wave.autoPwm ) {
317
+ overshootCcys = 0 ;
318
+ }
321
319
// up to and including this period 100% duty
322
320
const bool endOfPeriod = wave.nextPeriodCcy == wave.endDutyCcy ;
323
321
// active configuration and forward 100% duty
@@ -328,7 +326,12 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
328
326
}
329
327
else if (endOfPeriod) {
330
328
// preceeding period had zero idle cycle, continue direct into new duty cycle
331
- wave.nextPeriodCcy += fwdPeriods * wave.periodCcys ;
329
+ if (fwdPeriods) {
330
+ wave.nextPeriodCcy += fwdPeriods * wave.periodCcys ;
331
+ // adapt expiry such that it occurs during intended cycle
332
+ if (WaveformMode::EXPIRES == wave.mode )
333
+ wave.expiryCcy += fwdPeriods * wave.periodCcys ;
334
+ }
332
335
wave.endDutyCcy = wave.nextPeriodCcy + wave.dutyCcys ;
333
336
wave.nextPeriodCcy += wave.periodCcys ;
334
337
nextEdgeCcy = wave.endDutyCcy ;
@@ -352,18 +355,18 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
352
355
}
353
356
else {
354
357
waveform.states ^= 1UL << pin;
358
+ wave.endDutyCcy = now + wave.dutyCcys ;
359
+ wave.nextPeriodCcy += wave.periodCcys ;
355
360
if (fwdPeriods)
356
361
{
357
- // maintain phase, maintain duty/idle ratio, temporarily reduce frequency by fwdPeriods
358
- wave.endDutyCcy =
359
- wave.nextPeriodCcy + (fwdPeriods + 1 ) * wave.dutyCcys +
360
- (overshootCcys + wave.dutyCcys - fwdPeriods * wave.periodCcys );
361
- wave.nextPeriodCcy += (fwdPeriods + 1 ) * wave.periodCcys ;
362
- }
363
- else
364
- {
365
- wave.endDutyCcy = wave.nextPeriodCcy + wave.dutyCcys + overshootCcys;
366
- wave.nextPeriodCcy += wave.periodCcys ;
362
+ if (wave.autoPwm ) {
363
+ // maintain phase, maintain duty/idle ratio, temporarily reduce frequency by fwdPeriods
364
+ wave.endDutyCcy += (fwdPeriods + 1 ) * wave.dutyCcys - fwdPeriods * wave.periodCcys ;
365
+ }
366
+ wave.nextPeriodCcy += fwdPeriods * wave.periodCcys ;
367
+ // adapt expiry such that it occurs during intended cycle
368
+ if (WaveformMode::EXPIRES == wave.mode )
369
+ wave.expiryCcy += fwdPeriods * wave.periodCcys ;
367
370
}
368
371
if (pin == 16 ) {
369
372
GP16O |= 1 ; // GPIO16 write slow as it's RMW
0 commit comments