8000 New PWM overshoot mitigation code keeps frequency. Averages duty betw… · dok-net/arduino-esp8266@9eb92f0 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9eb92f0

Browse files
committed
New PWM overshoot mitigation code keeps frequency. Averages duty between consecutive periods.
1 parent 2eb980b commit 9eb92f0

File tree

1 file changed

+44
-22
lines changed

1 file changed

+44
-22
lines changed

cores/esp8266/core_esp8266_waveform.cpp

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,14 @@ enum class WaveformMode : uint8_t {INFINITE = 0, EXPIRES = 1, UPDATEEXPIRY = 2,
6666
// Waveform generator can create tones, PWM, and servos
6767
typedef struct {
6868
uint32_t nextPeriodCcy; // ESP clock cycle when a period begins. If WaveformMode::INIT, temporarily holds positive phase offset ccy count
69-
uint32_t endDutyCcy; // ESP clock cycle when going from duty to off
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
72-
uint32_t expiryCcy; // For time-limited waveform, the CPU clock cycle when this waveform must stop. If WaveformMode::UPDATE, temporarily holds relative ccy count
69+
uint32_t endDutyCcy; // ESP clock cycle when going from duty to off
70+
int32_t dutyCcys; // Set next off cycle at low->high to maintain phase
71+
int32_t adjDutyCcys; // Temporary correction for next period
72+
int32_t periodCcys; // Set next phase cycle at low->high to maintain phase
73+
uint32_t expiryCcy; // For time-limited waveform, the CPU clock cycle when this waveform must stop. If WaveformMode::UPDATE, temporarily holds relative ccy count
7374
WaveformMode mode;
74-
int8_t alignPhase; // < 0 no phase alignment, otherwise starts waveform in relative phase offset to given pin
75-
bool autoPwm; // perform PWM duty to idle cycle ratio correction under high load at the expense of precise timings
75+
int8_t alignPhase; // < 0 no phase alignment, otherwise starts waveform in relative phase offset to given pin
76+
bool autoPwm; // perform PWM duty to idle cycle ratio correction under high load at the expense of precise timings
7677
} Waveform;
7778

7879
namespace {
@@ -165,6 +166,7 @@ int startWaveformClockCycles(uint8_t pin, uint32_t highCcys, uint32_t lowCcys,
165166
}
166167
Waveform& wave = waveform.pins[pin];
167168
wave.dutyCcys = highCcys;
169+
wave.adjDutyCcys = 0;
168170
wave.periodCcys = periodCcys;
169171
wave.autoPwm = autoPwm;
170172

@@ -352,38 +354,58 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
352354
else {
353355
const uint32_t overshootCcys = now - waveNextEventCcy;
354356
if (static_cast<int32_t>(overshootCcys) >= 0) {
357+
const int32_t periodCcys = scaleCcys(wave.periodCcys);
355358
if (waveform.states & pinBit) {
356359
// active configuration and forward are 100% duty
357360
if (wave.periodCcys == wave.dutyCcys) {
358-
wave.nextPeriodCcy += scaleCcys(wave.periodCcys);
361+
wave.nextPeriodCcy += periodCcys;
359362
waveNextEventCcy = wave.endDutyCcy = wave.nextPeriodCcy;
360363
}
361-
else if (wave.autoPwm && static_cast<int32_t>(now - wave.nextPeriodCcy) >= 0) {
362-
waveNextEventCcy = wave.endDutyCcy = wave.nextPeriodCcy + scaleCcys(wave.dutyCcys) - overshootCcys;
363-
wave.nextPeriodCcy += scaleCcys(wave.periodCcys);
364-
// adapt expiry such that it occurs during intended cycle
365-
if (WaveformMode::EXPIRES == wave.mode)
366-
wave.expiryCcy += scaleCcys(wave.periodCcys);
367-
}
368364
else {
369-
waveNextEventCcy = wave.nextPeriodCcy;
370-
waveform.states ^= pinBit;
371-
if (16 == pin) {
372-
GP16O = 0;
365+
if (wave.autoPwm && static_cast<int32_t>(now - wave.nextPeriodCcy) >= 0) {
366+
wave.endDutyCcy += periodCcys - overshootCcys;
367+
wave.nextPeriodCcy += periodCcys;
368+
if (static_cast<int32_t>(now - wave.endDutyCcy) >= 0) {
369+
waveNextEventCcy = wave.nextPeriodCcy;
370+
}
371+
else {
372+
waveNextEventCcy = wave.endDutyCcy;
373+
}
374+
// adapt expiry such that it occurs during intended cycle
375+
if (WaveformMode::EXPIRES == wave.mode)
376+
wave.expiryCcy += periodCcys;
377+
}
378+
else if (wave.autoPwm) {
379+
wave.adjDutyCcys = overshootCcys;
380+
waveNextEventCcy = wave.nextPeriodCcy;
373381
}
374382
else {
375-
GPOC = pinBit;
383+
waveNextEventCcy = wave.nextPeriodCcy;
384+
}
385+
if (waveNextEventCcy == wave.nextPeriodCcy) {
386+
waveform.states ^= pinBit;
387+
if (16 == pin) {
388+
GP16O = 0;
389+
}
390+
else {
391+
GPOC = pinBit;
392+
}
376393
}
377394
}
378395
}
379396
else {
380397
if (!wave.dutyCcys) {
381-
wave.nextPeriodCcy += scaleCcys(wave.periodCcys);
398+
wave.nextPeriodCcy += periodCcys;
382399
wave.endDutyCcy = wave.nextPeriodCcy;
383400
}
384401
else {
385-
wave.nextPeriodCcy += scaleCcys(wave.periodCcys);
386-
wave.endDutyCcy = now + scaleCcys(wave.dutyCcys);
402+
wave.nextPeriodCcy += periodCcys;
403+
int32_t dutyCcys = scaleCcys(wave.dutyCcys);
404+
if (dutyCcys > wave.adjDutyCcys) {
405+
dutyCcys -= wave.adjDutyCcys;
406+
}
407+
wave.adjDutyCcys = 0;
408+
wave.endDutyCcy = now + dutyCcys;
387409
if (static_cast<int32_t>(wave.endDutyCcy - wave.nextPeriodCcy) >= 0) {
388410
wave.endDutyCcy = wave.nextPeriodCcy;
389411
}

0 commit comments

Comments
 (0)
0