Hacked ASUS VG279QM modified to single-strobe 60 fps capped VRR for emulators

Advanced display talk, display hackers, advanced game programmers, scientists, display researchers, display manufacturers, vision researchers & Advanced Display Articles on Blur Busters. The masters on Blur Busters.
elexor
Posts: 169
Joined: 07 Jan 2020, 04:53

Re: Hacked ASUS VG279QM modified to single-strobe 60 fps capped VRR for emulators

Post by elexor » 12 Jun 2021, 02:08

Chief Blur Buster wrote:
12 Jun 2021, 01:41
elexor wrote:
12 Jun 2021, 00:22
I could even create a program that automatically changes overdrive via ddc commands if i want. software variable overdrive
What's the DDC command for Overdrive Gain on the ASUS VG279QM?

I suspect DDC/CI is probably not fast enough for realtime overdrive adjustments, but you could try some tests to see how fast/slow the updates is -- DDC/CI usually runs at only 10 commands per second, and would not keep up with sudden framerate changes. Some monitors are indeed faster than others.
can't remember exactly I have messed with it before it's in softmcs one of the first manufacture specific sliders. i think it's the top one you can only switch between 0, 20, 40, 60 ,80, 100 if i recall. and it switches pretty fast but yeah would not be useful for rapid frame level overdrive adjustment. will be useful for automatic fixed rate strobing adjustment.

elexor
Posts: 169
Joined: 07 Jan 2020, 04:53

Re: Hacked ASUS VG279QM modified to single-strobe 60 fps capped VRR for emulators

Post by elexor » 12 Jun 2021, 02:12

this is my very basic program it's a wip to test if it would actually work.

Code: Select all

int backlightPulse = 7;                          // output to the backlight strobing cirecuit
int vsyncPulse = 6;                              // vsync reference signal from panel

int frameTime;
int frameTimes[100];
int frameTimeAvg;
int frameCounter;
int slewPhase;
int slewLock;

int strobePulseTime = 2000;                       // uS persistence to strobe at 
int strobePhaseOffset = 100;                      // phase offset adjust

unsigned long vsyncTimestamp;
unsigned long previousVsyncTimestamp;
unsigned long oldMillis;
unsigned long oldMicros;
unsigned long backlightOn;

