Last active
April 30, 2020 17:37
-
-
Save LVMBDV/912fd498a3c54c59e7a89f03feadb57c to your computer and use it in GitHub Desktop.
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
#include <SPI.h> | |
#include <SD.h> | |
#define ADDRLO_PORT PORTA | |
#define ADDRHI_PORT PORTC | |
#define DATA_PORT PORTD | |
#define MREQ_PIN PB0 | |
#define WR_PIN PB1 | |
#define RD_PIN PB2 | |
#define WAIT_PIN PB3 | |
#define CS_PIN PB3 | |
const uint16_t pageSize = 0xFFFF; | |
const uint16_t pageSwapTriggerOffset = 0xFFFD; | |
const uint16_t kPages = 256; | |
const char rom_filename[] PROGMEM = "rom.hex"; | |
const char log_filename[] PROGMEM = "log.txt"; | |
const char pagefile_format[] PROGMEM = "%u.hex"; | |
const char cpu_done_message[] PROGMEM = "cpu done\n"; | |
const char mreq_short[] PROGMEM = "rd or wr fell short\n"; | |
const char swap_msgformat[] PROGMEM = "swap %04x %04x\n"; | |
const char wrote_msgformat[] PROGMEM = "wrote %02x at %04x\n"; | |
const char read_msgformat[] PROGMEM = "read %02x at %04x\n"; | |
bool waitForCPU; | |
uint16_t currentPageIndex; | |
uint16_t nextPageIndex; | |
uint16_t touchedPages[kPages / 16] = {0}; | |
char filename[13]; | |
char logMsg[20]; | |
Sd2Card card; | |
SdVolume volume; | |
SdFile root; | |
SdFile currentPageFile; | |
void log(const char *msg) { | |
currentPageFile.close(); | |
currentPageFile.open(&root, log_filename, FILE_WRITE); | |
currentPageFile.write(msg); | |
currentPageFile.close(); | |
sprintf(filename, pagefile_format, currentPageIndex); | |
currentPageFile.open(&root, filename, FILE_WRITE); | |
} | |
void setup() { | |
portMode(ADDRLO_PORT, INPUT); | |
portMode(ADDRHI_PORT, INPUT); | |
portMode(DATA_PORT, INPUT); | |
pinMode(MREQ_PIN, INPUT_PULLUP); | |
pinMode(WR_PIN, INPUT_PULLUP); | |
pinMode(RD_PIN, INPUT_PULLUP); | |
pinMode(WAIT_PIN, OUTPUT); | |
digitalWrite(WAIT_PIN, HIGH); // no wait | |
card.init(SPI_HALF_SPEED, CS_PIN); | |
volume.init(card); | |
root.openRoot(volume); | |
waitForCPU = false; | |
int romSize = currentPageFile.open(&root, rom_filename, FILE_READ) ? currentPageFile.fileSize() : 0; | |
currentPageFile.close(); | |
log(romSize ? "ye rom\n" : "no rom\n"); | |
currentPageFile.close(); | |
currentPageFile.open(&root, "0.hex", FILE_WRITE | O_TRUNC); | |
currentPageFile.close(); | |
byte currentByte; | |
do { | |
currentPageFile.open(&root, rom_filename, FILE_READ); | |
currentPageFile.seekSet(--romSize); | |
currentByte = currentPageFile.read(); | |
currentPageFile.close(); | |
currentPageFile.open(&root, "0.hex", FILE_WRITE); | |
currentPageFile.seekSet(currentPageFile.fileSize()); | |
currentPageFile.write(currentByte); | |
currentPageFile.close(); | |
} while (romSize > 0); | |
log("rom copied\n"); | |
currentPageFile.open(&root, "0.hex", FILE_WRITE); | |
currentPageIndex = 0; | |
bitSet(touchedPages[0], 0); | |
} | |
void loop() { | |
if (!waitForCPU && !digitalRead(MREQ_PIN)) { | |
uint16_t address = (((uint16_t) portRead(ADDRLO_PORT)) << 8) | (portRead(ADDRHI_PORT) & 0xFE); | |
uint8_t data; | |
// wait until the cpu signals read or write along with mreq | |
do { | |
__asm__ __volatile__ ("nop\n\t"); | |
} while (digitalRead(RD_PIN) && digitalRead(WR_PIN)); | |
digitalWrite(WAIT_PIN, LOW); // wait while i read/write | |
if (!digitalRead(RD_PIN)) { // read | |
portMode(DATA_PORT, OUTPUT); // will output to data bus | |
if (address == pageSwapTriggerOffset) { | |
data = (nextPageIndex & 0xFF00) >> 8; | |
} else if (address == (pageSwapTriggerOffset + 1)) { | |
data = nextPageIndex & 0x00FF; | |
} else if (address >= currentPageFile.fileSize()) { | |
data = 0; | |
} else { | |
currentPageFile.seekSet(address); | |
data = currentPageFile.read(); | |
} | |
sprintf(logMsg, read_msgformat, data, address); | |
log(logMsg); | |
portWrite(DATA_PORT, data); // output to data bus | |
digitalWrite(WAIT_PIN, HIGH); // stop waiting, data is ready | |
waitForCPU = true; | |
} else if (!digitalRead(WR_PIN)) { // write | |
data = portRead(DATA_PORT); | |
if (address == pageSwapTriggerOffset) { // assuming low byte is written last | |
nextPageIndex = (nextPageIndex & 0x00FF) | (((uint16_t) data) << 8); | |
sprintf(filename, pagefile_format, nextPageIndex); | |
int flags = bitRead(touchedPages[nextPageIndex / 16], nextPageIndex % 16) ? 0 : O_TRUNC; | |
currentPageFile.close(); | |
currentPageFile.open(&root, filename, FILE_WRITE | flags); | |
sprintf(logMsg, swap_msgformat, currentPageIndex, nextPageIndex); | |
log(logMsg); | |
bitSet(touchedPages[nextPageIndex / 16], nextPageIndex % 16); | |
currentPageIndex = nextPageIndex; | |
} else if (address == (pageSwapTriggerOffset + 1)) { | |
nextPageIndex = (nextPageIndex & 0xFF00) | data; | |
} else { | |
if (address > currentPageFile.fileSize()) { | |
currentPageFile.seekSet(currentPageFile.fileSize()); | |
uint16_t fillerCounter = address - currentPageFile.fileSize(); | |
do { | |
currentPageFile.write('\0'); | |
fillerCounter--; | |
} while (fillerCounter > 0); | |
} | |
currentPageFile.seekSet(address); | |
currentPageFile.write(data); | |
sprintf(logMsg, wrote_msgformat, data, address); | |
log(logMsg); | |
} | |
digitalWrite(WAIT_PIN, HIGH); // stop waiting, write is finished | |
} else { | |
log(mreq_short); | |
} | |
} else if (waitForCPU && digitalRead(MREQ_PIN)) { | |
log(cpu_done_message); | |
waitForCPU = false; | |
portMode(DATA_PORT, INPUT); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment