mirror of
https://github.com/sanni/cartreader.git
synced 2024-12-26 13:01:52 +01:00
V29A: Write first 0x7FFF bytes of GB Memory cart
Don't understand how to switch banks right now or more precise when to switch banks without killing off the buffered write sequence.
This commit is contained in:
parent
4bb76e01e2
commit
79346e3a51
@ -2,8 +2,8 @@
|
|||||||
Cartridge Reader for Arduino Mega2560
|
Cartridge Reader for Arduino Mega2560
|
||||||
|
|
||||||
Author: sanni
|
Author: sanni
|
||||||
Date: 2017-10-07
|
Date: 2017-10-11
|
||||||
Version: V28I
|
Version: V29A
|
||||||
|
|
||||||
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
|
||||||
@ -34,7 +34,7 @@
|
|||||||
YamaArashi - GBA flashrom bank switch command
|
YamaArashi - GBA flashrom bank switch command
|
||||||
|
|
||||||
**********************************************************************************/
|
**********************************************************************************/
|
||||||
char ver[5] = "V28I";
|
char ver[5] = "V29A";
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
Define Output
|
Define Output
|
||||||
|
@ -1464,60 +1464,84 @@ void write_SFM(int startBank, uint32_t pos) {
|
|||||||
Menu
|
Menu
|
||||||
*****************************************/
|
*****************************************/
|
||||||
// GBM menu items
|
// GBM menu items
|
||||||
static const char gbmMenuItem1[] PROGMEM = "Read Flash";
|
static const char gbmMenuItem1[] PROGMEM = "Read ID";
|
||||||
static const char gbmMenuItem2[] PROGMEM = "Read Mapping";
|
static const char gbmMenuItem2[] PROGMEM = "Read Flash";
|
||||||
static const char gbmMenuItem3[] PROGMEM = "Write Flash";
|
static const char gbmMenuItem3[] PROGMEM = "Erase Flash";
|
||||||
static const char gbmMenuItem4[] PROGMEM = "Write Mapping";
|
static const char gbmMenuItem4[] PROGMEM = "Blankcheck";
|
||||||
static const char* const menuOptionsGBM[] PROGMEM = {gbmMenuItem1, gbmMenuItem2, gbmMenuItem3, gbmMenuItem4};
|
static const char gbmMenuItem5[] PROGMEM = "Write Flash";
|
||||||
|
static const char gbmMenuItem6[] PROGMEM = "Read Mapping";
|
||||||
|
static const char gbmMenuItem7[] PROGMEM = "Write Mapping";
|
||||||
|
static const char* const menuOptionsGBM[] PROGMEM = {gbmMenuItem1, gbmMenuItem2, gbmMenuItem3, gbmMenuItem4, gbmMenuItem5, gbmMenuItem6, gbmMenuItem7};
|
||||||
|
|
||||||
void gbmMenu() {
|
void gbmMenu() {
|
||||||
// create menu with title and 4 options to choose from
|
// create menu with title and 7 options to choose from
|
||||||
unsigned char mainMenu;
|
unsigned char mainMenu;
|
||||||
// Copy menuOptions out of progmem
|
// Copy menuOptions out of progmem
|
||||||
convertPgm(menuOptionsGBM, 2);
|
convertPgm(menuOptionsGBM, 6);
|
||||||
mainMenu = question_box("GB Memory Menu", menuOptions, 2, 0);
|
mainMenu = question_box("GB Memory Menu", menuOptions, 6, 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)
|
||||||
{
|
{
|
||||||
// Read Flash
|
// Read Flash ID
|
||||||
case 0:
|
case 0:
|
||||||
|
// Clear screen
|
||||||
|
display_Clear();
|
||||||
|
readFlashID_GBM();
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Read Flash
|
||||||
|
case 1:
|
||||||
// Clear screen
|
// Clear screen
|
||||||
display_Clear();
|
display_Clear();
|
||||||
// Reset to root directory
|
// Reset to root directory
|
||||||
sd.chdir("/");
|
sd.chdir("/");
|
||||||
|
|
||||||
// Read flash
|
// Read flash
|
||||||
readFlash_GBM();
|
// Map entire flashrom
|
||||||
|
send_GBM(0x04);
|
||||||
|
// Disable ports 0x0120...
|
||||||
|
send_GBM(0x08);
|
||||||
|
// Read 1MB rom
|
||||||
|
readROM_GBM(64);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Read mapping
|
|
||||||
case 1:
|
|
||||||
// Clear screen
|
|
||||||
display_Clear();
|
|
||||||
|
|
||||||
// Reset to root directory
|
// Erase Flash
|
||||||
sd.chdir("/");
|
|
||||||
|
|
||||||
// Read mapping
|
|
||||||
readMapping_GBM();
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Write Flash
|
|
||||||
case 2:
|
case 2:
|
||||||
// Clear screen
|
// Clear screen
|
||||||
display_Clear();
|
display_Clear();
|
||||||
|
|
||||||
// Print warning
|
// Print warning
|
||||||
println_Msg(F("Attention"));
|
println_Msg(F("Attention"));
|
||||||
println_Msg(F("This will erase your"));
|
println_Msg(F("This will erase your"));
|
||||||
println_Msg(F("NP Cartridge."));
|
println_Msg(F("NP Cartridge."));
|
||||||
println_Msg("");
|
println_Msg("");
|
||||||
|
println_Msg("");
|
||||||
println_Msg(F("Press Button"));
|
println_Msg(F("Press Button"));
|
||||||
println_Msg(F("to continue"));
|
println_Msg(F("to continue"));
|
||||||
display_Update();
|
display_Update();
|
||||||
wait();
|
wait();
|
||||||
|
// Clear screen
|
||||||
|
display_Clear();
|
||||||
|
eraseFlash_GBM();
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Blankcheck Flash
|
||||||
|
case 3:
|
||||||
|
// Clear screen
|
||||||
|
display_Clear();
|
||||||
|
if (blankcheckFlash_GBM()) {
|
||||||
|
println_Msg(F("OK"));
|
||||||
|
display_Update();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
println_Msg(F("ERROR"));
|
||||||
|
display_Update();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Write Flash
|
||||||
|
case 4:
|
||||||
// Clear screen
|
// Clear screen
|
||||||
display_Clear();
|
display_Clear();
|
||||||
|
|
||||||
@ -1529,11 +1553,23 @@ void gbmMenu() {
|
|||||||
sprintf(filePath, "%s/%s", filePath, fileName);
|
sprintf(filePath, "%s/%s", filePath, fileName);
|
||||||
|
|
||||||
// Write rom
|
// Write rom
|
||||||
writeRom_GBM();
|
writeFlash_GBM();
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Read mapping
|
||||||
|
case 5:
|
||||||
|
// Clear screen
|
||||||
|
display_Clear();
|
||||||
|
|
||||||
|
// Reset to root directory
|
||||||
|
sd.chdir("/");
|
||||||
|
|
||||||
|
// Read mapping
|
||||||
|
readMapping_GBM();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Write mapping
|
// Write mapping
|
||||||
case 3:
|
case 6:
|
||||||
// Clear screen
|
// Clear screen
|
||||||
display_Clear();
|
display_Clear();
|
||||||
|
|
||||||
@ -1595,6 +1631,11 @@ void gbmMenu() {
|
|||||||
Setup
|
Setup
|
||||||
*****************************************/
|
*****************************************/
|
||||||
void setup_GBM() {
|
void setup_GBM() {
|
||||||
|
// Set RST(PH0) to Input
|
||||||
|
DDRH &= ~(1 << 0);
|
||||||
|
// Activate Internal Pullup Resistors
|
||||||
|
PORTH |= (1 << 0);
|
||||||
|
|
||||||
// Set Address Pins to Output
|
// Set Address Pins to Output
|
||||||
//A0-A7
|
//A0-A7
|
||||||
DDRF = 0xFF;
|
DDRF = 0xFF;
|
||||||
@ -1602,12 +1643,29 @@ void setup_GBM() {
|
|||||||
DDRK = 0xFF;
|
DDRK = 0xFF;
|
||||||
|
|
||||||
// Set Control Pins to Output RST(PH0) CS(PH3) WR(PH5) RD(PH6)
|
// Set Control Pins to Output RST(PH0) CS(PH3) WR(PH5) RD(PH6)
|
||||||
DDRH |= (1 << 0) | (1 << 3) | (1 << 5) | (1 << 6);
|
DDRH |= (1 << 3) | (1 << 5) | (1 << 6);
|
||||||
// Output a high signal on all pins, pins are active low therefore everything is disabled now
|
// Output a high signal on all pins, pins are active low therefore everything is disabled now
|
||||||
PORTH |= (1 << 0) | (1 << 3) | (1 << 5) | (1 << 6);
|
PORTH |= (1 << 3) | (1 << 5) | (1 << 6);
|
||||||
|
|
||||||
// Set Data Pins (D0-D7) to Input
|
// Set Data Pins (D0-D7) to Input
|
||||||
DDRC = 0x00;
|
DDRC = 0x00;
|
||||||
|
|
||||||
|
delay(400);
|
||||||
|
|
||||||
|
// Check for Nintendo Power GB Memory cart
|
||||||
|
byte timeout = 0;
|
||||||
|
|
||||||
|
// First byte of NP register is always 0x21
|
||||||
|
while (readByte_GBM(0x120) != 0x21) {
|
||||||
|
// Enable ports 0x120h (F2)
|
||||||
|
send_GBM(0x09);
|
||||||
|
__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""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||||
|
timeout++;
|
||||||
|
if (timeout > 10) {
|
||||||
|
println_Msg(F("Error: Time Out"));
|
||||||
|
print_Error(F("Please power cycle"), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
@ -1616,27 +1674,24 @@ void setup_GBM() {
|
|||||||
// Read one word out of the cartridge
|
// Read one word out of the cartridge
|
||||||
byte readByte_GBM(word myAddress) {
|
byte readByte_GBM(word myAddress) {
|
||||||
// Set data pins to Input
|
// Set data pins to Input
|
||||||
DDRC = 0x00;
|
DDRC = 0x0;
|
||||||
PORTF = myAddress & 0xFF;
|
PORTF = myAddress & 0xFF;
|
||||||
PORTK = (myAddress >> 8) & 0xFF;
|
PORTK = (myAddress >> 8) & 0xFF;
|
||||||
|
|
||||||
// Wait until all is stable
|
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||||
__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""nop\n\t""nop\n\t");
|
|
||||||
|
|
||||||
// Pull read(PH6) low
|
// Switch CS(PH3) and RD(PH6) to LOW
|
||||||
|
PORTH &= ~(1 << 3);
|
||||||
PORTH &= ~(1 << 6);
|
PORTH &= ~(1 << 6);
|
||||||
|
|
||||||
// Wait ~310ns
|
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||||
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
|
||||||
|
|
||||||
// Read
|
// Read
|
||||||
byte tempByte = PINC;
|
byte tempByte = PINC;
|
||||||
|
|
||||||
// Pull read(PH6) high
|
// Switch CS(PH3) and RD(PH6) to HIGH
|
||||||
PORTH |= (1 << 6);
|
PORTH |= (1 << 6);
|
||||||
|
PORTH |= (1 << 3);
|
||||||
// Wait
|
|
||||||
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
|
||||||
|
|
||||||
return tempByte;
|
return tempByte;
|
||||||
}
|
}
|
||||||
@ -1649,23 +1704,20 @@ void writeByte_GBM(word myAddress, byte myData) {
|
|||||||
PORTK = (myAddress >> 8) & 0xFF;
|
PORTK = (myAddress >> 8) & 0xFF;
|
||||||
PORTC = myData;
|
PORTC = myData;
|
||||||
|
|
||||||
// Wait until all is stable
|
// Pull CS(PH3) and write(PH5) low
|
||||||
__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""nop\n\t""nop\n\t");
|
PORTH &= ~(1 << 3);
|
||||||
|
|
||||||
// Pull write(PH5) low
|
|
||||||
PORTH &= ~(1 << 5);
|
PORTH &= ~(1 << 5);
|
||||||
|
|
||||||
// Wait ~310ns
|
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||||
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
|
||||||
|
|
||||||
// Pull write(PH5) high
|
// Pull CS(PH3) and write(PH5) high
|
||||||
PORTH |= (1 << 5);
|
PORTH |= (1 << 5);
|
||||||
|
PORTH |= (1 << 3);
|
||||||
|
|
||||||
// Wait ~125ns
|
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||||
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
|
||||||
|
|
||||||
// Set data pins to Input
|
// Set data pins to Input (or read errors??!)
|
||||||
DDRC = 0x00;
|
DDRC = 0x0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
@ -1739,6 +1791,12 @@ void readROM_GBM(word numBanks) {
|
|||||||
**********************/
|
**********************/
|
||||||
void send_GBM(byte myCommand) {
|
void send_GBM(byte myCommand) {
|
||||||
switch (myCommand) {
|
switch (myCommand) {
|
||||||
|
case 0x01:
|
||||||
|
//CMD_01h -> ???
|
||||||
|
writeByte_GBM(0x0120, 0x01);
|
||||||
|
writeByte_GBM(0x013F, 0xA5);
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x02:
|
case 0x02:
|
||||||
//CMD_02h -> Write enable Step 2
|
//CMD_02h -> Write enable Step 2
|
||||||
writeByte_GBM(0x0120, 0x02);
|
writeByte_GBM(0x0120, 0x02);
|
||||||
@ -1803,95 +1861,92 @@ void send_GBM(byte myCommand) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CMD_0Fh -> Write address/byte to flash
|
void send_GBM(byte myCommand, word myAddress, byte myData) {
|
||||||
void send_Flash(word myAddress, byte myData) {
|
|
||||||
byte myAddrLow = myAddress & 0xFF;
|
byte myAddrLow = myAddress & 0xFF;
|
||||||
byte myAddrHigh = (myAddress >> 8) & 0xFF;
|
byte myAddrHigh = (myAddress >> 8) & 0xFF;
|
||||||
// Bank must be 0x01 for writes to 0x5555
|
|
||||||
|
switch (myCommand) {
|
||||||
|
case 0x0F:
|
||||||
|
// CMD_0Fh -> Write address/byte to flash
|
||||||
writeByte_GBM(0x0120, 0x0F);
|
writeByte_GBM(0x0120, 0x0F);
|
||||||
writeByte_GBM(0x0125, myAddrHigh);
|
writeByte_GBM(0x0125, myAddrHigh);
|
||||||
writeByte_GBM(0x0126, myAddrLow);
|
writeByte_GBM(0x0126, myAddrLow);
|
||||||
writeByte_GBM(0x0127, myData);
|
writeByte_GBM(0x0127, myData);
|
||||||
writeByte_GBM(0x013F, 0xA5);
|
writeByte_GBM(0x013F, 0xA5);
|
||||||
}
|
break;
|
||||||
|
|
||||||
// Enable NP ports 0x0120...
|
default:
|
||||||
boolean wakeup_GBM() {
|
print_Error(F("Unknown Command"), true);
|
||||||
byte timeout = 0;
|
break;
|
||||||
|
|
||||||
// First byte of NP register is always 0x21
|
|
||||||
while (readByte_GBM(0x0120) != 0x21) {
|
|
||||||
send_GBM(0x09);
|
|
||||||
__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""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
|
||||||
timeout++;
|
|
||||||
if (timeout > 10) {
|
|
||||||
println_Msg(F("Error: Time Out"));
|
|
||||||
print_Error(F("Please power cycle"), true);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void switchGame_GBM(byte myData) {
|
void switchGame_GBM(byte myData) {
|
||||||
// Enable ports 0x0120...
|
// Enable ports 0x0120 (F2)
|
||||||
wakeup_GBM();
|
send_GBM(0x09);
|
||||||
|
|
||||||
//CMD_C0h -> map selected game without reset
|
//CMD_C0h -> map selected game without reset
|
||||||
writeByte_GBM(0x0120, 0xC0 & myData);
|
writeByte_GBM(0x0120, 0xC0 & myData);
|
||||||
writeByte_GBM(0x013F, 0xA5);
|
writeByte_GBM(0x013F, 0xA5);
|
||||||
}
|
}
|
||||||
|
|
||||||
void enableWrite_GBM() {
|
|
||||||
send_GBM(0x0A);
|
|
||||||
send_GBM(0x02);
|
|
||||||
}
|
|
||||||
|
|
||||||
void resetFlash_GBM() {
|
void resetFlash_GBM() {
|
||||||
// Enable ports 0x0120...
|
// Enable ports 0x0120 (F2)
|
||||||
wakeup_GBM();
|
send_GBM(0x09);
|
||||||
|
|
||||||
// Send reset command
|
// Send reset command
|
||||||
writeByte_GBM(0x2100, 0x01);
|
writeByte_GBM(0x2100, 0x01);
|
||||||
send_Flash(0x5555, 0xAA);
|
send_GBM(0x0F, 0x5555, 0xAA);
|
||||||
send_Flash(0x2AAA, 0x55);
|
send_GBM(0x0F, 0x2AAA, 0x55);
|
||||||
send_Flash(0x5555, 0xF0);
|
send_GBM(0x0F, 0x5555, 0xF0);
|
||||||
delay(100);
|
delay(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean readFlashID_GBM() {
|
boolean readFlashID_GBM() {
|
||||||
|
// Enable ports 0x0120 (F2)
|
||||||
|
send_GBM(0x09);
|
||||||
|
|
||||||
writeByte_GBM(0x2100, 0x01);
|
writeByte_GBM(0x2100, 0x01);
|
||||||
// Read ID command
|
// Read ID command
|
||||||
send_Flash(0x5555, 0xAA);
|
send_GBM(0x0F, 0x5555, 0xAA);
|
||||||
send_Flash(0x2AAA, 0x55);
|
send_GBM(0x0F, 0x2AAA, 0x55);
|
||||||
send_Flash(0x5555, 0x90);
|
send_GBM(0x0F, 0x5555, 0x90);
|
||||||
|
|
||||||
// Read the two id bytes into a string
|
// Read the two id bytes into a string
|
||||||
sprintf(flashid, "%02X%02X", readByte_GBM(0), readByte_GBM(1));
|
sprintf(flashid, "%02X%02X", readByte_GBM(0), readByte_GBM(1));
|
||||||
if (strcmp(flashid, "C289") == 0) {
|
if (strcmp(flashid, "C289") == 0) {
|
||||||
|
print_Msg(F("Flash ID: "));
|
||||||
|
println_Msg(flashid);
|
||||||
|
display_Update();
|
||||||
|
resetFlash_GBM();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
print_Msg(F("Flash ID: "));
|
||||||
println_Msg(flashid);
|
println_Msg(flashid);
|
||||||
print_Error(F("Unknown Flash ID"), true);
|
print_Error(F("Unknown Flash ID"), true);
|
||||||
|
resetFlash_GBM();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void readMapping_GBM() {
|
void readMapping_GBM() {
|
||||||
// Enable ports 0x0120...
|
// Enable ports 0x0120 (F2)
|
||||||
wakeup_GBM();
|
send_GBM(0x09);
|
||||||
|
|
||||||
// Set WE and WP
|
// Set WE and WP (F4)
|
||||||
enableWrite_GBM();
|
send_GBM(0x0A);
|
||||||
|
send_GBM(0x1);
|
||||||
|
send_GBM(0x2);
|
||||||
|
|
||||||
// Enable hidden mapping area
|
// Enable hidden mapping area
|
||||||
writeByte_GBM(0x2100, 0x01);
|
writeByte_GBM(0x2100, 0x01);
|
||||||
send_Flash(0x5555, 0xAA);
|
send_GBM(0x0F, 0x5555, 0xAA);
|
||||||
send_Flash(0x2AAA, 0x55);
|
send_GBM(0x0F, 0x2AAA, 0x55);
|
||||||
send_Flash(0x5555, 0x77);
|
send_GBM(0x0F, 0x5555, 0x77);
|
||||||
send_Flash(0x5555, 0xAA);
|
send_GBM(0x0F, 0x5555, 0xAA);
|
||||||
send_Flash(0x2AAA, 0x55);
|
send_GBM(0x0F, 0x2AAA, 0x55);
|
||||||
send_Flash(0x5555, 0x77);
|
send_GBM(0x0F, 0x5555, 0x77);
|
||||||
|
|
||||||
// Read mapping
|
// Read mapping
|
||||||
println_Msg(F("Reading Mapping..."));
|
println_Msg(F("Reading Mapping..."));
|
||||||
@ -1933,62 +1988,52 @@ void readMapping_GBM() {
|
|||||||
resetFlash_GBM();
|
resetFlash_GBM();
|
||||||
}
|
}
|
||||||
|
|
||||||
void readFlash_GBM() {
|
|
||||||
// Enable ports 0x0120...
|
|
||||||
wakeup_GBM();
|
|
||||||
|
|
||||||
// Check flashid
|
|
||||||
if (readFlashID_GBM()) {
|
|
||||||
// Reset flashrom to leave flashID area and switch to output
|
|
||||||
resetFlash_GBM();
|
|
||||||
// Map entire flashrom
|
|
||||||
send_GBM(0x04);
|
|
||||||
// Disable ports 0x0120...
|
|
||||||
send_GBM(0x08);
|
|
||||||
// Read 1MB rom
|
|
||||||
readROM_GBM(64);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print_Error(F("Flash ID error"), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void eraseFlash_GBM() {
|
void eraseFlash_GBM() {
|
||||||
// Enable ports 0x0120...
|
println_Msg(F("Erasing..."));
|
||||||
wakeup_GBM();
|
display_Update();
|
||||||
|
|
||||||
// Set WE and WP
|
//enable access to ports 0120h (F2)
|
||||||
enableWrite_GBM();
|
send_GBM(0x09);
|
||||||
|
// Enable write (F4)
|
||||||
|
send_GBM(0x0A);
|
||||||
|
send_GBM(0x1);
|
||||||
|
send_GBM(0x2);
|
||||||
|
|
||||||
// Unprotect sector 0
|
// Unprotect sector 0
|
||||||
writeByte_GBM(0x2100, 0x01);
|
send_GBM(0x0F, 0x5555, 0xAA);
|
||||||
send_Flash(0x5555, 0xAA);
|
send_GBM(0x0F, 0x2AAA, 0x55);
|
||||||
send_Flash(0x2AAA, 0x55);
|
send_GBM(0x0F, 0x5555, 0x60);
|
||||||
send_Flash(0x5555, 0x60);
|
send_GBM(0x0F, 0x5555, 0xAA);
|
||||||
send_Flash(0x5555, 0xAA);
|
send_GBM(0x0F, 0x2AAA, 0x55);
|
||||||
send_Flash(0x2AAA, 0x55);
|
send_GBM(0x0F, 0x5555, 0x40);
|
||||||
writeByte_GBM(0x2100, 0x0);
|
|
||||||
send_Flash(0x0000, 0x40);
|
// Wait for unprotect to complete
|
||||||
|
while ((readByte_GBM(0) & 0x80) != 0x80) {}
|
||||||
|
|
||||||
// Send erase command
|
// Send erase command
|
||||||
writeByte_GBM(0x2100, 0x01);
|
send_GBM(0x0F, 0x5555, 0xaa);
|
||||||
send_Flash(0x5555, 0xaa);
|
send_GBM(0x0F, 0x2AAA, 0x55);
|
||||||
send_Flash(0x2AAA, 0x55);
|
send_GBM(0x0F, 0x5555, 0x80);
|
||||||
send_Flash(0x5555, 0x80);
|
send_GBM(0x0F, 0x5555, 0xaa);
|
||||||
send_Flash(0x5555, 0xaa);
|
send_GBM(0x0F, 0x2AAA, 0x55);
|
||||||
send_Flash(0x2AAA, 0x55);
|
send_GBM(0x0F, 0x5555, 0x10);
|
||||||
send_Flash(0x5555, 0x10);
|
|
||||||
|
|
||||||
// Wait for erase to complete
|
// Wait for erase to complete
|
||||||
while ((readByte_GBM(0) & 0x80) != 0x80) {
|
while ((readByte_GBM(0) & 0x80) != 0x80) {}
|
||||||
}
|
|
||||||
|
// Reset flashrom
|
||||||
|
resetFlash_GBM();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean blankcheckFlash_GBM() {
|
boolean blankcheckFlash_GBM() {
|
||||||
// Reset flashrom
|
print_Msg(F("Blankcheck..."));
|
||||||
resetFlash_GBM();
|
display_Update();
|
||||||
|
|
||||||
|
//enable access to ports 0120h (F2)
|
||||||
|
send_GBM(0x09);
|
||||||
|
|
||||||
// Map entire flashrom
|
// Map entire flashrom
|
||||||
//send_GBM(0x04);
|
send_GBM(0x04);
|
||||||
// Disable ports 0x0120...
|
// Disable ports 0x0120...
|
||||||
send_GBM(0x08);
|
send_GBM(0x08);
|
||||||
|
|
||||||
@ -2014,50 +2059,90 @@ boolean blankcheckFlash_GBM() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void writeFlash_GBM() {
|
void writeFlash_GBM() {
|
||||||
|
print_Msg(F("Writing..."));
|
||||||
|
display_Update();
|
||||||
|
|
||||||
// Open file on sd card
|
// Open file on sd card
|
||||||
if (myFile.open(filePath, O_READ)) {
|
if (myFile.open(filePath, O_READ)) {
|
||||||
// Get rom size from file
|
// Get rom size from file
|
||||||
fileSize = myFile.fileSize();
|
fileSize = myFile.fileSize();
|
||||||
|
if ((fileSize / 0x4000) > 64) {
|
||||||
for (unsigned long currBuffer = 0; currBuffer < fileSize; currBuffer += 128) {
|
print_Error(F("File is too big."), true);
|
||||||
// Fill SD buffer
|
|
||||||
myFile.read(sdBuffer, 128);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//enable access to ports 0120h
|
||||||
|
send_GBM(0x09);
|
||||||
|
// Enable write
|
||||||
|
send_GBM(0x0A);
|
||||||
|
send_GBM(0x2);
|
||||||
|
|
||||||
|
// Map entire flash rom
|
||||||
|
send_GBM(0x4);
|
||||||
|
|
||||||
|
// Set bank for unprotect later on, writes to 0x5555 need odd bank number
|
||||||
|
writeByte_GBM(0x2100, 0x1);
|
||||||
|
|
||||||
|
// disable ports 0x2100 and 0x120 or else addresses will not be writable
|
||||||
|
send_GBM(0x10);
|
||||||
|
send_GBM(0x08);
|
||||||
|
|
||||||
|
// Unprotect sector 0
|
||||||
|
writeByte_GBM(0x5555, 0xAA);
|
||||||
|
writeByte_GBM(0x2AAA, 0x55);
|
||||||
|
writeByte_GBM(0x5555, 0x60);
|
||||||
|
writeByte_GBM(0x5555, 0xAA);
|
||||||
|
writeByte_GBM(0x2AAA, 0x55);
|
||||||
|
writeByte_GBM(0x5555, 0x40);
|
||||||
|
|
||||||
|
// Check if flashrom is ready for writing or busy
|
||||||
|
while ((readByte_GBM(0) & 0x80) != 0x80) {}
|
||||||
|
|
||||||
|
// first bank: 0x0000-0x7FFF,
|
||||||
|
word currAddress = 0x0;
|
||||||
|
|
||||||
|
// only write the first bank for now as bank switching doesn't work yet
|
||||||
|
for (word currBank = 0x1; currBank < 0x2; currBank++) {
|
||||||
|
// Blink Led
|
||||||
|
PORTB ^= (1 << 4);
|
||||||
|
|
||||||
|
// all following banks: 0x4000-0x7FFF
|
||||||
|
if (currBank > 1) {
|
||||||
|
currAddress = 0x4000;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write one bank
|
||||||
|
for (; currAddress < 0x7FFF; currAddress += 128) {
|
||||||
|
// Fill SD buffer
|
||||||
|
myFile.read(sdBuffer, 128);
|
||||||
|
|
||||||
|
// Write flash buffer command
|
||||||
|
writeByte_GBM(0x5555, 0xAA);
|
||||||
|
writeByte_GBM(0x2AAA, 0x55);
|
||||||
|
writeByte_GBM(0x5555, 0xA0);
|
||||||
|
|
||||||
|
// Fill flash buffer
|
||||||
|
for (word currByte = 0; currByte < 128; currByte++) {
|
||||||
|
writeByte_GBM(currAddress + currByte, sdBuffer[currByte]);
|
||||||
|
}
|
||||||
|
// Execute write
|
||||||
|
writeByte_GBM(currAddress + 127, 0xFF);
|
||||||
|
|
||||||
|
// Wait for write to complete
|
||||||
|
while ((readByte_GBM(0) & 0x80) != 0x80) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
// Close the file:
|
// Close the file:
|
||||||
myFile.close();
|
myFile.close();
|
||||||
|
|
||||||
|
// Reset flashrom
|
||||||
|
resetFlash_GBM();
|
||||||
|
println_Msg(F("Done"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
print_Error(F("Can't open file"), false);
|
print_Error(F("Can't open file"), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeRom_GBM() {
|
|
||||||
// Enable ports 0x0120...
|
|
||||||
wakeup_GBM();
|
|
||||||
|
|
||||||
// Check flashid
|
|
||||||
if (readFlashID_GBM()) {
|
|
||||||
// Reset flashrom to leave flashID area and switch to output
|
|
||||||
resetFlash_GBM();
|
|
||||||
// Erase flash
|
|
||||||
print_Msg(F("Erasing..."));
|
|
||||||
display_Update();
|
|
||||||
eraseFlash_GBM();
|
|
||||||
if (blankcheckFlash_GBM()) {
|
|
||||||
println_Msg(F("Ok"));
|
|
||||||
display_Update();
|
|
||||||
writeFlash_GBM();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print_Error(F("Erase failed"), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print_Error(F("Flash ID error"), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void eraseMapping_GBM() {
|
void eraseMapping_GBM() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user