Improve PWM on ESP8266
- Better phase updates without dropping samples - Make second pin duty cycle always after first, even inverted
This commit is contained in:
		| @@ -242,7 +242,7 @@ int startWaveformClockCycles_weak(uint8_t pin, uint32_t highCcys, uint32_t lowCc | ||||
|       wave.mode = WaveformMode::UPDATEEXPIRY; | ||||
|       std::atomic_thread_fence(std::memory_order_release); | ||||
|       waveform.toSetBits = 1UL << pin; | ||||
|     } else if (alignPhase) { | ||||
|     } else if (alignPhase >= 0) { | ||||
|       // @willmmiles new feature | ||||
|       wave.mode = WaveformMode::UPDATEPHASE; // recalculate start | ||||
|       std::atomic_thread_fence(std::memory_order_release); | ||||
| @@ -303,7 +303,7 @@ static inline IRAM_ATTR int32_t scaleCcys(const int32_t ccys, const bool isCPU2X | ||||
|  | ||||
| static IRAM_ATTR void timer1Interrupt() { | ||||
|   const uint32_t isrStartCcy = ESP.getCycleCount(); | ||||
|   int32_t clockDrift = isrStartCcy - waveform.nextEventCcy; | ||||
|   //int32_t clockDrift = isrStartCcy - waveform.nextEventCcy; | ||||
|  | ||||
|   // ----- @willmmiles begin patch ----- | ||||
|   nmiCrashWorkaround(); | ||||
| @@ -341,12 +341,16 @@ static IRAM_ATTR void timer1Interrupt() { | ||||
|       break; | ||||
|     // @willmmiles new feature | ||||
|     case WaveformMode::UPDATEPHASE: | ||||
|       // in WaveformMode::UPDATEPHASE, we recalculate the targets without adjusting the state | ||||
|       // in WaveformMode::UPDATEPHASE, we recalculate the targets | ||||
|       if (waveform.alignPhase >= 0 && waveform.enabled & (1UL << waveform.alignPhase)) { | ||||
|         // Compute phase shift to realign with target | ||||
|         auto& align_wave = waveform.pins[waveform.alignPhase];                 | ||||
|         // Go back one cycle | ||||
|         wave.nextPeriodCcy = align_wave.nextPeriodCcy - scaleCcys(align_wave.periodCcys, isCPU2X) + scaleCcys(waveform.phaseCcy, isCPU2X); | ||||
|         wave.endDutyCcy = wave.nextPeriodCcy + scaleCcys(wave.dutyCcys, isCPU2X); | ||||
|         int32_t shift = static_cast<int32_t>(align_wave.nextPeriodCcy + scaleCcys(waveform.phaseCcy, isCPU2X) - wave.nextPeriodCcy); | ||||
|         const int32_t periodCcys = scaleCcys(wave.periodCcys, isCPU2X); | ||||
|         if (shift > periodCcys/2) shift -= periodCcys; | ||||
|         else if (shift <= -periodCcys/2) shift += periodCcys; | ||||
|         wave.nextPeriodCcy += shift; | ||||
|         wave.endDutyCcy += shift; | ||||
|       } | ||||
|     default: | ||||
|       break; | ||||
| @@ -462,7 +466,7 @@ static IRAM_ATTR void timer1Interrupt() { | ||||
|       } | ||||
|       now = ESP.getCycleCount(); | ||||
|     } | ||||
|     clockDrift = 0; | ||||
|     //clockDrift = 0; | ||||
|   } | ||||
|  | ||||
|   int32_t callbackCcys = 0; | ||||
|   | ||||
| @@ -565,7 +565,7 @@ void BusPwm::show() { | ||||
|    const unsigned analogPeriod = F_CPU / _frequency; | ||||
|    const unsigned maxBri = analogPeriod;  // compute to clock cycle accuracy | ||||
|    constexpr bool dithering = false;    | ||||
|    constexpr unsigned bitShift = 7;  // 2^7 clocks for dead time | ||||
|    constexpr unsigned bitShift = 8;  // 256 clocks for dead time, ~3us at 80MHz | ||||
| #else | ||||
|   // if _needsRefresh is true (UI hack) we are using dithering (credit @dedehai & @zalatnaicsongor) | ||||
|   // https://github.com/Aircoookie/WLED/pull/4115 and https://github.com/zalatnaicsongor/WLED/pull/1) | ||||
| @@ -609,8 +609,10 @@ void BusPwm::show() { | ||||
|         duty -= deadTime << 1; // shorten duty of larger signal except if full on | ||||
|       } | ||||
|     } | ||||
|     if (_reversed) duty = maxBri - duty; | ||||
|  | ||||
|     if (_reversed) { | ||||
|       if (i) hPoint += duty;  // align start at time zero | ||||
|       duty = maxBri - duty; | ||||
|     } | ||||
|     #ifdef ESP8266 | ||||
|     //stopWaveform(_pins[i]);  // can cause the waveform to miss a cycle. instead we risk crossovers. | ||||
|     startWaveformClockCycles(_pins[i], duty, analogPeriod - duty, 0, i ? _pins[0] : -1, hPoint, false); | ||||
| @@ -625,7 +627,8 @@ void BusPwm::show() { | ||||
|     ledc_update_duty((ledc_mode_t)gr, (ledc_channel_t)ch); | ||||
|     #endif | ||||
|      | ||||
|     hPoint += duty + (_reversed ? -1 : 1) * deadTime;        // offset to cascade the signals | ||||
|     if (!_reversed) hPoint += duty; | ||||
|     hPoint += deadTime;        // offset to cascade the signals | ||||
|     if (hPoint >= maxBri) hPoint -= maxBri; // offset is out of bounds, reset | ||||
|   } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Will Miles
					Will Miles