mirror of
https://github.com/sanni/cartreader.git
synced 2024-12-25 04:21:53 +01:00
V19B: Added GBA FRAM save support
This will allow you to read/write the Fujitsu MB85R256 Ferroelectric Random Access Memory Chip
This commit is contained in:
parent
c97c3ac855
commit
bdadbf2eb0
@ -2,8 +2,8 @@
|
|||||||
Cartridge Reader for Arduino Mega2560
|
Cartridge Reader for Arduino Mega2560
|
||||||
|
|
||||||
Author: sanni
|
Author: sanni
|
||||||
Date: 2016-09-14
|
Date: 2016-09-18
|
||||||
Version: V19A
|
Version: V19B
|
||||||
|
|
||||||
SD lib: https://github.com/greiman/SdFat
|
SD lib: https://github.com/greiman/SdFat
|
||||||
LCD lib: https://github.com/adafruit/Adafruit_SSD1306
|
LCD lib: https://github.com/adafruit/Adafruit_SSD1306
|
||||||
@ -33,7 +33,7 @@
|
|||||||
lukeskaff - Nintendo DS GBA slot timing
|
lukeskaff - Nintendo DS GBA slot timing
|
||||||
|
|
||||||
**********************************************************************************/
|
**********************************************************************************/
|
||||||
char ver[5] = "V19A";
|
char ver[5] = "V19B";
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
Define Output
|
Define Output
|
||||||
@ -530,7 +530,7 @@ void setup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Init SD card
|
// Init SD card
|
||||||
if (!sd.begin(chipSelectPin, SPI_FULL_SPEED)) {
|
if (!sd.begin(chipSelectPin, SPI_HALF_SPEED)) {
|
||||||
display_Clear();
|
display_Clear();
|
||||||
print_Error(F("SD Error"), true);
|
print_Error(F("SD Error"), true);
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
Variables
|
Variables
|
||||||
*****************************************/
|
*****************************************/
|
||||||
char calcChecksumStr[5];
|
char calcChecksumStr[5];
|
||||||
byte cartBuffer[513];
|
byte cartBuffer[512];
|
||||||
|
|
||||||
const int nintendoLogo[] PROGMEM = {
|
const int nintendoLogo[] PROGMEM = {
|
||||||
0x00, 0x00, 0x00, 0x00, 0x24, 0xFF, 0xAE, 0x51, 0x69, 0x9A, 0xA2, 0x21, 0x3D, 0x84, 0x82, 0x0A,
|
0x00, 0x00, 0x00, 0x00, 0x24, 0xFF, 0xAE, 0x51, 0x69, 0x9A, 0xA2, 0x21, 0x3D, 0x84, 0x82, 0x0A,
|
||||||
@ -31,11 +31,21 @@ const char GBAMenuItem3[] PROGMEM = "Write Save";
|
|||||||
const char GBAMenuItem4[] PROGMEM = "Reset";
|
const char GBAMenuItem4[] PROGMEM = "Reset";
|
||||||
const char* const menuOptionsGBA[] PROGMEM = {GBAMenuItem1, GBAMenuItem2, GBAMenuItem3, GBAMenuItem4};
|
const char* const menuOptionsGBA[] PROGMEM = {GBAMenuItem1, GBAMenuItem2, GBAMenuItem3, GBAMenuItem4};
|
||||||
|
|
||||||
const char GBARomMenuItem1[] PROGMEM = "4MB";
|
// Rom menu
|
||||||
const char GBARomMenuItem2[] PROGMEM = "8MB";
|
const char GBARomItem1[] PROGMEM = "4MB";
|
||||||
const char GBARomMenuItem3[] PROGMEM = "16MB";
|
const char GBARomItem2[] PROGMEM = "8MB";
|
||||||
const char GBARomMenuItem4[] PROGMEM = "32MB";
|
const char GBARomItem3[] PROGMEM = "16MB";
|
||||||
const char* const menuOptionsGBARom[] PROGMEM = {GBARomMenuItem1, GBARomMenuItem2, GBARomMenuItem3, GBARomMenuItem4};
|
const char GBARomItem4[] PROGMEM = "32MB";
|
||||||
|
const char* const romOptionsGBA[] PROGMEM = {GBARomItem1, GBARomItem2, GBARomItem3, GBARomItem4};
|
||||||
|
|
||||||
|
// Save menu
|
||||||
|
const char GBASaveItem1[] PROGMEM = "4K EEPROM";
|
||||||
|
const char GBASaveItem2[] PROGMEM = "64K EEPROM";
|
||||||
|
const char GBASaveItem3[] PROGMEM = "256K SRAM/FRAM";
|
||||||
|
const char GBASaveItem4[] PROGMEM = "512K SRAM/FRAM";
|
||||||
|
const char GBASaveItem5[] PROGMEM = "512K FLASHROM";
|
||||||
|
const char GBASaveItem6[] PROGMEM = "1M FLASHROM";
|
||||||
|
const char* const saveOptionsGBA[] PROGMEM = {GBASaveItem1, GBASaveItem2, GBASaveItem3, GBASaveItem4, GBASaveItem5, GBASaveItem6};
|
||||||
|
|
||||||
void gbaMenu() {
|
void gbaMenu() {
|
||||||
// create menu with title and 4 options to choose from
|
// create menu with title and 4 options to choose from
|
||||||
@ -52,7 +62,7 @@ void gbaMenu() {
|
|||||||
// create submenu with title and 4 options to choose from
|
// create submenu with title and 4 options to choose from
|
||||||
unsigned char GBARomMenu;
|
unsigned char GBARomMenu;
|
||||||
// Copy menuOptions out of progmem
|
// Copy menuOptions out of progmem
|
||||||
convertPgm(menuOptionsGBARom, 4);
|
convertPgm(romOptionsGBA, 4);
|
||||||
GBARomMenu = question_box("Select ROM size", menuOptions, 4, 0);
|
GBARomMenu = question_box("Select ROM size", menuOptions, 4, 0);
|
||||||
|
|
||||||
// wait for user choice to come back from the question box menu
|
// wait for user choice to come back from the question box menu
|
||||||
@ -88,28 +98,140 @@ void gbaMenu() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
display_Clear();
|
// Read save
|
||||||
// Change working dir to root
|
// create submenu with title and 6 options to choose from
|
||||||
sd.chdir("/");
|
unsigned char GBASaveMenu;
|
||||||
readSAVE_GBA();
|
// Copy menuOptions out of progmem
|
||||||
|
convertPgm(saveOptionsGBA, 6);
|
||||||
|
GBASaveMenu = question_box("Select save type", menuOptions, 6, 0);
|
||||||
|
|
||||||
|
// wait for user choice to come back from the question box menu
|
||||||
|
switch (GBASaveMenu)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
display_Clear();
|
||||||
|
sd.chdir("/");
|
||||||
|
// 4K EEPROM
|
||||||
|
setGBA_ROM();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
display_Clear();
|
||||||
|
sd.chdir("/");
|
||||||
|
// 64K EEPROM
|
||||||
|
setGBA_ROM();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
display_Clear();
|
||||||
|
sd.chdir("/");
|
||||||
|
// 256K SRAM/FRAM
|
||||||
|
readFRAM_GBA(32768);
|
||||||
|
setGBA_ROM();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
display_Clear();
|
||||||
|
sd.chdir("/");
|
||||||
|
// 512K SRAM/FRAM
|
||||||
|
readFRAM_GBA(65536);
|
||||||
|
setGBA_ROM();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
display_Clear();
|
||||||
|
sd.chdir("/");
|
||||||
|
// 512K FLASH
|
||||||
|
setGBA_ROM();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
display_Clear();
|
||||||
|
sd.chdir("/");
|
||||||
|
// 1M FLASH
|
||||||
|
setGBA_ROM();
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
display_Clear();
|
// Write save
|
||||||
// Change working dir to root
|
// create submenu with title and 6 options to choose from
|
||||||
sd.chdir("/");
|
unsigned char GBASavesMenu;
|
||||||
writeSAVE_GBA();
|
// Copy menuOptions out of progmem
|
||||||
unsigned long wrErrors;
|
convertPgm(saveOptionsGBA, 6);
|
||||||
wrErrors = verifySAVE_GBA();
|
GBASavesMenu = question_box("Select save type", menuOptions, 6, 0);
|
||||||
if (wrErrors == 0) {
|
|
||||||
println_Msg(F("Verified OK"));
|
// wait for user choice to come back from the question box menu
|
||||||
display_Update();
|
switch (GBASavesMenu)
|
||||||
}
|
{
|
||||||
else {
|
case 0:
|
||||||
print_Msg(F("Error: "));
|
display_Clear();
|
||||||
print_Msg(wrErrors);
|
sd.chdir("/");
|
||||||
println_Msg(F(" bytes "));
|
// 4K EEPROM
|
||||||
print_Error(F("did not verify."), false);
|
setGBA_ROM();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
display_Clear();
|
||||||
|
sd.chdir("/");
|
||||||
|
// 64K EEPROM
|
||||||
|
setGBA_ROM();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
display_Clear();
|
||||||
|
sd.chdir("/");
|
||||||
|
// 256K SRAM/FRAM
|
||||||
|
// Change working dir to root
|
||||||
|
writeFRAM_GBA(1, 32768);
|
||||||
|
writeErrors = verifyFRAM_GBA(32768);
|
||||||
|
if (writeErrors == 0) {
|
||||||
|
println_Msg(F("Verified OK"));
|
||||||
|
display_Update();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print_Msg(F("Error: "));
|
||||||
|
print_Msg(writeErrors);
|
||||||
|
println_Msg(F(" bytes "));
|
||||||
|
print_Error(F("did not verify."), false);
|
||||||
|
}
|
||||||
|
setGBA_ROM();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
display_Clear();
|
||||||
|
sd.chdir("/");
|
||||||
|
// 512K SRAM/FRAM
|
||||||
|
// Change working dir to root
|
||||||
|
writeFRAM_GBA(1, 65536);
|
||||||
|
writeErrors = verifyFRAM_GBA(65536);
|
||||||
|
if (writeErrors == 0) {
|
||||||
|
println_Msg(F("Verified OK"));
|
||||||
|
display_Update();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print_Msg(F("Error: "));
|
||||||
|
print_Msg(writeErrors);
|
||||||
|
println_Msg(F(" bytes "));
|
||||||
|
print_Error(F("did not verify."), false);
|
||||||
|
}
|
||||||
|
setGBA_ROM();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
display_Clear();
|
||||||
|
sd.chdir("/");
|
||||||
|
// 512K FLASH
|
||||||
|
setGBA_ROM();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
display_Clear();
|
||||||
|
sd.chdir("/");
|
||||||
|
// 1M FLASH
|
||||||
|
setGBA_ROM();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -127,28 +249,7 @@ void gbaMenu() {
|
|||||||
Setup
|
Setup
|
||||||
*****************************************/
|
*****************************************/
|
||||||
void setup_GBA() {
|
void setup_GBA() {
|
||||||
// Set address/data pins to OUTPUT
|
setGBA_ROM();
|
||||||
// AD0-AD7
|
|
||||||
DDRF = 0xFF;
|
|
||||||
// AD8-AD15
|
|
||||||
DDRK = 0xFF;
|
|
||||||
// AD16-AD23
|
|
||||||
DDRC = 0xFF;
|
|
||||||
|
|
||||||
// Output a HIGH signal
|
|
||||||
// AD0-AD7
|
|
||||||
PORTF = 0xFF;
|
|
||||||
// AD8-AD15
|
|
||||||
PORTK = 0xFF;
|
|
||||||
// AD16-AD23
|
|
||||||
PORTC = 0xFF;
|
|
||||||
|
|
||||||
// Set Control Pins to Output CS_SRAM(PH0) CS_ROM(PH3) WR(PH5) RD(PH6)
|
|
||||||
// CLK is N/C and IRQ is conected to GND inside the cartridge
|
|
||||||
DDRH |= (1 << 0) | (1 << 3) | (1 << 5) | (1 << 6);
|
|
||||||
// Output a high signal on CS_SRAM(PH0) CS_ROM(PH3) WR(PH5) RD(PH6)
|
|
||||||
// At power-on all the control lines are high/disabled
|
|
||||||
PORTH |= (1 << 0) | (1 << 3) | (1 << 5) | (1 << 6);
|
|
||||||
|
|
||||||
// Delay until all is stable
|
// Delay until all is stable
|
||||||
delay(500);
|
delay(500);
|
||||||
@ -178,6 +279,32 @@ void setup_GBA() {
|
|||||||
/******************************************
|
/******************************************
|
||||||
Low level functions
|
Low level functions
|
||||||
*****************************************/
|
*****************************************/
|
||||||
|
// Setup all ports and pins for readign the rom
|
||||||
|
void setGBA_ROM() {
|
||||||
|
// Set address/data pins to OUTPUT
|
||||||
|
// AD0-AD7
|
||||||
|
DDRF = 0xFF;
|
||||||
|
// AD8-AD15
|
||||||
|
DDRK = 0xFF;
|
||||||
|
// AD16-AD23
|
||||||
|
DDRC = 0xFF;
|
||||||
|
|
||||||
|
// Output a HIGH signal
|
||||||
|
// AD0-AD7
|
||||||
|
PORTF = 0xFF;
|
||||||
|
// AD8-AD15
|
||||||
|
PORTK = 0xFF;
|
||||||
|
// AD16-AD23
|
||||||
|
PORTC = 0xFF;
|
||||||
|
|
||||||
|
// Set Control Pins to Output CS_SRAM(PH0) CS_ROM(PH3) WR(PH5) RD(PH6)
|
||||||
|
// CLK is N/C and IRQ is conected to GND inside the cartridge
|
||||||
|
DDRH |= (1 << 0) | (1 << 3) | (1 << 5) | (1 << 6);
|
||||||
|
// Output a high signal on CS_SRAM(PH0) CS_ROM(PH3) WR(PH5) RD(PH6)
|
||||||
|
// At power-on all the control lines are high/disabled
|
||||||
|
PORTH |= (1 << 0) | (1 << 3) | (1 << 5) | (1 << 6);
|
||||||
|
}
|
||||||
|
|
||||||
// Read one word and toggle both CS and RD
|
// Read one word and toggle both CS and RD
|
||||||
word readWord_GBA(unsigned long myAddress) {
|
word readWord_GBA(unsigned long myAddress) {
|
||||||
//divide address by two since we read two bytes per offset
|
//divide address by two since we read two bytes per offset
|
||||||
@ -239,7 +366,7 @@ void readBlock_GBA(unsigned long myAddress, byte myArray[] , int numBytes) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/******************************************
|
/******************************************
|
||||||
Game Boy functions
|
Game Boy ROM Functions
|
||||||
*****************************************/
|
*****************************************/
|
||||||
// Read info out of rom header
|
// Read info out of rom header
|
||||||
void getCartInfo_GBA() {
|
void getCartInfo_GBA() {
|
||||||
@ -399,15 +526,219 @@ boolean compare_checksum_GBA () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void readSAVE_GBA() {
|
/******************************************
|
||||||
|
Game Boy SAVE Functions
|
||||||
|
*****************************************/
|
||||||
|
// MB85R256 FRAM (Ferroelectric Random Access Memory) 32,768 words x 8 bits
|
||||||
|
void readFRAM_GBA (unsigned long framSize) {
|
||||||
|
// Output a HIGH signal on CS_ROM(PH3) WE_SRAM(PH5)
|
||||||
|
PORTH |= (1 << 3) | (1 << 5);
|
||||||
|
|
||||||
|
// Set address ports to output
|
||||||
|
DDRF = 0xFF;
|
||||||
|
DDRK = 0xFF;
|
||||||
|
|
||||||
|
// Set data pins to input
|
||||||
|
DDRC = 0x00;
|
||||||
|
// Disable Pullups
|
||||||
|
//PORTC = 0x00;
|
||||||
|
|
||||||
|
// Output a LOW signal on CE_SRAM(PH0) and OE_SRAM(PH6)
|
||||||
|
PORTH &= ~((1 << 0) | (1 << 6));
|
||||||
|
|
||||||
|
// Get name, add extension and convert to char array for sd lib
|
||||||
|
strcpy(fileName, romName);
|
||||||
|
strcat(fileName, ".srm");
|
||||||
|
|
||||||
|
// create a new folder for the save file
|
||||||
|
EEPROM_readAnything(0, foldern);
|
||||||
|
sprintf(folder, "SAVE/%s/%d", romName, foldern);
|
||||||
|
sd.mkdir(folder, true);
|
||||||
|
sd.chdir(folder);
|
||||||
|
|
||||||
|
// Signal end of process
|
||||||
|
print_Msg(F("Reading to SAVE/"));
|
||||||
|
print_Msg(romName);
|
||||||
|
print_Msg(F("/"));
|
||||||
|
print_Msg(foldern);
|
||||||
|
print_Msg(F("/"));
|
||||||
|
print_Msg(fileName);
|
||||||
|
print_Msg(F("..."));
|
||||||
|
display_Update();
|
||||||
|
|
||||||
|
// write new folder number back to eeprom
|
||||||
|
foldern = foldern + 1;
|
||||||
|
EEPROM_writeAnything(0, foldern);
|
||||||
|
|
||||||
|
//open file on sd card
|
||||||
|
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
|
||||||
|
print_Error(F("SD Error"), true);
|
||||||
|
}
|
||||||
|
for (unsigned long currAddress = 0; currAddress < framSize; currAddress += 512) {
|
||||||
|
for (int c = 0; c < 512; c++) {
|
||||||
|
// Pull OE_SRAM(PH6) HIGH
|
||||||
|
PORTH |= (1 << 6);
|
||||||
|
|
||||||
|
// Set address
|
||||||
|
PORTF = (currAddress + c) & 0xFF;
|
||||||
|
PORTK = ((currAddress + c) >> 8) & 0xFF;
|
||||||
|
|
||||||
|
// Arduino running at 16Mhz -> one nop = 62.5ns
|
||||||
|
// Leave CS_SRAM HIGH for at least 85ns
|
||||||
|
__asm__("nop\n\t""nop\n\t");
|
||||||
|
|
||||||
|
// Pull OE_SRAM(PH6) LOW
|
||||||
|
PORTH &= ~ (1 << 6);
|
||||||
|
|
||||||
|
// Hold address for at least 25ns and wait 150ns before access
|
||||||
|
__asm__("nop\n\t""nop\n\t""nop\n\t");
|
||||||
|
|
||||||
|
// Read byte
|
||||||
|
sdBuffer[c] = PINC;
|
||||||
|
}
|
||||||
|
// Write sdBuffer to file
|
||||||
|
myFile.write(sdBuffer, 512);
|
||||||
|
}
|
||||||
|
// Close the file:
|
||||||
|
myFile.close();
|
||||||
|
|
||||||
|
// Signal end of process
|
||||||
|
println_Msg(F("Done"));
|
||||||
|
display_Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeSAVE_GBA() {
|
// Write file to SRAM
|
||||||
|
void writeFRAM_GBA (boolean browseFile, unsigned long framSize) {
|
||||||
|
// Output a HIGH signal on CS_ROM(PH3) and OE_SRAM(PH6)
|
||||||
|
PORTH |= (1 << 3) | (1 << 6);
|
||||||
|
|
||||||
|
// Set address ports to output
|
||||||
|
DDRF = 0xFF;
|
||||||
|
DDRK = 0xFF;
|
||||||
|
|
||||||
|
// Set data port to output
|
||||||
|
DDRC = 0xFF;
|
||||||
|
// Output a high signal
|
||||||
|
//PORTC = 0xFF;
|
||||||
|
|
||||||
|
// Output a LOW signal on CE_SRAM(PH0) and WE_SRAM(PH5)
|
||||||
|
PORTH &= ~((1 << 0) | (1 << 5));
|
||||||
|
|
||||||
|
if (browseFile) {
|
||||||
|
filePath[0] = '\0';
|
||||||
|
sd.chdir("/");
|
||||||
|
fileBrowser("Select srm file");
|
||||||
|
// Create filepath
|
||||||
|
sprintf(filePath, "%s/%s", filePath, fileName);
|
||||||
|
display_Clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sprintf(filePath, "%s", fileName);
|
||||||
|
|
||||||
|
//open file on sd card
|
||||||
|
if (myFile.open(filePath, O_READ)) {
|
||||||
|
for (unsigned long currAddress = 0; currAddress < framSize; currAddress += 512) {
|
||||||
|
//fill sdBuffer
|
||||||
|
myFile.read(sdBuffer, 512);
|
||||||
|
|
||||||
|
for (int c = 0; c < 512; c++) {
|
||||||
|
// Output Data on PORTC
|
||||||
|
PORTC = sdBuffer[c];
|
||||||
|
|
||||||
|
// Arduino running at 16Mhz -> one nop = 62.5ns
|
||||||
|
// Data setup time 50ns
|
||||||
|
__asm__("nop\n\t");
|
||||||
|
|
||||||
|
// Pull WE_SRAM (PH5) HIGH
|
||||||
|
PORTH |= (1 << 5);
|
||||||
|
|
||||||
|
// Set address
|
||||||
|
PORTF = (currAddress + c) & 0xFF;
|
||||||
|
PORTK = ((currAddress + c) >> 8) & 0xFF;
|
||||||
|
|
||||||
|
// Leave WE_SRAM (PH5) HIGH for at least 85ns
|
||||||
|
__asm__("nop\n\t""nop\n\t");
|
||||||
|
|
||||||
|
// Pull WE_SRAM (PH5) LOW
|
||||||
|
PORTH &= ~ (1 << 5);
|
||||||
|
|
||||||
|
// Hold address for at least 25ns and wait 150ns before next write
|
||||||
|
__asm__("nop\n\t""nop\n\t""nop\n\t");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Close the file:
|
||||||
|
myFile.close();
|
||||||
|
println_Msg(F("SRAM writing finished"));
|
||||||
|
display_Update();
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print_Error(F("File doesnt exist"), false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long verifySAVE_GBA() {
|
// Check if the SRAM was written without any error
|
||||||
|
unsigned long verifyFRAM_GBA(unsigned long framSize) {
|
||||||
|
// Output a HIGH signal on CS_ROM(PH3) WE_SRAM(PH5)
|
||||||
|
PORTH |= (1 << 3) | (1 << 5);
|
||||||
|
|
||||||
|
// Set address ports to output
|
||||||
|
DDRF = 0xFF;
|
||||||
|
DDRK = 0xFF;
|
||||||
|
|
||||||
|
// Set data pins to input
|
||||||
|
DDRC = 0x00;
|
||||||
|
// Disable Pullups
|
||||||
|
//PORTC = 0x00;
|
||||||
|
|
||||||
|
// Output a LOW signal on CE_SRAM(PH0) and OE_SRAM(PH6)
|
||||||
|
PORTH &= ~((1 << 0) | (1 << 6));
|
||||||
|
|
||||||
|
//open file on sd card
|
||||||
|
if (myFile.open(filePath, O_READ)) {
|
||||||
|
|
||||||
|
// Variable for errors
|
||||||
|
writeErrors = 0;
|
||||||
|
|
||||||
|
for (unsigned long currAddress = 0; currAddress < framSize; currAddress += 512) {
|
||||||
|
//fill sdBuffer
|
||||||
|
myFile.read(sdBuffer, 512);
|
||||||
|
|
||||||
|
for (int c = 0; c < 512; c++) {
|
||||||
|
// Pull OE_SRAM(PH6) HIGH
|
||||||
|
PORTH |= (1 << 6);
|
||||||
|
|
||||||
|
// Set address
|
||||||
|
PORTF = (currAddress + c) & 0xFF;
|
||||||
|
PORTK = ((currAddress + c) >> 8) & 0xFF;
|
||||||
|
|
||||||
|
// Arduino running at 16Mhz -> one nop = 62.5ns
|
||||||
|
// Leave CS_SRAM HIGH for at least 85ns
|
||||||
|
__asm__("nop\n\t""nop\n\t");
|
||||||
|
|
||||||
|
// Pull OE_SRAM(PH6) LOW
|
||||||
|
PORTH &= ~ (1 << 6);
|
||||||
|
|
||||||
|
// Hold address for at least 25ns and wait 150ns before access
|
||||||
|
__asm__("nop\n\t""nop\n\t""nop\n\t");
|
||||||
|
|
||||||
|
// Read byte
|
||||||
|
if (PINC != sdBuffer[c]) {
|
||||||
|
writeErrors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the file:
|
||||||
|
myFile.close();
|
||||||
|
return writeErrors;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print_Error(F("Can't open file"), false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//******************************************
|
//******************************************
|
||||||
// End of File
|
// End of File
|
||||||
//******************************************
|
//******************************************
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
// Received N64 Eeprom data bits, 1 page
|
// Received N64 Eeprom data bits, 1 page
|
||||||
bool tempBits[65];
|
bool tempBits[65];
|
||||||
int eepPages;
|
int eepPages;
|
||||||
|
// Savetype
|
||||||
|
byte saveType;
|
||||||
|
|
||||||
// N64 Controller
|
// N64 Controller
|
||||||
// 256 bits of received Controller data
|
// 256 bits of received Controller data
|
||||||
@ -35,9 +37,6 @@ N64_status;
|
|||||||
String button = "N/A";
|
String button = "N/A";
|
||||||
String lastbutton = "N/A";
|
String lastbutton = "N/A";
|
||||||
|
|
||||||
// Cartridge ID and size
|
|
||||||
byte saveType;
|
|
||||||
|
|
||||||
// Rom base address
|
// Rom base address
|
||||||
unsigned long romBase = 0x10000000;
|
unsigned long romBase = 0x10000000;
|
||||||
unsigned long sramBase = 0x08000000;
|
unsigned long sramBase = 0x08000000;
|
||||||
|
Loading…
Reference in New Issue
Block a user