From 45f67ed30087868b0ada46fd3f0d976d10879d60 Mon Sep 17 00:00:00 2001 From: sanni Date: Wed, 4 Apr 2018 22:20:53 +0200 Subject: [PATCH] V32: Add writing ST M27C322 Eproms (beta) Needs custom flash adapter with 12V step-up converter modul for VPP. 5V VCC seems to work even though datasheet specifies 6.25V VCC while programming. --- Cart_Reader/Cart_Reader.ino | 10 +- Cart_Reader/FLASH.ino | 296 +++++++++++++++++++++++++++++++++++- 2 files changed, 299 insertions(+), 7 deletions(-) diff --git a/Cart_Reader/Cart_Reader.ino b/Cart_Reader/Cart_Reader.ino index 98c448a..1fb23d1 100644 --- a/Cart_Reader/Cart_Reader.ino +++ b/Cart_Reader/Cart_Reader.ino @@ -2,8 +2,8 @@ Cartridge Reader for Arduino Mega2560 Author: sanni - Date: 2018-04-03 - Version: V31A + Date: 2018-04-04 + Version: V32 SD lib: https://github.com/greiman/SdFat LCD lib: https://github.com/adafruit/Adafruit_SSD1306 @@ -35,7 +35,7 @@ infinest - help with GB Memory cart **********************************************************************************/ -char ver[5] = "V31A"; +char ver[5] = "V32"; /****************************************** Define Starting Point @@ -134,6 +134,7 @@ SdFile myFile; #define mode_GBA 9 #define mode_GBM 10 #define mode_MD 11 +#define mode_EPROM 12 /****************************************** Variables @@ -1286,6 +1287,9 @@ void loop() { else if (mode == mode_FLASH16) { flashromMenu16(); } + else if (mode == mode_EPROM) { + epromMenu(); + } else if (mode == mode_SFM) { sfmMenu(); } diff --git a/Cart_Reader/FLASH.ino b/Cart_Reader/FLASH.ino index 1502905..65b744e 100644 --- a/Cart_Reader/FLASH.ino +++ b/Cart_Reader/FLASH.ino @@ -18,7 +18,8 @@ unsigned long blank; // Flash start menu static const char flashMenuItem1[] PROGMEM = "8bit adapter"; static const char flashMenuItem2[] PROGMEM = "16bit adapter"; -static const char* const menuOptionsFlash[] PROGMEM = {flashMenuItem1, flashMenuItem2}; +static const char flashMenuItem3[] PROGMEM = "Eprom adapter"; +static const char* const menuOptionsFlash[] PROGMEM = {flashMenuItem1, flashMenuItem2, flashMenuItem3}; // 8bit Flash menu items static const char flash8MenuItem1[] PROGMEM = "Blankcheck"; @@ -40,12 +41,19 @@ static const char flash16MenuItem6[] PROGMEM = "Print"; static const char flash16MenuItem7[] PROGMEM = "Reset"; static const char* const menuOptionsFLASH16[] PROGMEM = {flash16MenuItem1, flash16MenuItem2, flash16MenuItem3, flash16MenuItem4, flash16MenuItem5, flash16MenuItem6, flash16MenuItem7}; +// Eprom menu items +static const char epromMenuItem1[] PROGMEM = "Blankcheck"; +static const char epromMenuItem2[] PROGMEM = "Read 27C322"; +static const char epromMenuItem3[] PROGMEM = "Write 27C322"; +static const char epromMenuItem4[] PROGMEM = "Reset"; +static const char* const menuOptionsEprom[] PROGMEM = {epromMenuItem1, epromMenuItem2, epromMenuItem3, epromMenuItem4}; + void flashMenu() { - // create menu with title and 2 options to choose from + // create menu with title and 3 options to choose from unsigned char flashSlot; // Copy menuOptions out of progmem - convertPgm(menuOptionsFlash, 2); - flashSlot = question_box("Select flashrom slot", menuOptions, 2, 0); + convertPgm(menuOptionsFlash, 3); + flashSlot = question_box("Select flashrom slot", menuOptions, 3, 0); // wait for user choice to come back from the question box menu switch (flashSlot) @@ -63,6 +71,13 @@ void flashMenu() { setup_Flash16(); mode = mode_FLASH16; break; + + case 2: + display_Clear(); + display_Update(); + setup_Eprom(); + mode = mode_EPROM; + break; } } @@ -290,6 +305,55 @@ void flashromMenu16() { wait(); } +void epromMenu() { + // create menu with title "Eprom Writer" and 4 options to choose from + unsigned char mainMenu; + // Copy menuOptions out of progmem + convertPgm(menuOptionsEprom, 4); + mainMenu = question_box("Eprom Writer", menuOptions, 4, 0); + + // wait for user choice to come back from the question box menu + switch (mainMenu) + { + case 0: + display_Clear(); + println_Msg(F("Blankcheck")); + display_Update(); + time = millis(); + blankcheck_Eprom(); + break; + + case 1: + display_Clear(); + time = millis(); + read_Eprom(); + break; + + case 2: + filePath[0] = '\0'; + sd.chdir("/"); + fileBrowser("Select file"); + display_Clear(); + time = millis(); + write_Eprom(); + break; + + case 3: + time = 0; + display_Clear(); + display_Update(); + asm volatile (" jmp 0"); + break; + } + if (time != 0) { + print_Msg(F("Operation took: ")); + print_Msg((millis() - time) / 1000, DEC); + println_Msg("s"); + display_Update(); + } + wait(); +} + /****************************************** Setup *****************************************/ @@ -478,6 +542,34 @@ void setup_Flash16() { wait(); } +void setup_Eprom() { + // Set Address Pins to Output + //A0-A7 + DDRF = 0xFF; + //A8-A15 + DDRK = 0xFF; + //A16-A23 + DDRL = 0xFF; + + // Set Data Pins (D0-D15) to Input + DDRC = 0x00; + DDRA = 0x00; + // Disable Internal Pullups + PORTC = 0x00; + PORTA = 0x00; + + // Set Control Pins to Output VPP/OE(PH5) CE(PH6) + DDRH |= (1 << 5) | (1 << 6); + + // Setting CE(PH6) HIGH + PORTH |= (1 << 6); + // Setting VPP/OE(PH5) LOW + PORTH &= ~(1 << 5); + + // 27C322 is a 4MB eprom + flashSize = 4194304; +} + /****************************************** I/O Functions *****************************************/ @@ -1534,6 +1626,202 @@ void writeFlash16_29LV640() { } } +/****************************************** + Eprom functions +*****************************************/ +void writeWord_Eprom(unsigned long myAddress, word myData) { + // Data out + DDRC = 0xFF; + DDRA = 0xFF; + // Set address + PORTF = myAddress & 0xFF; + PORTK = (myAddress >> 8) & 0xFF; + PORTL = (myAddress >> 16) & 0xFF; + // Set data + PORTC = myData; + PORTA = (myData >> 8) & 0xFF; + + // Arduino running at 16Mhz -> one nop = 62.5ns + // Wait till output is stable + __asm__("nop\n\t"); + + // Switch VPP/OE(PH5) to HIGH + PORTH |= (1 << 5); + // Setting CE(PH6) LOW + PORTH &= ~(1 << 6); + + // Leave VPP HIGH for a 50us programming pulse + delayMicroseconds(50); + + // Setting CE(PH6) HIGH + PORTH |= (1 << 6); + // Switch VPP/OE(PH5) to LOW + PORTH &= ~(1 << 5); + + // Leave VPP LOW for a little bit + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"); +} + +word readWord_Eprom(unsigned long myAddress) { + // Data in + DDRC = 0x00; + DDRA = 0x00; + // Set address + PORTF = myAddress & 0xFF; + PORTK = (myAddress >> 8) & 0xFF; + PORTL = (myAddress >> 16) & 0xFF; + + // Arduino running at 16Mhz -> one nop = 62.5ns + __asm__("nop\n\t"); + + // Setting CE(PH6) LOW + PORTH &= ~(1 << 6); + + __asm__("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 CE(PH6) HIGH + PORTH |= (1 << 6); + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"); + + return tempWord; +} + +void blankcheck_Eprom() { + + println_Msg(F("Please wait...")); + display_Update(); + + blank = 1; + for (unsigned long currWord = 0; currWord < flashSize / 2; currWord++) { + if (readWord_Eprom(currWord) != 0xFFFF) { + currWord = flashSize / 2; + blank = 0; + } + } + if (blank) { + println_Msg(F("Flashrom is empty.")); + display_Update(); + } + else { + print_Error(F("Error: Not blank"), false); + } +} + +void read_Eprom() { + // Reset to root directory + sd.chdir("/"); + + // Get name, add extension and convert to char array for sd lib + EEPROM_readAnything(10, foldern); + sd.mkdir("FLASH", true); + sd.chdir("FLASH"); + sprintf(fileName, "FL%d", foldern); + strcat(fileName, ".bin"); + // write new folder number back to eeprom + foldern = foldern + 1; + EEPROM_writeAnything(10, foldern); + + display_Clear(); + print_Msg(F("Saving as ")); + print_Msg(fileName); + println_Msg(F("...")); + display_Update(); + + // Open file on sd card + if (!myFile.open(fileName, O_RDWR | O_CREAT)) { + println_Msg(F("Can't create file on SD.")); + display_Update(); + while (1); + } + word d = 0; + for (unsigned long currWord = 0; currWord < flashSize / 2; currWord += 256) { + for (word c = 0; c < 256; c++) { + word myWord = readWord_Eprom(currWord + c); + // Split word into two bytes + // Right + sdBuffer[d + 1] = ((myWord >> 8 ) & 0xFF); + // Left + sdBuffer[d] = (myWord & 0xFF); + d += 2; + } + myFile.write(sdBuffer, 512); + d = 0; + } + + // Close the file: + myFile.close(); + println_Msg(F("Finished reading.")); + display_Update(); +} + +void write_Eprom() { + // Create filepath + sprintf(filePath, "%s/%s", filePath, fileName); + println_Msg(F("Flashing file ")); + println_Msg(filePath); + 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); + + int d = 0; + for (unsigned long currWord = 0; currWord < fileSize / 2; currWord += 256) { + // Fill SD buffer + myFile.read(sdBuffer, 512); + + // Blink led + if (currWord % 2048 == 0) + PORTB ^= (1 << 4); + + // Work through SD buffer + for (int c = 0; c < 256; c++) { + word myWord = ( ( sdBuffer[d + 1] & 0xFF ) << 8 ) | ( sdBuffer[d] & 0xFF ); + + // No need to write word if it's 0xFFFF + if (myWord != 0xFFFF) { + // Error counter + byte n = 0; + + // Presto III allows up to 25 rewrites per word + do { + // Write word + writeWord_Eprom(currWord + c, myWord); + // Check for fail + if (n == 25) { + print_Msg("Program Error 0x"); + println_Msg(currWord + c, HEX); + print_Msg("0x"); + print_Msg(readWord_Eprom(currWord + c), HEX); + print_Msg(" != 0x"); + println_Msg(myWord, HEX); + print_Error(F("Press button to reset"), true); + } + n++; + } + while (readWord_Eprom(currWord + c) != myWord); + } + d += 2; + } + d = 0; + } + // Close the file: + myFile.close(); + } + else { + println_Msg(F("Can't open file on SD.")); + display_Update(); + } +} + //****************************************** // End of File //******************************************