void setup() {
  pinMode(6, INPUT);
  pinMode(7, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  
  if (digitalRead(vsyncPulse) == HIGH && micros() > vsyncTimestamp + 100 ) {                                            // detect vsync signal wait 100uS to prevent timestamping vsync more then once.
    vsyncTimestamp = micros();
    frameTime = vsyncTimestamp - previousVsyncTimestamp;                                                                // calculate frametime

    if (frameCounter >= 100) {                                                                                          // once 100 frames have been collected calculate average frametime
      frameCounter = 0;
      frameTimeAvg = averageFrametimeCal();
    }
    if (frameCounter < 100) {                                                                                           // collect and store 100 frametimes in an array
      frameTimes[frameCounter] = frameTime;
      frameCounter++;
    }
    previousVsyncTimestamp = micros();
  }

  if (backlightOn < (previousVsyncTimestamp + frameTimeAvg - strobePulseTime - strobePhaseOffset) && slewLock == 0 ) {   // check where average strobe lands relative to vsync 
    slewPhase = 10;                                                                                                      // slew phase + or - 10uS lock slew from changing untill next refresh cycle
    slewLock =  1;
  }
  else if (slewLock == 0) {
    slewPhase = -10;
    slewLock = 1;
  }

  if ((micros() - oldMicros) > (frameTimeAvg + slewPhase) ) {                                                            // average strobe interval + - 10uS slew rate
    oldMicros = micros();
    digitalWrite(backlightPulse, HIGH);
    backlightOn = micros();
    slewLock = 0;
  }
    

  if (micros() >= backlightOn + strobePulseTime) {                                                                       // turn off backlight pulse after strobePulseTime period
    digitalWrite(backlightPulse, LOW);
  }
  
  if ((millis() - oldMillis) > 2000) {
    oldMillis = millis();
    Serial.println(frameTimeAvg);
  }
 
}

int averageFrametimeCal() {
  int avgFrameTime = 0;
  int long frameTimeTotal = 0;
  
  for (int i = 0; i < 100; ++i) {
    frameTimeTotal += frameTimes[i];    
  }
  avgFrameTime = (frameTimeTotal / 100);
  return avgFrameTime;
}

User avatar
Chief Blur Buster
Site Admin
Posts: 11647
Joined: 05 Dec 2013, 15:44
Location: Toronto / Hamilton, Ontario, Canada
Contact:

Re: How do customs large vertical totals interact with gsync?

Post by Chief Blur Buster » 12 Jun 2021, 02:15

elexor wrote:
12 Jun 2021, 02:02
when i fix rate 60hz strobe i just use a vt of 5125 280hz scanrate. I really think fixed rate strobing with gsync can be useful for it's automatic QFT handling not having to mess around with scanline sync is really nice. not all programs allow it or work correctly with it.
Yes, VRR's natural QFT effect makes it a lot easier than fixed-Hz QFT combined with Scanline Sync.

With a 1/280sec scanout for 60Hz refresh cycles (via VT5125 equivalent), you also get the opportunity to have some ultra-low-strobe-crosstalk 60Hz mode. VT5125 means only 1080/5125ths of 1/60sec is spent refreshing, leaving (5125-1080)/5125ths of 1/60sec = a really large blanking interval of about ~13.1 milliseconds to hide LCD GtG pixel response between refresh cycles. That's far more than enough to darn near completely strobe crosstalk free.
Head of Blur Busters - BlurBusters.com | TestUFO.com | Follow @BlurBusters on Twitter

Image
Forum Rules wrote:  1. Rule #1: Be Nice. This is published forum rule #1. Even To Newbies & People You Disagree With!
  2. Please report rule violations If you see a post that violates forum rules, then report the post.
  3. ALWAYS respect indie testers here. See how indies are bootstrapping Blur Busters research!

elexor
Posts: 169
Joined: 07 Jan 2020, 04:53

Re: Hacked ASUS VG279QM modified to single-strobe 60 fps capped VRR for emulators

Post by elexor » 12 Jun 2021, 02:28

Chief Blur Buster wrote:
12 Jun 2021, 01:41
P.S. I would like to see more of the DIY community playing around mechanical strobing -- see Mechanical Strobing Project. I put some great new diagrams there! You would only need non-strobed operation combined with an adjustable Overdrive Gain -- the strobe pulse width/phase would be controlled by the mechanical wheel instead. Could work well with fast-GtG LCD/LcOS projectors. You sound like you might be interested in testing out a mechanical contraption like that (Option 3 vise mounted spinning cardboard disc with slits).

I seen that very cool. I wouldn't know much about strobing or gsync if it wasn't for your informational posts :) the mechanical route seems interesting but it would be throwing away alot of brightness no? good for strobing experiments.

User avatar
Chief Blur Buster
Site Admin
Posts: 11647
Joined: 05 Dec 2013, 15:44
Location: Toronto / Hamilton, Ontario, Canada
Contact:

Re: Hacked ASUS VG279QM modified to single-strobe 60 fps capped VRR for emulators

Post by Chief Blur Buster » 12 Jun 2021, 02:32

elexor wrote:
12 Jun 2021, 02:28
I seen that very cool. I wouldn't know much about strobing or gsync if it wasn't for your informational posts :) the mechanical route seems interesting but it would be throwing away alot of brightness no? good for strobing experiments.
Yes, that will be true. However, it's one of the only ways to reliably add strobing to, for example, an LCD projector or a LCoS projector (e.g. Sony SXRD chip).

Option 1: Expensive Projector
The Sony SXRD (LCoS) is relatively fast-GtG while running at only 60Hz, perfect for virtually crosstalk-free mechanical strobing, very bright so lots of headroom to chew up brightness, and should be able to produce a CRT-motion-clarity image out of an existing LCD / LCoS projector. With LCoS tech, GtG is already very fast, so will work really well with mechanical strobing. But LCoS/SXRD projectors are fairly expensive.

Option 2: Cheap Projector (with some software overdrive assistance)
Now, an alternative is simply to go with a Chinese 60Hz LCD projector (a mere $100-$200), but the GtG on those are pretty slow and will probably strobe-crosstalk a lot more, albiet a tiny slit following very late in the GtG cycle may actually be workable, since lightbulb-heated LCDs actually speed up after a while. Additional GtG-speedup is possible with software-based overdrive, perhaps as a GPU shader or a dedicated app filter (e.g. shader) in a Windows virtual display driver (e.g. a refresh-cycle-granularity version of SweetFX or ReShade). That would altogether need another open source programming project that is expected to happen in the not-too-distant future.

There's some impressive GtG speedups possible with some software-based overdrive on an LCD that doesn't have overdrive. (Like ATI Radeon Overdrive of twenty years ago). There was some experimental work with overdrive I learned someone did already (unbeknownst to my knowledge) but it's frame granularity and doesn't work well unless framerate=Hz, but will likely be quickly reborn with a future open source refresh-cycle-granularity shader-processing virtual display driver.

