It all started at the beginning of 2015 when an EPROM related topic was discussed in the Color Computer mailing list where I participate. I recall that way back in the 80s I coded a small program that I put on an EPROM and ran when the computer was started. I recall having to take numerous factors into consideration so that the code would run correctly.
I was curious enough about these long forgotten components (so forgotten that when I search for “EPROM” on Google it thinks it is a misspelling and corrects it to “EEPROM”) that I started to look for a reader. I found that most of the items that I found were readers/burners. I wondered what was needed to build just a reader.
Other thoughts included an EPROM emulator where some modern storage media could be used to emulate the physical functionality of an EPROM. I left that project on the shelf, deciding to first look further into the reader. This project interested me because of its learning potential.
The first task was determining how I was going to get the address to the EPROM. The second task was determining how I was going to get the data from the EPROM back to the computer. My preferred communications method is serial through USB since no modern computers have a serial port (RS232) anymore.
An option I considered was using a USB/Serial adapter who would then connect to the necessary electronics that would put the address out on the corresponding lines and would then fetch the data that the EPROM would spit out. This option evolved to using an Arduino. I liked this option because it already included the USB interface which could be used as though it were a serial interface. Serial communications was easily handled by a slew of languages.
I then put together a block diagram of the reader. On the PC end it consisted of a Windows application that would send a “read” command to the Arduino. A different read command was sent depending on the EPROM size selected by the user. The Arduino in turn would be responsible of interfacing with the EPROM and fetching the required data. I asked myself a question? Has anyone done this before?
I went off to my usual search Website and after some research I found a page that documented a reader of sorts. The Webpage is the following:
Update 2019-06-06: Above link deprecated, try the following:
The author got his inspiration from another device that included similar functionality. He used a couple of 74LS393 4-bit binary counters to generate the EPROM address. I was thinking of using the Arduino for this, somehow multiplexing the address lines so that I could generate the 16 bits; however, I liked the idea of having the Arduino pulse the clock on the ‘393s and have them generate the actual 16 bits. By cascading two ‘393s the device was able to count from 0 to 64K.
This strategy seemed ideal for reading the entire EPROM, but would definitely hamper the ability to read just one address. Since my objective was getting a data dump from the EPROM, I did not see this limitation as being a deal breaker.
I decided to change my technique and let the electronics generate the address, instead of having the Arduino do it directly. Now I had plenty of lines available for other purposes. I used the Arduino’s digital lines for the EPROM’s 8 data lines. I drew up an initial schematic based on the information found on the above referenced page and stared at it for a while making sure that everything looked right. Power was not a problem; I would get that from the Arduino which in turn would get it from the USB port.
When I was satisfied with the schematic I ordered parts which included a 28 pin ZIF socket and the 74LS393s. I then came to realize that I did not have any EPROMs. If I was going to test the circuit at all I would need an EPROM. Luckily one of my friends from the ChiBots robotics group had a bunch of EPROMs and gave me a few. The only downside was that they were all 27C64s. I would have liked to have had different sizes so that I could have tested my circuit with them.
Once I had the schematic drawn on a sheet of paper I started to look into how I could capture it. There are numerous software applications to capture the schematic. Since a friend of mine at RESET uses DIP Trace for his professional work I decided to give this software package a try. DIP Trace can best be called a software suite that consists of schematic capture and PCB design. This is a commercial product; however, they offer a free version for smaller projects that limits the number of pins to 300. This looked like the right choice.
I downloaded the software and found it easy to use. The hardest aspect I found about capturing the schematic was defining the Arduino Nano, and locating the EPROM component. I finally asked in a forum about the EPROM component. The solution was simple enough. I needed to specify greater detail in my component search. While 2764 did not return results, 27C64 did. After that hurdle I had the schematic ready.
Next was the Windows software application. I decided to use C#. My first objective was to create an app that sent a command to the Arduino telling it how many bytes to send back. While I was waiting for the parts to come in I coded an Arduino sketch that listened on the serial port and sent back a certain number of bytes depending on the command received. My goal here was to have the serial communications working before I ventured to get data from the EPROM.
My efforts resulted in a Windows application that tested for the presence of the Arduino with the “Reader” software, and once found would allow the user to select a “size”. Once the size was selected the user would click a button and the Arduino would start sending the bytes. The app would then place the resulting bytes in a list. Since this app was a precursor to the EPROM reading app I made sure that the size was something small. The command supported were digits from 0 to 6 and an asterisk. Sending a ‘0’ would cause the Arduino to send back one byte. Each consecutive number up to 6 would have the Arduino doubling the number of bytes sent back. The asterisk was a “Hi Five” sign. The Arduino would respond to this command by sending back a plus sign. The Hi Five acknowledgement was to test the presence and responsiveness of the Arduino.
A video of my tech notes for this preliminary project can be found here:
Tech Notes: C# Serial Programming
Once I had the serial communications working it was time to migrate this knowledge and apply it to the software for the EPROM Reader. I modified both the Arduino sketch and the C# application to adapt them to reading the EPROM instead of just sending a few bytes over.
The list in the Windows application was replaced by a nifty hex dump component whose appearance resembles that of the venerable MS-DOS Debug when the “dump” command is used. The Arduino sketch was updated to provide an address to the EPROM, read a byte from the EPROM, and handle its control signals.
When the parts arrived I got out a breadboard and a bunch of wires and started to build the first prototype. I finished that in perhaps 2ish hours, spread out across two days.
I designed the Windows application to support 4, 8, 16, 32 and 64K EPROMs. As an extra I added the ability to save the dumped EPROM contents to either a binary or text file. Once I had the application ready and the prototype built I was ready to test.
Obviously, my first test did get back something, namely zeroes. The first draft of both the Windows application and the Arduino sketch only returned a fraction of the number of bytes of the EPROM. Returning 8K bytes was overwhelming, so I fixed the two software components so that they would return and process 20 bytes.
While it was plausible that the EPROM’s contents were zero I assumed that this was bad data. I switched from using the C# application to using the Arduino IDE and its Serial Monitor to determine what I was getting back from the Arduino. I added logging to the different routines of the sketch and narrowed the problem down to the routine that read the value from the digital lines and converted it to a number. I had gotten the original software from the page referenced above and modified it for my purposes, but the original initialization and reading routines were mostly intact.
What I discovered was that the routine was not getting anything from the digital lines. It was as though they were disconnected. I used the serial println() function to send the actual reading from each of the bits and found that it was not sending anything. It could be that the ‘393s were not correctly connected and thus not generating the address that the EPROM was expecting. To see what was going on I hooked up 5 LEDs to the least significant bits of the address lines. I added some exaggerated delays to the sketch so that I could actually see the LEDs toggling. I ran the program and much to my surprise the address was being correctly generated! Yay! Score one for me.
Next I suspected that I was not controlling my EPROM /OE and /CE lines correctly, I added a couple of LEDs to these lines and retested. I found that they were being generated correctly. These lines were directly connected to two analog Ax lines of the Arduino and were controlled directly by the sketch. While the sketch was running, monitoring the serial line for a command, I kept the /CE and /OE lines high. Once the circuit received a “read” command I asserted the /CE line and kept it in that state until all the bytes were read. Then when entering “read” mode, I cleared the address buffer (the 2 ‘393s) as part of the initialization process. Once that was done I asserted the /OE line to get data onto the data buss. I then proceeded to call the routine that read the data, set the /OE back to high, and finally I applied a pulse on the clock of the counter to increment it to the next address.
I repeated the read cycle every time the Loop procedure was executed. Once the last byte was read and sent I set /CE to High and place the sketch back into listening mode, waiting for the next read command.
Still I was not able to read anything from the EPROM. The zeroes that I was getting were from the variable’s initial value. I looked over the code and found that the setting of the digital lines to input was not spanning all of the 8 bits. I corrected this by slightly tweaking the “for” statement. This; however, did not fix the problem.
After some research on the Internet and consulting Jeremy Blum’s book “Exploring Arduino: Tools and Techniques for Engineering Wizardry”, I found that it is recommended that pull up/down resistors be used on the digital line inputs. I started looking into that. A resistor value of 10K was recommended. Here is a link that discusses this:
Since I needed 8 of these I started looking for a resistor pack that fit these specifications.
In parallel I was also looking for a way to read the EPROM and save its contents to a file. I needed this because I wanted to have a reference. As soon as my own Reader was functional I would need to compare the data read with a data set that was known to be good. I did not want to purchase a reader/burner for two reasons: First the cost. Just about all the readers/burner cost $30 USD and up. The second reason was that I already had enough stuff in my house and did not want to get more stuff, especially something that I would use basically only once. I should mention that I found a burner/reader which was also compatible with EEPROMs and other programmable chips selling for $50ish USD. I will probably look into purchasing it should I need such functionality in the future.
I decided to consult with the Chicago Classic Computing Group on Facebook to see if they could suggest a solution. One person provided a link to a page which detailed the construction of a simple EPROM reader:
I looked over the page and the software. I noticed that the construction did not involve using any resistors at all! This was also the case with the original page that I used to design the circuit. I also noticed the similarities of the Arduino sketch. The main difference was how the data bits were being read. My sketch read them one at a time using discrete programming statements while the sketch on this page used a loop. In the end I decided to leave my code as it was, even if it was less eloquent than the example on the NYCR page.
Another item that I noticed was that it made mention of the /PGM and Vpp lines and how they were set during the reading process. This was something that I had not looked at. I decided to take another look at my schematic and found that both of these lines were tied to the two most significant address lines (A14 & A15) of the binary counter. Since I was only reading a few dozen bytes it was guaranteed that that these two address lines would be 0, or at a low state. Vpp did not seem to care, but I wondered about /PGM. The way the circuit was wired was intentional to provide support to different sizes of EPROMs where the two largest sizes (32 and 64K) used the Vpp and /PGM pins of smaller capacity EPROMs as address lines.
For testing, and knowing that my EPROM was a 27C64 I tied both /PGM and Vpp to Vcc. I tested again and it worked! I got bytes from the EPROM, nicely displayed on the Arduino’s Serial Monitor and in my Windows application screen. I tested with Vpp both at Vcc and ground and this made no difference. It was definitely the /PGM line that was causing the problem.
My first thought was to add a couple jumpers to select either an address line or a Vcc/Gnd signal to these pins, but decided against it. I wanted the circuit to self-configure depending on the EPROM size selected in the Windows app. I wanted a circuit that would select either the address line or the control signal based on a selection pin.
CTRL is the level applied to either the /PGM or Vpp lines. What I was looking for was a 2 input multiplexer. Fantastic! I just needed to locate an appropriate IC. I found the 74LS157. I should have been happy, but certain details kept gnawing at me. First was the fact that I would only be using 50% of the chip, since I only needed two muxes. The second was the fact that my control signals would be either Vcc or Gnd. I wondered if there was a simpler way to implement the “mux” functionality without using a formal multiplexer. Another factor was that the LS157 used a common selection line for the four muxes. I needed independent selection lines; one to control the Vpp input and another for the /PGM line.
After some research I found a mux equivalent circuit.
Since I needed two muxes this meant that I would need two 74LS00s; however, since the CTRL line was going to be either Vcc or Gnd I saw the possibility of simplifying this circuit further. I converted the circuit to an equation and got to simplifying it.
I could have gone further. Since it did not matter what the Vpp pin was, I could have just connected the address line directly to it, but no, I wanted the gates <eg>, so I left it as the equation is shown below.
In the end I only needed one additional chip; the 74LS00 NAND gate. The extra wiring needed was minimal while providing the flexibility to support EPROMs of different capacities. Now I just need to get some different sized EPROMs to fully test the above circuits.
I then changed my code so that the EPROM reader would read the full 8K bytes and retested and much to my surprise it did not work. The Arduino seemed to just hang after a certain number of bytes. I once again started to tweak both applications. I reverted to the initial 20 bytes and this worked fine. I wondered if the number of bytes read was a factor. I started to increase the number of bytes read until I reached 1,200. From there I increased it to 1,600 and there it failed. Why The Fail?
I then tested again using the serial monitor and this worked fine. I increased it to 8K and this also worked, albeit slowly. I needed to see if the Arduino sketch was sending back information so I added code to make the integrated LED blink every 100 milliseconds as the Arduino was sending bytes. This showed me that the Arduino was doing something. I tested again with the Windows application and again it failed.
I concluded that the problem had to be in the Windows application. It was there that I concentrated my efforts. I looked over the event driven code, but I did not find any obvious anomalies. This worked flawlessly if the number of bytes expected were less than 1,200. It is then that it occurred to me that both the Windows application and the Arduino sketch need to know how many bytes are going to be transferred. I looked at the code that initializes this in the serial class and found that I had old code left over from my initial serial communication tests. The Windows application was expecting less bytes than the Arduino was sending. My guess is that once the Windows application stopped receiving the Arduino would at some point not know what to do with the pending bytes.
The Windows application was always expecting a different number of bytes than were defined in the Arduino sketch. I fixed that discrepancy and retested. It worked! The EPROM reader was now functional. The only issue I had was that reading 8K took a while. I wanted the application to display some sort of progress indicator to let the user know that it was still working.
I added another event to the serial class that fired once for every 200 bytes received. In that event I updated a caption on the application’s screen to let the user know how many bytes had been received so far. This, along with the blinking LED on the Arduino was enough to let me know that something was still going on, albeit slow.
I did not like the time that it took to read the EPROM. I decided to measure the time that it took to read the 8K EPROM. It took 2:45 minutes. I wondered whether I had used the correct strategy in building the Arduino sketch. As mentioned before the sketch is a state machine where one of the states reads a byte from the EPROM, sends it to the host, and then exits the loop() function. This is repeated until the entire EPROM is read. The program then returns to the initial state and reading is done.
I wondered whether it would be faster if the entire EPROM was read within one Loop() execution. This was easy to test. I just moved code around so that I would have a loop within the “sending” state. Instead of just reading and sending one byte the sketch would have a loop that would read and send all the bytes. I made the change and much to my surprise the timing was basically the same, differing by less than a second.
My next idea was reducing the delays from 10 to 5 milliseconds. I have two delays, one when I send a pulse to the address counter and another after I assert the /OE line. After I reduced the delay to 5 ms my read time of the 8K EPROM improved to 1:22 minutes. I further decreased the delay to 2 ms. The timing went down to 0:34 minutes. I tested using both versions of the sketch, finding that there was no discernible difference between reading and sending 1 byte vs reading and sending all bytes within one execution of the loop() function.
Once I had the circuit working and verifying that the captured schematic reflected the current state of the circuit I set out to create the PCB. DIP Trace can easily create the PCB from the schematic (this is still an understatement since all the user has to do is hit Ctrl-B while in the schematic capture application and the initial PCB is created). Once that is done the user is presented with the PCB layout with rat lines. From there the designer can move the parts around, allow the software to automatically do the placement, and manual or auto route the rat lines.
I auto routed everything. I was surprised that I used up 103 pins of the 300 available in the free version. Once my designs get more complicated I will probably purchase the upgrade that supports 500 pins for $145 USD. Once I had everything looking nice and routed I printed the PCB on a sheet of paper. Having the printout I placed the components on the printed PCB to get a look at what the finished product would look like.
While I reserved room for the Arduino Nano and the EPROM I failed to take into account the exaggerated size of the ZIF socket. My board size was around 2 x 2, but this did not leave enough room for the socket. I started from scratch again leaving the component placement alone, but still I could not make the ZIF socket fit without wasting PCB real estate. I finally caved and changed the component placement. At first I had the Nano and the EPROM side by side, but this did not favor an efficient layout. It was only after I placed the TTL ICs next to the Nano and the EPROM perpendicular (to the Nano) that I was able find a suitable layout.
I again printed the board, but found that the ZIF socket was too close to the jumper. I needed more room. I increased the board size and tried again. It wasn’t until the fourth attempt that it seemed that the board had enough room. The board’s final size came to 2 x 2.84”. The ZIF socket has a length of 2 inches so the socket will take up the entire width of the board.
Next was the manufacture of the PCB. My first choice was Osh Park, but I wanted other options to compare quality and cost. I consulted the Color Computer mailing list since various members have designed PCBs. They provided me with some recommendations, one of them being Hackvana. I had already heard of Osh Park and wanted to give them a try so I decided to try Osh Park for now and on the next run I would try Hackvana.
I generated the Gerber and N/C drill files and ordering the PCBs was painless. Note that I used the plural of PCB. This is because Osh Park has an order minimum of three. At first I was not sure which files I should submit to Osh Park; however, there is always someone that has done this before and has kindly documented it. In this case I found a couple of videos on You Tube that described the ordering process. What I learned is that if a specific PCB layout file is blank, I do not need to send it in. For example, there are assembly and silk screen files. I did not use the assembly “layer” for anything and also did not use a bottom silkscreen. Since these were blank I did not need to submit them.
I placed my order on July 11, 2015. The Website indicated July 23 as a possible date when they would have the boards from the manufacturer. Osh Park requires a minimum order of three boards at $5 USD per square inch for a two layer board. My board was just under 6 inches square so my total was about $28 USD.
The next day I received an email from Osh Park indicating that my boards had been assigned to a panel and sent to the manufacturer along with 86 other orders for a total of 486 boards.
I impatiently waited… and waited. Then on July 22 I got an email from OSH Park indicating that they had received the boards from the manufacturer and they would ship to my address within 48 hours. More waiting I thought, but then later on that day I got another email saying that the board had been shipped!
I received the board on Friday July 24.
Assembly and Testing
I took a chance on having the PCB made without more rigorous testing. I was almost expecting some oversight on my part. I decided to test each individual trace to verify that it matched the schematic. This was a redundant task since the board correctly reflected the design on the schematic, but decided to do it anyway for this first board at least. A huge advantage of the design software is that the data from the captured schematic is used to generate the initial PCB layout with rat lines, so it is guaranteed that the PCB designed using the corresponding software will be a faithful representation of the schematic.
Although the PCB layout software allows changes in the circuit, it is by far a better choice to modify the circuit in the schematic capture and then apply those changes to the PCB. This way it is simple to keep the schematic and PCB layout in synch. This is not done automatically, but having the option to do so is a great help.
After I verified all the connections I started assembly. Since this was the prototype I decided to socket everything which was in effect just the three 14 pin chips. The EPROM was going on a ZIF socket and I got a machine tooled female header for the Arduino Nano.
Unfortunately I was not able to get the Nano to go into the female header. It seemed like the Nano’s pins were too thick. I had some 40 pin DIP sockets and thought about using one of these, although the Nano is a 30 pin device, so I hacked the DIP socket and chopped off 5 rows.
After everything was soldered I plugged in the Nano and the three chips. All looked good and I was ready to test. I only needed a jumper block to connect pins 2 and 3 of the 24/28 pin EPROM select header so that the EPROM pin would get the address line and not Vcc. Much to my dismay I could not find any jumper blocks! I tried shorting the two headers using a wire, but the space was limited and I was not able to set the wire tight around the headers. I knew I had a wire wrap tool, but thanks to my efficient organizing method I was not able to find the tool. Finally after painstaking searching every compartment of my tool box I was able to locate a bag full of jumper blocks.
Inserting the jumper block was a piece of cake. I finally had the EPROM Reader fully assembled.
Next up was the moment of truth. I connected everything. Since I used a different Arduino Nano I downloaded the EPROM Reader sketch to it. It recognized everything correctly. Next I tested using the serial monitor. The 8K bytes were uploaded correctly. Finally I used my own software and everything worked as it should.
The Arduino Nano that I used was one of many work alike models. This Nano uses a CH340G instead of the usual FTDI USB/Serial chip. Apparently this has caused certain problems. My development and working environment was Windows 7, 32 bit, and I experienced no problems. I connected the Nano and waited for a few minutes while Windows detected it, and installed the necessary drivers. I also tested with Windows 8.1, no problem for me there either. Mileage may vary depending on your Windows installation.
I am not sure who would want an EPROM reader, but I enjoyed working on this project and its educational worth. It forced me to get out of my comfort zone and learn how to use DIP Trace and how to get the PCB made. On the software side I learned how to get data from a device external to the Arduino , how to send it over the serial line and how to design an event driven application in Windows using C# to communicate with the Arduino.
I wondered whether it would be a good idea to change the structure of this board and convert it to a shield that can be used with the Arduino Uno and compatibles. However, for now I like the way it is.
I am happy with the turnout because this is my first project that included all phases from conceptualization to manufacture. I can see myself tackling other projects that involve these steps without the concerns I had for this project. I hope to become more proficient at using the design software and designing the layout for the boards as I move forward with other projects.
Color Computer mailing list: https://pairlist5.pair.net/pipermail/coco/
Chicago Area Robotics: http://www.chibots.org/
RESET, R & D think tank based in Mexico: http://www.reset.com.mx
Chicago Classic Computing: http://chiclassiccomp.org/
Hackvana PCBs: http://www.hackvana.com/store/
Update 2019-06-06: Hackvana has closed, link deprecated. Home page is still up: Hackvana has closed
OSH Park: https://oshpark.com/