@@ -67,8 +67,8 @@ enum class WaveformMode : uint8_t {INFINITE = 0, EXPIRES = 1, UPDATEEXPIRY = 2,
6767typedef struct {
6868 uint32_t nextPeriodCcy; // ESP clock cycle when a period begins. If WaveformMode::INIT, temporarily holds positive phase offset ccy count
6969 uint32_t endDutyCcy; // ESP clock cycle when going from duty to off
70- uint32_t dutyCcys; // Set next off cycle at low->high to maintain phase
71- uint32_t periodCcys; // Set next phase cycle at low->high to maintain phase
70+ int32_t dutyCcys; // Set next off cycle at low->high to maintain phase
71+ int32_t periodCcys; // Set next phase cycle at low->high to maintain phase
7272 uint32_t expiryCcy; // For time-limited waveform, the CPU clock cycle when this waveform must stop. If WaveformMode::UPDATE, temporarily holds relative ccy count
7373 WaveformMode mode;
7474 int8_t alignPhase; // < 0 no phase alignment, otherwise starts waveform in relative phase offset to given pin
@@ -249,14 +249,13 @@ int ICACHE_RAM_ATTR stopWaveform(uint8_t pin) {
249249
250250// For dynamic CPU clock frequency switch in loop the scaling logic would have to be adapted.
251251// Using constexpr makes sure that the CPU clock frequency is compile-time fixed.
252- static ICACHE_RAM_ATTR uint32_t __attribute__ ((noinline)) getScaledCcyCount( uint32_t ref ) {
252+ static inline ICACHE_RAM_ATTR int32_t scaleCcys ( int32_t ccys ) {
253253 constexpr bool cpuFreq80MHz = clockCyclesPerMicrosecond () == 80 ;
254- const uint32_t elapsed = ESP.getCycleCount () - ref;
255254 if (cpuFreq80MHz) {
256- return ref + ((CPU2X & 1 ) ? elapsed >> 1 : elapsed );
255+ return ((CPU2X & 1 ) ? ccys << 1 : ccys );
257256 }
258257 else {
259- return ref + ((CPU2X & 1 ) ? elapsed : elapsed << 1 );
258+ return ((CPU2X & 1 ) ? ccys : ccys >> 1 );
260259 }
261260}
262261
@@ -297,7 +296,8 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
297296 }
298297 // fall through
299298 case WaveformMode::UPDATEEXPIRY:
300- wave.expiryCcy += wave.nextPeriodCcy ; // in WaveformMode::UPDATEEXPIRY, expiryCcy temporarily holds relative CPU cycle count
299+ // in WaveformMode::UPDATEEXPIRY, expiryCcy temporarily holds relative CPU cycle count
300+ wave.expiryCcy = wave.nextPeriodCcy + scaleCcys (wave.expiryCcy );
301301 wave.mode = WaveformMode::EXPIRES;
302302 break ;
303303 default :
@@ -329,10 +329,8 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
329329 const int stopPin = waveform.nextPin ;
330330 int pin = stopPin;
331331 while (busyPins) {
332- uint32_t now;
333- do {
334- now = getScaledCcyCount (isrStartCcy);
335- } while (static_cast <int32_t >(isrNextEventCcy - now) > 0 );
332+ while (static_cast <int32_t >(isrNextEventCcy - ESP.getCycleCount ()) > 0 ) {
333+ }
336334 isrNextEventCcy = isrTimeoutCcy;
337335 do {
338336 const uint32_t pinBit = 1UL << pin;
@@ -343,6 +341,7 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
343341 Waveform& wave = waveform.pins [pin];
344342
345343 uint32_t waveNextEventCcy = (waveform.states & pinBit) ? wave.endDutyCcy : wave.nextPeriodCcy ;
344+ const uint32_t now = ESP.getCycleCount ();
346345 if (WaveformMode::EXPIRES == wave.mode &&
347346 static_cast <int32_t >(waveNextEventCcy - wave.expiryCcy ) >= 0 &&
348347 static_cast <int32_t >(now - wave.expiryCcy ) >= 0 ) {
@@ -356,11 +355,11 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
356355 if (waveform.states & pinBit) {
357356 // active configuration and forward are 100% duty
358357 if (wave.periodCcys == wave.dutyCcys ) {
359- wave.nextPeriodCcy += wave.periodCcys ;
358+ wave.nextPeriodCcy += scaleCcys ( wave.periodCcys ) ;
360359 waveNextEventCcy = wave.endDutyCcy = wave.nextPeriodCcy ;
361360 }
362361 else if (wave.autoPwm && static_cast <int32_t >(now - wave.nextPeriodCcy ) >= 0 ) {
363- const uint32_t adj = (overshootCcys + wave.dutyCcys ) / wave.periodCcys ;
362+ const uint32_t adj = (overshootCcys + scaleCcys ( wave.dutyCcys ) ) / wave.periodCcys ;
364363 // maintain phase, maintain duty/idle ratio, temporarily reduce frequency by fwdPeriods
365364 waveNextEventCcy = wave.endDutyCcy = wave.nextPeriodCcy + adj * wave.dutyCcys ;
366365 wave.nextPeriodCcy += adj * wave.periodCcys ;
@@ -381,14 +380,14 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
381380 }
382381 else {
383382 if (!wave.dutyCcys ) {
384- wave.nextPeriodCcy += wave.periodCcys ;
383+ wave.nextPeriodCcy += scaleCcys ( wave.periodCcys ) ;
385384 wave.endDutyCcy = wave.nextPeriodCcy ;
386385 }
387386 else {
388- wave.nextPeriodCcy += wave.periodCcys ;
389- wave.endDutyCcy = now + wave.dutyCcys ;
387+ wave.nextPeriodCcy += scaleCcys ( wave.periodCcys ) ;
388+ wave.endDutyCcy = now + scaleCcys ( wave.dutyCcys ) ;
390389 if (static_cast <int32_t >(wave.endDutyCcy - wave.nextPeriodCcy ) >= 0 ) {
391- const uint32_t adj = (overshootCcys + wave.dutyCcys ) / wave.periodCcys ;
390+ const uint32_t adj = (overshootCcys + scaleCcys ( wave.dutyCcys ) ) / wave.periodCcys ;
392391 wave.nextPeriodCcy += adj * wave.periodCcys ;
393392 if (wave.autoPwm ) {
394393 // maintain phase, maintain duty/idle ratio, temporarily reduce frequency by fwdPeriods
@@ -425,16 +424,14 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
425424 isrNextEventCcy = waveNextEventCcy;
426425 }
427426 }
428-
429- now = getScaledCcyCount (isrStartCcy);
430427 } while ((pin = (pin < waveform.endPin ) ? pin + 1 : waveform.startPin ) != stopPin);
431428 }
432429
433430 int32_t callbackCcys = 0 ;
434431 if (waveform.timer1CB ) {
435- callbackCcys = microsecondsToClockCycles (waveform.timer1CB ());
432+ callbackCcys = scaleCcys ( microsecondsToClockCycles (waveform.timer1CB () ));
436433 }
437- const uint32_t now = getScaledCcyCount (isrStartCcy );
434+ const uint32_t now = ESP. getCycleCount ( );
438435 int32_t nextTimerCcys = waveform.nextEventCcy - now;
439436 // Account for unknown duration of timer1CB().
440437 if (waveform.timer1CB && nextTimerCcys > callbackCcys) {
@@ -454,8 +451,5 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
454451
455452 // Register access is fast and edge IRQ was configured before.
456453 // Timer is 80MHz fixed. 160MHz binaries need scaling.
457- // For dynamic CPU clock frequency switch in loop the scaling logic would have to be adapted.
458- // Using constexpr makes sure that the CPU clock frequency is compile-time fixed.
459- constexpr bool cpuFreq80MHz = clockCyclesPerMicrosecond () == 80 ;
460- T1L = cpuFreq80MHz ? nextTimerCcys : nextTimerCcys >> 1 ;
454+ T1L = (CPU2X & 1 ) ? nextTimerCcys >> 1 : nextTimerCcys;
461455}
0 commit comments