Wednesday, 7 September 2011

21. Building An EEPROM Programmer (Part 2).

The Arduino can receive data via the Serial interface. This is how I want to send the Z80 programs to the EEPROM. The problem is the Arduino is not reading fast enough and so what gets sent is lost. Its fine for sending the odd few bytes now and then, but (using my zx81.rom as a test) sending 8K of data is a bit much for it to handle in one go.

The Serial buffer on the Arduino is 128 bytes, so all I was getting to start with was the first 128 bytes of the 8K successfully, after that it was a random sets of 128 bytes from the Serial port that it grabbed hold of before the stream of data ended.

To compensate for this, I decided to send 64 bytes at a time with 1 second interval. Now this is fairly easy to do in Linux with a script:

eeprom_send.sh
#!/bin/bash
split -C 64 ${1} ${1}.part.
for part in `ls ${1}.part.*`
do
 cat ${part} >> ${2}
 sleep 1
done
rm -f ${1}.part.*

To use it type:
./eeprom_send.sh zx81.rom /dev/ttyACM0

But first you just need to program the Arduino and then open the serial monitor window (dont ask me why).

Here is the Arduino program:
/*
 EEPROM Programmer
*/
#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 A;
int D;
int wait;

void setup() {
  
  Serial.begin(115200);
  Serial.flush();
  
  pinMode(STS,   OUTPUT);
  
  // 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],OUTPUT);
  }
  
  // Setup Control Pins
  pinMode(CE, OUTPUT);
  pinMode(WE, OUTPUT);
  pinMode(OE, OUTPUT);
  
  // Setup Chip
  digitalWrite(CE, LOW);
  digitalWrite(WE, LOW);
  digitalWrite(OE, HIGH);

  Serial.println("Waiting for Data...");
  while(Serial.available()==0) {
    digitalWrite(STS,LOW);
    delay(100);
    digitalWrite(STS,HIGH);
    delay(100);
  }

  for (A=0;A<memsize;A++) {
    
    D=Serial.read();
    digitalWrite(STS,HIGH);  //Signal that we're writing.

    // 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]);
    }
    delay(1);
    
    digitalWrite(OE,LOW);   // Reads Disabled
    delay(1);

    digitalWrite(CE,HIGH);    // Chip Enable
    delay(1);

    digitalWrite(WE,HIGH);    // Write Enabled
    delay(1);
    
    // Setup Data Pins
    for (i=0;i<8;i++) {
      if((D&bit(i))>0) {
        DD[i]=HIGH;
      } else {
        DD[i]=LOW;
      }      
      digitalWrite(DP[i],DD[i]);
    }
    delay(1);

    digitalWrite(WE,LOW);      // Write Disabled
    delay(1);

    digitalWrite(CE,LOW);      // Chip Disabled
    delay(1);

    digitalWrite(OE,HIGH);       // Reads Enabled
    delay(1);
    
   digitalWrite(STS,LOW); // Signal that we're waiting
    wait=0;
    while(Serial.available()==0) {
      delay(1);
      if (wait>2000) {
        A=memsize;
        break;
      }
      wait++;
    }
    
  }
  
}

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

5 comments:

  1. Hi Dave, I've used your code to write ROM data to a 4 Megabit EPROM chip (27C322). Seems to work well (still writing some data on it right now), but writing is extremely slow through the arduino; over two hours to write the whole chip.

    ReplyDelete
  2. I would try and reduce the delay between bursts as sleep will accept sub second values such as 0.1, or even use the whole 128 buffer by changing the value of 64 to 128 in the shell script. I think the baud rate is maxed at 115200 so that wont go any faster.

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

    ReplyDelete
  4. It turns out nothing is being written to the EPROM at all. I might be having trouble setting the EPROM to program mode, the datasheet says programming mode is when "VPP input is at 12.V, GVPP is at VIH and E is pulsed to VIL. VCC is specified to be 6.25V ± 0.25V."

    ReplyDelete
  5. I used an EEPROM that works on 5V. See post http://z80dave.blogspot.co.uk/2011/08/18-pinups-oops-i-mean-pinouts.html, its only 64kbits though. You'd have to add a 5v to 12v step up circuit. This is similar to how you'd program the PIC microcontrollers, but I have programmer for these that I bought off the internet.

    ReplyDelete