From 775b36a0219b5eaee1cc0913fe74cc5785619c9b Mon Sep 17 00:00:00 2001 From: "Morgan 'ARR\\!' Allen" Date: Mon, 13 Jan 2020 19:54:28 -0800 Subject: [PATCH] include controller code --- 6502-controller/6502-controller.ino | 292 ++++++++++++++++++++++++++++ 1 file changed, 292 insertions(+) create mode 100644 6502-controller/6502-controller.ino diff --git a/6502-controller/6502-controller.ino b/6502-controller/6502-controller.ino new file mode 100644 index 0000000..07876cb --- /dev/null +++ b/6502-controller/6502-controller.ino @@ -0,0 +1,292 @@ +#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(); + } +}