Skip to content

Instantly share code, notes, and snippets.

@mfurtak
Last active May 29, 2017 19:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mfurtak/64ebab97613349a36cc20f383329dc9d to your computer and use it in GitHub Desktop.
Save mfurtak/64ebab97613349a36cc20f383329dc9d to your computer and use it in GitHub Desktop.
/**
* Designed for use with two 74HC595N shift registers,
* one AT28C64B EEPROM, and an Arduino Micro.
*
* Based on work by Ben Eater from https://www.youtube.com/watch?v=K88pgWhEb1M
*/
// Arduino pins connected to the shift register pins
#define SHIFT_DATA 2
#define SHIFT_CLK 3
#define SHIFT_LATCH 4
// Arduino pins connected to the 8 EEPROM data I/O lines
#define EEPROM_D0 5
// and so on in between here...
#define EEPROM_D7 12
// Arduino pin connected to the EEPROM write enable pin
#define WRITE_ENABLE 13
/**
* Makes the value shifted into the shift registers
* available on the output pins
*/
void pulseShiftLatch() {
digitalWrite(SHIFT_LATCH, LOW);
digitalWrite(SHIFT_LATCH, HIGH);
// 1 microsecond is the shortest amount of time we can
// delay in the Arduino API. The latch pulse needs to
// be at least 20ns according to the datasheet.
delayMicroseconds(1);
digitalWrite(SHIFT_LATCH, LOW);
}
/**
* Pulse the EEPROM write enable (/WE) pin to trigger a
* write of the byte on the data lines
*/
void pulseWrite() {
digitalWrite(WRITE_ENABLE, HIGH);
digitalWrite(WRITE_ENABLE, LOW);
// 1 microsecond is the shortest amount of time we can
// delay in the Arduino API. The write pulse needs to
// be at least 100ns according to the datasheet.
delayMicroseconds(1);
digitalWrite(WRITE_ENABLE, HIGH);
// The datasheet claims to need the data to be held for
// 0ns after /WE goes high, but if I don't delay, I get
// inconsistent reads.
delay(10);
}
/**
* Shifts low 13 bits of the the provided int address out
* on SHIFT_DATA, most significant bit first.
*
* The outputEnable flag controls the MSB of the shifted
* 16 bit value, which we'll use for the /OE control pin.
*/
void setAddress(int address, bool outputEnable) {
// Output enable is active low, and we'll ensure that the
// MSB of the address is zero, so change nothing if
// outputEnable is true. If false, we need to set the MSB
// to a 1.
int outputEnableBit = outputEnable ? 0x0000 : 0x8000;
// The AT28C64B that I am using supports up to 13 bits of
// address, so we'll ensure that any higher bits than that
// are 0
address = address & 0x1FFF;
// Apply the output enable bit to the address value
address = address | outputEnableBit;
shiftOut(SHIFT_DATA, SHIFT_CLK, MSBFIRST, address >> 8);
shiftOut(SHIFT_DATA, SHIFT_CLK, MSBFIRST, address);
pulseShiftLatch();
}
/**
* Read the byte at the specifed address from the EEPROM
*/
byte readByte(int address) {
setAddress(address, /* outputEnable */ true);
byte data = 0;
for (int pin = EEPROM_D7; pin >= EEPROM_D0; pin -= 1) {
pinMode(pin, INPUT);
data = (data << 1) + digitalRead(pin);
}
return data;
}
/**
* Write the provided byte to the specified address of the EEPROM
*/
void writeByte(int address, byte data) {
setAddress(address, /* outputEnable */ false);
for (int pin = EEPROM_D0; pin <= EEPROM_D7; pin += 1) {
pinMode(pin, OUTPUT);
digitalWrite(pin, data & 0x01);
data = data >> 1;
}
pulseWrite();
}
void beginSerial() {
Serial.begin(9600);
while (!Serial) {
;
}
}
/**
* Dump the first 256 bytes of the EEPROM to the serial port
*/
void printContents() {
beginSerial();
for (int base = 0; base < 256; base += 16) {
byte data[16];
for (int offset = 0; offset < 16; offset += 1) {
data[offset] = readByte(base + offset);
}
char buf[80];
sprintf(buf, "%03x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
base, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15]);
Serial.println(buf);
}
}
/**
* Erase the first 256 bytes of the EEPROM by setting them to 0xFF
*/
void eraseContents() {
for (int i = 0; i < 256; i += 1) {
writeByte(i, 0xFF);
}
}
void setup() {
pinMode(SHIFT_DATA, OUTPUT);
pinMode(SHIFT_CLK, OUTPUT);
pinMode(SHIFT_LATCH, OUTPUT);
for (int pin = EEPROM_D0; pin <= EEPROM_D7; pin += 1) {
pinMode(pin, OUTPUT);
}
digitalWrite(WRITE_ENABLE, HIGH);
pinMode(WRITE_ENABLE, OUTPUT);
eraseContents();
char greeting[14] = "Hello, world!";
for (int i = 0; i < 14; i += 1) {
writeByte(i, (byte)greeting[i]);
}
printContents();
}
void loop() {
// put your main code here, to run repeatedly:
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment