Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 9eb92f0

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

File tree

Expand file treeCollapse file tree

1 file changed

+44
-22
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+44
-22
lines changed

‎cores/esp8266/core_esp8266_waveform.cpp

Copy file name to clipboardExpand all lines: cores/esp8266/core_esp8266_waveform.cpp
+44-22Lines 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)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.