espressif / esp-dsp

DSP library for ESP-IDF
Apache License 2.0
442 stars 87 forks source link

SOLVED: TRIAC delayed-trigger compensation routine for ESP32(-S3) (DSP-119) #76

Open f4lc0n-asm opened 8 months ago

f4lc0n-asm commented 8 months ago

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

dcomp_v1.2.zip

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

TD-er commented 8 months ago

Why in assembly? Is this compatible with all ESP32 platforms? It looks like it is a big lookup table, so I can imagine it is fast. But still that doesn't explain why it has to be in assembly code.

Also I guess it would be nice to have a bit more explanation about the actual use case and what makes this a requirement for that use case.

f4lc0n-asm commented 8 months ago

The ASM version is 2× faster than C -Ofast!!! Since it extensively uses Xtensa FPU, it is compatible with ESP32 and ESP32-S3. It is suitable for cases when you want to linearly control the power delivered to a load connected to AC mains or any sinus power source in general, which can have much higher frequency - hence the need for speed…