mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-25 20:02:37 +03:00
* Allow 100% high or low periods. Let output remain at current level on stopping instead of always turning to low. * Fix serious jitter issues in previous versions. * Use ESP.getCycleCount() just like everyone else. * Highest timer rate at which this runs stable appears to be 2µs (500kHz). * Guard for zero period length undefined waveforms. Fix for zero duty or off cycles and expiring from them. * Cycle precision for expiry instead of special treatment for 0 value. * Give expiry proper precedence over updating a waveform * Important comment * Refactored, identical behavior. * Use plural for bit arrays. * Fix for completely duty or all off cycle period case. * Expiration is explicitly relative to service time. * Comment updated, here it's about cycles not usecs. * Revert misconception of how waveformToEnable/Disable communicates with the NMI handler. * Rewrite to keep phase in sync if period remains same during duty cycle change. Refactor identifies to distinguish CPU clock cycle from waveform cycle. * Rather iterate even if full-duty or no-duty cycle in period, than too many calculations in NMI handler. * Must fire timer early to reach waveform deadlines, otherwise under some load aggressive jitter occurs. * Schedule expiry explicitly, too. Needed to keep track of next timer ccy in each iteration, not just when changing level. * Quick change lets analogWrite keep phase for any duty cycle (including 0% and 100%). * Set duration to multiple of period, so tone stops on LOW pin output. * Improve phase timing * Eror causing next Timer IRQ to fail busy-to-off cycle transitions. * Regression fix, don't reset timer if pending shortly. * Rather reschedule ISR instead of busy looping during permitted maximum time. * Lead time improved for ISR * Reduce number of cycle calculations. * Reactive the gcc optimize pragmas. * Simplify calculation. * handles overshoot where an updated period is shorter than the previous duty cycle * Misleading code, there must ever be only one bit set at a time, start and stop block until the ISR has handled and reset the token. * Prevent missing a duty cycle unless it is overshot already. * Continuously remove distant pending waveform edges from the loop, continuously update now. * Replace volatile for one-way exchange into ISR with memory fence. * Remove redundant stack object. * Revert pending waveform removal from loop - corrupts continuous next event computation. * Reduce if/do ... while to while * Convert relative timings to absolute. * Relax waveform start to possibly cluster phases into same IRQ interval. * max 12us in ISR seems to work best for servo/fan/led/tone combo test. * Restructured code in ISR for expiration, this saves 36 byte IRAM, and improves PWM resolution. * Simplified overshot detection and 0% / 100% duty cycle. * Leave ISR early if rescheduling is more promising than busy-waiting until next edge. * Stabilized timings. * Prevent WDT under load. * Use clock cycle resolution instead of us for analogWrite. * Reduce idle calculations in ISR. * Optimize in-ISR time. * Support starting new waveform in phase with another running waveform. * Align phase for analogWrite PWMs. * Tune preshoot, add lost period fast forward. * Adapt phase sync code from analogWrite to Servo * Fix for going off 100% duty cycle period. * Eschew obfuscation. * Fixed logic for zero duty cycle. * Determine generator quantum during same IRQ - this is better than timer resolution, but non-zero. * Tune timings, fix write barriers and overshoot logic. * Migrate Tone to waveform with CPU cycle precision * Can do 60kHz PWM. * Recalibrated timings after performance optimizations. Initialize GPIO if needed. * Fix regression for waveform runtime. * Test cycle duration values for signed arithmetic safety. * Performance tuning. * Performance tweak, in-ISR quantum is now 1.12µs. * Round up duration instead of down - possibly to zero, which means forever. * Extend phase alignment with optional phase offset. * Slightly better in-ISR quantum approximation for steadier increments. * Waveform stopped by runtime limit in iSR doesn't deinit the timer, but stopWaveform refuses to do anything if the waveform was stopped by runtime, either. * Improved quantum correction code. * Fix broken multi-wave generation. * Aggregate GPIO output across inner loop. True phase sync, and now better performance. * IRQ latency can be reduced from 2 to 1 us now, no WDT etc. * Improved handling of complete idle cycle miss, progress directly into duty cycle. * Recalibrated after latest changes and reverts. * Overshoot compensation for duty cycle results in PWM milestone. * Adjustments to duty/idle cycle to mitigate effects of floating duty cycle logic. * Remove implicit condition from loop guard and fix timer restart duration * Host all static globals in an anonymous static struct. * Busy wait directly for next pending event and go to that pin. * Record nextEventCcy in waveform struct to save a few cycles. * Adapt duty cycle modification to only fix full duty and all idle cases. * Remember next pin to operate between IRQs. * Don't set pinMode each time on already running PWM or Tone. * Remove quantum, correct irq latency from testing,reuse isr timeout from master et al * Move updating "now" out of inner loop, prevents float between pins that are in phase lock. * Merge init loop with action loop again. * Adaptive PWM frequency and floating duty cycle. * Predictive static frequency scaling. * Dynamic frequency down-scaling * Frequency scaling is only for PWM-like applications, anything needing real time duty cycles or frequency must be able to fail on overload. * Conserve IRAM cache, resort to best effort. * Directly scale frequency for all duty/all idle waves to reasonable maximum, reduces thrashing. * Getting the math right beats permanently reducing PWM frequency. * Rename identifier to help think about the problem. * AutoPwm correction moved to correct location - after overshoot recalc - and allow limited duty floating * Finish overshoot math fixes. * First set pin mode, then digital write. * Simplify calculations, fix non-autoPwm for servo use, where exact duty is needed, idle is elastic. * Move wave initialization and modification outside the inner loop. * Some optimizing. * Updating "now" in the inner loop should lessen interference * Finally get rid of volatile and use atomic thread fence memory barriers, great for ISR performance. * Improved idle cycle overshoot mitigation. * Improved duty cycle overshoot mitigation. Case for investigation: 3% (shl 5) vs. 1.5% (shl 6), either less fuzz, but a few marked stray spots, or more fuzz, but no bumps in counter-PWM travel test. * Move startPin etc. into common static struct * Persist next event cycle across ISR invocations, like initPin was before. * Recalibrated DELTAIRQ and IRQLATENCY. Tested @ 3x 40kHz PWM + 440Hz Tone * CPU clock to Timer1 ccy correction must be dynamic even when BSP is compiled for fixed CPU clock. * Corrected use of Timer1 registers and add rationale to Timer1 use in comment. Recalibrate for improved frequence downscaling @ 80MHz and 160MHz. * Let duty cycle overshoot correction depend on relative impact compareed to both period and duty. * 80MHz/160MHz specific code can be compile-time selected in general, only NMI is affected by apparent CPU frequency scaling in SDK code. * Seems that removing the redudant resetting of edge interrupt mode shaves 0.5us off rearm latency. * Recalibrated delta irq ccys. * Off-by-one in 100% duty overshoot correction. * Simple register writes. * Memory fences checked and joining events into same loop iteration that are close to one another. * Shorten progression when going off 100% duty. * Code simplifications. * Dynamically map pins out from in-ISR handling based on next event timing. Major performance boost. * Reverting maximum IRQ period to 10ms. This sets the wave reprogramming rate to 100Hz max. * Revert recent change that is the most likely cause of reported PWM frequency drop regression. * Much simplified overshoot mitigation code. * Fixing overshoot mitigation, 3x 880Hz, 256 states now. * Increase resolution by keeping reference time moving forward earlier. * Mitigation logic for ESP8266 SDK boosting to 160MHz during some WiFi ops. * Event timestamps are all recorded for compile-time CPU frequency, the timer ticks conversion must be set at compile-time also. The SDK WiFi 160MHz boost mitigation temporarily handles the CPU clock running twice as fast. * Expired pins must not be checked for next event. * Recalibrate after latest changes. * Save a few bytes code. * Guards are in place, so xor rather than and bitwise not. * Reduce memory use. * SDK boost to 160MHz may last across multiple ISR invocations, therefore adjust target ccy instead of ccount. * Overshoot mitigation w/o PWM frequency change. * New PWM overshoot mitigation code keeps frequency. Averages duty between consecutive periods. * Small refactoring, remove code path that is never taken even at 3x25kHz/1023 PWM. * Don't ever skip off duty, no matter if late or infinitely short. * Shed speed-up code that didn't speed up things. * Must always recompute new waveform.nextEventCcy if there is any busy pin. * Break out of ISR if timespan to next event allows, instead of busy waiting and stealing CPU cycles from userland. * Minor code simplification. * Improve code efficiency. * Improved performance of loop. * Recalibrated. * No positive effect of lead time inclusion was found during testing, remove this code. Maximum period duration limit is implicit to timer, consider it documented constraint, don't runtime check in ISR. * Fix WDT when at 160MHz CPU clock the Timer1 is set below 1µs. * Consolidate 160MHz constexpr check, finish 1µs minimum for Timer1 fix. * Test for non-zero before subtract should improve performance. * Reviewers/tested noted they were seeing WDT, and this change appeared to fix that. * More expressive use of parentheses and alias CPU2X for reduced code size. * Bug fix: at 160MHz compiled, don't force minimum Timer1 latency to 2µs. * Alternate CPU frequency scaling mitigation. * Handle time-of-flight in the right spot. * Remove _toneMap from Tone.cpp Co-authored-by: david gauchard <gauchard@laas.fr>