About 1 year ago, I bought this cheap chinese EPROM programmer (Top2005+) on eBay to help me during my various repairs. It can read and write most common 8-bit EPROMs, test most common 8-bit SRAM and test all TTLs I've encountered so far. All in all it works quite well, taking the price into consideration.
But having used the programmer and TopWin6 for a while, some things really started to annoy me:
- The SRAM-tester is really something that takes some getting used to, and I for my account would claim that it is faulty. Let me tell you why...
When you test an SRAM, what it does is take whatever is in the applications internal buffer (restricted to the size of the SRAM-unit) and uploads it to the SRAM; then it verifies the contents of the SRAM against the buffer. (Now what I would expect of a SRAM tester was to use some predefined (or randomly generated) stream of bytes for the test!!!) This behaviour is extremely stupid, because when you start TopWin6, the buffer is initialized with 1's (FF's in byte terms), so if you don't remember to fill the buffer with something else, you'll get the following scenario when doing an SRAM-test:
First you upload FF's to the SRAM, then you verify what's in the SRAM with FF's. Now as all the pins in the ZIF-socket is equipped with pull-ups this means, that an SRAM-unit that has all its data pins floating, will verify as good...unfortunately this is very common for SRAMs that are totally dead!!! (below you first see a test of a dead 6264; first with the default buffer with FF's and then with AA's. The first test verifies it as good...
- TopWin6 only supports testing 8bit SRAMs. However I have more than once been in a situation where I had to test 4bit SRAM (see i.e. this rep log). I can't see why?
- For some reason TopWin6 doesn't support reading and/or programming 16bit EPROMs (like i.e. 271024 and 272048) even though the ZIF-socket has got 40 pins.
Well now I do make my living being a programmer and I do know a thing or two about different kinds of hardware. So I thought: "HA! I can do better };-P".
So I started googling to see if anyone had done something similar (no reason to start from scratch, if you can stand on someone elses shoulders). First I found this brilliant article by OpenSchemes, where they dissect a Top2005 (notice the missing '+'). This is not precisely my programmer, but it has alot of similarities with the Top2005+. On one key point they differ; Top2005 has a Xilinx SpartanXL XCS05XL FPGA, whereas the Top2005+ uses the newer Xilinx Spartan2 XC2S15 FPGA; a fact that actually makes it more similar to one of it's big brothers Top2049.
So I started googling to see if anyone had done something similar (no reason to start from scratch, if you can stand on someone elses shoulders). First I found this brilliant article by OpenSchemes, where they dissect a Top2005 (notice the missing '+'). This is not precisely my programmer, but it has alot of similarities with the Top2005+. On one key point they differ; Top2005 has a Xilinx SpartanXL XCS05XL FPGA, whereas the Top2005+ uses the newer Xilinx Spartan2 XC2S15 FPGA; a fact that actually makes it more similar to one of it's big brothers Top2049.
Now if you look closely in the comments of the OpenSchemes article, you'll find a link to Toprammer for Top2049, an open source project by Michael Büsch written in python with the low-level parts of the algorithms coded in Verilog for the FPGA. I owe that guy many thx, as this project has been a great inspiration to me while coding my own.
Now I had alot of very awesome raw reverse-engineering material (although not exactly for the Top2005+, but for very similar programmers), so next I had to choose my 'weapon': The programming language. Well for me, it wasn't that much of a choice. As coding C# has been my bread-and-butter for the last 8 years, it has become more-or-less my programming native tongue. So C# is was.
As I had never tried to code anything interfacing with an USB-device, I went hunting for an easy-to-use USB-library for .NET and quickly found LibUsbDotNet that seemed to fit my needs. It comes with a few easy-to-understand examples, and the interface is very easy to use.
My goal was to find solutions to the 3 points mentioned above. Also I wanted to keep it simple, so I wouldn't do any FPGA-programming (as I don't know how to code i.e. Verilog) but rather use the ictest.bin-file that ships with TopWin6, implement all algorithm-logic in C# and just send the raw pin-assignments to the Top2005+. Also I wanted a simple way to add support for new ICs.
Let the coding begin };-P:
At first I hadn't realized, that the Top2005+ has an FPGA different to the one in Top2005, so I wasted some time trying to upload the XCS05XL-version of the ictest.bin-file, but ofcause it didn't work. It was only when I finally installed an USB-sniffer (as I have never used a USB-sniffer before, I have no idea if it's good or bad compared to others; but you get a free 30-days-trial of the full app, and it's fairly easy to use), that I saw, that the bit-stream being send to the Top by TopWin6 when preparing for an IC-test, wasn't what I expected to see. The sniffer also revealed, that besides the bit-stream-uploading, only about 15 other commands were send to the Top at start-up. In order to move forward a little faster, I just accepted these commands as 'black magic' to get it all working, and hardcoded them into my app. So now my Top was ready for some bit-bashing };-P
I started out by trying to read a 2716-compatible ROM (from a bootleg MoonCresta), just to see if I could get the Top to do anything at all. By comparing the article by OpenSchemes and the source of Toprammer, I could see that the commands where the same, so I figured that they would also apply to a Top2005+...and so they did };-P Pretty soon I had some simple mock-up code that could read the IC, and when checking the result with MAME, I got the same result as when reading it with TopWin6. The proof-of-concept was a success, and I started to make the code more 'generic' moving different parts into their own files and classes and making it possible to define an EPROM-specification in XML.
Now on to a 271024 (the NeoGeoMVS-BIOS). Here I met the first real hardware obstacle: The pin-out didn't fit the ZIF-socket pattern (not all pins can be assigned to GND/Vcc/Vpp); even though the ZIF has 40pins, it isn't possible to assign the pins 11 and 30 to GND.
Now I had alot of very awesome raw reverse-engineering material (although not exactly for the Top2005+, but for very similar programmers), so next I had to choose my 'weapon': The programming language. Well for me, it wasn't that much of a choice. As coding C# has been my bread-and-butter for the last 8 years, it has become more-or-less my programming native tongue. So C# is was.
As I had never tried to code anything interfacing with an USB-device, I went hunting for an easy-to-use USB-library for .NET and quickly found LibUsbDotNet that seemed to fit my needs. It comes with a few easy-to-understand examples, and the interface is very easy to use.
My goal was to find solutions to the 3 points mentioned above. Also I wanted to keep it simple, so I wouldn't do any FPGA-programming (as I don't know how to code i.e. Verilog) but rather use the ictest.bin-file that ships with TopWin6, implement all algorithm-logic in C# and just send the raw pin-assignments to the Top2005+. Also I wanted a simple way to add support for new ICs.
Let the coding begin };-P:
I started out by trying to read a 2716-compatible ROM (from a bootleg MoonCresta), just to see if I could get the Top to do anything at all. By comparing the article by OpenSchemes and the source of Toprammer, I could see that the commands where the same, so I figured that they would also apply to a Top2005+...and so they did };-P Pretty soon I had some simple mock-up code that could read the IC, and when checking the result with MAME, I got the same result as when reading it with TopWin6. The proof-of-concept was a success, and I started to make the code more 'generic' moving different parts into their own files and classes and making it possible to define an EPROM-specification in XML.
Now on to a 271024 (the NeoGeoMVS-BIOS). Here I met the first real hardware obstacle: The pin-out didn't fit the ZIF-socket pattern (not all pins can be assigned to GND/Vcc/Vpp); even though the ZIF has 40pins, it isn't possible to assign the pins 11 and 30 to GND.
It was time for a little improvisation; MacGyver-style };-P. I tied pin 20 (/OE) to GND (which WAS possible) instead of logical 0; this meant that the data outputs would always be active, but as my first priority was to read (and not write the EPROM) I didn't care at the moment. Next I connected pins 11 and 30 to 20 by using 2 wires.
...and PRESTO! I was able to read the contents of the bios-rom from my NeoGeo-MVS board };-P
...and also one of the EPROMs from my Gunbird board (a 27C2048)
Then, bold as I was because of my success, I tried programming the only empty 16bit EPROM I had (a 27C1024)...I failed! (ofcause I'd tried programming some of the smaller EPROMs first to see if I'd implemented the Classic Algorithm correctly; they all validated just fine!) When trying to validate it afterwards, I got a bunch of read-errors, that is the bits were not stabile (sometimes returns 0 and sometimes 1). Hmmm...went back and had a read at the data-sheet again and realized that
- /OE shouldn't be low during programming
- During programming Vcc should be raised to 6.5V
- 27C1024-27C4096 should be programmed with a special rapid algorithm as opposed to the Classic Algorithm (for more on programming algorithms see i.e. this wiki on EPROMs; the mentioned rapid is called Snap! in the wiki)
Now it was my hope, that I would be able to program 16bit EPROMs using (some form of) The Classic Algorithm, as implementing the rapid algorithm would have to be done with the FPGA using i.e. Verilog. So to get started with 1. and 2., I ordered a 40pin ZIF-socket (with extra long pins) and this little DC-DC step-up converter
And while waiting for my goods to arrive, I started working on an SRAM-tester, as one of my other goals of this project was to make a better SRAM-tester and to be able to test 4bit SRAMs.
The tester is very simple: It starts by writing the pattern '0101...', '1010...', '0101...' to the SRAM, then reads the SRAM and verifys the read data against the written pattern. Then it does the same again but with the complemented pattern '1010...', '0101...', '1010...'. I started by implementing the test for an 8bit SRAM (6116) that I was able to test with TopWin6 also; tried it on some working and some faulty units, and got the same results with both my test and TopWin6. Next step was to try it on a 6148 4bit SRAM, and then I met my next hardware obstacle. As with 27C1024 it isn't possible to place a dil18 IC (with standard Vcc-Gnd layout, that is Vcc on pin18 and GND on pin9) in the Top2005+ so that it gets proper supply. So again I had to do a bit of MacGyvering. By moving the IC one place forward and rewiring GND I was able to make it work
And proudly I was able to put the first check mark on my Goal-list; I was now able to test any SRAM that I could somehow fit into the Top2005+ };-P
Meanwhile the ZIF-socket had arrived from China, and I started working on making it into an adapter that could be used for 16bit EPROMS. First I realized, that the best way to place the adapter was opposite to the mounted ZIF-socket; that way the 2 handles wouldn't collide with each other. Next I carved a bit of the corner off with my Dremel to make room for the handle on the mounted ZIF.
Now a little rewiring was needed, and I started with this mock-up with the wires dangling around
Reading worked fine, but as I hadn't recieved the step-up-converter yet, I couldn't test proramming.
So now I had to make it look just a little bit nicer. Even though the pins on the socket I was using was extra long, having wires directly on the underside of it would result in it being elevated so much, that it would give rise to bad connections. So I carved away the plastic between the 2 rows of pins, making a 'valley' about 0.5mm deep. Then I drew the wires in there.
The IC-pins 11 and 30 (both GND) are mapped to ZIF-pin 20 (blue wires) as this one CAN actually be grounded. IC-pin 20 (inverse OutputEnable /OE) is mapped to ZIF-pin 30 (red wire). The switch on Vcc (pin 40) is there because I want to be able to easily attach the step-up-converter to provide 6.5V when programming, but still use 5V when reading. That's actually all thre is to it };-P
Now I just had to wait for the step-up-converter to arrive, and one monday afternoon it finally did! Full of hope and optimism I tried programming my only 27C1024 (the red wire is GND and needed by the step-up-converter)...
but alas };-( When trying to read the programmed EPROM all went well at first, but then I started to get a bunch of read errors (unstable bits, that is). Hmmm.... tried programming the gorram thing a couple of times more, and then I started noticing, that the read errors occurred in the same memory region every time. A sneaking suspicion started to emerge in my head: Had my only 16bit test-EPROM been faulty all along? };-O. Rushed to eBay and ordered 4 new 27C1024s! Now this waiting was even worse than with the step-up-converter }:-S So to 'ease the pain' I began making the code ready for a public release. That included correcting a couple of casing inconsistencies in filenames. (Now on a Windows machine, this isn't of much importance, as NTFS is case insensitive. But as hg (aka Mercurial, the version control system I use) is meant for use on different platforms, filenames with different casing are not considered the same.) The easiest way to do that, is to make a clone of the repo to a linux box, make the changes there (as the linux file system IS case sesitive), and then sync with the primary repo again. So time to boot up that old Ubuntu-system };-P
Now while I had the code on my linux-system, I decided to try and see if I could get it running on Mono (an open source implementation of .NET that runs on Windows, linux, and Mac) just for the fun of it.
After just a few small adjustments, the code compiled and ran flawlessly on linux. One thing I noticed though, was an enormous increase in speed, so I implemented a little test that timed 1000 ZIF-socket writes and displayed the average and the same for reads...below is the result (Windows native .NET is the first; Mono running on Ubuntu is the second)
The 2 important low level operations in my app ran twice as fast on Mono. Now this was a bit unexpected };-O. My theory is, that libusb-1.0, the library that LibUsbDotNet runs on top of, has a way better implementation on linux than on Windows; that's the only explanation I've been able to come up with. You migth also notice, that even though the low level operations is twice as fast, the 'Elapsed time' in the tests above are almost the same. That is because disposing the unmanaged USB-resources in the linux-case, is much slower, for some reason. But when reading or writing large EPROMs, that factor becomes insignificant. So an important note: I recommend using the app on Mono.
But finally my 4 new 27C1024s arrived from China. I just couldn't wait, but had to try right away. So I programmed the latest free UniBios image for the NeoGeoMVS; that way I could test it on real hardware. When I read the EPROM after programming I got no read errors and the read image validated as UniBios against MAME. With shaky hands I replaced the MVS-bios with my programmed EPROM, aaaaaand PRESTO!!!
I had finally succeed in programming an 16bit EPROM with my cheap-ass chinese programmer };-P
"Okay, so where can I get this jawsome piece of software?", you might ask...
Well you can get it right here };-P. Once you've downloaded the zip (or cloned the git-repo), you need to compile and install the app. But all that is documented in the Doc-folder. Please feel free to use the app any way you like or be inspired to do you own (as long as you don't break the GPL };-P).
Please leave comments; always nice to hear what people thinks about of what you do };-P