const int dataPin = 10; /* DS */
const int clockPin = 11; /* SHCP */
const int latchPin = 12; /* STCP */
// used for testing only
int _WE = HIGH;
int _OE = HIGH;
int16_t address = 0b101010101011111;
uint8_t data = 0b10101111;
// used for serial read/write
int addyROM = 0;
String READ, WRITE, HEX_CODE;
uint8_t mode = 0;
uint8_t dataLine[16];
void setDataPinsToReadState()
{
for (int i = 2; i < 10; i++)
{
pinMode(i, INPUT);
}
}
void setup()
{
Serial.begin(115200);
// set _WE as output and high (disabled)
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, _WE);
// set _OE as output and high (disabled)
pinMode(A5, OUTPUT);
digitalWrite(A5, _OE);
// set data, clock and latch pins as output and low (default) (disabled)
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(latchPin, OUTPUT);
// set data pins as input (default: read)
setDataPinsToReadState();
READ = String("READ");
WRITE = String("WRITE");
HEX_CODE = String("HEX");
Serial.println(F("ROM programmer ready. Enter READ or WRITE to continue"));
}
void setAddress(uint16_t addy)
{
// set up the address
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, addy >> 8); // Most significant byte
shiftOut(dataPin, clockPin, MSBFIRST, addy); // Least signifcant byte
digitalWrite(latchPin, HIGH);
delay(5);
}
uint8_t readData()
{
// read from ROM
uint8_t readData = 0;
for (int i = 7; i >= 0; i--)
{
readData |= digitalRead(i + 2) << i;
}
return readData;
}
void loop()
{
switch (mode)
{
case 0:
// --- COMMAND MODE ---
if (Serial.available())
{
String command = Serial.readStringUntil('\n');
if (command == READ)
{
mode = 1;
setDataPinsToReadState();
digitalWrite(A5, LOW); // output enable
Serial.println(F("READ MODE"));
}
if (command == HEX_CODE)
{
mode = 3;
setDataPinsToReadState();
digitalWrite(A5, LOW); // output enable
Serial.println(F("HEX READ MODE"));
}
if (command == WRITE)
{
mode = 2;
Serial.println(F("WRITE MODE"));
}
}
break;
case 1:
case 3:
//{
// --- READ MODE ---
// read...
setAddress(addyROM);
uint8_t dataROM = readData();
// print...
if (mode == 1)
{
Serial.print((char)dataROM);
}
else
{
// a prettier mode for user display
// based on: hexdump -C to_enc.txt
// e.g.
// 00000000 e2 96 88 e2 96 88 e2 96 88 e2 96 88 e2 96 88 e2 |................|
dataLine[addyROM % 16] = dataROM;
if (addyROM % 16 == 15 && addyROM >= 15)
{
// TODO fix the leading zeros
Serial.print(addyROM - 15, HEX);
Serial.print(F(" "));
for (int i = 0; i < 16; i++)
{
Serial.print(dataLine[i], HEX);
Serial.print(F(" "));
if (i == 7 || i == 15)
{
Serial.print(F(" "));
}
}
Serial.print(F("|"));
for (int i = 0; i < 16; i++)
{
Serial.print((char)dataLine[i]);
}
Serial.println(F("|"));
}
}
// complete...
addyROM++;
if (addyROM == /*0x8000*/0x10)
{
digitalWrite(A5, HIGH); // output disable
addyROM = 0;
mode = 0;
Serial.println(F("\nROM programmer ready. Enter READ or WRITE to continue"));
}
//}
break;
case 2:
// now fixed. compiler didn't like skipping the var init in case 1
// apparently... might check on godbolt to see what gives.
// alas godbolt actually throws a compilation error so can't
Serial.println("for some reason this no run... o_O***");
break;
}
if (mode == 2) // ...so using an if statment instead u_u
{
// --- WRITE MODE ---
if (Serial.available())
{
// write...
setAddress(addyROM);
// latch the address on the ROM - set _WE low
digitalWrite(LED_BUILTIN, LOW);
if (addyROM == 0)
{
// if first byte, set data pins as outputs
for (int i = 7; i >= 0; i--)
{
// start outputting on pin
pinMode(i + 2, OUTPUT);
}
}
// read data from Serial
uint8_t dataROM = Serial.read();
// set data on data bus
for (int i = 7; i >= 0; i--)
{
// set pin value
digitalWrite(i + 2, dataROM >> i & 1);
}
// latch the data on the ROM - set _WE high
delay(5);
digitalWrite(LED_BUILTIN, HIGH);
delay(5);
// complete...
addyROM++;
if (addyROM == /*0x8000*/0x10)
{
setDataPinsToReadState();
addyROM = 0;
mode = 0;
Serial.println(F("\nROM programmer ready. Enter READ or WRITE to continue"));
}
}
}
}
// --- TEST ROUTINE - NO LONGER NEEDED/CALLED ---
void alt_loop()
{
// --- WRITING ---
// set up the address
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, address >> 8); // Most significant byte
shiftOut(dataPin, clockPin, MSBFIRST, address); // Least signifcant byte
digitalWrite(latchPin, HIGH);
delay(500);
// latch the address on the ROM - set _WE low
delay(1000);
digitalWrite(LED_BUILTIN, !_WE);
_WE = !_WE;
// set up the data...
for (int i = 7; i >= 0; i--)
{
// start outputting on pin
pinMode(i + 2, OUTPUT);
// set pin value
digitalWrite(i + 2, data >> i & 1);
}
// latch the data on the ROM - set _WE high
delay(1000);
digitalWrite(LED_BUILTIN, !_WE);
_WE = !_WE;
// allow a moment for ROM to read the data
delay(500);
// stop outputting on data bus
setDataPinsToReadState();
// --- READING ---
delay(1000);
// stop outputting on data bus
setDataPinsToReadState();
// set up the address
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, address >> 8); // Most significant byte
shiftOut(dataPin, clockPin, MSBFIRST, address); // Least signifcant byte
digitalWrite(latchPin, HIGH);
delay(500);
// start ROM outputing data - set _OE low
digitalWrite(A5, !_OE);
_OE = !_OE;
delay(500);
// read from ROM
uint8_t readData = 0;
for (int i = 7; i >= 0; i--)
{
readData |= digitalRead(i + 2) << i;
}
// output read byte
Serial.print(F("Received from address: "));
Serial.print(address & 0b111111111111111, HEX);
Serial.print(F(", data: "));
Serial.println(readData, HEX);
// done reading from ROM - set _OE high
digitalWrite(A5, !_OE);
_OE = !_OE;
// Invert the address and data for next time
address = ~address;
data = ~data;
}