mirror of
https://github.com/sanni/cartreader.git
synced 2024-11-11 07:25:07 +01:00
V2.3: Remove 16bit flash adapter menu
If you're still using the old 16bit adapter(the one with the additional pins left and right on the snes cart edge) you can enable the menu again by changing one line in Cart_Reader.ino: // Enable 16bit flash adapter menu #define enable_flash16
This commit is contained in:
parent
9c3e5e9d38
commit
a27ee157e8
@ -2,8 +2,8 @@
|
|||||||
Cartridge Reader for Arduino Mega2560
|
Cartridge Reader for Arduino Mega2560
|
||||||
|
|
||||||
Author: sanni
|
Author: sanni
|
||||||
Date: 22-10-2018
|
Date: 30-10-2018
|
||||||
Version: 2.2
|
Version: 2.3
|
||||||
|
|
||||||
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
|
||||||
@ -37,7 +37,7 @@
|
|||||||
vogelfreiheit - N64 flashram fix
|
vogelfreiheit - N64 flashram fix
|
||||||
|
|
||||||
**********************************************************************************/
|
**********************************************************************************/
|
||||||
char ver[5] = "2.2";
|
char ver[5] = "2.3";
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
Define Starting Point
|
Define Starting Point
|
||||||
@ -71,6 +71,8 @@ char ver[5] = "2.2";
|
|||||||
******************************************/
|
******************************************/
|
||||||
// If set to 1 then the crc32 checksum will be calculated after reading a N64 rom
|
// If set to 1 then the crc32 checksum will be calculated after reading a N64 rom
|
||||||
boolean n64crc = 1;
|
boolean n64crc = 1;
|
||||||
|
// Enable 16bit flash adapter menu
|
||||||
|
//#define enable_flash16
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
Libraries
|
Libraries
|
||||||
|
@ -19,9 +19,9 @@ boolean hiROM = 1;
|
|||||||
Menu
|
Menu
|
||||||
*****************************************/
|
*****************************************/
|
||||||
// Flash start menu
|
// Flash start menu
|
||||||
static const char flashMenuItem1[] PROGMEM = "8bit adapter";
|
static const char flashMenuItem1[] PROGMEM = "8bit Flash adapter";
|
||||||
static const char flashMenuItem2[] PROGMEM = "16bit adapter(old)";
|
static const char flashMenuItem2[] PROGMEM = "Eprom adapter(beta)";
|
||||||
static const char flashMenuItem3[] PROGMEM = "Eprom adapter(beta)";
|
static const char flashMenuItem3[] PROGMEM = "16bit Flash adapter";
|
||||||
static const char* const menuOptionsFlash[] PROGMEM = {flashMenuItem1, flashMenuItem2, flashMenuItem3};
|
static const char* const menuOptionsFlash[] PROGMEM = {flashMenuItem1, flashMenuItem2, flashMenuItem3};
|
||||||
|
|
||||||
// 8bit Flash menu items
|
// 8bit Flash menu items
|
||||||
@ -57,8 +57,13 @@ void flashMenu() {
|
|||||||
// create menu with title and 3 options to choose from
|
// create menu with title and 3 options to choose from
|
||||||
unsigned char flashSlot;
|
unsigned char flashSlot;
|
||||||
// Copy menuOptions out of progmem
|
// Copy menuOptions out of progmem
|
||||||
|
#ifdef enable_flash16
|
||||||
convertPgm(menuOptionsFlash, 3);
|
convertPgm(menuOptionsFlash, 3);
|
||||||
flashSlot = question_box("Select adapter PCB", menuOptions, 3, 0);
|
flashSlot = question_box("Select adapter PCB", menuOptions, 3, 0);
|
||||||
|
#else
|
||||||
|
convertPgm(menuOptionsFlash, 2);
|
||||||
|
flashSlot = question_box("Select adapter PCB", menuOptions, 2, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
// wait for user choice to come back from the question box menu
|
// wait for user choice to come back from the question box menu
|
||||||
switch (flashSlot)
|
switch (flashSlot)
|
||||||
@ -76,17 +81,17 @@ void flashMenu() {
|
|||||||
case 1:
|
case 1:
|
||||||
display_Clear();
|
display_Clear();
|
||||||
display_Update();
|
display_Update();
|
||||||
setup_Flash16();
|
setup_Eprom();
|
||||||
id_Flash16();
|
mode = mode_EPROM;
|
||||||
wait();
|
|
||||||
mode = mode_FLASH16;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
display_Clear();
|
display_Clear();
|
||||||
display_Update();
|
display_Update();
|
||||||
setup_Eprom();
|
setup_Flash16();
|
||||||
mode = mode_EPROM;
|
id_Flash16();
|
||||||
|
wait();
|
||||||
|
mode = mode_FLASH16;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ void mdMenu() {
|
|||||||
unsigned char mainMenu;
|
unsigned char mainMenu;
|
||||||
// Copy menuOptions out of progmem
|
// Copy menuOptions out of progmem
|
||||||
convertPgm(menuOptionsMD, 5);
|
convertPgm(menuOptionsMD, 5);
|
||||||
mainMenu = question_box("MEGA DRIVE Reader", menuOptions, 3, 0);
|
mainMenu = question_box("MEGA DRIVE Reader", menuOptions, 5, 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
|
||||||
switch (mainMenu)
|
switch (mainMenu)
|
||||||
@ -90,18 +90,47 @@ void mdMenu() {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*case 3:
|
case 3:
|
||||||
// Change working dir to root
|
// Change working dir to root
|
||||||
|
filePath[0] = '\0';
|
||||||
sd.chdir("/");
|
sd.chdir("/");
|
||||||
writeFlash_MD();
|
fileBrowser("Select file");
|
||||||
// Reset
|
display_Clear();
|
||||||
wait();
|
// Setting CS(PH3) LOW
|
||||||
asm volatile (" jmp 0");
|
PORTH &= ~(1 << 3);
|
||||||
|
|
||||||
|
// ID flash
|
||||||
|
resetFlash_MD();
|
||||||
|
idFlash_MD();
|
||||||
|
resetFlash_MD();
|
||||||
|
print_Msg("Flash ID: ");
|
||||||
|
println_Msg(flashid);
|
||||||
|
if (strcmp(flashid, "C2F1") == 0) {
|
||||||
|
println_Msg("MX29F1610 detected");
|
||||||
|
flashSize = 2097152;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print_Error(F("Error: Unknown flashrom"), true);
|
||||||
|
}
|
||||||
|
display_Update();
|
||||||
|
|
||||||
|
eraseFlash_MD();
|
||||||
|
resetFlash_MD();
|
||||||
|
blankcheck_MD();
|
||||||
|
write29F1610_MD();
|
||||||
|
resetFlash_MD();
|
||||||
|
delay(1000);
|
||||||
|
resetFlash_MD();
|
||||||
|
delay(1000);
|
||||||
|
verifyFlash_MD();
|
||||||
|
// Set CS(PH3) HIGH
|
||||||
|
PORTH |= (1 << 3);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
|
// Reset
|
||||||
asm volatile (" jmp 0");
|
asm volatile (" jmp 0");
|
||||||
break;*/
|
break;
|
||||||
}
|
}
|
||||||
println_Msg(F(""));
|
println_Msg(F(""));
|
||||||
println_Msg(F("Press Button..."));
|
println_Msg(F("Press Button..."));
|
||||||
@ -206,6 +235,55 @@ word readWord_MD(unsigned long myAddress) {
|
|||||||
return tempWord;
|
return tempWord;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void writeFlash_MD(unsigned long myAddress, word myData) {
|
||||||
|
PORTF = myAddress & 0xFF;
|
||||||
|
PORTK = (myAddress >> 8) & 0xFF;
|
||||||
|
PORTL = (myAddress >> 16) & 0xFF;
|
||||||
|
PORTC = myData;
|
||||||
|
PORTA = (myData >> 8) & 0xFF;
|
||||||
|
|
||||||
|
// Arduino running at 16Mhz -> one nop = 62.5ns
|
||||||
|
// Wait till output is stable
|
||||||
|
__asm__("nop\n\t");
|
||||||
|
|
||||||
|
// Switch WE(PH5) to LOW
|
||||||
|
PORTH &= ~(1 << 5);
|
||||||
|
|
||||||
|
// Leave WE low for at least 60ns
|
||||||
|
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||||
|
|
||||||
|
// Switch WE(PH5)to HIGH
|
||||||
|
PORTH |= (1 << 5);
|
||||||
|
|
||||||
|
// Leave WE high for at least 50ns
|
||||||
|
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||||
|
}
|
||||||
|
|
||||||
|
word readFlash_MD(unsigned long myAddress) {
|
||||||
|
PORTF = myAddress & 0xFF;
|
||||||
|
PORTK = (myAddress >> 8) & 0xFF;
|
||||||
|
PORTL = (myAddress >> 16) & 0xFF;
|
||||||
|
|
||||||
|
// Arduino running at 16Mhz -> one nop = 62.5ns
|
||||||
|
__asm__("nop\n\t");
|
||||||
|
|
||||||
|
// Setting OE(PH6) LOW
|
||||||
|
PORTH &= ~(1 << 6);
|
||||||
|
|
||||||
|
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||||
|
|
||||||
|
// Read
|
||||||
|
word tempWord = ( ( PINA & 0xFF ) << 8 ) | ( PINC & 0xFF );
|
||||||
|
|
||||||
|
__asm__("nop\n\t");
|
||||||
|
|
||||||
|
// Setting OE(PH6) HIGH
|
||||||
|
PORTH |= (1 << 6);
|
||||||
|
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||||
|
|
||||||
|
return tempWord;
|
||||||
|
}
|
||||||
|
|
||||||
// Switch data pins to write
|
// Switch data pins to write
|
||||||
void dataOut_MD() {
|
void dataOut_MD() {
|
||||||
DDRC = 0xFF;
|
DDRC = 0xFF;
|
||||||
@ -494,6 +572,209 @@ unsigned long verifySram_MD() {
|
|||||||
return writeErrors;
|
return writeErrors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//******************************************
|
||||||
|
// Flashrom Functions
|
||||||
|
//******************************************
|
||||||
|
void resetFlash_MD() {
|
||||||
|
// Set data pins to output
|
||||||
|
dataOut_MD();
|
||||||
|
|
||||||
|
// Reset command sequence
|
||||||
|
writeFlash_MD(0x5555, 0xaa);
|
||||||
|
writeFlash_MD(0x2aaa, 0x55);
|
||||||
|
writeFlash_MD(0x5555, 0xf0);
|
||||||
|
|
||||||
|
// Set data pins to input again
|
||||||
|
dataIn_MD();
|
||||||
|
}
|
||||||
|
|
||||||
|
void write29F1610_MD() {
|
||||||
|
// Create filepath
|
||||||
|
sprintf(filePath, "%s/%s", filePath, fileName);
|
||||||
|
print_Msg(F("Flashing file "));
|
||||||
|
print_Msg(filePath);
|
||||||
|
println_Msg(F("..."));
|
||||||
|
display_Update();
|
||||||
|
|
||||||
|
// Open file on sd card
|
||||||
|
if (myFile.open(filePath, O_READ)) {
|
||||||
|
// Get rom size from file
|
||||||
|
fileSize = myFile.fileSize();
|
||||||
|
if (fileSize > flashSize) {
|
||||||
|
print_Error(F("File size exceeds flash size."), true);
|
||||||
|
}
|
||||||
|
// Set data pins to output
|
||||||
|
dataOut_MD();
|
||||||
|
|
||||||
|
// Fill sdBuffer with 1 page at a time then write it repeat until all bytes are written
|
||||||
|
int d = 0;
|
||||||
|
for (unsigned long currByte = 0; currByte < fileSize / 2; currByte += 64) {
|
||||||
|
myFile.read(sdBuffer, 128);
|
||||||
|
|
||||||
|
// Blink led
|
||||||
|
if (currByte % 4096 == 0) {
|
||||||
|
PORTB ^= (1 << 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write command sequence
|
||||||
|
writeFlash_MD(0x5555, 0xaa);
|
||||||
|
writeFlash_MD(0x2aaa, 0x55);
|
||||||
|
writeFlash_MD(0x5555, 0xa0);
|
||||||
|
|
||||||
|
// Write one full page at a time
|
||||||
|
for (byte c = 0; c < 64; c++) {
|
||||||
|
word currWord = ( ( sdBuffer[d] & 0xFF ) << 8 ) | ( sdBuffer[d + 1] & 0xFF );
|
||||||
|
writeFlash_MD(currByte + c, currWord);
|
||||||
|
d += 2;
|
||||||
|
}
|
||||||
|
d = 0;
|
||||||
|
|
||||||
|
// Check if write is complete
|
||||||
|
delayMicroseconds(100);
|
||||||
|
busyCheck_MD();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set data pins to input again
|
||||||
|
dataIn_MD();
|
||||||
|
|
||||||
|
// Close the file:
|
||||||
|
myFile.close();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
println_Msg(F("Can't open file"));
|
||||||
|
display_Update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void idFlash_MD() {
|
||||||
|
// Set data pins to output
|
||||||
|
dataOut_MD();
|
||||||
|
|
||||||
|
// ID command sequence
|
||||||
|
writeFlash_MD(0x5555, 0xaa);
|
||||||
|
writeFlash_MD(0x2aaa, 0x55);
|
||||||
|
writeFlash_MD(0x5555, 0x90);
|
||||||
|
|
||||||
|
// Set data pins to input again
|
||||||
|
dataIn_MD();
|
||||||
|
|
||||||
|
// Read the two id bytes into a string
|
||||||
|
sprintf(flashid, "%02X%02X", readFlash_MD(0) & 0xFF, readFlash_MD(1) & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte readStatusReg_MD() {
|
||||||
|
// Set data pins to output
|
||||||
|
dataOut_MD();
|
||||||
|
|
||||||
|
// Status reg command sequence
|
||||||
|
writeFlash_MD(0x5555, 0xaa);
|
||||||
|
writeFlash_MD(0x2aaa, 0x55);
|
||||||
|
writeFlash_MD(0x5555, 0x70);
|
||||||
|
|
||||||
|
// Set data pins to input again
|
||||||
|
dataIn_MD();
|
||||||
|
|
||||||
|
// Read the status register
|
||||||
|
byte statusReg = readFlash_MD(0);
|
||||||
|
return statusReg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void eraseFlash_MD() {
|
||||||
|
// Set data pins to output
|
||||||
|
dataOut_MD();
|
||||||
|
|
||||||
|
// Erase command sequence
|
||||||
|
writeFlash_MD(0x5555, 0xaa);
|
||||||
|
writeFlash_MD(0x2aaa, 0x55);
|
||||||
|
writeFlash_MD(0x5555, 0x80);
|
||||||
|
writeFlash_MD(0x5555, 0xaa);
|
||||||
|
writeFlash_MD(0x2aaa, 0x55);
|
||||||
|
writeFlash_MD(0x5555, 0x10);
|
||||||
|
|
||||||
|
// Set data pins to input again
|
||||||
|
dataIn_MD();
|
||||||
|
|
||||||
|
busyCheck_MD();
|
||||||
|
}
|
||||||
|
|
||||||
|
void blankcheck_MD() {
|
||||||
|
blank = 1;
|
||||||
|
for (unsigned long currByte = 0; currByte < flashSize / 2; currByte++) {
|
||||||
|
if (readFlash_MD(currByte) != 0xFFFF) {
|
||||||
|
currByte = flashSize / 2;
|
||||||
|
blank = 0;
|
||||||
|
}
|
||||||
|
if (currByte % 4096 == 0) {
|
||||||
|
PORTB ^= (1 << 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!blank) {
|
||||||
|
print_Error(F("Error: Not blank"), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void verifyFlash_MD() {
|
||||||
|
// Open file on sd card
|
||||||
|
if (myFile.open(filePath, O_READ)) {
|
||||||
|
// Get rom size from file
|
||||||
|
fileSize = myFile.fileSize();
|
||||||
|
if (fileSize > flashSize) {
|
||||||
|
print_Error(F("File size exceeds flash size."), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
blank = 0;
|
||||||
|
word d = 0;
|
||||||
|
for (unsigned long currByte = 0; currByte < fileSize / 2; currByte += 256) {
|
||||||
|
if (currByte % 4096 == 0) {
|
||||||
|
PORTB ^= (1 << 4);
|
||||||
|
}
|
||||||
|
//fill sdBuffer
|
||||||
|
myFile.read(sdBuffer, 512);
|
||||||
|
for (int c = 0; c < 256; c++) {
|
||||||
|
word currWord = ((sdBuffer[d] << 8) | sdBuffer[d + 1]);
|
||||||
|
|
||||||
|
if (readFlash_MD(currByte + c) != currWord) {
|
||||||
|
blank++;
|
||||||
|
}
|
||||||
|
d += 2;
|
||||||
|
}
|
||||||
|
d = 0;
|
||||||
|
}
|
||||||
|
if (blank == 0) {
|
||||||
|
println_Msg(F("Flashrom verified OK"));
|
||||||
|
display_Update();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print_Msg(F("Error: "));
|
||||||
|
print_Msg(blank);
|
||||||
|
println_Msg(F(" bytes "));
|
||||||
|
print_Error(F("did not verify."), false);
|
||||||
|
}
|
||||||
|
// Close the file:
|
||||||
|
myFile.close();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
println_Msg(F("Can't open file"));
|
||||||
|
display_Update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delay between write operations based on status register
|
||||||
|
void busyCheck_MD() {
|
||||||
|
// Set data pins to input
|
||||||
|
dataIn_MD();
|
||||||
|
|
||||||
|
// Read the status register
|
||||||
|
word statusReg = readFlash_MD(0);
|
||||||
|
|
||||||
|
while ((statusReg | 0xFF7F) != 0xFFFF) {
|
||||||
|
statusReg = readFlash_MD(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set data pins to output
|
||||||
|
dataOut_MD();
|
||||||
|
}
|
||||||
|
|
||||||
//******************************************
|
//******************************************
|
||||||
// End of File
|
// End of File
|
||||||
//******************************************
|
//******************************************
|
||||||
|
@ -205,7 +205,7 @@ void writeROM_SV (void) {
|
|||||||
sprintf(checksumStr, "%02X%02X", readBank_SNES(0, 65503), readBank_SNES(0, 65502));
|
sprintf(checksumStr, "%02X%02X", readBank_SNES(0, 65503), readBank_SNES(0, 65502));
|
||||||
|
|
||||||
//if CRC is not 8B86, BS-X cart is not inserted. Display error and reset
|
//if CRC is not 8B86, BS-X cart is not inserted. Display error and reset
|
||||||
if(strcmp("8B86", checksumStr) != 0)
|
if (strcmp("8B86", checksumStr) != 0)
|
||||||
{
|
{
|
||||||
display_Clear();
|
display_Clear();
|
||||||
print_Error(F("Error: Must use BS-X cart"), true);
|
print_Error(F("Error: Must use BS-X cart"), true);
|
||||||
@ -251,7 +251,7 @@ void writeROM_SV (void) {
|
|||||||
for (int currBank = 0xC0; currBank < 0xD0; currBank++) {
|
for (int currBank = 0xC0; currBank < 0xD0; currBank++) {
|
||||||
draw_progressbar(((currBank - 0xC0) * 0x10000), 0x100000);
|
draw_progressbar(((currBank - 0xC0) * 0x10000), 0x100000);
|
||||||
for (long currByte = 0; currByte < 65536; currByte++) {
|
for (long currByte = 0; currByte < 65536; currByte++) {
|
||||||
if(0xFF != readBank_SNES(currBank, currByte))
|
if (0xFF != readBank_SNES(currBank, currByte))
|
||||||
{
|
{
|
||||||
println_Msg(F(""));
|
println_Msg(F(""));
|
||||||
println_Msg(F("Erase failed"));
|
println_Msg(F("Erase failed"));
|
||||||
@ -295,7 +295,7 @@ void writeROM_SV (void) {
|
|||||||
for (int currBank = 0xC0; currBank < 0xD0; currBank++) {
|
for (int currBank = 0xC0; currBank < 0xD0; currBank++) {
|
||||||
draw_progressbar(((currBank - 0xC0) * 0x10000), 0x100000);
|
draw_progressbar(((currBank - 0xC0) * 0x10000), 0x100000);
|
||||||
for (long currByte = 0; currByte < 65536; currByte++) {
|
for (long currByte = 0; currByte < 65536; currByte++) {
|
||||||
if(myFile.read() != readBank_SNES(currBank, currByte))
|
if (myFile.read() != readBank_SNES(currBank, currByte))
|
||||||
{
|
{
|
||||||
println_Msg(F(""));
|
println_Msg(F(""));
|
||||||
println_Msg(F("Verify failed"));
|
println_Msg(F("Verify failed"));
|
||||||
@ -415,7 +415,7 @@ void detectCheck_SV(void) {
|
|||||||
// completion of a program or erase operation will not be evident.
|
// completion of a program or erase operation will not be evident.
|
||||||
while ((ret & 0x80) == 0x00) {
|
while ((ret & 0x80) == 0x00) {
|
||||||
i++;
|
i++;
|
||||||
if( i > 10000)
|
if ( i > 10000)
|
||||||
{
|
{
|
||||||
//timeout
|
//timeout
|
||||||
break;
|
break;
|
||||||
@ -454,4 +454,3 @@ void eraseAll_SV(void)
|
|||||||
//******************************************
|
//******************************************
|
||||||
// End of File
|
// End of File
|
||||||
//******************************************
|
//******************************************
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user