I recently learned two different parties are (attempting to) write something from scratch, but probably neither will be out this year. If it does, Blur Busters has a lot of ideas with any upcoming open source virtual display drivers (in addition to software based overdrive), including neat stuff like BFI, simulated VRR like www.testufo.com/vrr

P.S. Don't use DLP with mechanical strobing, it kills DLP's color depth badly, due to DLP's temporal dithering. 10% persistence means 10% of the bits of color depth!
Head of Blur Busters - BlurBusters.com | TestUFO.com | Follow @BlurBusters on Twitter

Image
Forum Rules wrote:  1. Rule #1: Be Nice. This is published forum rule #1. Even To Newbies & People You Disagree With!
  2. Please report rule violations If you see a post that violates forum rules, then report the post.
  3. ALWAYS respect indie testers here. See how indies are bootstrapping Blur Busters research!

User avatar
Chief Blur Buster
Site Admin
Posts: 11647
Joined: 05 Dec 2013, 15:44
Location: Toronto / Hamilton, Ontario, Canada
Contact:

Re: Hacked ASUS VG279QM modified to single-strobe 60 fps capped VRR for emulators

Post by Chief Blur Buster » 12 Jun 2021, 02:33

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).
Head of Blur Busters - BlurBusters.com | TestUFO.com | Follow @BlurBusters on Twitter

Image
Forum Rules wrote:  1. Rule #1: Be Nice. This is published forum rule #1. Even To Newbies & People You Disagree With!
  2. Please report rule violations If you see a post that violates forum rules, then report the post.
  3. ALWAYS respect indie testers here. See how indies are bootstrapping Blur Busters research!

elexor
Posts: 169
Joined: 07 Jan 2020, 04:53

Re: Hacked ASUS VG279QM modified to single-strobe 60 fps capped VRR for emulators

Post by elexor » 12 Jun 2021, 02:59

Chief Blur Buster wrote:
12 Jun 2021, 02:33
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.
Will probably leave that one to the experts fluctuating frame times is very difficult to deal with. ;)
Chief Blur Buster wrote:
12 Jun 2021, 02:33
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).
not really noticing any flicker with capped fps and games that hold stable fps. I only notice variable crosstalk if frametimes get out of control and that is preferable to me then backlight flicker.
Chief Blur Buster wrote:
12 Jun 2021, 02:33
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.
using a teensy 4.1 600mhz so it seems to be microsecond accurate I learnt early on never to use any hard delays that could hold up the program. maybe it wouldn't run so well on a normal arduino.
Chief Blur Buster wrote:
12 Jun 2021, 02:33
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.
yeah.. I have zero mitigation right now for very low framerates and sudden loading screens. 30hz flicker can be painful I have experienced it while it doesn't send me into a fit and does give you a headache after awhile. :shock:
Chief Blur Buster wrote:
12 Jun 2021, 02:33
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...
it's not hard to outperform elmbsync it's pretty bad in every aspect.

User avatar
Chief Blur Buster
Site Admin
Posts: 11647
Joined: 05 Dec 2013, 15:44
Location: Toronto / Hamilton, Ontario, Canada
Contact:

Re: Hacked ASUS VG279QM modified to single-strobe 60 fps capped VRR for emulators

Post by Chief Blur Buster » 12 Jun 2021, 03:12

elexor wrote:
12 Jun 2021, 02:59
Will probably leave that one to the experts fluctuating frame times is very difficult to deal with. ;)
For now if you do this -- then for simplicity, avoid predictive future frametimes for this -- just use the micros() between two trailing VSYNCs. The easy peasy stuff.

It's okay for the VSYNCs to jitter (frametime error, VSYNC measurement error), it's more important to keep the pulse width as a exact percentage of the time interval between pulses.

For "exactness" simplicity, key between the leading edges of the backlight-ON, as the micros() measurement, and turn off the pulse as an exact ratio as possible of this time interval (as prescribed by a configured pulse width percentage constant).

Allowed to error/jitter without flicker side effects (at the 10 microsecond timescale):
- Framerate erraticness
- VSYNC jitter (relative to real VSYNC)
- VSYNC measurement error

Can't be allowed to jitter:
- Pulse width consistency as percentage of pulse interval

