#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(); } }