rama wrote:
The caching fix is out, along with that HTotal-- button and nicer readouts.
This should make it easier to dial in better HDMI accepted timings.
Perfect, thank you, I can confirm the caching fix works as do the HTotal-- button and the more detailed readouts are a real blessing.

One thing I think noticed in a couple of places is confusion between sfr/ofr variables when retrying, like this:
Code:
if (ofr < 1.0f) {
delay(1);
sfr = getOutputFrameRate(); // retry
}
(Should the second "sfr" be "ofr"?)
It's a bit Heath Robinson as I'm not sure of the best way to do it but I added a little helper function to try to snap timings to an integral frame rate:
Code:
boolean snapToIntegralFrameRate(void) {
// Fetch the current output frame rate
float ofr = getOutputFrameRate();
if (ofr < 1.0f) {
delay(1);
ofr = getOutputFrameRate();
}
if (ofr < 1.0f) {
return false;
}
// Get the target frame rate.
float target = round(ofr);
// We'll be adjusting the htotal incrementally, so store current and best match.
uint16_t currentHTotal = GBS::VDS_HSYNC_RST::read();
uint16_t closestHTotal = currentHTotal;
// What's the closest we've been to the frame rate?
float closestDifference = fabs(target - ofr);
// Repeatedly adjust htotals until we find the closest match.
for (;;) {
delay(1);
// Try to move closer to the desired framerate.
if (target > ofr) {
if (currentHTotal > 0 && applyBestHTotal(currentHTotal - 1)) {
--currentHTotal;
} else {
return false;
}
} else if (target < ofr) {
if (currentHTotal < 4095 && applyBestHTotal(currentHTotal + 1)) {
++currentHTotal;
} else {
return false;
}
} else {
return true;
}
// Are we closer?
ofr = getOutputFrameRate();
if (ofr < 1.0f) {
delay(1);
ofr = getOutputFrameRate();
}
if (ofr < 1.0f) {
return false;
}
// If we're getting closer, continue trying, otherwise break out of the test loop.
float newDifference = fabs(target - ofr);
if (newDifference < closestDifference) {
closestDifference = newDifference;
closestHTotal = currentHTotal;
} else {
break;
}
}
// Reapply the closest htotal if need be.
if (closestHTotal != currentHTotal) {
applyBestHTotal(closestHTotal);
}
return true;
}
I added an 'S' command as I don't believe that's currently used (for "snap") in the main loop:
Code:
case 'S':
{
SerialM.println("Snap to integral frame rate");
snapToIntegralFrameRate();
break;
}
...as well as a button to the webui.html:
Code:
'<p>Snap to integral frame rate</p>' +
'<button class="button" type="button" onclick="loadDoc(\'S\')">Snap to integral frame rate</button>' +
This now works for me, if I press the button I added to the UI it adjusts htotal in steps until it finds the output framerate that's closest to an integral value. Active FrameTime Lock needs to be disabled for this to work, naturally. What this means is that I can now just hook everything up, select the desired preset, and press that new button and it all works. A bit of a kludge and I'm sure you can think of a hundred better ways to achieve this but in the short term it's doing what I need it to!
