Skip to content

Programming the ATC2864 EEPROM

October 3, 2015

Years ago I used an eeprom(electronically reprogrammable read only memory) to replace a prom in an 1802 project. The pinout is similar but not exactly the same as the 27256 uv erasable eprom used in the ZMC kit. I still have the code that i used for programming the chips so i dug it out along with an arduino variant called a Sanguino. The Sanguino uses an atmega644p chip and has enough I/O to directly address the 13 address, eight data, and two control signals i need for the eeprom.
15-10-03 programmer
It’s a bit fragile looking but it should work. The biggest problem will be over time, whether I can hope to still use it or put it back together in a few years. In my dreams I’ll get lee to include circuitry to program it onboard the Z80 cpu board.
As it is the sanguino has been left way behind by the march of the arduino ide. I can cobble up something to use it but i’m having to program it with an ICSP programmer rather than the bootloader.

//Sanguino based prom programmer for 28c64 eeprom
// Commands via serial from the PC:
// d means display the source data
// r means read the prom
// w means write the prom from the source data
// l means lock the prom with its software data protection
// u means unlock the prom software data protection
// t toggles the bits in location 0 to test swdp
// z zero the prom
//
//Port C, digital pins 16-23 are addresses 0-7
//Port A, digital pins 31,30,29,28,27 are addresses 8-12
//Port B, digital pins 0-7 are used for D0-D7
//Port D, only a couple of lines are used.
#include <avr/pgmspace.h>
int notreadpin=14; // used to toggle the -MRD line
int writepin=15; //used to toggle -WE (active high through external inverter)

byte swdpd[]={0xAA,0x55,0xA0,0xFF}; //software data protection(swdp) data to write
unsigned int  swdpa[]={0x1555,0x0AAA,0x1555,0x0000}; //swdp addresses
int  swdpl=3; //swdp sequence length

byte swdupd[]={0xAA,0x55,0x80,0xAA,0x55,0x20}; //software data protection disable (swdp) data to write
unsigned int  swdupa[]={0x1555,0x0AAA,0x1555,0x1555,0x0AAA,0x1555}; //swdp disable addresses
int  swdupl=6; //swdp disable sequence length
//#include <simplestfail.h>
//#include <slowfast.h>
//#include <uon3.h>
//#include <idiot4.h>
//#include <kiss.h>
//#include <needles.h>
#include <send8000.h>
unsigned int addr; byte data; unsigned int addr0;
unsigned int progbegin; unsigned int progend;
unsigned int altbegin=0xdead; 

int cksum=0;
void setup() {
  DDRC=B11111111; //port C pins 23...16 all output - used for low address
  DDRA=DDRA | B00011111; //port A pins 27...31 are output - used for high address
  DDRB=B00000000; //port B pins 7...0 all input to start - used for data  
  digitalWrite(writepin,LOW); pinMode(writepin,OUTPUT);
  digitalWrite(notreadpin,HIGH); pinMode(notreadpin,OUTPUT);
  Serial.begin(9600);
  Serial.println(" "); Serial.print(">");  //initial prompt
  progbegin=msibgn; 
  progend=msibgn+msicnt-1;
}
void addrset(){ //set up an address via hex input
//altbegin is globally declared above
    Serial.print("Alternate address is "); p3hex(altbegin);Serial.print(". Change to 0x");
    altbegin=gethex();
    Serial.println(" "); 
    Serial.print("Alternate address is "); p3hex(altbegin);Serial.println(" ");
    
}
int gethex(){
  char  stringin[]="         "; //9 positions, only 8 entries allowed
  char charin = nextByte();
  byte i = 0;
  while (charin != 13) {  // wait for cr
      if ((i<8) && validhex(charin)) {stringin[i] = charin; i++; Serial.print(charin);}    
      else beep();
      charin = nextByte();
  }
  return(strtoul(stringin, NULL, 16));
}
boolean validhex(char totest){
  if ( (totest>='0' && totest <='9')  || (totest>='a' && totest <='f') || (totest>='A' && totest <='F'))
      return(true);
  else 
      return(false);
} 
byte nextByte() {
    while(1) {
        if(Serial.available() > 0) {
            byte b =  Serial.read();
            return b;
        }
    }
}
void swdp(unsigned int swdseqa[], byte swdseqd[], int swdseql) { //apply software data protection
// routine locks or unlocks the eeprom by quickly sending the correct sequences
  byte indx;
  DDRB=B11111111; // data pins are outputs
  unsigned int addrp; byte datap; //individual addresses and data bytes for software data protection
  for (indx=0; indx<swdseql; indx++){
    addrp=swdseqa[indx]; datap=swdseqd[indx];
    fastwrite(addrp,datap);
  }
  delay(11); // make sure the write finishes
  DDRB=B00000000; // data pins are inputs  
}  

void fastwrite(unsigned int addr, byte data){
  byte addr0= addr & 0x00FF;
  PORTC=addr0;
  addr0=addr >> 8 & 0x001F;
  PORTA=addr0;
//  delayMicroseconds(3); //nominal delay for address hold and data setup 100 ns
  digitalWrite(writepin,HIGH); //turn on pin to start the write cycle 
  PORTB=data;
  delayMicroseconds(100); //nominal delay for address hold and data setup 100 ns
  digitalWrite(writepin,LOW); //turn off pin to end the write cycle 
}
void writeprom(){
//  progbegin=msibgn; 
//  progend=msibgn+msicnt-1;
  cksum=0;
  DDRB=B11111111; // data pins are outputs
  for (addr=progbegin;addr<(progend+1);addr=addr+8){
    p3hex(addr); Serial.print(":");    
    for (addr0=addr;addr0<min(addr+8,(progend+1));addr0++){
      data = pgm_read_byte_near(msipgm+addr0-msibgn);    //was      data=msipgm[addr0];
      cksum=cksum+data;
      Serial.print(" ");p2hex(data);
      fastwrite(addr0,data);
      delay(11); //allow write to finish
    } 
    Serial.println(" ");
    if (Serial.available()>0) {char dmmy=Serial.read(); break;}
  }
  Serial.print("checksum"); Serial.println(cksum,HEX);
  DDRB=B00000000; // data pins are inputs  
}
byte readone(unsigned int raddr){
  byte byteread;
  DDRB=B00000000; // data pins are inputs  
  byte raddr0= raddr & 0x00FF; PORTC=raddr0; //set A0-A7
  raddr0=(raddr >> 8) & 0x001F;  PORTA=raddr0; //set A8-A12
  digitalWrite(notreadpin,LOW);  //set the output enable line 
  delayMicroseconds(3); //brief delay
  byteread=PINB;  //get the input data
  digitalWrite(notreadpin,HIGH);  //reset the output enable line 
  return byteread;
}
void readprom(){
//  progbegin=msibgn; 
//  progend=msibgn+msicnt-1;
  cksum=0;
  for (addr=progbegin;addr<(progend+1);addr=addr+8){
    p3hex(addr); Serial.print(":");    
    for (addr0=addr;addr0<min(addr+8,(progend+1));addr0++){
      data=readone(addr0); cksum=cksum+data;
      Serial.print(" ");p2hex(data);
    } 
    Serial.println(" ");
    if (Serial.available()>0) {char dmmy=Serial.read(); break;}
  }
  Serial.print("checksum"); Serial.println(cksum,HEX);
}
void toggle(){
  addr0=0;
  data=readone(addr0);
  p3hex(addr0); Serial.print(" was:"); p2hex(data); Serial.println(" ");
  data=data ^ 0xFF; //flip the bits of the byte from loc'n 0
  DDRB=B11111111; // data pins are outputs
  fastwrite(addr0,data); 
  DDRB=B00000000; // data pins are inputs  
  delay(11); //make sure write finished
  p3hex(addr0); Serial.print(" now:");    
  data=readone(addr0); p2hex(data);Serial.println(" ");    
}

void displaysource(){
  cksum=0;
//  progbegin=msibgn; 
//  progend=msibgn+msicnt-1;
  for (addr=progbegin;addr<(progend+1);addr=addr+8){
    p3hex(addr); Serial.print(":");    
    for (addr0=addr;addr0<min(addr+8,(progend+1));addr0++){
      data = pgm_read_byte_near(msipgm+addr0-progbegin);    //was      data=msipgm[addr0]; 
      cksum=cksum+data;
      Serial.print(" ");p2hex(data);
    } 
    Serial.println(" ");
    if (Serial.available()>0) {char dmmy=Serial.read(); break;}
  }
  Serial.print("checksum"); Serial.println(cksum,HEX);
}
void p2hex (byte toprnt){
  if (toprnt<16) Serial.print("0");
  Serial.print(toprnt,HEX);
}

void p3hex (unsigned int toprnt){
  if (toprnt<256) Serial.print("0");
  if (toprnt<16) Serial.print("0");
  Serial.print(toprnt,HEX);
}


void loop(){
  char cmd=' ';
    if (Serial.available()>0){
        cmd=Serial.read(); Serial.print(cmd,BYTE);
        switch(cmd){
          case 'r': {Serial.println("ead");readprom(); break;}
          case 'w': {Serial.println("rite");writeprom(); break;}
          case 'd': {Serial.println("isplay");displaysource(); break;}
          case 'l': {Serial.println("ock eeprom"); swdp(swdpa,swdpd,swdpl); break;}
          case 'u': {Serial.println("nlock eeprom"); swdp(swdupa,swdupd,swdupl); break;}
          case 't': {Serial.println("oggle location 0");toggle(); break;}
          case 'a': {Serial.println("ddress setting");addrset(); break;}
          case 'z': {Serial.println("ero Prom");zeroprom(); break;}
          default: {beep(); break;}
        }
        Serial.print(">");
    }
}
void zeroprom(){
  addr0=0;
  DDRB=B11111111; // data pins are outputs
  data=0;
  for (addr0=0; addr0<8192; addr0++){
    fastwrite(addr0,data); 
    delay(11); //make sure write finished
  }
  DDRB=B00000000; // data pins are inputs  
  Serial.println("Prom zeroed");    
}
void beep(){
  Serial.print("?"); Serial.print(7,BYTE);
}


void stall(){
int countdown;
  Serial.print("Stalling.."); 
  for (countdown=10;countdown>=0;countdown--){
    Serial.print(countdown); Serial.print("...");
    delay(500);
  }
  Serial.println(""); 
  Serial.println("Done!"); 
}
Advertisements

From → Olduino/Z

Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: