292 lines
5.5 KiB
C++
292 lines
5.5 KiB
C++
#define PIN_CLK 13
|
|
#define PIN_RST A4
|
|
#define PIN_RW A5
|
|
#define PIN_CE A3
|
|
#define PIN_BTN PC13
|
|
#define CLK_DELAY 100
|
|
|
|
#define ROM_SIZE 0x7fff
|
|
|
|
const char ADDR[] = { PC4, PB13, PB14, PB15, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14 };
|
|
const char DATA[] = { PB1, PB2, PB12, PA11, PA12, PC5, PC6, PC8 };
|
|
|
|
uint8_t running = 0;
|
|
uint8_t start = 0;
|
|
|
|
PROGMEM static uint8_t rom[ROM_SIZE];
|
|
uint16_t rom_idx = 0;
|
|
uint32_t rom_load_start = 0;
|
|
|
|
enum states {
|
|
IDLE,
|
|
WRITE // write rom to memory
|
|
};
|
|
|
|
enum states state = IDLE;
|
|
|
|
uint16_t readAddress() {
|
|
uint16_t addr = 0;
|
|
|
|
for(uint8_t i = 1; i < 16; i++) {
|
|
addr = (addr << 1) + (digitalRead(ADDR[i]) ? 1 : 0);
|
|
}
|
|
|
|
return addr;
|
|
}
|
|
uint16_t readState() {
|
|
uint8_t bit = 0;
|
|
uint16_t addr = 0;
|
|
uint8_t data = 0;
|
|
uint8_t i = 0;
|
|
// check chip enable, 0 = enabled; 1 = disabled
|
|
uint8_t CE = digitalRead(PIN_CE) ? 0 : 1;
|
|
|
|
// debugging lines start with D:
|
|
Serial.print("D: ");
|
|
|
|
for(i = 1; i < 16; i++) {
|
|
bit = digitalRead(ADDR[i]) ? 1 : 0;
|
|
addr = (addr << 1) + bit;
|
|
|
|
Serial.print(bit);
|
|
}
|
|
|
|
Serial.print(" ");
|
|
|
|
for(i = 0; i < 8; i++) {
|
|
pinMode(DATA[i], INPUT);
|
|
|
|
bit = digitalRead(DATA[i]) ? 1 : 0;
|
|
data = (data << 1) + bit;
|
|
|
|
Serial.print(bit);
|
|
|
|
// set DATA pinMode based on Chip Enable
|
|
pinMode(DATA[i], CE ? OUTPUT : INPUT);
|
|
}
|
|
|
|
Serial.printf(
|
|
" %04x %c %02x %s\r\n",
|
|
addr,
|
|
(digitalRead(PIN_RW) ? 'r' : 'W'),
|
|
data,
|
|
CE ? "CE" : "!CE"
|
|
);
|
|
|
|
return addr;
|
|
}
|
|
|
|
void resetHigh() {
|
|
Serial.println("D: Setting reset HIGH");
|
|
|
|
pinMode(PIN_RST, OUTPUT);
|
|
digitalWrite(PIN_RST, HIGH);
|
|
}
|
|
|
|
void resetLow() {
|
|
Serial.println("D: Setting reset LOW");
|
|
|
|
pinMode(PIN_RST, OUTPUT);
|
|
digitalWrite(PIN_RST, LOW);
|
|
}
|
|
|
|
void startClock() {
|
|
running = 1;
|
|
|
|
Serial.println("D: starting clock");
|
|
}
|
|
|
|
void stopClock() {
|
|
running = 0;
|
|
|
|
Serial.println("D: stoping clock");
|
|
}
|
|
|
|
unsigned int lastUserButton = 0;
|
|
|
|
void advanceClock() {
|
|
//pinMode(PIN_RST, OUTPUT);
|
|
//digitalWrite(PIN_RST, HIGH);
|
|
|
|
digitalWrite(PIN_CLK, !digitalRead(PIN_CLK));
|
|
delay(CLK_DELAY);
|
|
|
|
digitalWrite(PIN_CLK, !digitalRead(PIN_CLK));
|
|
delay(CLK_DELAY);
|
|
}
|
|
|
|
void onUserButton() {
|
|
if(millis() - lastUserButton > 100) {
|
|
readState();
|
|
|
|
advanceClock();
|
|
|
|
lastUserButton = millis();
|
|
}
|
|
}
|
|
|
|
void onChipEnable() {
|
|
uint8_t CE = digitalRead(PIN_CE) ? 0 : 1;
|
|
|
|
//Serial.printf("CE: %s\n", CE ? "Disabled" : "Enabled");
|
|
|
|
for(uint8_t i = 0; i < 8; i++) {
|
|
pinMode(DATA[i], CE ? OUTPUT : INPUT);
|
|
}
|
|
|
|
//setOutByte(rom[readAddress()]);
|
|
}
|
|
|
|
void setOutByte(char b) {
|
|
for(uint8_t i = 0; i < 8; i++) {
|
|
pinMode(DATA[i], OUTPUT);
|
|
|
|
if((b >> (7 - i)) & 1)
|
|
digitalWrite(DATA[i], HIGH);
|
|
else
|
|
digitalWrite(DATA[i], LOW);
|
|
}
|
|
}
|
|
|
|
void reset() {
|
|
uint8_t CE = digitalRead(PIN_CE) ? 0 : 1;
|
|
|
|
// set data pins according to Chip Enable state
|
|
// 1 = disabled; 0 = enabled
|
|
for(uint8_t i = 0; i < 8; i++) {
|
|
pinMode(DATA[i], CE ? OUTPUT : INPUT);
|
|
digitalWrite(DATA[i], LOW);
|
|
}
|
|
}
|
|
|
|
void clearProgMem() {
|
|
uint8_t i = 0;
|
|
|
|
// clear rom
|
|
bzero((void*)&rom, ROM_SIZE);
|
|
|
|
Serial.println("D: memory cleared");
|
|
}
|
|
|
|
void onAddressChange() {
|
|
uint16_t addr = readAddress();
|
|
uint8_t byt = rom[addr];
|
|
setOutByte(byt);
|
|
//Serial.printf("%04x: %02x\r\n", addr, byt);
|
|
}
|
|
|
|
void setup() {
|
|
uint8_t i = 0;
|
|
|
|
Serial.begin(115200);
|
|
|
|
for(i = 0; i < 16; i++) {
|
|
pinMode(ADDR[i], INPUT);
|
|
attachInterrupt(digitalPinToInterrupt(ADDR[i]), onAddressChange, CHANGE);
|
|
}
|
|
|
|
reset();
|
|
|
|
//setOutByte(0xea);
|
|
|
|
pinMode(PIN_CLK, OUTPUT);
|
|
pinMode(PIN_RST, INPUT);
|
|
pinMode(PIN_BTN, INPUT);
|
|
pinMode(PIN_RW, INPUT);
|
|
pinMode(PIN_CE, INPUT);
|
|
attachInterrupt(digitalPinToInterrupt(PIN_BTN), onUserButton, FALLING);
|
|
attachInterrupt(digitalPinToInterrupt(PIN_CE), onChipEnable, CHANGE);
|
|
|
|
digitalWrite(PIN_CLK, LOW);
|
|
digitalWrite(PIN_RST, LOW);
|
|
|
|
start = millis();
|
|
|
|
Serial.println("D: clearing rom");
|
|
|
|
clearProgMem();
|
|
}
|
|
|
|
void loop() {
|
|
if(state == WRITE) {
|
|
while(true && rom_idx < 0x7ffe && millis() - rom_load_start < 3000) {
|
|
// freshen the start time
|
|
if(Serial.available() > 0) rom_load_start = millis();
|
|
|
|
while(Serial.available() > 0) {
|
|
rom[rom_idx++] = Serial.read();
|
|
}
|
|
}
|
|
|
|
state = IDLE;
|
|
|
|
Serial.printf("Read 0x%04X bytes into memory\r\n", rom_idx);
|
|
Serial.printf("0x7ffc: 0x%02X 0x%02X\r\n", rom[0x7ffc], rom[0x7ffd]);
|
|
|
|
return;
|
|
}
|
|
|
|
uint8_t CE = digitalRead(PIN_CE) ? 0 : 1;
|
|
|
|
if(running) {
|
|
uint16_t addr = readState();
|
|
|
|
if(CE) {
|
|
//setOutByte(rom[addr]);
|
|
//Serial.printf("Setting output %02X\r\n", rom[addr]);
|
|
}
|
|
|
|
advanceClock();
|
|
}
|
|
|
|
if(Serial.available() > 0) {
|
|
char c = Serial.read();
|
|
|
|
//Serial.print(c);
|
|
|
|
if(c == '0') resetHigh();
|
|
if(c == '1') resetLow();
|
|
if(c == '3') readState();
|
|
if(c == '4') startClock();
|
|
if(c == '5') stopClock();
|
|
if(c == '6') reset();
|
|
if(c == '7') clearProgMem();
|
|
if(c == '8') {
|
|
for(uint16_t i = 0; i < 0x100; i++) {
|
|
if(i % 16 == 0) Serial.printf("0x%04X: ", i);
|
|
|
|
Serial.printf("%02x", rom[i]);
|
|
|
|
if(i % 2 == 1) Serial.print(" ");
|
|
|
|
if(i % 16 == 15) Serial.println();
|
|
}
|
|
}
|
|
|
|
if(c == 'l') {
|
|
// activate load mode and reset counter
|
|
state = WRITE;
|
|
rom_idx = 0;
|
|
rom_load_start = millis();
|
|
bzero((void*)&rom, ROM_SIZE);
|
|
|
|
Serial.println("D: ready for ROM");
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
if(c == '2') {
|
|
// only leave in for debugging
|
|
while(!Serial.available()) {};
|
|
|
|
char b = Serial.read();
|
|
|
|
setOutByte(b);
|
|
}
|
|
*/
|
|
|
|
// flush serial queue
|
|
// while(Serial.available() > 0) Serial.read();
|
|
}
|
|
}
|