elexor wrote: ↑12 Jun 2021, 02:12
this is my very basic program it's a wip to test if it would actually work.
Nice and simple!
If you want to support VRR strobing over a wider range for fluctuating framerates, you'll want to dynamically shorten/lengthen your pulse as a percentage of current refresh interval time (frametime), to try and keep photons hitting eyeballs relatively constant. This will minimize flicker, though you will want to keep it as microsecond-accurate as possible.
Even 10 microsecond may cause visible flicker (A 1% change to 1ms MPRT pulse width is 10 microsecond, and can show up as a 1% brightness increase/decrease. This is one of these extreme "
Milliseconds Matters" stuff; 10 microseconds actually creates human visible flicker error in VRR strobe experiments. The easiest way to avoid erratic-flicker-effect of strobed VRR, while continuing to single-strobe VRR, is to control pulse width proportionally to pulse interval as exact a ratio as possible (right to the exact millisecond or less).
Repeatedly doing that may cause a candlelight-flicker effect), so high performance Arduino capable of controlling pulse widths very accurately (to the microsecond) would probably be preferred; pulse width would be an exact percentage of the time interval between two backlight-ons, right to the exact millisecond (where possible).
With sufficient Arduino performance, this should be possible, as long as you have a constant number of programming instructions (so that every refresh cycle runs the same number of CPU cycles of Arduino execution). An inaccurate VSYNC trigger is less important than accurately making pulse width percentage microsecond-proportional to interval between pulses, so you can just simply use the micros() time interval between the leading edges of the pulse-on, to compute your pulse width. Another variable dictating strobe percentage of refresh cycle (e.g. 10% persistence or 20% persistence.
Ideally, this should be a prediction of future frametime, but works acceptably on past frametimes. and you'll want to automatically double strobe as soon as framerates fall below approximately 50fps, to prevent painful eye-searing flicker. But while still being compatible with emulator frame rates and such.
Then you might have an implementation that outperforms the out-of-the-box ELMB-SYNC. As long as your strobe is phase-relative to the bottom of the refresh cycle (beginning of VBI), you're relatively in sync with a fixed overdrive setting, and can mostly forgo a varying overdrive when it comes to strobed VRR -- at least for simplicity's sake. It won't be perfect, but you're strobing a fixed-time right after a fixed-velocity scanout, regardless of the interval between refresh cycles. You will get the varying strobe crosstalk issue, so you'll have strobe crosstalk starting to leak-downwards from the top edge, the higher the framerate you go, but this is a lesser evil to having a better-than-ELMB-SYNC strobe algorithm, and you can simply cap about 20fps or 30fps or 40fps below max Hz (280Hz) to keep this mostly under control...
You might possibly need more megahertz in your Arduino clone to allow enough C code to execute to the exact microsecond; there are some Arduino-clone options (e.g. Teensy 4 at 600 MHz), to prevent the VRR-flicker. This stuff is where 10 microseconds becomes human visible flicker, so a bit overkill is needed if you're going to realtime-vary the pulse widths as a ratio to intervals between the leading edges of strobe pulses.
This will allow you to do a universal VRR strobe algorithm.
Summary, simplest algorithm to avoid VRR flicker
- Accept noisy VSYNC
- Accept phase noise (relative to VSYNC)
- Make your leading edge of pulse constant-time relative to bottom of your refresh cycle (VBI pulse), like you already do
- However, precision of pulse width as a ratio between time intervals between pulse widths is PARAMOUNT
To prevent painful flicker at super-low Hz (e.g. 30fps), you'll probably want to start devilhorning (like ELMB-SYNC) at an ultra low Hz such as 50Hz or below, unless the LFC algorithm of G-SYNC is already doing it for you automatically; then you might not need to (it'll simply multistrobe once LFC activates). If you need to devil-horn your VRR strobe, do it only well below 60Hz as an ultra-high-frequency PWM that keeps the same persistence ratio, continuously, until the next refresh cycle arrives. (Hopefully LFC makes this unnecessary to do, and you simply edit your VRR min Hz to your preferred min flicker frequency, such as 48 Hz or 55 Hz).
Now, there probably will still be pros/cons with the various VRR strobe algorithms. You'll want a toggle setting (button on Arduino, or a USB command) for different types of VRR strobe modes. (Be noted, enabling real time USB commands to the Arduino during VRR strobe control, will cause temporary flicker effects due to the USB processing overhead making it less-than-microsecond-accurate).