McBazel GBS-C Clock Gen Fix & Troubleshooting
Hey guys, ever run into those weird visual glitches on your retro gaming setups? You know, the ones that make you scratch your head and wonder if it's your cables, your console, or maybe even your brain? Well, if you're rocking a McBazel ODV GBS-C and messing with its clock generator, you might have stumbled upon some of those head-scratchers too. It turns out, some of these boards have a little hiccup where the I2C wires for the clock generator are swapped from the factory. It's not a dealbreaker, especially since the ESP8266 on board is super flexible and lets us assign pins pretty much anywhere. I've been digging into the GBS code, and I managed to swap those pins around so the clock generator gets recognized and hooked up. The good news? It mostly works! The bad news? Well, it's not perfectly perfect, and that's what we're gonna dive into today.
When you enable something called 'frametime lock,' the image can get a bit fuzzy. It's like it's lost its horizontal sync for a second, and this fuzziness pops up randomly and hangs around for a bit. If you disable frametime lock, the issue seems to disappear, but then you might get a tear line creepin' onto the screen eventually, and the only way to get rid of it is a good old reset. I've been doing all my testing with a PlayStation 1 and PlayStation 2, hooked up via RGB cables, running at 50Hz. Since turning off frametime lock makes the problem vanish, I'm leaning away from it being a cable issue. Sometimes, when these visual gremlins show up, I get a debug error reading 0x1A. I've seen other folks dealing with similar errors on NeoGeo setups, but the fixes they tried didn't quite cut it for me. So, I'm sharing my findings and the code modifications I've made, hoping someone out there might have a clue or a pointer on what's causing this persistent fuzziness and tearing. It’s a common device, so understanding and fixing this is super relevant for a lot of us in the retro gaming community.
The Initial Problem and My Workaround
So, the core issue here is that on certain McBazel GBS-C boards, the I2C communication lines for the external clock generator are wired backward. This means the GBS-C can't talk to the clock generator properly out of the box. Luckily, the ESP8266 microcontroller used in the GBS-C is incredibly versatile. Unlike some microcontrollers where specific pins are hardcoded for certain functions like I2C, the ESP8266 lets you reassign most pins to act as I2C SDA (Serial Data) and SCL (Serial Clock) lines. This flexibility is a lifesaver for us tinkerers! I dove into the gbs-control firmware, which is the software running on the GBS-C, and modified it to swap the I2C pins whenever it needs to communicate with the clock generator. This way, when the software is expecting the pins in one configuration, it uses the reversed wiring, and when it doesn't need to talk to the clock generator, it can switch back to its default or intended pin assignments.
The good news, as I mentioned, is that this workaround does allow the GBS-C to recognize and utilize the external clock generator. This is a pretty big deal because the clock generator is key for precise video signal timing, especially when you're trying to achieve accurate refresh rates and resolutions for retro consoles. Without it working, you're often stuck with the GBS-C's internal clock, which might not be ideal for all setups or might not offer the fine-tuned control needed for perfect sync. So, the fact that my pin-swapping code gets the clock generator online and communicating is a significant step forward. It means the hardware is capable, and the main hurdle was just a simple wiring mismatch.
However, the celebration is short-lived because the system isn't perfectly stable. This brings us to the 'bad news' – the 90% working scenario. While the clock generator is detected and seemingly used, enabling the 'frametime lock' feature can introduce visual artifacts. Specifically, the image can become fuzzy, almost like it's struggling to maintain horizontal synchronization. This fuzziness isn't constant; it flickers in and out, appearing at random intervals and lasting for unpredictable durations. It’s incredibly distracting when you’re trying to immerse yourself in a game. Furthermore, if you decide to disable the frametime lock to avoid the fuzziness, another issue crops up. Eventually, a horizontal 'tear line' will appear somewhere on the screen. This tear line is like a disruption in the video signal, causing a visible break and misalignment of the image. The only way to get rid of this tear line, unfortunately, is to perform a full system reset of the GBS-C. This suggests that even without frametime lock enabled, there's an underlying instability in the clock generation or synchronization process.
Diving Deeper: The Code and the Symptoms
Let's get a bit more technical, guys, and look at the code I modified and the specific symptoms we're seeing. The core of the problem lies in how the gbs-control firmware interacts with the external clock generator, particularly the Si5351 chip often used. My initial fix involved creating two simple functions: i2c_swap_pins() and i2c_restore_pins(). The i2c_swap_pins() function uses Wire.begin(default_scl_pin, default_sda_pin); – essentially telling the ESP8266 to use the pins that are expected by the clock generator for I2C communication, even though they are physically wired the opposite way on the board. Conversely, i2c_restore_pins() switches back to the default or original pin assignments, Wire.begin(default_sda_pin, default_scl_pin);, presumably for other I2C devices or internal functions that might rely on the standard configuration. These functions are called strategically before and after any communication with the clock generator chip.
One of the key functions I had to modify is externalClockGenResetClock(). This function is responsible for initializing and setting the frequency of the external clock generator. Inside this function, after determining the desired output clock frequency (rto->freqExtClockGen) based on the display's active clock setting, I now call i2c_swap_pins() before interacting with the Si5351 chip (represented by the Si object) and i2c_restore_pins() afterward. There were also specific frequency adjustments needed for certain clock speeds, like 108MHz and 40.5MHz, where the library seemed to be doubling the clock. My fix included forcing a specific frequency (Si.setFreq(0, 87000000) for 108MHz and Si.setFreq(0, 48500000) for 40.5MHz) with a small delay, acting as a quick workaround to nudge it into the correct frequency. This function is crucial because it dictates the base clock signal that the GBS-C uses for its internal operations and output timing.
Another area of modification was within the externalClockGenSyncInOutRate() function. This is where the GBS-C tries to synchronize its output frame rate with the input signal's frame rate using the external clock generator. Here, too, I wrapped the setExternalClockGenFrequencySmooth() call within i2c_swap_pins() and i2c_restore_pins(). The setExternalClockGenFrequencySmooth() function itself was also updated in framesync.h. It now uses the pin-swapping functions internally whenever it calls Si.setFreq(). This function is designed to smoothly adjust the clock frequency by stepping up or down in small increments (STEP_SIZE_HZ) to avoid abrupt changes that could cause visual glitches. The handleWiFi(0) call inside the loop is interesting; it suggests that even during these critical clock adjustments, the firmware is trying to keep network operations responsive, which might introduce timing jitter.
The externalClockGenDetectAndInitialize() function, responsible for finding and setting up the clock generator, also needed the pin-swapping treatment around the I2C communication parts, specifically when checking the device status and writing to configuration registers like XTAL_CL. Additionally, there were two instances of Si.enable(0) that I wrapped with the i2c_swap_pins() and i2c_restore_pins() calls to ensure the chip is enabled correctly using the reversed I2C lines.
Finally, in the serial command handling, when the 'f' command is used to manually set the external clock frequency, the Si.setFreq(0, rto->freqExtClockGen) call is now properly enclosed within the pin-swapping functions. This ensures that manual frequency changes are also communicated correctly to the clock generator. The debug error 0x1A I mentioned earlier is often related to I2C communication timeouts or NACK (Negative Acknowledgement) errors, which perfectly aligns with the idea that the communication with the clock generator is sometimes unreliable due to the pin mismatch or timing issues.
Analyzing the Fuzzy Sync and Tear Lines
Okay, let's really dig into why we're seeing this fuzziness and tearing, especially when frametime lock is involved. The McBazel ODV GBS-C is essentially a video scaler and processor. It takes an incoming video signal (like from your PS1 or PS2) and outputs it to your modern display, often at higher resolutions or with features like scanlines. The clock generator is super critical because it dictates the timing of everything the GBS-C does – how it samples the incoming video, how it processes it, and how it generates the output signal. If this timing is off, even by a tiny bit, you get visual artifacts.
When frametime lock is enabled, the GBS-C tries to precisely match its output frame rate to a locked value, often derived from the input signal. This is supposed to provide a super smooth, consistent viewing experience, free from judder. However, if the external clock generator isn't perfectly stable or if the communication with it is intermittent (which is likely given the reversed I2C wiring issue), this precise locking mechanism can break. The fuzziness you see is likely a symptom of horizontal sync loss. The display timing is slightly off, causing the electron beam (or its digital equivalent) to not quite align the scanlines correctly. It's like trying to read a book where the lines are slightly blurred or shifted – readable, but not perfect.
The fact that this fuzziness appears and disappears randomly suggests that the clock generator is sometimes stable and sometimes drifts or loses sync with the GBS-C's internal processing. This could be due to several factors: intermittent I2C communication errors caused by the reversed pins, noise on the I2C lines, or even timing conflicts between the ESP8266's other tasks and the clock generator's demanding timing requirements. The 0x1A debug error might be the GBS-C's way of saying,