cartreader/Cart_Reader/FLASH.ino
sanni cfb9e39cbf V4.9: Improve WS Initialization
Thanks to skaman.
The code does a deeper sanity check of the header data when initializing the cart.  It avoids having to constantly press buttons to reinit the cart.  Carts can still not initialize the MBC properly but that's normal for the WonderSwan.  Clean the pins on the cart and check that the cart and adapter are seated properly.  If the cart doesn't unlock immediately, then let the sketch run for a bit.  For stubborn carts, a power cycle might be necessary.
The sketch fixes a few typos, removes some trailing spaces, and adds another ROM size (used by Benesse Pocket Challenge V2 carts).
2020-04-20 10:35:48 +02:00

2376 lines
60 KiB
C++

//******************************************
// FLASHROM MODULE
//******************************************
/******************************************
Variables
*****************************************/
// Flashrom
unsigned long flashSize;
byte flashromType;
byte secondID = 1;
unsigned long time;
unsigned long blank;
unsigned long sectorSize;
uint16_t bufferSize;
boolean hiROM = 1;
/******************************************
Menu
*****************************************/
// Flash start menu
static const char flashMenuItem1[] PROGMEM = "8bit Flash adapter";
static const char flashMenuItem2[] PROGMEM = "Eprom adapter";
static const char flashMenuItem3[] PROGMEM = "MX26L6420 adapter";
static const char flashMenuItem4[] PROGMEM = "Reset";
static const char* const menuOptionsFlash[] PROGMEM = {flashMenuItem1, flashMenuItem2, flashMenuItem3, flashMenuItem4};
// 8bit Flash menu items
static const char flash8MenuItem1[] PROGMEM = "Blankcheck";
static const char flash8MenuItem2[] PROGMEM = "Erase";
static const char flash8MenuItem3[] PROGMEM = "Read";
static const char flash8MenuItem4[] PROGMEM = "Write";
static const char flash8MenuItem5[] PROGMEM = "ID";
static const char flash8MenuItem6[] PROGMEM = "Print";
static const char flash8MenuItem7[] PROGMEM = "Reset";
static const char* const menuOptionsFLASH8[] PROGMEM = {flash8MenuItem1, flash8MenuItem2, flash8MenuItem3, flash8MenuItem4, flash8MenuItem5, flash8MenuItem6, flash8MenuItem7};
// 16bit Flash menu items
static const char flash16MenuItem1[] PROGMEM = "Blankcheck";
static const char flash16MenuItem2[] PROGMEM = "Erase";
static const char flash16MenuItem3[] PROGMEM = "Read";
static const char flash16MenuItem4[] PROGMEM = "Write";
static const char flash16MenuItem5[] PROGMEM = "ID";
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";
static const char epromMenuItem3[] PROGMEM = "Write";
static const char epromMenuItem4[] PROGMEM = "Verify";
static const char epromMenuItem5[] PROGMEM = "Print";
static const char epromMenuItem6[] PROGMEM = "Reset";
static const char* const menuOptionsEprom[] PROGMEM = {epromMenuItem1, epromMenuItem2, epromMenuItem3, epromMenuItem4, epromMenuItem5, epromMenuItem6};
void flashMenu() {
// create menu with title and 3 options to choose from
unsigned char flashSlot;
// Copy menuOptions out of progmem
convertPgm(menuOptionsFlash, 4);
flashSlot = question_box(F("Select adapter PCB"), menuOptions, 4, 0);
// wait for user choice to come back from the question box menu
switch (flashSlot)
{
case 0:
display_Clear();
display_Update();
hiROM = 1;
setup_Flash8();
id_Flash8();
wait();
mode = mode_FLASH8;
break;
case 1:
display_Clear();
display_Update();
setup_Eprom();
mode = mode_EPROM;
break;
case 2:
display_Clear();
display_Update();
setup_Flash16();
id_Flash16();
wait();
mode = mode_FLASH16;
break;
case 3:
resetArduino();
break;
}
}
void flashromMenu8() {
// create menu with title and 7 options to choose from
unsigned char mainMenu;
// Copy menuOptions out of progmem
convertPgm(menuOptionsFLASH8, 7);
mainMenu = question_box(F("Flashrom Writer 8"), menuOptions, 7, 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();
resetFlash8();
blankcheck_Flash();
break;
case 1:
display_Clear();
println_Msg(F("Erasing Flashrom"));
println_Msg(F("Please wait..."));
display_Update();
time = millis();
switch (flashromType) {
case 1: eraseFlash29F032(); break;
case 2: eraseFlash29F1610(); break;
case 3: eraseFlash28FXXX(); break;
}
println_Msg(F("Flashrom erased"));
display_Update();
resetFlash8();
break;
case 2:
time = millis();
resetFlash8();
readFlash();
break;
case 3:
filePath[0] = '\0';
sd.chdir("/");
fileBrowser(F("Select file"));
display_Clear();
time = millis();
switch (flashromType) {
case 1:
writeFlash29F032();
break;
case 2:
if (strcmp(flashid, "C2F3") == 0)
writeFlash29F1601();
else if ((strcmp(flashid, "C2F1") == 0) || (strcmp(flashid, "C2F9") == 0))
writeFlash29F1610();
else if ((strcmp(flashid, "C2C4") == 0) || (strcmp(flashid, "C249") == 0) ||
(strcmp(flashid, "C2A7") == 0) || (strcmp(flashid, "C2A8") == 0) ||
(strcmp(flashid, "C2C9") == 0) || (strcmp(flashid, "C2CB") == 0))
writeFlash29LV640();
else if (strcmp(flashid, "017E") == 0) {
// sector size, write buffer size
writeFlash29GL(sectorSize, bufferSize);
}
else if ((strcmp(flashid, "0458") == 0) || (strcmp(flashid, "0158") == 0) ||
(strcmp(flashid, "01AB") == 0))
writeFlash29F800();
break;
case 3:
writeFlash28FXXX();
break;
}
delay(100);
// Reset twice just to be sure
resetFlash8();
resetFlash8();
verifyFlash();
break;
case 4:
time = 0;
display_Clear();
println_Msg(F("ID Flashrom"));
switch (flashromType) {
case 1: idFlash29F032(); break;
case 2: idFlash29F1610(); break;
case 3: idFlash28FXXX(); break;
}
println_Msg(F(""));
printFlash(40);
println_Msg(F(""));
display_Update();
resetFlash8();
break;
case 5:
time = 0;
display_Clear();
println_Msg(F("Print first 70Bytes"));
display_Update();
resetFlash8();
printFlash(70);
break;
case 6:
time = 0;
display_Clear();
display_Update();
resetFlash8();
resetArduino();
break;
}
if (time != 0) {
print_Msg(F("Operation took : "));
print_Msg((millis() - time) / 1000, DEC);
println_Msg(F("s"));
display_Update();
}
print_Msg(F("Press Button..."));
display_Update();
wait();
}
void flashromMenu16() {
// create menu with title "Flashrom Writer 16" and 7 options to choose from
unsigned char mainMenu;
// Copy menuOptions out of progmem
convertPgm(menuOptionsFLASH16, 7);
mainMenu = question_box(F("Flashrom Writer 16"), menuOptions, 7, 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();
resetFlash16();
blankcheck16();
break;
case 1:
display_Clear();
println_Msg(F("Erase Flashrom"));
display_Update();
time = millis();
resetFlash16();
eraseFlash16();
println_Msg(F("Flashrom erased."));
display_Update();
break;
case 2:
display_Clear();
time = millis();
resetFlash16();
readFlash16();
break;
case 3:
filePath[0] = '\0';
sd.chdir("/");
fileBrowser(F("Select file"));
display_Clear();
time = millis();
if (strcmp(flashid, "C2F3") == 0) {
writeFlash16_29F1601();
}
else if ((strcmp(flashid, "C2C4") == 0) || (strcmp(flashid, "C249") == 0) || (strcmp(flashid, "C2A7") == 0) || (strcmp(flashid, "C2A8") == 0) || (strcmp(flashid, "C2C9") == 0) || (strcmp(flashid, "C2CB") == 0) || (strcmp(flashid, "C2FC") == 0)) {
writeFlash16_29LV640();
}
else {
writeFlash16();
}
delay(100);
resetFlash16();
delay(100);
verifyFlash16();
break;
case 4:
time = 0;
display_Clear();
println_Msg(F("ID Flashrom"));
idFlash16();
println_Msg(F(""));
printFlash16(40);
println_Msg(F(""));
display_Update();
resetFlash16();
break;
case 5:
time = 0;
display_Clear();
println_Msg(F("Print first 70Bytes"));
display_Update();
resetFlash16();
printFlash16(70);
break;
case 6:
time = 0;
display_Clear();
display_Update();
resetFlash16();
resetArduino();
break;
}
if (time != 0) {
print_Msg(F("Operation took: "));
print_Msg((millis() - time) / 1000, DEC);
println_Msg("s");
display_Update();
}
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, 6);
mainMenu = question_box(F("Eprom Writer"), menuOptions, 6, 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(F("Select file"));
display_Clear();
time = millis();
write_Eprom();
delay(1000);
verify_Eprom();
break;
case 3:
filePath[0] = '\0';
sd.chdir("/");
fileBrowser(F("Verify against"));
sprintf(filePath, "%s/%s", filePath, fileName);
display_Clear();
time = millis();
verify_Eprom();
break;
case 4:
display_Clear();
time = millis();
print_Eprom(80);
break;
case 5:
time = 0;
display_Clear();
display_Update();
resetArduino();
break;
}
if (time != 0) {
print_Msg(F("Operation took: "));
print_Msg((millis() - time) / 1000, DEC);
println_Msg("s");
display_Update();
}
wait();
}
/******************************************
Flash IDs
*****************************************/
void id_Flash8() {
// ID flash
idFlash29F032();
// Print start screen
idtheflash:
display_Clear();
display_Update();
println_Msg(F("Flashrom Writer 8bit"));
println_Msg(" ");
println_Msg(" ");
print_Msg(F("Flash ID: "));
println_Msg(flashid);
if (strcmp(flashid, "C2F1") == 0) {
println_Msg(F("MX29F1610 detected"));
flashSize = 2097152;
flashromType = 2;
}
else if (strcmp(flashid, "C2F3") == 0) {
println_Msg(F("MX29F1601 detected"));
flashSize = 2097152;
flashromType = 2;
}
else if (strcmp(flashid, "C2F9") == 0) {
println_Msg(F("MX29L3211 detected"));
println_Msg(F("ATTENTION 3.3V"));
flashSize = 4194304;
flashromType = 2;
}
else if ((strcmp(flashid, "C2C4") == 0) || (strcmp(flashid, "C249") == 0)) {
println_Msg(F("MX29LV160 detected"));
println_Msg(F("ATTENTION 3.3V"));
flashSize = 2097152;
flashromType = 2;
}
else if ((strcmp(flashid, "C2A7") == 0) || (strcmp(flashid, "C2A8") == 0)) {
println_Msg(F("MX29LV320 detected"));
println_Msg(F("ATTENTION 3.3V"));
flashSize = 4194304;
flashromType = 2;
}
else if ((strcmp(flashid, "C2C9") == 0) || (strcmp(flashid, "C2CB") == 0)) {
println_Msg(F("MX29LV640 detected"));
println_Msg(F("ATTENTION 3.3V"));
flashSize = 8388608;
flashromType = 2;
}
else if (strcmp(flashid, "0141") == 0) {
println_Msg(F("AM29F032B detected"));
flashSize = 4194304;
flashromType = 1;
}
else if (strcmp(flashid, "01AD") == 0) {
println_Msg(F("AM29F016B detected"));
flashSize = 2097152;
flashromType = 1;
}
else if (strcmp(flashid, "20AD") == 0) {
println_Msg(F("AM29F016D detected"));
flashSize = 2097152;
flashromType = 1;
}
else if (strcmp(flashid, "04AD") == 0) {
println_Msg(F("AM29F016D detected"));
flashSize = 2097152;
flashromType = 1;
}
else if (strcmp(flashid, "04D4") == 0) {
println_Msg(F("MBM29F033C detected"));
flashSize = 4194304;
flashromType = 1;
}
else if (strcmp(flashid, "0458") == 0) {
println_Msg(F("MBM29F800BA detected"));
flashSize = 1048576;
flashromType = 2;
}
else if (strcmp(flashid, "01AB") == 0) {
println_Msg(F("AM29F400AB detected"));
flashSize = 131072 * 4;
flashromType = 2;
}
else if (strcmp(flashid, "0158") == 0) {
println_Msg(F("AM29F800BB detected"));
flashSize = 1048576;
flashromType = 2;
}
else if (strcmp(flashid, "01A3") == 0) {
println_Msg(F("AM29LV033C detected"));
flashSize = 131072 * 32;
flashromType = 1;
}
else if (strcmp(flashid, "017E") == 0) {
// S29GL032M
if (readByte_Flash(28) == 0x1A) {
println_Msg(F("S29GL032M detected"));
flashSize = 4194304;
sectorSize = 65536;
bufferSize = 32;
}
// Unknown S29GL type
else {
println_Msg(F("Unknown S29GL Type"));
flashSize = 4194304;
sectorSize = 65536;
bufferSize = 32;
}
println_Msg(F("ATTENTION 3.3V"));
flashromType = 2;
}
else if (strcmp(flashid, "B088") == 0) {
// LH28F016SUT
println_Msg(F("LH28F016SUT detected"));
println_Msg(F("ATTENTION 3/5 setting"));
flashSize = 2097152;
sectorSize = 65536;
bufferSize = 256;
flashromType = 3;
}
else if ((strcmp(flashid, "8916") == 0) ||
(strcmp(flashid, "8917") == 0) ||
(strcmp(flashid, "8918") == 0)) {
// E28FXXXJ3A
print_Msg(F("E28F"));
switch (flashid[3]) {
case '6':
flashSize = 131072 * 32;
print_Msg(F("320"));
break;
case '7':
flashSize = 131072 * 64;
print_Msg(F("640"));
break;
case '8':
flashSize = 131072 * 128;
print_Msg(F("128"));
break;
}
println_Msg(F("J3A detected"));
sectorSize = 131072;
bufferSize = 32;
flashromType = 3;
}
else if (secondID == 1) {
// Backup first ID read-out
strncpy(vendorID, flashid, 5);
// Read ID a second time using a different command
idFlash29F1610();
secondID = 2;
goto idtheflash;
}
else if (secondID == 2) {
// test if 28FXXX series flash
idFlash28FXXX();
secondID = 0;
goto idtheflash;
}
else {
// ID not found
display_Clear();
println_Msg(F("Flashrom Writer 8bit"));
println_Msg(" ");
print_Msg(F("ID Type 1: "));
println_Msg(vendorID);
print_Msg(F("ID Type 2: "));
println_Msg(flashid);
println_Msg(" ");
print_Error(F("UNKNOWN FLASHROM"), true);
}
println_Msg(" ");
println_Msg(F("Press Button..."));
display_Update();
resetFlash8();
}
void id_Flash16() {
// ID flash
idFlash16();
resetFlash16();
println_Msg(F("Flashrom Writer 16bit"));
println_Msg(" ");
print_Msg(F("Flash ID: "));
println_Msg(flashid);
if (strcmp(flashid, "C2F1") == 0) {
println_Msg(F("MX29F1610 detected"));
println_Msg(" ");
flashSize = 2097152;
flashromType = 2;
}
else if (strcmp(flashid, "C2F3") == 0) {
println_Msg(F("MX29F1601 detected"));
flashSize = 2097152;
flashromType = 2;
}
else if (strcmp(flashid, "C2F9") == 0) {
println_Msg(F("MX29L3211 detected"));
println_Msg(F("ATTENTION 3.3V"));
flashSize = 4194304;
flashromType = 2;
}
else if ((strcmp(flashid, "C2C4") == 0) || (strcmp(flashid, "C249") == 0)) {
println_Msg(F("MX29LV160 detected"));
println_Msg(F("ATTENTION 3.3V"));
flashSize = 2097152;
flashromType = 2;
}
else if ((strcmp(flashid, "C2A7") == 0) || (strcmp(flashid, "C2A8") == 0)) {
println_Msg(F("MX29LV320 detected"));
println_Msg(F("ATTENTION 3.3V"));
flashSize = 4194304;
flashromType = 2;
}
else if ((strcmp(flashid, "C2C9") == 0) || (strcmp(flashid, "C2CB") == 0)) {
println_Msg(F("MX29LV640 detected"));
println_Msg(F("ATTENTION 3.3V"));
flashSize = 8388608;
flashromType = 2;
}
else if (strcmp(flashid, "C2FC") == 0) {
println_Msg(F("MX26L6420 detected"));
println_Msg(F("ATTENTION 3.3V"));
flashSize = 8388608;
flashromType = 2;
}
else {
print_Error(F("Unknown flashrom"), true);
println_Msg(" ");
}
println_Msg(" ");
println_Msg(F("Press Button..."));
display_Update();
}
/******************************************
Setup
*****************************************/
void setup_Flash8() {
// Set Address Pins to Output
//A0-A7
DDRF = 0xFF;
//A8-A15
DDRK = 0xFF;
//A16-A23
DDRL = 0xFF;
// Set Control Pins to Output RST(PH0) OE(PH1) OE_SNS(PH3) WE(PH4) WE_SNS(PH5) CE(PH6)
DDRH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
// Setting RST(PH0) OE(PH1) OE_SNS(PH3) WE(PH4) WE_SNS(PH5) HIGH
PORTH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5);
// Setting CE(PH6) LOW
PORTH &= ~(1 << 6);
// Set Data Pins (D0-D7) to Input
DDRC = 0x00;
// Disable Internal Pullups
PORTC = 0x00;
}
void setup_Flash16() {
// Set Address Pins to Output
//A0-A7
DDRF = 0xFF;
//A8-A15
DDRK = 0xFF;
//A16-A23
DDRL = 0xFF;
// Set Control Pins to Output RST(PH0) OE(PH1) BYTE(PH3) WE(PH4) WP(PH5) CE(PH6)
DDRH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
// Set Data Pins (D0-D15) to Input
DDRC = 0x00;
DDRA = 0x00;
// Disable Internal Pullups
PORTC = 0x00;
PORTA = 0x00;
// Setting RST(PH0) OE(PH1) BYTE(PH3) WE(PH4) WP(PH5) HIGH
PORTH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5);
// Setting CE(PH6) LOW
PORTH &= ~(1 << 6);
delay(100);
}
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
*****************************************/
// Switch data pins to read
void dataIn8() {
// Set to Input
DDRC = 0x00;
}
// Switch data pins to write
void dataOut16() {
DDRC = 0xFF;
DDRA = 0xFF;
}
// Switch data pins to read
void dataIn16() {
DDRC = 0x00;
DDRA = 0x00;
}
/******************************************
Low level functions
*****************************************/
void writeByte_Flash(unsigned long myAddress, byte myData) {
PORTF = myAddress & 0xFF;
if (hiROM) {
PORTK = (myAddress >> 8) & 0xFF;
PORTL = (myAddress >> 16) & 0xFF;
}
else {
PORTK = (myAddress >> 8) & 0x7F;
// Set A15(PK7) HIGH to disable SRAM
PORTK |= (1 << 7);
PORTL = (myAddress >> 15) & 0xFF;
}
PORTC = myData;
// Arduino running at 16Mhz -> one nop = 62.5ns
// Wait till output is stable
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
// Switch WE(PH4) WE_SNS(PH5) to LOW
PORTH &= ~((1 << 4) | (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");
// Switch WE(PH4) WE_SNS(PH5) to HIGH
PORTH |= (1 << 4) | (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");
}
byte readByte_Flash(unsigned long myAddress) {
PORTF = myAddress & 0xFF;
if (hiROM) {
PORTK = (myAddress >> 8) & 0xFF;
PORTL = (myAddress >> 16) & 0xFF;
}
else {
PORTK = (myAddress >> 8) & 0x7F;
// Set A15(PK7) HIGH to disable SRAM
PORTK |= (1 << 7);
PORTL = (myAddress >> 15) & 0xFF;
}
// Arduino running at 16Mhz -> one nop = 62.5ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
// Setting OE(PH1) OE_SNS(PH3) LOW
PORTH &= ~((1 << 1) | (1 << 3));
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
// Read
byte tempByte = PINC;
// Setting OE(PH1) OE_SNS(PH3) HIGH
PORTH |= (1 << 1) | (1 << 3);
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
return tempByte;
}
void writeWord_Flash(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(PH4) to LOW
PORTH &= ~(1 << 4);
// 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");
// Switch WE(PH4) to HIGH
PORTH |= (1 << 4);
// 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");
}
word readWord_Flash(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(PH1) LOW
PORTH &= ~(1 << 1);
__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 OE(PH1) HIGH
PORTH |= (1 << 1);
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
return tempWord;
}
/******************************************
29F032 flashrom functions
*****************************************/
void resetFlash29F032() {
// Set data pins to output
dataOut();
// Reset command sequence
writeByte_Flash(0x555, 0xf0);
// Set data pins to input again
dataIn8();
delay(500);
}
void idFlash29F032() {
// Set data pins to output
dataOut();
// ID command sequence
writeByte_Flash(0x555, 0xaa);
writeByte_Flash(0x2aa, 0x55);
writeByte_Flash(0x555, 0x90);
// Set data pins to input again
dataIn8();
// Read the two id bytes into a string
sprintf(flashid, "%02X%02X", readByte_Flash(0), readByte_Flash(1));
}
void eraseFlash29F032() {
// Set data pins to output
dataOut();
// Erase command sequence
writeByte_Flash(0x555, 0xaa);
writeByte_Flash(0x2aa, 0x55);
writeByte_Flash(0x555, 0x80);
writeByte_Flash(0x555, 0xaa);
writeByte_Flash(0x2aa, 0x55);
writeByte_Flash(0x555, 0x10);
// Set data pins to input again
dataIn8();
// Read the status register
byte statusReg = readByte_Flash(0);
// After a completed erase D7 will output 1
while ((statusReg & 0x80) != 0x80) {
// Blink led
PORTB ^= (1 << 4);
delay(100);
// Update Status
statusReg = readByte_Flash(0);
}
}
void writeFlash29F032() {
// 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();
// Fill sdBuffer
for (unsigned long currByte = 0; currByte < fileSize; currByte += 512) {
myFile.read(sdBuffer, 512);
// Blink led
if (currByte % 2048 == 0)
PORTB ^= (1 << 4);
for (int c = 0; c < 512; c++) {
// Write command sequence
writeByte_Flash(0x555, 0xaa);
writeByte_Flash(0x2aa, 0x55);
writeByte_Flash(0x555, 0xa0);
// Write current byte
writeByte_Flash(currByte + c, sdBuffer[c]);
busyCheck29F032(sdBuffer[c]);
}
}
// Set data pins to input again
dataIn8();
// Close the file:
myFile.close();
}
else {
println_Msg(F("Can't open file"));
display_Update();
}
}
void busyCheck29F032(byte c) {
// Set data pins to input
dataIn8();
// Setting OE(PH1) OE_SNS(PH3) CE(PH6)LOW
PORTH &= ~((1 << 1) | (1 << 3) | (1 << 6));
// Setting WE(PH4) WE_SNES(PH5) HIGH
PORTH |= (1 << 4) | (1 << 5);
//When the Embedded Program algorithm is complete, the device outputs the datum programmed to D7
while ((PINC & 0x80) != (c & 0x80)) {}
// Set data pins to output
dataOut();
// Setting OE(PH1) OE_SNS(PH3) HIGH
PORTH |= (1 << 1) | (1 << 3);
}
/******************************************
29F1610 flashrom functions
*****************************************/
void resetFlash29F1610() {
// Set data pins to output
dataOut();
// Reset command sequence
writeByte_Flash(0x5555 << 1, 0xaa);
writeByte_Flash(0x2aaa << 1, 0x55);
writeByte_Flash(0x5555 << 1, 0xf0);
// Set data pins to input again
dataIn8();
delay(500);
}
void writeFlash29F1610() {
// 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);
// Set data pins to output
dataOut();
for (unsigned long currByte = 0; currByte < fileSize; currByte += 128) {
// Fill sdBuffer with 1 page at a time then write it repeat until all bytes are written
myFile.read(sdBuffer, 128);
// Blink led
if (currByte % 3072 == 0)
PORTB ^= (1 << 4);
// Check if write is complete
delayMicroseconds(100);
busyCheck29F1610();
// Write command sequence
writeByte_Flash(0x5555 << 1, 0xaa);
writeByte_Flash(0x2aaa << 1, 0x55);
writeByte_Flash(0x5555 << 1, 0xa0);
// Write one full page at a time
for (byte c = 0; c < 128; c++) {
writeByte_Flash(currByte + c, sdBuffer[c]);
}
}
// Check if write is complete
busyCheck29F1610();
// Set data pins to input again
dataIn8();
// Close the file:
myFile.close();
}
else {
println_Msg(F("Can't open file on SD"));
display_Update();
}
}
void writeFlash29F1601() {
// 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);
// Set data pins to output
dataOut();
for (unsigned long currByte = 0; currByte < fileSize; currByte += 128) {
// Fill sdBuffer with 1 page at a time then write it repeat until all bytes are written
myFile.read(sdBuffer, 128);
// Blink led
if (currByte % 3072 == 0)
PORTB ^= (1 << 4);
// Check if write is complete
delayMicroseconds(100);
busyCheck29F1610();
// Write command sequence
writeByte_Flash(0x5555 << 1, 0xaa);
writeByte_Flash(0x2aaa << 1, 0x55);
writeByte_Flash(0x5555 << 1, 0xa0);
// Write one full page at a time
for (byte c = 0; c < 128; c++) {
writeByte_Flash(currByte + c, sdBuffer[c]);
if (c == 127) {
// Write the last byte twice or else it won't write at all
writeByte_Flash(currByte + c, sdBuffer[c]);
}
}
}
// Check if write is complete
busyCheck29F1610();
// Set data pins to input again
dataIn8();
// Close the file:
myFile.close();
}
else {
println_Msg(F("Can't open file on SD"));
display_Update();
}
}
void idFlash29F1610() {
// Set data pins to output
dataOut();
// ID command sequence
writeByte_Flash(0x5555 << 1, 0xaa);
writeByte_Flash(0x2aaa << 1, 0x55);
writeByte_Flash(0x5555 << 1, 0x90);
// Set data pins to input again
dataIn8();
// Read the two id bytes into a string
sprintf(flashid, "%02X%02X", readByte_Flash(0), readByte_Flash(2));
}
byte readStatusReg() {
// Set data pins to output
dataOut();
// Status reg command sequence
writeByte_Flash(0x5555 << 1, 0xaa);
writeByte_Flash(0x2aaa << 1, 0x55);
writeByte_Flash(0x5555 << 1, 0x70);
// Set data pins to input again
dataIn8();
// Read the status register
byte statusReg = readByte_Flash(0);
return statusReg;
}
void eraseFlash29F1610() {
// Set data pins to output
dataOut();
// Erase command sequence
writeByte_Flash(0x5555 << 1, 0xaa);
writeByte_Flash(0x2aaa << 1, 0x55);
writeByte_Flash(0x5555 << 1, 0x80);
writeByte_Flash(0x5555 << 1, 0xaa);
writeByte_Flash(0x2aaa << 1, 0x55);
writeByte_Flash(0x5555 << 1, 0x10);
// Set data pins to input again
dataIn8();
busyCheck29F1610();
}
// Delay between write operations based on status register
void busyCheck29F1610() {
// Set data pins to input
dataIn8();
// Read the status register
byte statusReg = readByte_Flash(0);
while ((statusReg & 0x80) != 0x80) {
statusReg = readByte_Flash(0);
}
// Set data pins to output
dataOut();
}
/******************************************
MX29LV flashrom functions
*****************************************/
void busyCheck29LV640(unsigned long myAddress, byte myData) {
// Set data pins to input
dataIn8();
// Read the status register
byte statusReg = readByte_Flash(myAddress);
while ((statusReg & 0x80) != (myData & 0x80)) {
statusReg = readByte_Flash(myAddress);
}
// Set data pins to output
dataOut();
}
void writeFlash29LV640() {
// 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);
// Set data pins to output
dataOut();
for (unsigned long currByte = 0; currByte < fileSize; currByte += 512) {
// Fill sdBuffer
myFile.read(sdBuffer, 512);
// Blink led
if (currByte % 4096 == 0)
PORTB ^= (1 << 4);
for (int c = 0; c < 512; c++) {
// Write command sequence
writeByte_Flash(0x555 << 1, 0xaa);
writeByte_Flash(0x2aa << 1, 0x55);
writeByte_Flash(0x555 << 1, 0xa0);
// Write current byte
writeByte_Flash(currByte + c, sdBuffer[c]);
// Check if write is complete
busyCheck29LV640(currByte + c, sdBuffer[c]);
}
}
// Set data pins to input again
dataIn8();
// Close the file:
myFile.close();
}
else {
println_Msg(F("Can't open file on SD"));
display_Update();
}
}
/******************************************
S29GL flashrom functions
*****************************************/
void writeFlash29GL(unsigned long sectorSize, byte bufferSize) {
// 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);
// Set data pins to output
dataOut();
for (unsigned long currSector = 0; currSector < fileSize; currSector += sectorSize) {
// Blink led
PORTB ^= (1 << 4);
// Write to flashrom
for (unsigned long currSdBuffer = 0; currSdBuffer < sectorSize; currSdBuffer += 512) {
// Fill SD buffer
myFile.read(sdBuffer, 512);
// Write bufferSize bytes at a time
for (int currWriteBuffer = 0; currWriteBuffer < 512; currWriteBuffer += bufferSize) {
// 2 unlock commands
writeByte_Flash(0x555 << 1, 0xaa);
writeByte_Flash(0x2aa << 1, 0x55);
// Write buffer load command at sector address
writeByte_Flash(currSector + currSdBuffer + currWriteBuffer, 0x25);
// Write byte count (minus 1) at sector address
writeByte_Flash(currSector + currSdBuffer + currWriteBuffer, bufferSize - 1);
// Load bytes into buffer
for (byte currByte = 0; currByte < bufferSize; currByte++) {
writeByte_Flash(currSector + currSdBuffer + currWriteBuffer + currByte, sdBuffer[currWriteBuffer + currByte]);
}
// Write Buffer to Flash
writeByte_Flash(currSector + currSdBuffer + currWriteBuffer + bufferSize - 1, 0x29);
// Read the status register at last written address
dataIn8();
byte statusReg = readByte_Flash(currSector + currSdBuffer + currWriteBuffer + bufferSize - 1);
while ((statusReg & 0x80) != (sdBuffer[currWriteBuffer + bufferSize - 1] & 0x80)) {
statusReg = readByte_Flash(currSector + currSdBuffer + currWriteBuffer + bufferSize - 1);
}
dataOut();
}
}
}
// Set data pins to input again
dataIn8();
// Close the file:
myFile.close();
}
else {
println_Msg(F("Can't open file on SD"));
display_Update();
}
}
/******************************************
29F800 functions
*****************************************/
void writeFlash29F800() {
// 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);
// Set data pins to output
dataOut();
// Fill sdBuffer
for (unsigned long currByte = 0; currByte < fileSize; currByte += 512) {
myFile.read(sdBuffer, 512);
// Blink led
if (currByte % 2048 == 0)
PORTB ^= (1 << 4);
for (int c = 0; c < 512; c++) {
// Write command sequence
writeByte_Flash(0x5555 << 1, 0xaa);
writeByte_Flash(0x2aaa << 1, 0x55);
writeByte_Flash(0x5555 << 1, 0xa0);
// Write current byte
writeByte_Flash(currByte + c, sdBuffer[c]);
busyCheck29F032(sdBuffer[c]);
}
}
// Set data pins to input again
dataIn8();
// Close the file:
myFile.close();
}
else {
println_Msg(F("Can't open file on SD"));
display_Update();
}
}
/******************************************
28FXXX series flashrom functions
*****************************************/
void idFlash28FXXX() {
dataOut();
writeByte_Flash(0x0, 0x90);
dataIn8();
// Read the two id bytes into a string
sprintf(flashid, "%02X%02X", readByte_Flash(0), readByte_Flash(1));
}
void resetFlash28FXXX() {
dataOut();
writeByte_Flash(0x0, 0xff);
dataIn();
delay(500);
}
uint8_t statusFlash28FXXX() {
dataOut();
writeByte_Flash(0x0, 0x70);
dataIn8();
return readByte_Flash(0x0);
}
void eraseFlash28FXXX() {
// only can erase block by block
for (uint32_t ba = 0; ba < flashSize; ba += sectorSize)
{
dataOut();
writeByte_Flash(ba, 0x20);
writeByte_Flash(ba, 0xd0);
dataIn8();
while ((readByte_Flash(ba) & 0x80) == 0x00);
// blink LED
PORTB ^= (1 << 4);
}
}
void writeFlash28FXXX() {
sprintf(filePath, "%s/%s", filePath, fileName);
print_Msg(F("Flashing file "));
println_Msg(filePath);
display_Update();
// Open file on sd card
if (myFile.open(filePath, O_READ)) {
if ((strcmp(flashid, "B088") == 0))
writeFlashLH28F0XX();
else if ((strcmp(flashid, "8916") == 0) ||
(strcmp(flashid, "8917") == 0) ||
(strcmp(flashid, "8918") == 0)) {
writeFlashE28FXXXJ3A();
}
myFile.close();
}
else {
println_Msg(F("Can't open file on SD"));
display_Update();
}
}
void writeFlashE28FXXXJ3A() {
fileSize = myFile.fileSize();
if (fileSize > flashSize) {
print_Error(F("File size exceeds flash size."), false);
return;
}
uint32_t block_addr;
uint32_t block_addr_mask = ~(sectorSize - 1);
// Fill sdBuffer
for (uint32_t currByte = 0; currByte < fileSize; currByte += 512) {
myFile.read(sdBuffer, 512);
// Blink led
if (currByte % 2048 == 0)
PORTB ^= (1 << 4);
block_addr = currByte & block_addr_mask;
for (uint32_t c = 0; c < 512; c += bufferSize) {
// write to buffer start
dataOut();
writeByte_Flash(block_addr, 0xe8);
// waiting for buffer available
dataIn8();
while ((readByte_Flash(block_addr) & 0x80) == 0x00);
dataOut();
// set write byte count
writeByte_Flash(block_addr, bufferSize - 1);
// filling buffer
for (uint32_t d = 0; d < bufferSize; d++)
writeByte_Flash(currByte + c + d, sdBuffer[c + d]);
// start flashing page
writeByte_Flash(block_addr, 0xd0);
// waiting for finishing
dataIn8();
while ((readByte_Flash(block_addr) & 0x80) == 0x00);
}
}
dataIn8();
}
void writeFlashLH28F0XX() {
fileSize = myFile.fileSize();
if (fileSize > flashSize) {
print_Error(F("File size exceeds flash size."), false);
return;
}
// Fill sdBuffer
for (uint32_t currByte = 0; currByte < fileSize; currByte += 512) {
myFile.read(sdBuffer, 512);
// Blink led
if (currByte % 2048 == 0)
PORTB ^= (1 << 4);
for (uint32_t c = 0; c < 512; c += bufferSize) {
// sequence load to page
dataOut();
writeByte_Flash(0x0, 0xe0);
writeByte_Flash(0x0, bufferSize - 1); // BCL
writeByte_Flash(0x0, 0x00); // BCH should be 0x00
for (uint32_t d = 0; d < bufferSize; d++)
writeByte_Flash(d, sdBuffer[c + d]);
// start flashing page
writeByte_Flash(0x0, 0x0c);
writeByte_Flash(0x0, bufferSize - 1); // BCL
writeByte_Flash(currByte + c, 0x00); // BCH should be 0x00
// waiting for finishing
dataIn8();
while ((readByte_Flash(currByte + c) & 0x80) == 0x00);
}
}
dataIn8();
}
/******************************************
Common flashrom functions
*****************************************/
void blankcheck_Flash() {
println_Msg(F("Please wait..."));
display_Update();
blank = 1;
for (unsigned long currByte = 0; currByte < flashSize; currByte++) {
// Check if all bytes are 0xFF
if (readByte_Flash(currByte) != 0xFF) {
currByte = flashSize;
blank = 0;
}
}
if (blank) {
println_Msg(F("Flashrom is empty"));
display_Update();
}
else {
print_Error(F("Error: Not blank"), false);
}
}
void verifyFlash() {
println_Msg(F("Verifying..."));
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);
blank = 0;
for (unsigned long currByte = 0; currByte < fileSize; currByte += 512) {
//fill sdBuffer
myFile.read(sdBuffer, 512);
for (int c = 0; c < 512; c++) {
if (readByte_Flash(currByte + c) != sdBuffer[c]) {
blank++;
}
}
}
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 on SD"));
display_Update();
}
}
void readFlash() {
// Reset to root directory
sd.chdir("/");
// Get name, add extension and convert to char array for sd lib
EEPROM_readAnything(0, 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(0, 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)) {
print_Error(F("Can't create file on SD"), true);
}
for (unsigned long currByte = 0; currByte < flashSize; currByte += 512) {
for (int c = 0; c < 512; c++) {
sdBuffer[c] = readByte_Flash(currByte + c);
}
myFile.write(sdBuffer, 512);
}
// Close the file:
myFile.close();
println_Msg(F("Finished reading"));
display_Update();
}
void printFlash(int numBytes) {
char myBuffer[3];
for (int currByte = 0; currByte < numBytes; currByte += 10) {
for (int c = 0; c < 10; c++) {
itoa (readByte_Flash(currByte + c), myBuffer, 16);
for (int i = 0; i < 2 - strlen(myBuffer); i++) {
print_Msg("0");
}
// Now print the significant bits
print_Msg(myBuffer);
}
println_Msg("");
}
display_Update();
}
void resetFlash8() {
switch (flashromType) {
case 1: resetFlash29F032(); break;
case 2: resetFlash29F1610(); break;
case 3: resetFlash28FXXX(); break;
}
}
/******************************************
29L3211 16bit flashrom functions
*****************************************/
void resetFlash16() {
// Set data pins to output
dataOut16();
// Reset command sequence
writeWord_Flash(0x5555, 0xaa);
writeWord_Flash(0x2aaa, 0x55);
writeWord_Flash(0x5555, 0xf0);
// Set data pins to input again
dataIn16();
delay(500);
}
void writeFlash16() {
// 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);
// Set data pins to output
dataOut16();
// 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 % 2048 == 0)
PORTB ^= (1 << 4);
// Check if write is complete
delayMicroseconds(100);
busyCheck16();
// Write command sequence
writeWord_Flash(0x5555, 0xaa);
writeWord_Flash(0x2aaa, 0x55);
writeWord_Flash(0x5555, 0xa0);
// Write one full page at a time
for (byte c = 0; c < 64; c++) {
word currWord = ( ( sdBuffer[d + 1] & 0xFF ) << 8 ) | ( sdBuffer[d] & 0xFF );
writeWord_Flash(currByte + c, currWord);
d += 2;
}
d = 0;
}
// Check if write is complete
busyCheck16();
// Set data pins to input again
dataIn16();
// Close the file:
myFile.close();
}
else {
println_Msg(F("Can't open file on SD."));
display_Update();
}
}
void writeFlash16_29F1601() {
// 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);
// Set data pins to output
dataOut16();
// 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 % 2048 == 0)
PORTB ^= (1 << 4);
// Check if write is complete
delayMicroseconds(100);
busyCheck16();
// Write command sequence
writeWord_Flash(0x5555, 0xaa);
writeWord_Flash(0x2aaa, 0x55);
writeWord_Flash(0x5555, 0xa0);
// Write one full page at a time
for (byte c = 0; c < 64; c++) {
word currWord = ( ( sdBuffer[d + 1] & 0xFF ) << 8 ) | ( sdBuffer[d] & 0xFF );
writeWord_Flash(currByte + c, currWord);
if (c == 63) {
// Write the last byte twice or else it won't write at all
writeWord_Flash(currByte + c, sdBuffer[d + 1]);
}
d += 2;
}
d = 0;
}
// Check if write is complete
busyCheck16();
// Set data pins to input again
dataIn16();
// Close the file:
myFile.close();
}
else {
println_Msg(F("Can't open file on SD."));
display_Update();
}
}
void idFlash16() {
// Set data pins to output
dataOut16();
// ID command sequence
writeWord_Flash(0x5555, 0xaa);
writeWord_Flash(0x2aaa, 0x55);
writeWord_Flash(0x5555, 0x90);
// Set data pins to input again
dataIn16();
// Read the two id bytes into a string
sprintf(flashid, "%02X%02X", readWord_Flash(0) & 0xFF, readWord_Flash(1) & 0xFF);
}
byte readStatusReg16() {
// Set data pins to output
dataOut16();
// Status reg command sequence
writeWord_Flash(0x5555, 0xaa);
writeWord_Flash(0x2aaa, 0x55);
writeWord_Flash(0x5555, 0x70);
// Set data pins to input again
dataIn16();
// Read the status register
byte statusReg = readWord_Flash(0);
return statusReg;
}
void eraseFlash16() {
// Set data pins to output
dataOut16();
// Erase command sequence
writeWord_Flash(0x5555, 0xaa);
writeWord_Flash(0x2aaa, 0x55);
writeWord_Flash(0x5555, 0x80);
writeWord_Flash(0x5555, 0xaa);
writeWord_Flash(0x2aaa, 0x55);
writeWord_Flash(0x5555, 0x10);
// Set data pins to input again
dataIn16();
busyCheck16();
}
void blankcheck16() {
println_Msg(F("Please wait..."));
display_Update();
blank = 1;
for (unsigned long currByte = 0; currByte < flashSize / 2; currByte++) {
if (readWord_Flash(currByte) != 0xFFFF) {
currByte = flashSize / 2;
blank = 0;
}
}
if (blank) {
println_Msg(F("Flashrom is empty."));
display_Update();
}
else {
print_Error(F("Error: Not blank"), false);
}
}
void verifyFlash16() {
println_Msg(F("Verifying..."));
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);
}
blank = 0;
word d = 0;
for (unsigned long currByte = 0; currByte < fileSize / 2; currByte += 256) {
//fill sdBuffer
myFile.read(sdBuffer, 512);
for (int c = 0; c < 256; c++) {
word currWord = ((sdBuffer[d + 1] << 8) | sdBuffer[d]);
if (readWord_Flash(currByte + c) != currWord) {
blank++;
}
d += 2;
}
d = 0;
}
if (blank == 0) {
println_Msg(F("Flashrom verified OK"));
display_Update();
}
else {
println_Msg(F("Verification ERROR!"));
print_Msg(blank);
print_Error(F("B did not verify."), false);
display_Update();
}
// Close the file:
myFile.close();
}
else {
println_Msg(F("Can't open file on SD."));
display_Update();
}
}
void readFlash16() {
// Reset to root directory
sd.chdir("/");
// Get name, add extension and convert to char array for sd lib
EEPROM_readAnything(0, 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(0, 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 currByte = 0; currByte < flashSize / 2; currByte += 256) {
for (word c = 0; c < 256; c++) {
word currWord = readWord_Flash(currByte + c);
// Split word into two bytes
// Right
sdBuffer[d + 1] = (( currWord >> 8 ) & 0xFF);
// Left
sdBuffer[d] = (currWord & 0xFF);
d += 2;
}
myFile.write(sdBuffer, 512);
d = 0;
}
// Close the file:
myFile.close();
println_Msg(F("Finished reading."));
display_Update();
}
void printFlash16(int numBytes) {
/*
right_byte = short_val & 0xFF;
left_byte = ( short_val >> 8 ) & 0xFF
short_val = ( ( left_byte & 0xFF ) << 8 ) | ( right_byte & 0xFF );
*/
char buf[3];
for (int currByte = 0; currByte < numBytes / 2; currByte += 5) {
// 5 words per line
for (int c = 0; c < 5; c++) {
word currWord = readWord_Flash(currByte + c);
// Split word into two bytes
byte left_byte = currWord & 0xFF;
byte right_byte = ( currWord >> 8 ) & 0xFF;
sprintf (buf, "%x", left_byte);
for (int i = 0; i < 2 - strlen(buf); i++) {
print_Msg("0");
}
// Now print the significant bits
print_Msg(buf);
sprintf (buf, "%x", right_byte);
for (int i = 0; i < 2 - strlen(buf); i++) {
print_Msg("0");
}
// Now print the significant bits
print_Msg(buf);
}
println_Msg("");
}
display_Update();
}
// Delay between write operations based on status register
void busyCheck16() {
// Set data pins to input
dataIn16();
// Read the status register
word statusReg = readWord_Flash(0);
while ((statusReg | 0xFF7F) != 0xFFFF) {
statusReg = readWord_Flash(0);
}
// Set data pins to output
dataOut16();
}
/******************************************
MX29LV flashrom functions 16bit
*****************************************/
// Delay between write operations based on status register
void busyCheck16_29LV640(unsigned long myAddress, word myData) {
// Set data pins to input
dataIn16();
// Read the status register
word statusReg = readWord_Flash(myAddress);
while ((statusReg & 0x80) != (myData & 0x80)) {
statusReg = readWord_Flash(myAddress);
}
// Set data pins to output
dataOut16();
}
void writeFlash16_29LV640() {
// 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);
// Set data pins to output
dataOut16();
int d = 0;
for (unsigned long currWord = 0; currWord < fileSize / 2; currWord += 256) {
// Fill sdBuffer
myFile.read(sdBuffer, 512);
// Blink led
if (currWord % 4096 == 0)
PORTB ^= (1 << 4);
for (int c = 0; c < 256; c++) {
// Write command sequence
writeWord_Flash(0x5555, 0xaa);
writeWord_Flash(0x2aaa, 0x55);
writeWord_Flash(0x5555, 0xa0);
// Write current word
word myWord = ( ( sdBuffer[d + 1] & 0xFF ) << 8 ) | ( sdBuffer[d] & 0xFF );
writeWord_Flash(currWord + c, myWord);
d += 2;
// Check if write is complete
busyCheck16_29LV640(currWord + c, myWord);
}
d = 0;
}
// Set data pins to input again
dataIn16();
// Close the file:
myFile.close();
}
else {
println_Msg(F("Can't open file on SD."));
display_Update();
}
}
/******************************************
Eprom functions
*****************************************/
word writeWord_Eprom(unsigned long myAddress, word myData) {
// Data out
DDRC = 0xFF;
DDRA = 0xFF;
// Arduino running at 16Mhz -> one nop = 62.5ns
__asm__("nop\n\t");
// Set address
PORTF = myAddress & 0xFF;
PORTK = (myAddress >> 8) & 0xFF;
PORTL = (myAddress >> 16) & 0xFF;
// Set data
PORTC = myData;
PORTA = (myData >> 8) & 0xFF;
__asm__("nop\n\t");
// Switch VPP/OE(PH5) to HIGH
PORTH |= (1 << 5);
// Wait 1us for VPP High to Chip Enable Low
delayMicroseconds(1);
// Setting CE(PH6) LOW
PORTH &= ~(1 << 6);
// Leave VPP HIGH for 50us Chip Enable Program Pulse Width
delayMicroseconds(55);
// Setting CE(PH6) HIGH
PORTH |= (1 << 6);
// Wait 2us for Chip Enable High to VPP Transition
delayMicroseconds(2);
// Switch VPP/OE(PH5) to LOW
PORTH &= ~(1 << 5);
// Leave CE High for 1us for VPP Low to Chip Enable Low
delayMicroseconds(1);
// Data in
DDRC = 0x00;
DDRA = 0x00;
// Arduino running at 16Mhz -> one nop = 62.5ns
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
// Setting CE(PH6) LOW
PORTH &= ~(1 << 6);
// Wait 1us for Chip Enable Low to Output Valid while program verify
delayMicroseconds(3);
// Read
word tempWord = ( ( PINA & 0xFF ) << 8 ) | ( PINC & 0xFF );
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
// Setting CE(PH6) HIGH
PORTH |= (1 << 6);
// Delay 130ns for Chip Enable High to Output Hi-Z
__asm__("nop\n\t""nop\n\t""nop\n\t");
return tempWord;
}
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);
// Delay for 100ns for Address Valid/Chip Enable Low to Output Valid
__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 );
// Setting CE(PH6) HIGH
PORTH |= (1 << 6);
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(0, 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(0, 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);
// Switch VPP/OE(PH5) to HIGH
PORTH |= (1 << 5);
delay(1000);
for (unsigned long currWord = 0; currWord < fileSize / 2; currWord += 256) {
// Fill SD buffer
myFile.read(sdBuffer, 512);
int d = 0;
// Blink led
if (currWord % 2048 == 0)
PORTB ^= (1 << 4);
// Work through SD buffer
for (int c = 0; c < 256; c++) {
word checkWord;
word myWord = ( ( sdBuffer[d + 1] & 0xFF ) << 8 ) | ( sdBuffer[d] & 0xFF );
// Error counter
byte n = 0;
// Presto III allows up to 25 rewrites per word
do {
// Write word
checkWord = writeWord_Eprom(currWord + c, myWord);
// Check for fail
if (n == 25) {
print_Msg(F("Program Error 0x"));
println_Msg(currWord + c, HEX);
print_Msg(F("0x"));
print_Msg(readWord_Eprom(currWord + c), HEX);
print_Msg(F(" != 0x"));
println_Msg(myWord, HEX);
print_Error(F("Press button to reset"), true);
}
n++;
}
while (checkWord != myWord);
d += 2;
}
}
// Close the file:
myFile.close();
}
else {
println_Msg(F("Can't open file on SD."));
display_Update();
}
}
void verify_Eprom() {
println_Msg(F("Verifying..."));
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);
}
blank = 0;
word d = 0;
for (unsigned long currWord = 0; currWord < (fileSize / 2); currWord += 256) {
//fill sdBuffer
myFile.read(sdBuffer, 512);
for (int c = 0; c < 256; c++) {
word myWord = (((sdBuffer[d + 1] & 0xFF) << 8) | (sdBuffer[d] & 0xFF));
if (readWord_Eprom(currWord + c) != myWord) {
blank++;
}
d += 2;
}
d = 0;
}
if (blank == 0) {
println_Msg(F("Eprom verified OK"));
display_Update();
}
else {
println_Msg(F("Verification ERROR!"));
print_Msg(blank);
print_Error(F(" words did not verify."), false);
display_Update();
}
// Close the file:
myFile.close();
}
else {
println_Msg(F("Can't open file on SD."));
display_Update();
}
}
void print_Eprom(int numBytes) {
char buf[3];
for (int currByte = 0; currByte < numBytes / 2; currByte += 5) {
// 5 words per line
for (int c = 0; c < 5; c++) {
word currWord = readWord_Eprom(currByte + c);
// Split word into two bytes
byte left_byte = currWord & 0xFF;
byte right_byte = ( currWord >> 8 ) & 0xFF;
sprintf (buf, "%x", left_byte);
for (int i = 0; i < 2 - strlen(buf); i++) {
print_Msg("0");
}
// Now print the significant bits
print_Msg(buf);
sprintf (buf, "%x", right_byte);
for (int i = 0; i < 2 - strlen(buf); i++) {
print_Msg("0");
}
// Now print the significant bits
print_Msg(buf);
}
println_Msg("");
}
display_Update();
}
//******************************************
// End of File
//******************************************