So you'll want to micros() measure right at the "ON" signal you send to the backlight, and use the interval between two leading edges of the square wave, and math a % of it to create your microsecond-exact pulse width. This will allow beautiful single-strobed VRR without erratic flicker over a much more massive framerate range -- the beauty of seeing erratic framerates without seeing noticeable flicker. Framerate ramping, framerate randomness, it'll be nice single-strobed VRR with minimal crosstalk (except near max Hz, but you can cap far away from it, e.g. 55fps-240fps beautiful single-strobe range for a 280Hz panel.

But you'll have to also add a low-framerate flicker protection algorithm (see below).
elexor wrote:
12 Jun 2021, 02:59
not really noticing any flicker with capped fps and games that hold stable fps. I only notice variable crosstalk if frametimes get out of control and that is preferable to me then backlight flicker.
Your use of a Teensy 4.1 was the right move and its performance is probably why you're not seeing candlelight flicker effects seen in less-precise strobed VRR experiments. Its ability to control things to the exact microsecond is doing its job, even with easy simple programming.
elexor wrote:
12 Jun 2021, 02:59
yeah.. I have zero mitigation right now for very low framerates and sudden loading screens. 30hz flicker can be painful I have experienced it while it doesn't send me into a fit and does give you a headache after awhile. :shock:
If you can find a way to trick NVIDIA's LFC flavour to begin at a higher refresh rate, coax it. This is probably easier with FreeSync implementations (you just add an EDID override with a higher min Hz) rather than G-SYNC Native implementations.

Barring that, you're going to devil-horn (copycat the ELMB SYNC algorithm) like I suggested. Except you begin doing that at perhaps 1/55sec after the last VSYNC and no VSYNC has arrived. You're simply executing high frequency PWM at the same ratios, ignoring VSYNC, as a way to "filler in" the screen brightness, until the new VSYNC arrives, then you suddenly turn off the devil horning algorithm, and resume your normal good-single-strobe-VRR agorithm.

Basically you rapidly flash on and off the backlight every few microseconds. If your pulse width is configured at 25% persistence (time interval between flashes), you might need to loop 4us on, 12us OFF until the very-late next VSYNC arrives. You'll want to configure a configurable ultrahigh PWM frequency, because some backlight brightnesses go out of whack at too high frequency PWM, because of capacitance effects and LED phosphor decay effets (0.1ms timescales). You're still preserving the pulse width as a ratio between leading edges of current and previous pulse, except you're suddenly doing at a high frequency once you're say past a min-framerate threshold (e.g. 1/55sec) since the last VSYNC without a new VSYNC arriving. This greatly reduces the painful low-Hz flicker (30Hz) from menus and such.

There are (almost certainly) better algorithms, but this is the simplest, most rudimentary low-Hz-flicker-avoidance algorithm to begin with.
elexor wrote:
12 Jun 2021, 02:59
it's not hard to outperform elmbsync it's pretty bad in every aspect.
At least for these implementations, I am not surprised, indeed.

ASUS likely made some "avoid flicker like the plague" decisions that probably benefits less experienced audiences (to minimize user complaints), but us power users want to have more flexibility. Multiple ELMB-SYNC modes adjustable in menus, would have been pretty neat -- to allow advanced users who want single-strobe from ~55Hz-thru-max-Hz.
Head of Blur Busters - BlurBusters.com | TestUFO.com | Follow @BlurBusters on Twitter

Image
Forum Rules wrote:  1. Rule #1: Be Nice. This is published forum rule #1. Even To Newbies & People You Disagree With!
  2. Please report rule violations If you see a post that violates forum rules, then report the post.
  3. ALWAYS respect indie testers here. See how indies are bootstrapping Blur Busters research!

elexor
Posts: 169
Joined: 07 Jan 2020, 04:53

Re: Hacked ASUS VG279QM modified to single-strobe 60 fps capped VRR for emulators

Post by elexor » 12 Jun 2021, 03:52

Thanks for all the info chief this will help me improve it for sure.

I would love to just leave my monitor at 280hz gsync 50-240hz LFC off

what i hoped to do was make optimized strobing effortless no mode switching just cap your fps and you are good to go.

elexor
Posts: 169
Joined: 07 Jan 2020, 04:53

Re: Hacked ASUS VG279QM modified to single-strobe 60 fps capped VRR for emulators

Post by elexor » 12 Jun 2021, 06:37

Chief Blur Buster wrote:
12 Jun 2021, 03:12
wow got it to single frame down to 30fps while still being in 280hz gsync mode. no idea how i did it usually it will do LFC if 1 frame dips under 85hz i think. been messing with resolutions in cru maybe i broke something...

One big problem is the framerate dips under 30fps for any reason the whole monitor will blank out not just the backlight the whole monitor black screens vsync signal disappears. it recovers once the framerate rises back above 30fps some games it will blank out on loading screens and take awhile to come back.

so I need to find a way to stop it going under 30fps or figure out how to reset it back to it's normal behavior.

Post Reply