Tuesday, 6 September 2011

20. Building An EEPROM Programmer (Part 1).

Please note that I have disabled comments on this post purely due to a persistent spammer - Dave 23/04/2021.

Its all very well having an EEPROM chip to store our program for the Z80, but somehow we need to get the code onto it. Enter, the EEPROM programmer. So far I have wired up the EEPROM to the Arduino Mega and I can read from it successfully. Writing to it is easy enough, but just now I can't bulk load a file to it. When I do, go find Part 2 :)

Here's a diagram I made using this great tool called Fritizing:
As you can see I've used a 74LS04 Hex Inverter to make sure the 3 control lines are HIGH by default as the pins on the Arduino are LOW by default and as the control pins are 'Active Low' we don't want data overwritten accidentally. It also means that setting the pin to HIGH in the Arduino code means the pin is Active.

Here's the EEPROM Reader code for the Arduino Mega:
/*
 EEPROM Chip Reader
*/

#define memsize 8192

int STS   = 13;  // Status Indicator

int AP[16] = {22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52};
int AD[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int DP[8]  = {23,25,27,29,31,33,35,37};
int DD[8]  = {0,0,0,0,0,0,0,0};

int CE  = 4;
int OE  = 3;
int WE  = 2;

int i;
int j;
int D;
int A;

void setup() {
      
  // Setup Control Pins
  pinMode(CE, OUTPUT);
  pinMode(WE, OUTPUT);
  pinMode(OE, OUTPUT);
  
  // Disable Chip, and disable read and write.
  digitalWrite(CE, LOW);
  digitalWrite(WE, LOW);
  digitalWrite(OE, LOW);

  Serial.begin(115200);
  
  Serial.println("Reading EEPROM...");
  
  pinMode(STS,   OUTPUT);
  digitalWrite(STS,HIGH);
  
  // Setup Address Pins 
  for (i=0;i<16;i++) {
    pinMode(AP[i],OUTPUT);
  }
  
  // Setup Data Pins
  for (i=0;i<8;i++) {
    pinMode(DP[i],INPUT);
  }

  delay(1000);
  
  for (A=0;A<memsize;) {
    
    if (A<4096) Serial.print("0");
    if (A<256)  Serial.print("0");
    if (A<16)   Serial.print("0");
    Serial.print(A,HEX);
    Serial.print(" ");

    for (j=0;j<16;j++) {
    
      // Setup Address Pins
      for (i=0;i<16;i++) {
        if((A&bit(i))>0) {
          AD[i]=HIGH;
        } else {
          AD[i]=LOW;
        }      
        digitalWrite(AP[i],AD[i]);
      }
    
      digitalWrite(CE,HIGH);      // Chip Enabled
      digitalWrite(OE,HIGH);      // Read Enabled
    
      // Read Data Pins
      D=0;
      for (i=0;i<8;i++) {
        DD[i]=digitalRead(DP[i]);
        D=D+bit(i)*DD[i];
      }
    
      digitalWrite(OE,LOW);     // Read Disabled
      digitalWrite(CE,LOW);     // Chip Disabled
    
      if (D<16) Serial.print("0");
      Serial.print(D,HEX);
      Serial.print(" ");
      
      A++;
    }
    
    Serial.println();
    
  }
  
}

void loop() {
  digitalWrite(STS, HIGH);   // set the LED on
  delay(500);              // wait for a second
  digitalWrite(STS, LOW);    // set the LED off
  delay(500);              // wait for a second
}

19 comments:

  1. I followed your example for the Arduino Mega (2560) (the board I used) on a 8755A Micro-controller and since this IC was not a programmed IC I was able to read the data from it...which should have been all FF's in Hex and it was...Thank you for your example. My next step is to program this IC but I know I need to figure out how to provide Vdd between 5 and 25 volts for the program and verify functions. Your example helped out so much...once I'm able to actually program this device I will be glad to send the setup and for the read and write procedures for this device using the Arduino Mega 2560

    ReplyDelete
    Replies
    1. Glad you found it useful. I need to get back onto this project and finally build a Z80 computer. There are so many things to learn about and experiment with in electronics that I just end up getting distracted. Distractable Dave my wife calls me lol

      Delete
  2. I know the feeling...I've been working on building a 8085 SBC for about two years and finally got around to figuring out how to read/write the EEPROM...but I still need to program some other PROMs too so this is just the start for me. I've been working with electronics and programming for 15+ years at least job wise...on and off hobby wise for too long.

    ReplyDelete
  3. Thanks for posting this Dave, I was trying to use a standard Arduino, but came up against the lack of data pins. Using your code and circuit it worked first time.

    Thanks for saving me the cost of a dedicated programmer. :)

    ReplyDelete
  4. Hi Dave, thanks for a great Z80 resource.

    I feel I know the answer but is there anyway I can use my uno for this?

    Thanks

    Ashley

    ReplyDelete
    Replies
    1. Hi Ashley, the UNO is slightly limited by the number of outputs. Possible options are:
      (a) to use the same output for both data and addresses and use external latches/buffers to hold the data and address values (although maximum address value is still limited by the number of output on the UNO) and you'd need at least 1 more output to switch between the external devices,
      or (b) have 8 data outputs and another output to send a pulse to external counter ICs e.g. link 4x 74193 to make a 16 line addresses incrementing by one for each pulse.

      Hope that helps.

      Delete
    2. I realised as I posted this , I am talking about writing to an EEPROM and this post was about reading, so the only difference is the that address needed to be written and the data read so in the case of option (a) this would mean switching the mode of the pins between output for address and input for read. In option (b) the data pins would be inputs and the 'clock' pulse an ouptut.

      Delete
    3. Thanks for the quick reply Dave, I did a little more research and found the EEPROMMER, I cannot say how it works but I think I might be able to achieve the same with my uno.

      Thanks

      Ashley

      Delete
    4. Hi again Dave, sorry I meant to write MEEPROMMER. I have since had time to look at and understand the elegant solution by Mario Keller and it appears to be as you suggested (b) an 8 bit shift register is used for addressing.

      Thanks

      Ashley

      Delete
    5. Hi Ash. I just did a blog post about using binary counters that could be used as address lines. See http://z80dave.blogspot.co.uk/2014/02/42-working-with-74193-4-bit-binary.html.

      Delete
    6. Thanks Dave, that's helpful in understanding the logic.

      Ashley

      Delete
  5. Thanks Dave, I got this working pretty much straight away once I figured I'd wired the NOT gates incorrectly. I changed the program to embed the data in the code for ease. It's also for a Z80 homebrew. I think I'll create a soldered strip board, as I suspect I'll be change the code very often.

    ReplyDelete
  6. This comment has been removed by the author.

    ReplyDelete
  7. Sorry Dave, your schematic seems wrong.
    Please check pinout of LS04 chip.

    ReplyDelete
    Replies
    1. Yes you are correct, green wires should be pins 1, 3 and 5 and purple wires 2, 4 and 6. Well done for finding that but I'm sorry but there is no prize for "Spot the deliberate mistake." :D

      Delete
  8. This comment has been removed by the author.

    ReplyDelete
  9. Hi there
    I've been reading his useful page a few times now and I have a question, given my ignorance on the subject!
    I need to flash an ATMEL AT29C020 and I have an Arduino DUE. The Atmel seems to be very similar to the one you're using here but the datasheet mentions 5V operations while the DUE only works at 3.3V - even though it has a 5V output that can be used.
    I'm just wondering whether this project would work with my hardware?
    Thanks!

    ReplyDelete
  10. Shit Man .......
    When building it using the diagram it is impossible to work. This is because wrong connectioning the SN72LS04. Outputs and Inputs of the invertergates are used wrong.

    ReplyDelete
  11. you are totally right! I need to see if I still have the Fritzing Project files for that. However there may be a better way to do it as most modern programmable ROMs use I²C or SPI, and require only 3 connections.

    ReplyDelete