Arduino_eprom - gdamjan/gdamjan.github.io GitHub Wiki

Ова е кодот напишан за проектот што го правиме во 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)
⚠️ **GitHub.com Fallback** ⚠️