Description
This is a highly optimized TRIAC delayed-trigger compensation routine for ESP32(-S3).
It compensates the TRIAC trigger time so that the power delivered to resistive load is changing linearly when the original TRIAC trigger time is also changing linearly.
Input: Relative delay of TRIAC trigger (0: start of half-sine wave up to 1: end of half-sine wave)
Output: Linearized relative delay (0 up to 1, 0 when input < 0, 1 when input > 1, NaN when input is NaN)
Relative error of power delivered to resistive load: < 1e-5
Cycles: 14-186 (includes CALL8, close to upper bound most of the time unless special input cases mentioned above)
Instructions: 10-142 (includes CALL8, close to upper bound most of the time unless special input cases mentioned above)
Comment:
The power delivered with TRIAC to a resistive load during a half sinewave is simply Integrate[Sin[x]^2, x], which yields x/2 - 1/4 Sin[2 x] (indefinite integral - needs to be converted to definite one from x to Pi).
Linearization eq.: Reduce[(Pi/2 - (x/2 - 1/4 Sin[2 x]))/(Pi/2) == 1 - y/Pi, {x, y}] yields y == x - Sin[2 x]/2. But InverseFunction[Function[x, x - Sin[2 x]/2]] will get you nowhere :/
That is why I created this simple and most importantly fast routine!
Ring up your prodigy mathematician acquaintances - maybe, they will be able to devise an infinite series for the inverse function and conveniently truncate it when the required precision is met.
I am attaching the sources. Use 7-Zip to extract them from the 7-Zip archive. Feel free to incorporate them into this project. Let me know if you need me to tweak the ASM source.
Cheers!
f4lc0n
Fixed: Function description in plin.s.
Added: PLin function - same as DComp, but the input is the required relative output power (from 0 to 1).
Added: Graphs for DComp and PLin compensation functions - see the tiny PDF files.
Added: C source for Xtensa GCC folks since the C -Ofast floating-point code is an unmitigated disaster. The ASM version as a whole is 2× faster than C -Ofast!!! This is thanks to the highly optimized floating-point code at the end of the ASM routine, which is more than 3× faster than C -Ofast!!! To conclude, the Xtensa GCC is pretty good at optimizing integer code - e.g. if(c<minc) minc=c; is translated into just 1 ASM instruction MIN, which is both apt and cool! On the other hand, GCC quickly runs out of floating-point registers and starts using the stack with dire consequences for speed. Please tell the Xtensa GCC folks this is the one area really deserving their attention!!! Thanks.
Added: ESP32(-S3) target and instruction count in ASM and C source comments
Updated: Cycle count in ASM source comments