Monday, July 30, 2018

NES Dejitter

When choosing my "modern" TV, I did a lot of research and comparison and wound up with the very excellent KDL-70R550A which has so far supported everything I have thrown at it.  Every console via the OSSC just works, every scaling mode, every oddball resolution, every janky sync signal, everything.

A few weeks ago, I installed an NESRGB on an NES for a friend.  He was using an OSSC to scale it to his PC monitor and a Panasonic Plasma, but could never get better than 2x.  He wasn't terribly concerned as those were stopgaps until his "real" gaming TV arrived.  Unfortunately the TV he bought couldn't tolerate the NES's irregular sync signal.  Fiddling with OSSC settings made it possible to display in 5x mode, but it would randomly lose sync.


Some Background

Others have analyzed and explained it far better than I, but the gist of the problem my friend was having was because of a design flaw in the original NES/SNES video output.  CRT televisions were considerably more forgiving of this flaw than most modern displays.  

This thread at shmups goes into great detail:
https://shmups.system11.org/viewtopic.php?f=6&t=61285

The gist of it is that the NES and SNES have irregularities in the sync pulse that tells the display where to draw lines from the incoming video.  CRTs displayed video in real time, whereas modern displays want to see a whole frame completed before sending it to the screen.  

The Easy Road...

It is, perhaps, fortuitous that marqs of the shmups forum had just recently completed hardware development of a "dejitter" mod designed to straighten out the irregular sync signal.  The hardware design has been available in a DIY fashion for some time via github (https://github.com/marqs85/snes_dejitter) but after reading through the programming instructions, I had no desire to fuss with building the board myself. 

Fortunately BuckoA51 (of the shmups forum) decided to start selling pre-assembled and programmed dejitter boards via videogameperfection.com.  I ordered one and told my friend to ship the NES back to me.

...Sometimes Crumbles Beneath You

About two days after placing my order, someone found a problem in the NES installations which required a firmware fix.  Though to his credit marqs identified and fixed the problem almost immediately, my big plan to avoid going through some complicated steps to reprogram the dejitter board was now a complete failure.


Step 1: You're Basically On Your Own

Reprogramming the dejitter chip represented a challenge for a couple of reasons.  Firstly, the interface socket, appears to be completely custom.  Secondly, it can apparently only be accomplished with an application called "OpenOCD" which is about a 2/10 in user friendliness and a 1/10 in intuitive design.

The first thing you'll notice about the instructions for programming is that there is no "get this specific programmer, get this software, enter these commands" instruction.  Most of it seems to assume that you have some existing knowledge and capability with CPLD programming.  In fact when asked this question, the OpenOCD developers replied with a statement to the effect that they purposefully avoid telling people which programmer to buy because the software is supposed to be universal.

The Real Step 1: Getting OpenOCD to play with USB Blaster Clones

As I mentioned earlier, the socket on the dejitter board is, as far as I can tell, proprietary, however the signals are standard.  I needed to create an adapter to go from the USB jtag header to the 6-pin socket on the dejitter board.  Fortunately the pins are all labeled so all that was needed was to look up a reference to the USB Blaster pins and match them.

I'm not completely new to programming CPLDs, though my knowledge is about as deep as a single sheet of paper.  (The original forum thread, posted above, has an excellent write up by the user NoAffinity with instructions for performing updates to the CPLD via a Raspberry Pi, and after going a different route myself, I believe that may be a better way to go if you have a Pi laying around)

About 9 or 10 years ago, I bought a "USB Blaster" to perform software updates on my v1 Everdrive64.  At the time I had no idea it was a cheap clone and not a real "USB Blaster".  It always just worked for me.

My "clone" USB Blaster

After looking at "official" USB Blaster prices, yeah, there's no way mine isn't a cheap clone. I paid more than $10, but not $300.  Evidently, for about 99% of what you'd want to do with it, it functions just like the real thing, but when it comes to OpenOCD - the supposedly "universal" software, the clone fails one of the basic startup checks.


OpenOCD will error out when it can't get latency timing because that's not a feature with USB Blaster clones, I wound up messing with the OpenOCD source code to "patch" out the check.


The steps I detail below are specific to Fedora Linux, but if you're using a different distro, or Windows, the modification of the source file "ublast_access_ftdi.c" should still work, you'd just go about compiling and installing it differently.


Download and install the Source RPM for OpenOCD 0.10.0 for your distro.
This puts the source tarball at ~/rpmbuild/SOURCES/openocd-0.10.0.tar.bz2

Unpack it:
Code:
cd ~/rpmbuild/SOURCES/
tar -xf openocd-0.10.0.tar.bz2


With the source tarball extracted, edit the source file that controls the latency timer check:

Code:
vim ~/rpmbuild/SOURCES/openocd-0.10.0/src/jtag/drivers/usb_blaster/ublast_access_ftdi.c


Comment out lines 105-109 and save the file:

Code:
105 /* if (ftdi_get_latency_timer(ftdic, &latency_timer) < 0)
106       LOG_ERROR("unable to get latency timer");
107    else
108       LOG_DEBUG("current latency timer: %u", latency_timer);
109 */


Then while still in the directory "~/rpmbuild/SOURCES", rename the old tarball and replace it with the edited source:

Code:
mv openocd-0.10.0.tar.bz2 openocd-0.10.0.tar.bz2.old
tar -cf openocd-0.10.0.tar openocd-0.10.0
bzip2 openocd-0.10.0.tar


With that done build the RPM

Code:
cd ~/rpmbuild/SPECS
rpmbuild -bb openocd.spec


Of course this requires that you have "rpm-build" installed, and will probably bug you for a bunch of dependencies.

When successful rpmbuild should give you the location of the RPM

Code:
Wrote: /home/user/rpmbuild/RPMS/x86_64/openocd-0.10.0-2.fc26.x86_64.rpm
Wrote: /home/user/rpmbuild/RPMS/x86_64/openocd-debuginfo-0.10.0-2.fc26.x86_64.rpm


From there just install the newly-created RPM and it will no longer check for a latency timer on USB Blaster clones. 



Step 2: Voltage Matters


With OpenOCD no longer failing because of that latency timer check, I was able to move on to the next problem.  OpenOCD was happy to use the USB Blaster, but it couldn't see the CPLD on the dejitter board.

The USB Blaster does not provide voltage to the chip it's programming - the chip actually has to be energized by some other means for the programmer to update it.  The expectation is that you'll have it installed on the NES and the NES turned on when you try to update it.  In my case since the NES was still in the mail on it's way to me, I simply wired an external 5v power source to the chip. The dejitter chip was built with the expectation that the programmer one might use to update it will only tolerate 3.3 volts rather than the 5V that the NES is going to be pumping into the circuit.  For this it has a resistor (R4) on the voltage pin.  After a forum conversation with marqs, I decided to short this pin because my USB Blaster is rated for 5v.


After doing this I was able to actually see the CPLD correctly in the OpenOCD interface, however it would still fail to program.

Finally I switched to a higher-current 5V power supply. The one I was initially using was rated at 700mA - and it may not have even been that high. I switched to a 2400mA supply and the OpenOCD was able to program the chip on the first try.


Step 3: Write The Instructions



Since the dejitter board was primarily designed as a SNES/Super Famicom fix and just happened to work for the NES/Famicom, most of the original instructions did not describe how to install the chip in anything else.

The Wiki at https://www.retromodwiki.com/wiki/NES_dejitter_mod did not originally have instructions for the front-loading NES (NES-001) until I provided them.  I was able to figure it out thanks to the general guidance at the beginning of that page, and the NES-001 schematic available at the excellent console5.com wiki.

The basic idea is to take the original crystal oscillator used for video processing out of circuit, and replace it with the oscillator circuit on the dejitter board.  Then the video sync signal is intercepted and cleaned by the dejitter board.  Figuring out what to do was a matter of mapping the clock circuit out with a continuity tester and comparing that to the schematic.

To prep the NES-001 for the dejitter mod, you need to remove the X1 crystal oscillator, and the C44 and C45 capacitors.  To make sure the mod board will fit, you'll also want to bend the three capacitors circled in yellow flat against the board.

Next you'll want to solder a wire between the outer vias of C44 and C45.  This connects the PPU and CPU "CLK" pins together.  Later on you'll connect the clock on the dejitter board to the CLK pin on the PPU so this will give both components a timing reference.


I recommend attaching the dejitter mod to the NES RGB like this, as it will ensure that you have access to the update socket if needed, and it lines up with the valley between the CPU and the PPU socket.

The rest of the instructions for wiring the dejitter mod to the nesrgb are available at https://www.retromodwiki.com/wiki/NES_dejitter_mod.


After installing the dejitter mod, I've tested the NES on every TV in my house and it's rock solid.