Last active
June 14, 2017 16:49
-
-
Save cogwheel/dcc8789264711e7d6cfb3957164201d5 to your computer and use it in GitHub Desktop.
Revised programmer with unlock
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Programmer for Xicor X28C256 EEPROM, using Mega2560 for parallel I/O */ | |
/* Address pins */ | |
#define A0 30 | |
#define A1 31 | |
#define A2 32 | |
#define A3 33 | |
#define A4 34 | |
#define A5 35 | |
#define A6 36 | |
#define A7 37 | |
#define A8 38 | |
#define A9 39 | |
#define A10 40 | |
#define A11 41 | |
#define A12 42 | |
#define A13 43 | |
#define A14 44 | |
/* I/O pins */ | |
#define IO0 22 | |
#define IO1 23 | |
#define IO2 24 | |
#define IO3 25 | |
#define IO4 26 | |
#define IO5 27 | |
#define IO6 28 | |
#define IO7 29 | |
/* Control signal pins */ | |
#define CE_LOW 51 | |
#define OE_LOW 52 | |
#define WE_LOW 53 | |
void enableChip() { | |
digitalWrite(CE_LOW, 0); | |
} | |
/* Set a bunch of pins' modes at once */ | |
void pinModes(int pin0, int pinN, int mode) { | |
for (int i = pin0; i <= pinN; ++i) { | |
pinMode(i, mode); | |
} | |
} | |
/* Set I/O pin modes to given direction */ | |
void setIO(int direction) { | |
pinModes(IO0, IO7, direction); | |
} | |
/* Like shiftOut but for a range of pins */ | |
void shiftPinsOut(int pin0, int pinN, uint32_t data) { | |
for (int i = pin0; i <= pinN; ++i) { | |
uint32_t out = (data >> (i - pin0)) & 1; | |
digitalWrite(i, out); | |
} | |
} | |
/* Set I/O data */ | |
void setData(char data) { | |
shiftPinsOut(IO0, IO7, data); | |
} | |
/* Set address pins */ | |
void setAddress(short address) { | |
shiftPinsOut(A0, A14, address); | |
} | |
/* Like shiftIn but parallel */ | |
uint32_t shiftPinsIn(int pin0, int pinN) { | |
uint32_t data = 0; | |
for (int i = pin0; i <= pinN; ++i) { | |
uint32_t in = digitalRead(i); | |
data |= in << (i - pin0); | |
} | |
return data; | |
} | |
/* Write a byte to ROM - minimal setup & delay */ | |
void writeByteFast(short address, char data) { | |
setAddress(address); | |
setData(data); | |
digitalWrite(WE_LOW, 0); | |
delayMicroseconds(1); | |
digitalWrite(WE_LOW, 1); | |
delayMicroseconds(1); | |
} | |
/* Allow EEPROM write cycle to finish before next read/write operation */ | |
void waitForWrite() { | |
delay(10); /* TODO: poll for completion */ | |
} | |
/* Write a byte to ROM - set up pins, wait for write to finish */ | |
void writeByte(short address, char data) { | |
setIO(OUTPUT); | |
writeByteFast(address, data); | |
waitForWrite(); | |
} | |
/* Write bytes to ROM using fast page writes | |
address must be a multiple of 64 (i.e. low 6 bits should be 0) | |
size can be any number of bytes (within ROM limits) */ | |
void writeBytes(short address, char const data[], short size) { | |
setIO(OUTPUT); | |
for (short i = 0; i < size; ++i) { | |
writeByteFast(address + i, data[i]); | |
} | |
waitForWrite(); | |
} | |
/* Read a byte from ROM */ | |
uint8_t readByte(short address) { | |
setAddress(address); | |
uint32_t data; | |
digitalWrite(OE_LOW, 0); | |
delayMicroseconds(1); | |
data = shiftPinsIn(IO0, IO7); | |
digitalWrite(OE_LOW, 1); | |
delayMicroseconds(1); | |
return data; | |
} | |
char const test[] = "This text is a 64 byte string that I'm hoping to write to my ROM"; | |
void testWrite() { | |
writeBytes(0, test, sizeof(test)/sizeof(test[0]) - 1); | |
/* TODO: readString */ | |
Serial.begin(115200); | |
setIO(INPUT); | |
for (short i = 0; i < 64; ++i) { | |
char val = readByte(i); | |
Serial.print(val); | |
if (val != test[i]) { | |
digitalWrite(LED_BUILTIN, 1); | |
} | |
} | |
} | |
/* Magic sequence of writes to disable write protection */ | |
void unlock() { | |
pinModes(IO0, IO7, OUTPUT); | |
writeByte(0x5555, 0xaa); | |
writeByte(0x2aaa, 0x55); | |
writeByte(0x5555, 0x80); | |
writeByte(0x5555, 0xaa); | |
writeByte(0x2aaa, 0x55); | |
writeByte(0x5555, 0x20); | |
waitForWrite(); | |
} | |
void setup() { | |
shiftPinsOut(CE_LOW, WE_LOW, 0xFF); | |
pinModes(CE_LOW, WE_LOW, OUTPUT); | |
enableChip(); | |
pinMode(LED_BUILTIN, OUTPUT); | |
digitalWrite(LED_BUILTIN, 0); | |
pinModes(A0, A14, OUTPUT); | |
unlock(); | |
testWrite(); | |
} | |
void loop() { | |
// put your main code here, to run repeatedly: | |
delay(1000); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment