Arduino_eprom

Damjan Georgievski edited this page Oct 28, 2018 · 2 revisions

Ова е кодот напишан за проектот што го правиме во http://twitter.com/#search?q=%23skopjehacklab за http://wiki.lugola.net/Хаклаб/Проекти/Arduino_базиран_EPROM_програматор направен со Arduino.

Main stuff:

/*
 *    EPROM programmer
 *
 *    pins 0 and 1 of the Arduino are serial communication - DON'T touch them 
 *    dataPins are 2-9, 8 pins connected to EEPROM data pins
 *    pin 10 is connected to CD4040 clock input, 
 *      used to advance the counters and thus increment the address
 *    pin 11 is connected to EEPROM OE (negative output enable / Vpp 13V) 
 *      but also negated by an NPN
 *    pin 12 is connected to EEPROM CE (negative chip enable / PGM)
 *    pin 13 is connected to reset the counters 
 *      optionaly select read/program mode (5V / 6.5V + 13V)
 *
 */

#define FIRSTDATA_PIN  2
#define CLOCK_PIN     10
#define OE_PIN        11
#define CE_PIN        12
#define RESET_PIN       13


void commonSetup() {
  pinMode(CLOCK_PIN, OUTPUT);
  pinMode(CE_PIN, OUTPUT);
  pinMode(OE_PIN, OUTPUT);
  pinMode(RESET_PIN, OUTPUT);
  /* set the arduino data pins to input (safe high-Z) */
  setDataPinsMode(INPUT);
  /* set eprom data pins high-Z */
  digitalWrite(CE_PIN, HIGH); 
}

/* pin 13 is toggled to reset the C4040 counters - 
 * that sets the address bus to 0x00 */
void resetCounters() {
  digitalWrite(RESET_PIN, HIGH);
  delayMicroseconds(1);
  digitalWrite(RESET_PIN, LOW);
}

void setDataPinsMode(int dir) {
  for (int i=0; i<8; i++) {
    pinMode(FIRSTDATA_PIN + i, dir);
  }
}

/*  send a clock singnal to the serial counters (CD4040) and wait for 
 *  it to propagate to the last pin */
void advanceAddress() {
  digitalWrite(CLOCK_PIN, LOW);
  /*  Minimum Clock Pulse Width of CD4040 is 500ns */
  delayMicroseconds(1);
  digitalWrite(CLOCK_PIN, HIGH);
  /*  maximum time to propagate the low edge on CLOCK_PIN to the last 
   *  pin of the first counter:
   *  1300ns to Q4 + the rest 8 Q pins * 330ns = 4000ns
   *  double for the two CD4040 counters ~8000ns = 8us
   */
  delayMicroseconds(8); 
}


void setup() {
  Serial.begin(115200);
  commonSetup();
  resetCounters();
}

void loop() {
  if (Serial.available() > 0) {
    int cmd = Serial.read();
    switch(cmd) {
    case 'W':
      writerSetup();
      writeLoop();
      Serial.println("ok.");
    case 'R':
      readerSetup();
      readLoop();
      Serial.println("ok.");
    case 'C':
      resetCounters();
      Serial.println("ok.");
    }
  }
}

Reader:

/*  
 *  READ a byte from the EPROM data bus, pin by pin from the data pins
 *  The data pins must be set to INPUT mode before calling this proc 
 */
byte readByteFromPins() {
  byte result = B00000000;
  for(int i=0; i<8; i++) {
    int value = digitalRead(FIRSTDATA_PIN + i);
    result |= value << i;
  }
  return result;
}

/* Configure the EPROM for reading */
void readerSetup () {
  setDataPinsMode(INPUT);
  digitalWrite(OE_PIN, HIGH);
  digitalWrite(CE_PIN, LOW);
}

/* first read from Serial how many bytes to read from eeprom */
void readLoop() {
  if (Serial.available() > 0) {
    int num = Serial.read();
    for (int k=0; k<num; k++) {
      Serial.write(readByteFromPins());
      advanceAddress();   // increment the address via the 2 counters
    }
  }
}

Writer:

char buffer[256];

/* write a byte out to pins */
void writeByteToPins (const byte value) {
  int bitValue;
  setDataPinsMode(OUTPUT);
  for(int i=0; i<8; i++) {     
    bitValue = (value >> i) & B00000001;
    digitalWrite(FIRSTDATA_PIN + i, bitValue);
  }
}

/* 
 * write a byte to an EPROM, then verify. 
 * It takes some playing with the OE and CE etc.. 
 * try 10 times before giving up (and return -1)
 * on success return 0
 */
int writeDataByte(const byte data) {
  byte verify;
  int tries = 0;
  do {
    if (tries >= 10) {
      return -1;
    }
    // put 12.5V on Vpp / !OE pin of EEPROM
    digitalWrite(OE_PIN, LOW); // 12.5V
    digitalWrite(CE_PIN, HIGH); // 
    // make sure EPROM data pins are INPUT before setting mine to OUTPUT (tDF?)
    delayMicroseconds(1);

    writeByteToPins(data);

    /* trigger program mode */
    digitalWrite(CE_PIN, LOW);    // Delay from here must be 100uS ..
    delayMicroseconds(100);       //  tOPW 
    digitalWrite(CE_PIN, HIGH);   //  .. to here
    delayMicroseconds(2);         //  tOEH?

    /* lets verify the write now */
    setDataPinsMode(INPUT);       // make sure data pins are set to INPUT before !OE goes LOW
    digitalWrite(OE_PIN, HIGH);   //    0V - end programing
    delayMicroseconds(2);         //  tOR
    digitalWrite(CE_PIN, LOW);    //    0V - verify
    delayMicroseconds(2);         //  tCE
    verify = readByteFromPins();
    digitalWrite(CE_PIN, HIGH);   //  
    tries++;
  } 
  while (data != verify);
  return 0;
}


void writeBuffer(int length) {
  for (int i = 0; i < length; i++) {
    byte data = buffer[i];
    if(writeDataByte(data) == 0) {
      Serial.print("OK: "); 
      Serial.println(data); 
    } 
    else {
      Serial.print("ERR: "); 
      Serial.println(data);      
    }
    advanceAddress();
  }
}

void writerSetup() {
 // empty fo now
}

/* first read one byte, a length (max 255)
 then read length bytes from serial and store it to a buffer
 at last write the buffer to the eeprom */
void writeLoop() {
  int received = 0;
  while (Serial.available() <= 0) { }; // busy wait until there's something to read
  int length = Serial.read();
  while (received < length) {
    if (Serial.available() > 0) {
      buffer[received] = Serial.read();
      received++;
    }
  }
  Serial.println("WRITING");
  writeBuffer(received);
}

Python control script:

import serial
import struct, time
ser = serial.Serial("/dev/ttyUSB1", 115200, timeout=2)

# to reset the arduino
ser.setDTR(0)
time.sleep(0.100) # 100ms should be enough
ser.setDTR(1)

# write data to the current address of eprom, in chunks less than 256 bytes long
DATA = "Something to write to the EEPROM"
ser.write('W')
ser.write(struct.pack('B', len(DATA)))
ser.write(DATA)
ser.read(100)

# reset the counters, set the address to 0x00
ser.write('C')

# read data from the current address of eprom, in chunks of less than 256 bytes long
ser.write('R')
ser.write(struct.pack('B', 200))
ser.read(200)
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.