diff --git a/Cart_Reader/Cart_Reader.ino b/Cart_Reader/Cart_Reader.ino index 80129c0..70a0009 100644 --- a/Cart_Reader/Cart_Reader.ino +++ b/Cart_Reader/Cart_Reader.ino @@ -1,1376 +1,1376 @@ -/********************************************************************************** - Cartridge Reader for Arduino Mega2560 - - Author: sanni - Date: 20-09-2018 - Version: 1.8 - - SD lib: https://github.com/greiman/SdFat - LCD lib: https://github.com/adafruit/Adafruit_SSD1306 - Clockgen: https://github.com/etherkit/Si5351Arduino - RGB Tools lib: https://github.com/joushx/Arduino-RGB-Tools - - Compiled with Arduino 1.8.5 - - Thanks to: - MichlK - ROM-Reader for Super Nintendo - Jeff Saltzman - 4-Way Button - Wayne and Layne - Video-Game-Shield menu - skaman - SNES enhancements, SA1 sram support and GB flash fix - nocash - Nintendo Power and GBA Eeprom commands and lots of other info - crazynation - N64 bus timing - hkz/themanbehindthecurtain - N64 flashram commands - jago85 - help with N64 stuff - Andrew Brown/Peter Den Hartog - N64 controller protocol - bryc - mempak - Shaun Taylor - N64 controller CRC functions - Angus Gratton - CRC32 - Tamanegi_taro - SA1 fix and PCE support - Snes9x - SuperFX sram fix - zzattack - multigame pcb fix - Pickle - SDD1 fix - insidegadgets - GBCartRead - RobinTheHood - GameboyAdvanceRomDumper - YamaArashi - GBA flashrom bank switch command - infinest - help with GB Memory cart - -**********************************************************************************/ -char ver[5] = "1.8"; - -/****************************************** - Define Starting Point -******************************************/ -// mainMenu, n64Menu, snsMenu, gbxMenu, segaMenu, flashMenu, pceMenu -#define startMenu mainMenu - -/****************************************** - Define Output -******************************************/ -// To use the Serial Monitor change -// enable_OLED to 0 and enable_Serial to 1 -#define enable_OLED 1 -#define enable_Serial 0 - -/****************************************** - Define Input -******************************************/ -// If you are using the old version with only one button add // in front of the next line -#define enable_Button2 - -/****************************************** - Define SD Speed -******************************************/ -// Change to half speed if you get an sd error or it hangs when writing -#define sdSpeed SPI_FULL_SPEED -//#define sdSpeed SPI_HALF_SPEED - -/****************************************** - Options -******************************************/ -// If set to 1 then the crc32 checksum will be calculated after reading a N64 rom -boolean n64crc = 1; - -/****************************************** - Libraries - *****************************************/ -// Basic Libs -#include -#include -#include - -// AVR Eeprom -#include -#include "EEPROMAnything.h" - -// Graphic I2C LCD -#include -#include -#define OLED_RESET 4 -Adafruit_SSD1306 display(OLED_RESET); -// Check if Adafruit_SSD1306.h was setup for 128x64 -#if (SSD1306_LCDHEIGHT != 64) -#error("Incorrect height defined in Adafruit_SSD1306.h"); -#endif - -// Adafruit Clock Generator -#include -Si5351 clockgen; - -// RGB LED -#include - -// Set pins of red, green and blue -RGBTools rgb(12, 11, 10); - -typedef enum COLOR_T { - blue_color, - red_color, - purple_color, - green_color, - turquoise_color, - yellow_color, - white_color, -} color_t; - -// SD Card (Pin 50 = MISO, Pin 51 = MOSI, Pin 52 = SCK, Pin 53 = SS) -#include -#define chipSelectPin 53 -SdFat sd; -SdFile myFile; - -/****************************************** - Defines - *****************************************/ -// Mode menu -#define mode_N64_Cart 0 -#define mode_N64_Controller 1 -#define mode_SNES 2 -#define mode_SFM 3 -#define mode_SFM_Flash 4 -#define mode_SFM_Game 5 -#define mode_GB 6 -#define mode_FLASH8 7 -#define mode_FLASH16 8 -#define mode_GBA 9 -#define mode_GBM 10 -#define mode_MD 11 -#define mode_EPROM 12 -#define mode_PCE 13 - -/****************************************** - Variables - *****************************************/ -// Button timing -static int debounce = 20; // ms debounce period to prevent flickering when pressing or releasing the button -static int DCgap = 250; // max ms between clicks for a double click event -static int holdTime = 2000; // ms hold period: how long to wait for press+hold event -static int longHoldTime = 5000; // ms long hold period: how long to wait for press+hold event -// Variables for button 1 -boolean buttonVal1 = HIGH; // value read from button -boolean buttonLast1 = HIGH; // buffered value of the button's previous state -boolean DCwaiting1 = false; // whether we're waiting for a double click (down) -boolean DConUp1 = false; // whether to register a double click on next release, or whether to wait and click -boolean singleOK1 = true; // whether it's OK to do a single click -long downTime1 = -1; // time the button was pressed down -long upTime1 = -1; // time the button was released -boolean ignoreUp1 = false; // whether to ignore the button release because the click+hold was triggered -boolean waitForUp1 = false; // when held, whether to wait for the up event -boolean holdEventPast1 = false; // whether or not the hold event happened already -boolean longholdEventPast1 = false;// whether or not the long hold event happened already -// Variables for button 2 -boolean buttonVal2 = HIGH; // value read from button -boolean buttonLast2 = HIGH; // buffered value of the button's previous state -boolean DCwaiting2 = false; // whether we're waiting for a double click (down) -boolean DConUp2 = false; // whether to register a double click on next release, or whether to wait and click -boolean singleOK2 = true; // whether it's OK to do a single click -long downTime2 = -1; // time the button was pressed down -long upTime2 = -1; // time the button was released -boolean ignoreUp2 = false; // whether to ignore the button release because the click+hold was triggered -boolean waitForUp2 = false; // when held, whether to wait for the up event -boolean holdEventPast2 = false; // whether or not the hold event happened already -boolean longholdEventPast2 = false;// whether or not the long hold event happened already - -// For incoming serial data -int incomingByte; - -// Variables for the menu -int choice = 0; -// Temporary array that holds the menu option read out of progmem -char menuOptions[7][20]; -boolean ignoreError = 0; - -// File browser -char fileName[26]; -char filePath[50]; -byte currPage; -byte lastPage; -byte numPages; -boolean root = 0; -boolean filebrowse = 0; -char fileOptions[30][20]; - -// Common -char romName[17]; -unsigned long sramSize = 0; -int romType = 0; -byte saveType; -word romSize = 0; -byte numBanks = 128; -char checksumStr[5]; -bool errorLvl = 0; -byte romVersion = 0; -char cartID[5]; -unsigned long cartSize; -char flashid[5]; -char vendorID[5]; -unsigned long fileSize; -unsigned long sramBase; - -// Variable to count errors -unsigned long writeErrors; - -// Operation mode -byte mode; - -//remember folder number to create a new folder for every save -int foldern; -char folder[36]; - -// Array that holds the data -byte sdBuffer[512]; - -//****************************************** -// Bitmaps -//****************************************** -static const unsigned char PROGMEM icon [] = { - 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x00, 0x0F, 0xFF, - 0x00, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x00, - 0x0F, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0xF8, - 0x00, 0x0F, 0xFF, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0xF8, 0x00, 0x0F, 0xFF, 0x00, 0x0F, 0xFF, 0x00, - 0x00, 0xFF, 0x80, 0x0F, 0xFF, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0xFF, 0x80, 0x0F, 0x00, 0x0F, 0xFF, - 0xFF, 0xFF, 0xF0, 0x0F, 0x80, 0x0F, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0x80, 0x0F, 0x00, - 0x0F, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0x80, 0x0F, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0x80, - 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x80, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x0F, 0xF0, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x0F, 0xF0, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0x00, 0xF0, 0xF0, 0x0F, 0xFF, - 0xF0, 0x00, 0xFF, 0xFF, 0x00, 0xF0, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0x00, 0xF0, 0xF0, - 0x0F, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0x00, 0xF0, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0xF0, 0x00, - 0xFF, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0xF0, 0x00, 0xFF, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0xFF, - 0xF0, 0x00, 0xFF, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0xF0, 0x00, 0xFF, 0xF0, 0x00, 0x0F, 0xF0, - 0x00, 0xFF, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0xF0, 0x00, 0x0F, 0xF0, 0x00, - 0x0F, 0xF0, 0x00, 0xFF, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0xF0, 0x00, 0x0F, - 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0xF0, - 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, - 0xFF, 0xF0, 0x00, 0x0F, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xF0, 0x0F, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xF0, - 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x1F, 0xF0, 0xFF, 0xF0, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x1F, 0xF0, 0xFF, 0xF0, 0xFF, 0x0F, 0xFF, 0x0F, 0xF0, 0x1F, 0xF0, - 0xFF, 0xF0, 0xFF, 0x0F, 0xFF, 0x0F, 0xF0, 0x1F, 0xF0, 0xFF, 0xF0, 0xFF, 0x0F, 0xFF, 0x0F, 0xF0, - 0x01, 0xF0, 0xFF, 0xF0, 0xFF, 0x0F, 0xFF, 0x0F, 0x80, 0x01, 0xF0, 0xFF, 0xF0, 0xFF, 0x0F, 0xFF, - 0x0F, 0x80, 0x01, 0xF0, 0xFF, 0xF0, 0xFF, 0x0F, 0xFF, 0x0F, 0x80, 0x01, 0xF0, 0xFF, 0xF0, 0xFF, - 0x0F, 0xFF, 0x0F, 0x80, 0x01, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x80, 0x01, 0xF0, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x80, 0x01, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x80, 0x01, - 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x80, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, - 0x80, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0F, 0x80, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x01, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x01, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80 -}; - -static const unsigned char PROGMEM sig [] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0xF0, 0x80, 0x40, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x90, 0xCC, 0x4E, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x90, 0x5C, 0x7B, 0x19, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xB8, 0x56, 0x31, 0x09, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0xA8, 0x72, 0x31, 0x0F, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xAC, 0x23, 0x21, 0x86, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xE7, 0xA1, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -//For PC Engine -extern void pcsMenu(void); -extern void pceMenu(void); - -/****************************************** - Menu -*****************************************/ -// Main menu -static const char modeItem1[] PROGMEM = "Nintendo 64"; -static const char modeItem2[] PROGMEM = "Super Nintendo"; -static const char modeItem3[] PROGMEM = "Game Boy"; -static const char modeItem4[] PROGMEM = "Mega Drive"; -static const char modeItem5[] PROGMEM = "Flashrom Programmer"; -static const char modeItem6[] PROGMEM = "PC Engine/TG16"; -static const char modeItem7[] PROGMEM = "About"; -static const char* const modeOptions[] PROGMEM = {modeItem1, modeItem2, modeItem3, modeItem4, modeItem5, modeItem6, modeItem7}; - -void aboutScreen() { - display_Clear(); - // Draw the Logo - display.drawBitmap(0, 0, sig, 128, 64, 1); - println_Msg(F("Cartridge Reader")); - println_Msg(F("github.com/sanni")); - print_Msg(F("2018 Version ")); - println_Msg(ver); - println_Msg(F("")); - println_Msg(F("")); - println_Msg(F("")); - println_Msg(F("")); - println_Msg(F("Press Button")); - display_Update(); - - while (1) { - if (enable_OLED) { - // get input button - int b = checkButton(); - - // if the cart readers input button is pressed shortly - if (b == 1) { - asm volatile (" jmp 0"); - } - - // if the cart readers input button is pressed long - if (b == 3) { - asm volatile (" jmp 0"); - } - - // if the button is pressed super long - if (b == 4) { - display_Clear(); - println_Msg(F("Resetting folder...")); - display_Update(); - delay(2000); - foldern = 0; - EEPROM_writeAnything(10, foldern); - asm volatile (" jmp 0"); - } - } - if (enable_Serial) { - wait_serial(); - asm volatile (" jmp 0"); - } - rgb.setColor(random(0, 255), random(0, 255), random(0, 255)); - delay(random(50, 100)); - } -} - -void mainMenu() { - // create menu with title and 6 options to choose from - unsigned char modeMenu; - // Copy menuOptions out of progmem - convertPgm(modeOptions, 7); - modeMenu = question_box("Cartridge Reader", menuOptions, 7, 0); - - // wait for user choice to come back from the question box menu - switch (modeMenu) - { - case 0: - n64Menu(); - break; - - case 1: - snsMenu(); - break; - - case 2: - gbxMenu(); - break; - - case 3: - segaMenu(); - break; - - case 4: - flashMenu(); - break; - case 5: - pcsMenu(); - break; - case 6: - aboutScreen(); - break; - } -} - -/****************************************** - Setup - *****************************************/ -void setup() { - // Set Button Pins(PD7, PG2) to Input - DDRD &= ~(1 << 7); - DDRG &= ~(1 << 2); - // Activate Internal Pullup Resistors - //PORTD |= (1 << 7); - //PORTG |= (1 << 2); - - // Read current folder number out of eeprom - EEPROM_readAnything(10, foldern); - - if (enable_OLED) { - // GLCD - display.begin(SSD1306_SWITCHCAPVCC, 0x3C); - display.setTextSize(1); - display.setTextColor(WHITE); - - // Clear the screen buffer. - display_Clear(); - delay(100); - - // Draw line - display.drawLine(0, 32, 127, 32, WHITE); - display_Update(); - delay(100); - - // Initialize LED - rgb.setColor(0, 0, 0); - - // Clear the screen. - display_Clear(); - display_Update(); - delay(25); - - // Draw the Logo - display.drawBitmap(28, 0, icon, 72, 64, 1); - for (int s = 1; s < 64; s += 2) { - // Draw Scanlines - display.drawLine(0, s, 127, s, BLACK); - } - display_Update(); - delay(50); - - // Clear the screen. - display_Clear(); - display_Update(); - delay(25); - - // Draw the Logo - display.drawBitmap(28, 0, icon, 72, 64, 1); - for (int s = 1; s < 64; s += 2) { - // Draw Scanlines - display.drawLine(0, s, 127, s, BLACK); - } - display.setCursor(100, 55); - display.println(ver); - display_Update(); - delay(200); - } - - if (enable_Serial) { - // Serial Begin - Serial.begin(9600); - Serial.println(F("Cartridge Reader")); - Serial.println(F("2018 sanni")); - Serial.println(""); - // LED Error - rgb.setColor(0, 0, 255); - } - else { - // LED Off - rgb.setColor(0, 0, 0); - } - - // Init SD card - if (!sd.begin(chipSelectPin, sdSpeed)) { - display_Clear(); - print_Error(F("SD Error"), true); - } - - if (enable_Serial) { - // Print SD Info - Serial.print(F("SD Card: ")); - Serial.print(sd.card()->cardSize() * 512E-9); - Serial.print(F("GB FAT")); - Serial.println(int(sd.vol()->fatType())); - } - - startMenu(); -} - -/****************************************** - Common I/O Functions - *****************************************/ -// Switch data pins to write -void dataOut() { - DDRC = 0xFF; -} - -// Switch data pins to read -void dataIn() { - // Set to Input and activate pull-up resistors - DDRC = 0x00; - // Pullups - PORTC = 0xFF; -} - -/****************************************** - Helper Functions - *****************************************/ -// Converts a progmem array into a ram array -void convertPgm(const char* const pgmOptions[], byte numArrays) { - for (int i = 0; i < numArrays; i++) { - strcpy_P(menuOptions[i], (char*)pgm_read_word(&(pgmOptions[i]))); - } -} - -void print_Error(const __FlashStringHelper *errorMessage, boolean forceReset) { - errorLvl = 1; - rgb.setColor(255, 0, 0); - println_Msg(errorMessage); - display_Update(); - - if (forceReset) { - if (enable_Serial) { - println_Msg(F("Fatal Error, please reset")); - while (1); - } - else { - println_Msg(F("")); - println_Msg(F("Press Button...")); - display_Update(); - wait(); - if (ignoreError == 0) { - asm volatile (" jmp 0"); - } - else { - ignoreError = 0; - display_Clear(); - println_Msg(F("")); - println_Msg(F("")); - println_Msg(F("")); - println_Msg(F(" Error Overwrite")); - display_Update(); - delay(2000); - } - } - } -} - -void wait() { - if (enable_OLED) { - wait_btn(); - } - if (enable_Serial) { - wait_serial(); - } -} - -void print_Msg(const __FlashStringHelper *string) { - if (enable_OLED) - display.print(string); - if (enable_Serial) - Serial.print(string); -} - -void print_Msg(const char string[]) { - if (enable_OLED) - display.print(string); - if (enable_Serial) - Serial.print(string); -} - -void print_Msg(long unsigned int message) { - if (enable_OLED) - display.print(message); - if (enable_Serial) - Serial.print(message); -} - -void print_Msg(byte message, int outputFormat) { - if (enable_OLED) - display.print(message, outputFormat); - if (enable_Serial) - Serial.print(message, outputFormat); -} - -void print_Msg(String string) { - if (enable_OLED) - display.print(string); - if (enable_Serial) - Serial.print(string); -} - -void println_Msg(String string) { - if (enable_OLED) - display.println(string); - if (enable_Serial) - Serial.println(string); -} - -void println_Msg(byte message, int outputFormat) { - if (enable_OLED) - display.println(message, outputFormat); - if (enable_Serial) - Serial.println(message, outputFormat); -} - -void println_Msg(const char message[]) { - if (enable_OLED) - display.println(message); - if (enable_Serial) - Serial.println(message); -} - -void println_Msg(const __FlashStringHelper *string) { - if (enable_OLED) - display.println(string); - if (enable_Serial) - Serial.println(string); -} - -void println_Msg(long unsigned int message) { - if (enable_OLED) - display.println(message); - if (enable_Serial) - Serial.println(message); -} - -void display_Update() { - if (enable_OLED) - display.display(); - if (enable_Serial) - delay(100); -} - -void display_Clear() { - if (enable_OLED) { - display.clearDisplay(); - display.setCursor(0, 0); - } -} - -unsigned char question_box(const char* question, char answers[7][20], int num_answers, int default_choice) { - if (enable_OLED) { - return questionBox_OLED(question, answers, num_answers, default_choice); - } - if (enable_Serial) { - return questionBox_Serial(question, answers, num_answers, default_choice); - } -} - -/****************************************** - Serial Out -*****************************************/ -void wait_serial() { - while (Serial.available() == 0) { - } - incomingByte = Serial.read() - 48; - /* if ((incomingByte == 53) && (fileName[0] != '\0')) { - // Open file on sd card - sd.chdir(folder); - if (myFile.open(fileName, O_READ)) { - // Get rom size from file - fileSize = myFile.fileSize(); - - // Send filesize - char tempStr[16]; - sprintf(tempStr, "%d", fileSize); - Serial.write(tempStr); - - // Wait for ok - while (Serial.available() == 0) { - } - - // Send file - for (unsigned long currByte = 0; currByte < fileSize; currByte++) { - // Blink led - if (currByte % 1024 == 0) - PORTB ^= (1 << 4); - Serial.write(myFile.read()); - } - // Close the file: - myFile.close(); - } - else { - print_Error(F("Can't open file"), true); - } - }*/ -} - -byte questionBox_Serial(const char* question, char answers[7][20], int num_answers, int default_choice) { - // Print menu to serial monitor - if (filebrowse) { - Serial.print("Filebrowser: "); - } - Serial.println(question); - for (byte i = 0; i < num_answers; i++) { - Serial.print(i); - Serial.print(F(")")); - Serial.println(answers[i]); - } - // Wait for user input - Serial.println(""); - Serial.println(F("Please browse pages with 'u'(up) and 'd'(down)")); - Serial.println(F("and enter a selection by typing a number(0-6): _ ")); - while (Serial.available() == 0) { - } - - // Read the incoming byte: - incomingByte = Serial.read() - 48; - - /* Import file (i) - if (incomingByte == 57) { - if (filebrowse == 1) { - // Make sure we have an import directory - sd.mkdir("IMPORT", true); - - // Create and open file on sd card - EEPROM_readAnything(10, foldern); - sprintf(fileName, "IMPORT/%d.bin", foldern); - if (!myFile.open(fileName, O_RDWR | O_CREAT)) { - print_Error(F("Can't create file on SD"), true); - } - - // Read file from serial - fileSize = 0; - while (Serial.available() > 0) { - myFile.write(Serial.read()); - fileSize++; - // Blink led - PORTB ^= (1 << 4); - } - - // Close the file: - myFile.close(); - - // Write new folder number back to eeprom - foldern = foldern + 1; - EEPROM_writeAnything(10, foldern); - - print_Msg("Imported "); - print_Msg(fileSize); - print_Msg(" bytes to file "); - println_Msg(fileName); - return 7; - } - }*/ - - // Page up (u) - if (incomingByte == 69) { - if (filebrowse == 1) { - if (currPage > 1) { - lastPage = currPage; - currPage--; - } - else { - root = 1; - } - } - } - - // Page down (d) - else if (incomingByte == 52) { - if ((numPages > currPage) && (filebrowse == 1)) { - lastPage = currPage; - currPage++; - } - } - - // Print the received byte for validation e.g. in case of a different keyboard mapping - //Serial.println(incomingByte); - //Serial.println(""); - return incomingByte; -} - -/****************************************** - RGB LED -*****************************************/ -void rgbLed(byte Color) { - switch (Color) { - case blue_color: - rgb.setColor(0, 0, 255); - break; - case red_color: - rgb.setColor(255, 0, 0); - break; - case purple_color: - rgb.setColor(255, 0, 255); - break; - case green_color: - rgb.setColor(0, 255, 0); - break; - case turquoise_color: - rgb.setColor(0, 255, 255); - break; - case yellow_color: - rgb.setColor(255, 255, 0); - break; - case white_color: - rgb.setColor(255, 255, 255); - break; - } -} - -/****************************************** - OLED Menu Module -*****************************************/ -// Read button state -int checkButton() { -#ifdef enable_Button2 - if (checkButton2() != 0) - return 3; - else - return (checkButton1()); -#else - return (checkButton1()); -#endif -} - -// Read button 1 -int checkButton1() { - int event = 0; - // Read the state of the button (PD7) - buttonVal1 = (PIND & (1 << 7)); - // Button pressed down - if (buttonVal1 == LOW && buttonLast1 == HIGH && (millis() - upTime1) > debounce) { - downTime1 = millis(); - ignoreUp1 = false; - waitForUp1 = false; - singleOK1 = true; - holdEventPast1 = false; - longholdEventPast1 = false; - if ((millis() - upTime1) < DCgap && DConUp1 == false && DCwaiting1 == true) DConUp1 = true; - else DConUp1 = false; - DCwaiting1 = false; - } - // Button released - else if (buttonVal1 == HIGH && buttonLast1 == LOW && (millis() - downTime1) > debounce) { - if (not ignoreUp1) { - upTime1 = millis(); - if (DConUp1 == false) DCwaiting1 = true; - else { - event = 2; - DConUp1 = false; - DCwaiting1 = false; - singleOK1 = false; - } - } - } - // Test for normal click event: DCgap expired - if ( buttonVal1 == HIGH && (millis() - upTime1) >= DCgap && DCwaiting1 == true && DConUp1 == false && singleOK1 == true) { - event = 1; - DCwaiting1 = false; - } - // Test for hold - if (buttonVal1 == LOW && (millis() - downTime1) >= holdTime) { - // Trigger "normal" hold - if (not holdEventPast1) { - event = 3; - waitForUp1 = true; - ignoreUp1 = true; - DConUp1 = false; - DCwaiting1 = false; - //downTime1 = millis(); - holdEventPast1 = true; - } - // Trigger "long" hold - if ((millis() - downTime1) >= longHoldTime) { - if (not longholdEventPast1) { - event = 4; - longholdEventPast1 = true; - } - } - } - buttonLast1 = buttonVal1; - return event; -} - -// Read button 2 -int checkButton2() { - int event = 0; - // Read the state of the button (PD7) - buttonVal2 = (PING & (1 << 2)); - // Button pressed down - if (buttonVal2 == LOW && buttonLast2 == HIGH && (millis() - upTime2) > debounce) { - downTime2 = millis(); - ignoreUp2 = false; - waitForUp2 = false; - singleOK2 = true; - holdEventPast2 = false; - longholdEventPast2 = false; - if ((millis() - upTime2) < DCgap && DConUp2 == false && DCwaiting2 == true) DConUp2 = true; - else DConUp2 = false; - DCwaiting2 = false; - } - // Button released - else if (buttonVal2 == HIGH && buttonLast2 == LOW && (millis() - downTime2) > debounce) { - if (not ignoreUp2) { - upTime2 = millis(); - if (DConUp2 == false) DCwaiting2 = true; - else { - event = 2; - DConUp2 = false; - DCwaiting2 = false; - singleOK2 = false; - } - } - } - // Test for normal click event: DCgap expired - if ( buttonVal2 == HIGH && (millis() - upTime2) >= DCgap && DCwaiting2 == true && DConUp2 == false && singleOK2 == true) { - event = 1; - DCwaiting2 = false; - } - // Test for hold - if (buttonVal2 == LOW && (millis() - downTime2) >= holdTime) { - // Trigger "normal" hold - if (not holdEventPast2) { - event = 3; - waitForUp2 = true; - ignoreUp2 = true; - DConUp2 = false; - DCwaiting2 = false; - //downTime2 = millis(); - holdEventPast2 = true; - } - // Trigger "long" hold - if ((millis() - downTime2) >= longHoldTime) { - if (not longholdEventPast2) { - event = 4; - longholdEventPast2 = true; - } - } - } - buttonLast2 = buttonVal2; - return event; -} - -// Wait for user to push button -void wait_btn() { - // Change led to green - if (errorLvl == 0) - rgbLed(green_color); - - while (1) - { - // get input button - int b = checkButton(); - - // Send some clock pulses to the Eeprom in case it locked up - if ((mode == mode_N64_Cart) && ((saveType == 5) || (saveType == 6))) { - pulseClock_N64(1); - } - // if the cart readers input button is pressed shortly - if (b == 1) { - errorLvl = 0; - break; - } - - // if the cart readers input button is pressed long - if (b == 3) { - if (errorLvl) { - // Debug - //ignoreError = 1; - errorLvl = 0; - } - break; - } - } -} - -// Display a question box with selectable answers. Make sure default choice is in (0, num_answers] -unsigned char questionBox_OLED(const char* question, char answers[7][20], int num_answers, int default_choice) { - - //clear the screen - display.clearDisplay(); - display.display(); - display.setCursor(0, 0); - - // change the rgb led to the start menu color - rgbLed(default_choice); - - // print menu - display.println(question); - for (unsigned char i = 0; i < num_answers; i++) { - // Add space for the selection dot - display.print(" "); - // Print menu item - display.println(answers[i]); - } - display.display(); - - // start with the default choice - choice = default_choice; - - // draw selection box - display.drawPixel(0, 8 * choice + 12, WHITE); - display.display(); - - unsigned long idleTime = millis(); - byte currentColor = 0; - - // wait until user makes his choice - while (1) { - // Attract Mode - if (millis() - idleTime > 300000) { - if ((millis() - idleTime) % 4000 == 0) { - if (currentColor < 7) { - currentColor++; - } - else { - currentColor = 0; - } - } - rgbLed(currentColor); - } - - /* Check Button - 1 click - 2 doubleClick - 3 hold - 4 longHold */ - int b = checkButton(); - - if (b == 2) { - idleTime = millis(); - - // remove selection box - display.drawPixel(0, 8 * choice + 12, BLACK); - display.display(); - - if ((choice == 0) && (filebrowse == 1)) { - if (currPage > 1) { - lastPage = currPage; - currPage--; - break; - } - else { - root = 1; - break; - } - } - else if (choice > 0) { - choice--; - } - else { - choice = num_answers - 1; - } - - // draw selection box - display.drawPixel(0, 8 * choice + 12, WHITE); - display.display(); - - // change RGB led to the color of the current menu option - rgbLed(choice); - } - - // go one down in the menu if the Cart Dumpers button is clicked shortly - - if (b == 1) { - idleTime = millis(); - - // remove selection box - display.drawPixel(0, 8 * choice + 12, BLACK); - display.display(); - - if ((choice == num_answers - 1 ) && (numPages > currPage) && (filebrowse == 1)) { - lastPage = currPage; - currPage++; - break; - } - else - choice = (choice + 1) % num_answers; - - // draw selection box - display.drawPixel(0, 8 * choice + 12, WHITE); - display.display(); - - // change RGB led to the color of the current menu option - rgbLed(choice); - } - - // if the Cart Dumpers button is hold continiously leave the menu - // so the currently highlighted action can be executed - - if (b == 3) { - idleTime = millis(); - break; - } - } - - // pass on user choice - rgb.setColor(0, 0, 0); - return choice; -} - -/****************************************** - Filebrowser Module -*****************************************/ -void fileBrowser(const char browserTitle[]) { - char fileNames[30][26]; - int currFile; - filebrowse = 1; - - // Empty filePath string - filePath[0] = '\0'; - - // Temporary char array for filename - char nameStr[26]; - -browserstart: - - // Set currFile back to 0 - currFile = 0; - currPage = 1; - lastPage = 1; - - // Read in File as long as there are files - while (myFile.openNext(sd.vwd(), O_READ)) { - - // Get name of file - myFile.getName(nameStr, 27); - - // Ignore if hidden - if (myFile.isHidden()) { - } - // Indicate a directory. - else if (myFile.isDir()) { - // Copy full dirname into fileNames - sprintf(fileNames[currFile], "%s%s", "/", nameStr); - // Truncate to 19 letters for LCD - nameStr[19] = '\0'; - // Copy short string into fileOptions - sprintf(fileOptions[currFile], "%s%s", "/", nameStr); - currFile++; - } - // It's just a file - else if (myFile.isFile()) { - // Copy full filename into fileNames - sprintf(fileNames[currFile], "%s", nameStr); - // Truncate to 19 letters for LCD - nameStr[19] = '\0'; - // Copy short string into fileOptions - sprintf(fileOptions[currFile], "%s", nameStr); - currFile++; - } - myFile.close(); - } - - // "Calculate number of needed pages" - if (currFile < 8) - numPages = 1; - else if (currFile < 15) - numPages = 2; - else if (currFile < 22) - numPages = 3; - else if (currFile < 29) - numPages = 4; - else if (currFile < 36) - numPages = 5; - - // Fill the array "answers" with 7 options to choose from in the file browser - char answers[7][20]; - -page: - - // If there are less than 7 entries, set count to that number so no empty options appear - byte count; - if (currFile < 8) - count = currFile; - else if (currPage == 1) - count = 7; - else if (currFile < 15) - count = currFile - 7; - else if (currPage == 2) - count = 7; - else if (currFile < 22) - count = currFile - 14; - else if (currPage == 3) - count = 7; - else if (currFile < 29) - count = currFile - 21; - else { - display_Clear(); - - println_Msg(F("Too many files")); - display_Update(); - println_Msg(F("")); - println_Msg(F("Press Button...")); - display_Update(); - wait(); - } - - for (byte i = 0; i < 8; i++ ) { - // Copy short string into fileOptions - sprintf( answers[i], "%s", fileOptions[ ((currPage - 1) * 7 + i)] ); - } - - // Create menu with title "Filebrowser" and 1-7 options to choose from - unsigned char answer = question_box(browserTitle, answers, count, 0); - - // Check if the page has been switched - if (currPage != lastPage) { - lastPage = currPage; - goto page; - } - - // Check if we are supposed to go back to the root dir - if (root) { - // Empty filePath string - filePath[0] = '\0'; - // Rewind filesystem - //sd.vwd()->rewind(); - // Change working dir to root - sd.chdir("/"); - // Start again - root = 0; - goto browserstart; - } - - // wait for user choice to come back from the question box menu - switch (answer) - { - case 0: - strcpy(fileName, fileNames[0 + ((currPage - 1) * 7)]); - break; - - case 1: - strcpy(fileName, fileNames[1 + ((currPage - 1) * 7)]); - break; - - case 2: - strcpy(fileName, fileNames[2 + ((currPage - 1) * 7)]); - break; - - case 3: - strcpy(fileName, fileNames[3 + ((currPage - 1) * 7)]); - break; - - case 4: - strcpy(fileName, fileNames[4 + ((currPage - 1) * 7)]); - break; - - case 5: - strcpy(fileName, fileNames[5 + ((currPage - 1) * 7)]); - break; - - case 6: - strcpy(fileName, fileNames[6 + ((currPage - 1) * 7)]); - break; - - case 7: - // File import - break; - } - - // Add directory to our filepath if we just entered a new directory - if (fileName[0] == '/') { - // add dirname to path - strcat(filePath, fileName); - // Remove / from dir name - char* dirName = fileName + 1; - // Change working dir - sd.chdir(dirName); - // Start browser in new directory again - goto browserstart; - } - else { - // Afer everything is done change SD working directory back to root - sd.chdir("/"); - } - filebrowse = 0; -} - -/****************************************** - Main loop -*****************************************/ -void loop() { - if (mode == mode_N64_Controller) { - n64ControllerMenu(); - } - else if (mode == mode_N64_Cart) { - n64CartMenu(); - } - else if (mode == mode_SNES) { - snesMenu(); - } - else if (mode == mode_FLASH8) { - flashromMenu8(); - } - else if (mode == mode_FLASH16) { - flashromMenu16(); - } - else if (mode == mode_EPROM) { - epromMenu(); - } - else if (mode == mode_SFM) { - sfmMenu(); - } - else if (mode == mode_GB) { - gbMenu(); - } - else if (mode == mode_GBA) { - gbaMenu(); - } - else if (mode == mode_SFM_Flash) { - sfmFlashMenu(); - } - else if (mode == mode_SFM_Game) { - sfmGameOptions(); - } - else if (mode == mode_GBM) { - gbmMenu(); - } - else if (mode == mode_MD) { - mdMenu(); - } - else if (mode == mode_PCE) { - pceMenu(); - } - else { - display_Clear(); - println_Msg(F("Menu Error")); - println_Msg(""); - println_Msg(""); - print_Msg(F("Mode = ")); - print_Msg(mode); - println_Msg(F("")); - println_Msg(F("Press Button...")); - display_Update(); - wait(); - asm volatile (" jmp 0"); - } -} - -//****************************************** -// End of File +/********************************************************************************** + Cartridge Reader for Arduino Mega2560 + + Author: sanni + Date: 05-10-2018 + Version: 1.9 + + SD lib: https://github.com/greiman/SdFat + LCD lib: https://github.com/adafruit/Adafruit_SSD1306 + Clockgen: https://github.com/etherkit/Si5351Arduino + RGB Tools lib: https://github.com/joushx/Arduino-RGB-Tools + + Compiled with Arduino 1.8.7 + + Thanks to: + MichlK - ROM-Reader for Super Nintendo + Jeff Saltzman - 4-Way Button + Wayne and Layne - Video-Game-Shield menu + skaman - SNES enhancements, SA1 sram support and GB flash fix + nocash - Nintendo Power and GBA Eeprom commands and lots of other info + crazynation - N64 bus timing + hkz/themanbehindthecurtain - N64 flashram commands + jago85 - help with N64 stuff + Andrew Brown/Peter Den Hartog - N64 controller protocol + bryc - mempak + Shaun Taylor - N64 controller CRC functions + Angus Gratton - CRC32 + Tamanegi_taro - SA1 fix and PCE support + Snes9x - SuperFX sram fix + zzattack - multigame pcb fix + Pickle - SDD1 fix + insidegadgets - GBCartRead + RobinTheHood - GameboyAdvanceRomDumper + YamaArashi - GBA flashrom bank switch command + infinest - help with GB Memory cart + +**********************************************************************************/ +char ver[5] = "1.9"; + +/****************************************** + Define Starting Point +******************************************/ +// mainMenu, n64Menu, snsMenu, gbxMenu, segaMenu, flashMenu, pceMenu +#define startMenu mainMenu + +/****************************************** + Define Output +******************************************/ +// To use the Serial Monitor change +// enable_OLED to 0 and enable_Serial to 1 +#define enable_OLED 1 +#define enable_Serial 0 + +/****************************************** + Define Input +******************************************/ +// If you are using the old version with only one button add // in front of the next line +#define enable_Button2 + +/****************************************** + Define SD Speed +******************************************/ +// Change to half speed if you get an sd error or it hangs when writing +#define sdSpeed SPI_FULL_SPEED +//#define sdSpeed SPI_HALF_SPEED + +/****************************************** + Options +******************************************/ +// If set to 1 then the crc32 checksum will be calculated after reading a N64 rom +boolean n64crc = 1; + +/****************************************** + Libraries + *****************************************/ +// Basic Libs +#include +#include +#include + +// AVR Eeprom +#include +#include "EEPROMAnything.h" + +// Graphic I2C LCD +#include +#include +#define OLED_RESET 4 +Adafruit_SSD1306 display(OLED_RESET); +// Check if Adafruit_SSD1306.h was setup for 128x64 +#if (SSD1306_LCDHEIGHT != 64) +#error("Incorrect height defined in Adafruit_SSD1306.h"); +#endif + +// Adafruit Clock Generator +#include +Si5351 clockgen; + +// RGB LED +#include + +// Set pins of red, green and blue +RGBTools rgb(12, 11, 10); + +typedef enum COLOR_T { + blue_color, + red_color, + purple_color, + green_color, + turquoise_color, + yellow_color, + white_color, +} color_t; + +// SD Card (Pin 50 = MISO, Pin 51 = MOSI, Pin 52 = SCK, Pin 53 = SS) +#include +#define chipSelectPin 53 +SdFat sd; +SdFile myFile; + +/****************************************** + Defines + *****************************************/ +// Mode menu +#define mode_N64_Cart 0 +#define mode_N64_Controller 1 +#define mode_SNES 2 +#define mode_SFM 3 +#define mode_SFM_Flash 4 +#define mode_SFM_Game 5 +#define mode_GB 6 +#define mode_FLASH8 7 +#define mode_FLASH16 8 +#define mode_GBA 9 +#define mode_GBM 10 +#define mode_MD 11 +#define mode_EPROM 12 +#define mode_PCE 13 + +/****************************************** + Variables + *****************************************/ +// Button timing +static int debounce = 20; // ms debounce period to prevent flickering when pressing or releasing the button +static int DCgap = 250; // max ms between clicks for a double click event +static int holdTime = 2000; // ms hold period: how long to wait for press+hold event +static int longHoldTime = 5000; // ms long hold period: how long to wait for press+hold event +// Variables for button 1 +boolean buttonVal1 = HIGH; // value read from button +boolean buttonLast1 = HIGH; // buffered value of the button's previous state +boolean DCwaiting1 = false; // whether we're waiting for a double click (down) +boolean DConUp1 = false; // whether to register a double click on next release, or whether to wait and click +boolean singleOK1 = true; // whether it's OK to do a single click +long downTime1 = -1; // time the button was pressed down +long upTime1 = -1; // time the button was released +boolean ignoreUp1 = false; // whether to ignore the button release because the click+hold was triggered +boolean waitForUp1 = false; // when held, whether to wait for the up event +boolean holdEventPast1 = false; // whether or not the hold event happened already +boolean longholdEventPast1 = false;// whether or not the long hold event happened already +// Variables for button 2 +boolean buttonVal2 = HIGH; // value read from button +boolean buttonLast2 = HIGH; // buffered value of the button's previous state +boolean DCwaiting2 = false; // whether we're waiting for a double click (down) +boolean DConUp2 = false; // whether to register a double click on next release, or whether to wait and click +boolean singleOK2 = true; // whether it's OK to do a single click +long downTime2 = -1; // time the button was pressed down +long upTime2 = -1; // time the button was released +boolean ignoreUp2 = false; // whether to ignore the button release because the click+hold was triggered +boolean waitForUp2 = false; // when held, whether to wait for the up event +boolean holdEventPast2 = false; // whether or not the hold event happened already +boolean longholdEventPast2 = false;// whether or not the long hold event happened already + +// For incoming serial data +int incomingByte; + +// Variables for the menu +int choice = 0; +// Temporary array that holds the menu option read out of progmem +char menuOptions[7][20]; +boolean ignoreError = 0; + +// File browser +char fileName[26]; +char filePath[50]; +byte currPage; +byte lastPage; +byte numPages; +boolean root = 0; +boolean filebrowse = 0; +char fileOptions[30][20]; + +// Common +char romName[17]; +unsigned long sramSize = 0; +int romType = 0; +byte saveType; +word romSize = 0; +byte numBanks = 128; +char checksumStr[5]; +bool errorLvl = 0; +byte romVersion = 0; +char cartID[5]; +unsigned long cartSize; +char flashid[5]; +char vendorID[5]; +unsigned long fileSize; +unsigned long sramBase; + +// Variable to count errors +unsigned long writeErrors; + +// Operation mode +byte mode; + +//remember folder number to create a new folder for every save +int foldern; +char folder[36]; + +// Array that holds the data +byte sdBuffer[512]; + +//****************************************** +// Bitmaps +//****************************************** +static const unsigned char PROGMEM icon [] = { + 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x00, 0x0F, 0xFF, + 0x00, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x00, + 0x0F, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0xF8, + 0x00, 0x0F, 0xFF, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0xF8, 0x00, 0x0F, 0xFF, 0x00, 0x0F, 0xFF, 0x00, + 0x00, 0xFF, 0x80, 0x0F, 0xFF, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0xFF, 0x80, 0x0F, 0x00, 0x0F, 0xFF, + 0xFF, 0xFF, 0xF0, 0x0F, 0x80, 0x0F, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0x80, 0x0F, 0x00, + 0x0F, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0x80, 0x0F, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0x80, + 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x80, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x0F, 0xF0, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x0F, 0xF0, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0x00, 0xF0, 0xF0, 0x0F, 0xFF, + 0xF0, 0x00, 0xFF, 0xFF, 0x00, 0xF0, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0x00, 0xF0, 0xF0, + 0x0F, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0x00, 0xF0, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0xF0, 0x00, + 0xFF, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0xF0, 0x00, 0xFF, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0xFF, + 0xF0, 0x00, 0xFF, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0xF0, 0x00, 0xFF, 0xF0, 0x00, 0x0F, 0xF0, + 0x00, 0xFF, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0xF0, 0x00, 0x0F, 0xF0, 0x00, + 0x0F, 0xF0, 0x00, 0xFF, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0xF0, 0x00, 0x0F, + 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0xF0, + 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, + 0xFF, 0xF0, 0x00, 0x0F, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xF0, 0x0F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xF0, + 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x1F, 0xF0, 0xFF, 0xF0, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x1F, 0xF0, 0xFF, 0xF0, 0xFF, 0x0F, 0xFF, 0x0F, 0xF0, 0x1F, 0xF0, + 0xFF, 0xF0, 0xFF, 0x0F, 0xFF, 0x0F, 0xF0, 0x1F, 0xF0, 0xFF, 0xF0, 0xFF, 0x0F, 0xFF, 0x0F, 0xF0, + 0x01, 0xF0, 0xFF, 0xF0, 0xFF, 0x0F, 0xFF, 0x0F, 0x80, 0x01, 0xF0, 0xFF, 0xF0, 0xFF, 0x0F, 0xFF, + 0x0F, 0x80, 0x01, 0xF0, 0xFF, 0xF0, 0xFF, 0x0F, 0xFF, 0x0F, 0x80, 0x01, 0xF0, 0xFF, 0xF0, 0xFF, + 0x0F, 0xFF, 0x0F, 0x80, 0x01, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x80, 0x01, 0xF0, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x80, 0x01, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x80, 0x01, + 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x80, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, + 0x80, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0x80, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x01, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x01, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80 +}; + +static const unsigned char PROGMEM sig [] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0xF0, 0x80, 0x40, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x90, 0xCC, 0x4E, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x90, 0x5C, 0x7B, 0x19, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xB8, 0x56, 0x31, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0xA8, 0x72, 0x31, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xAC, 0x23, 0x21, 0x86, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xE7, 0xA1, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +//For PC Engine +extern void pcsMenu(void); +extern void pceMenu(void); + +/****************************************** + Menu +*****************************************/ +// Main menu +static const char modeItem1[] PROGMEM = "Nintendo 64"; +static const char modeItem2[] PROGMEM = "Super Nintendo"; +static const char modeItem3[] PROGMEM = "Game Boy"; +static const char modeItem4[] PROGMEM = "Mega Drive"; +static const char modeItem5[] PROGMEM = "Flashrom Programmer"; +static const char modeItem6[] PROGMEM = "PC Engine/TG16"; +static const char modeItem7[] PROGMEM = "About"; +static const char* const modeOptions[] PROGMEM = {modeItem1, modeItem2, modeItem3, modeItem4, modeItem5, modeItem6, modeItem7}; + +void aboutScreen() { + display_Clear(); + // Draw the Logo + display.drawBitmap(0, 0, sig, 128, 64, 1); + println_Msg(F("Cartridge Reader")); + println_Msg(F("github.com/sanni")); + print_Msg(F("2018 Version ")); + println_Msg(ver); + println_Msg(F("")); + println_Msg(F("")); + println_Msg(F("")); + println_Msg(F("")); + println_Msg(F("Press Button")); + display_Update(); + + while (1) { + if (enable_OLED) { + // get input button + int b = checkButton(); + + // if the cart readers input button is pressed shortly + if (b == 1) { + asm volatile (" jmp 0"); + } + + // if the cart readers input button is pressed long + if (b == 3) { + asm volatile (" jmp 0"); + } + + // if the button is pressed super long + if (b == 4) { + display_Clear(); + println_Msg(F("Resetting folder...")); + display_Update(); + delay(2000); + foldern = 0; + EEPROM_writeAnything(10, foldern); + asm volatile (" jmp 0"); + } + } + if (enable_Serial) { + wait_serial(); + asm volatile (" jmp 0"); + } + rgb.setColor(random(0, 255), random(0, 255), random(0, 255)); + delay(random(50, 100)); + } +} + +void mainMenu() { + // create menu with title and 6 options to choose from + unsigned char modeMenu; + // Copy menuOptions out of progmem + convertPgm(modeOptions, 7); + modeMenu = question_box("Cartridge Reader", menuOptions, 7, 0); + + // wait for user choice to come back from the question box menu + switch (modeMenu) + { + case 0: + n64Menu(); + break; + + case 1: + snsMenu(); + break; + + case 2: + gbxMenu(); + break; + + case 3: + segaMenu(); + break; + + case 4: + flashMenu(); + break; + case 5: + pcsMenu(); + break; + case 6: + aboutScreen(); + break; + } +} + +/****************************************** + Setup + *****************************************/ +void setup() { + // Set Button Pins(PD7, PG2) to Input + DDRD &= ~(1 << 7); + DDRG &= ~(1 << 2); + // Activate Internal Pullup Resistors + //PORTD |= (1 << 7); + //PORTG |= (1 << 2); + + // Read current folder number out of eeprom + EEPROM_readAnything(10, foldern); + + if (enable_OLED) { + // GLCD + display.begin(SSD1306_SWITCHCAPVCC, 0x3C); + display.setTextSize(1); + display.setTextColor(WHITE); + + // Clear the screen buffer. + display_Clear(); + delay(100); + + // Draw line + display.drawLine(0, 32, 127, 32, WHITE); + display_Update(); + delay(100); + + // Initialize LED + rgb.setColor(0, 0, 0); + + // Clear the screen. + display_Clear(); + display_Update(); + delay(25); + + // Draw the Logo + display.drawBitmap(28, 0, icon, 72, 64, 1); + for (int s = 1; s < 64; s += 2) { + // Draw Scanlines + display.drawLine(0, s, 127, s, BLACK); + } + display_Update(); + delay(50); + + // Clear the screen. + display_Clear(); + display_Update(); + delay(25); + + // Draw the Logo + display.drawBitmap(28, 0, icon, 72, 64, 1); + for (int s = 1; s < 64; s += 2) { + // Draw Scanlines + display.drawLine(0, s, 127, s, BLACK); + } + display.setCursor(100, 55); + display.println(ver); + display_Update(); + delay(200); + } + + if (enable_Serial) { + // Serial Begin + Serial.begin(9600); + Serial.println(F("Cartridge Reader")); + Serial.println(F("2018 sanni")); + Serial.println(""); + // LED Error + rgb.setColor(0, 0, 255); + } + else { + // LED Off + rgb.setColor(0, 0, 0); + } + + // Init SD card + if (!sd.begin(chipSelectPin, sdSpeed)) { + display_Clear(); + print_Error(F("SD Error"), true); + } + + if (enable_Serial) { + // Print SD Info + Serial.print(F("SD Card: ")); + Serial.print(sd.card()->cardSize() * 512E-9); + Serial.print(F("GB FAT")); + Serial.println(int(sd.vol()->fatType())); + } + + startMenu(); +} + +/****************************************** + Common I/O Functions + *****************************************/ +// Switch data pins to write +void dataOut() { + DDRC = 0xFF; +} + +// Switch data pins to read +void dataIn() { + // Set to Input and activate pull-up resistors + DDRC = 0x00; + // Pullups + PORTC = 0xFF; +} + +/****************************************** + Helper Functions + *****************************************/ +// Converts a progmem array into a ram array +void convertPgm(const char* const pgmOptions[], byte numArrays) { + for (int i = 0; i < numArrays; i++) { + strcpy_P(menuOptions[i], (char*)pgm_read_word(&(pgmOptions[i]))); + } +} + +void print_Error(const __FlashStringHelper *errorMessage, boolean forceReset) { + errorLvl = 1; + rgb.setColor(255, 0, 0); + println_Msg(errorMessage); + display_Update(); + + if (forceReset) { + if (enable_Serial) { + println_Msg(F("Fatal Error, please reset")); + while (1); + } + else { + println_Msg(F("")); + println_Msg(F("Press Button...")); + display_Update(); + wait(); + if (ignoreError == 0) { + asm volatile (" jmp 0"); + } + else { + ignoreError = 0; + display_Clear(); + println_Msg(F("")); + println_Msg(F("")); + println_Msg(F("")); + println_Msg(F(" Error Overwrite")); + display_Update(); + delay(2000); + } + } + } +} + +void wait() { + if (enable_OLED) { + wait_btn(); + } + if (enable_Serial) { + wait_serial(); + } +} + +void print_Msg(const __FlashStringHelper *string) { + if (enable_OLED) + display.print(string); + if (enable_Serial) + Serial.print(string); +} + +void print_Msg(const char string[]) { + if (enable_OLED) + display.print(string); + if (enable_Serial) + Serial.print(string); +} + +void print_Msg(long unsigned int message) { + if (enable_OLED) + display.print(message); + if (enable_Serial) + Serial.print(message); +} + +void print_Msg(byte message, int outputFormat) { + if (enable_OLED) + display.print(message, outputFormat); + if (enable_Serial) + Serial.print(message, outputFormat); +} + +void print_Msg(String string) { + if (enable_OLED) + display.print(string); + if (enable_Serial) + Serial.print(string); +} + +void println_Msg(String string) { + if (enable_OLED) + display.println(string); + if (enable_Serial) + Serial.println(string); +} + +void println_Msg(byte message, int outputFormat) { + if (enable_OLED) + display.println(message, outputFormat); + if (enable_Serial) + Serial.println(message, outputFormat); +} + +void println_Msg(const char message[]) { + if (enable_OLED) + display.println(message); + if (enable_Serial) + Serial.println(message); +} + +void println_Msg(const __FlashStringHelper *string) { + if (enable_OLED) + display.println(string); + if (enable_Serial) + Serial.println(string); +} + +void println_Msg(long unsigned int message) { + if (enable_OLED) + display.println(message); + if (enable_Serial) + Serial.println(message); +} + +void display_Update() { + if (enable_OLED) + display.display(); + if (enable_Serial) + delay(100); +} + +void display_Clear() { + if (enable_OLED) { + display.clearDisplay(); + display.setCursor(0, 0); + } +} + +unsigned char question_box(const char* question, char answers[7][20], int num_answers, int default_choice) { + if (enable_OLED) { + return questionBox_OLED(question, answers, num_answers, default_choice); + } + else if (enable_Serial) { + return questionBox_Serial(question, answers, num_answers, default_choice); + } +} + +/****************************************** + Serial Out +*****************************************/ +void wait_serial() { + while (Serial.available() == 0) { + } + incomingByte = Serial.read() - 48; + /* if ((incomingByte == 53) && (fileName[0] != '\0')) { + // Open file on sd card + sd.chdir(folder); + if (myFile.open(fileName, O_READ)) { + // Get rom size from file + fileSize = myFile.fileSize(); + + // Send filesize + char tempStr[16]; + sprintf(tempStr, "%d", fileSize); + Serial.write(tempStr); + + // Wait for ok + while (Serial.available() == 0) { + } + + // Send file + for (unsigned long currByte = 0; currByte < fileSize; currByte++) { + // Blink led + if (currByte % 1024 == 0) + PORTB ^= (1 << 4); + Serial.write(myFile.read()); + } + // Close the file: + myFile.close(); + } + else { + print_Error(F("Can't open file"), true); + } + }*/ +} + +byte questionBox_Serial(const char* question, char answers[7][20], int num_answers, int default_choice) { + // Print menu to serial monitor + //Serial.println(question); + for (byte i = 0; i < num_answers; i++) { + Serial.print(i); + Serial.print(F(")")); + Serial.println(answers[i]); + } + // Wait for user input + Serial.println(""); + Serial.println(F("Please browse pages with 'u'(up) and 'd'(down)")); + Serial.println(F("and enter a selection by typing a number(0-6): _ ")); + while (Serial.available() == 0) { + } + + // Read the incoming byte: + incomingByte = Serial.read() - 48; + + /* Import file (i) + if (incomingByte == 57) { + if (filebrowse == 1) { + // Make sure we have an import directory + sd.mkdir("IMPORT", true); + + // Create and open file on sd card + EEPROM_readAnything(10, foldern); + sprintf(fileName, "IMPORT/%d.bin", foldern); + if (!myFile.open(fileName, O_RDWR | O_CREAT)) { + print_Error(F("Can't create file on SD"), true); + } + + // Read file from serial + fileSize = 0; + while (Serial.available() > 0) { + myFile.write(Serial.read()); + fileSize++; + // Blink led + PORTB ^= (1 << 4); + } + + // Close the file: + myFile.close(); + + // Write new folder number back to eeprom + foldern = foldern + 1; + EEPROM_writeAnything(10, foldern); + + print_Msg("Imported "); + print_Msg(fileSize); + print_Msg(" bytes to file "); + println_Msg(fileName); + return 7; + } + }*/ + + // Page up (u) + if (incomingByte == 69) { + if (filebrowse == 1) { + if (currPage > 1) { + lastPage = currPage; + currPage--; + } + else { + root = 1; + } + } + } + + // Page down (d) + else if (incomingByte == 52) { + if ((numPages > currPage) && (filebrowse == 1)) { + lastPage = currPage; + currPage++; + } + } + + // Print the received byte for validation e.g. in case of a different keyboard mapping + //Serial.println(incomingByte); + //Serial.println(""); + return incomingByte; +} + +/****************************************** + RGB LED +*****************************************/ +void rgbLed(byte Color) { + switch (Color) { + case blue_color: + rgb.setColor(0, 0, 255); + break; + case red_color: + rgb.setColor(255, 0, 0); + break; + case purple_color: + rgb.setColor(255, 0, 255); + break; + case green_color: + rgb.setColor(0, 255, 0); + break; + case turquoise_color: + rgb.setColor(0, 255, 255); + break; + case yellow_color: + rgb.setColor(255, 255, 0); + break; + case white_color: + rgb.setColor(255, 255, 255); + break; + } +} + +/****************************************** + OLED Menu Module +*****************************************/ +// Read button state +int checkButton() { +#ifdef enable_Button2 + if (checkButton2() != 0) + return 3; + else + return (checkButton1()); +#else + return (checkButton1()); +#endif +} + +// Read button 1 +int checkButton1() { + int event = 0; + // Read the state of the button (PD7) + buttonVal1 = (PIND & (1 << 7)); + // Button pressed down + if (buttonVal1 == LOW && buttonLast1 == HIGH && (millis() - upTime1) > debounce) { + downTime1 = millis(); + ignoreUp1 = false; + waitForUp1 = false; + singleOK1 = true; + holdEventPast1 = false; + longholdEventPast1 = false; + if ((millis() - upTime1) < DCgap && DConUp1 == false && DCwaiting1 == true) DConUp1 = true; + else DConUp1 = false; + DCwaiting1 = false; + } + // Button released + else if (buttonVal1 == HIGH && buttonLast1 == LOW && (millis() - downTime1) > debounce) { + if (not ignoreUp1) { + upTime1 = millis(); + if (DConUp1 == false) DCwaiting1 = true; + else { + event = 2; + DConUp1 = false; + DCwaiting1 = false; + singleOK1 = false; + } + } + } + // Test for normal click event: DCgap expired + if ( buttonVal1 == HIGH && (millis() - upTime1) >= DCgap && DCwaiting1 == true && DConUp1 == false && singleOK1 == true) { + event = 1; + DCwaiting1 = false; + } + // Test for hold + if (buttonVal1 == LOW && (millis() - downTime1) >= holdTime) { + // Trigger "normal" hold + if (not holdEventPast1) { + event = 3; + waitForUp1 = true; + ignoreUp1 = true; + DConUp1 = false; + DCwaiting1 = false; + //downTime1 = millis(); + holdEventPast1 = true; + } + // Trigger "long" hold + if ((millis() - downTime1) >= longHoldTime) { + if (not longholdEventPast1) { + event = 4; + longholdEventPast1 = true; + } + } + } + buttonLast1 = buttonVal1; + return event; +} + +// Read button 2 +int checkButton2() { + int event = 0; + // Read the state of the button (PD7) + buttonVal2 = (PING & (1 << 2)); + // Button pressed down + if (buttonVal2 == LOW && buttonLast2 == HIGH && (millis() - upTime2) > debounce) { + downTime2 = millis(); + ignoreUp2 = false; + waitForUp2 = false; + singleOK2 = true; + holdEventPast2 = false; + longholdEventPast2 = false; + if ((millis() - upTime2) < DCgap && DConUp2 == false && DCwaiting2 == true) DConUp2 = true; + else DConUp2 = false; + DCwaiting2 = false; + } + // Button released + else if (buttonVal2 == HIGH && buttonLast2 == LOW && (millis() - downTime2) > debounce) { + if (not ignoreUp2) { + upTime2 = millis(); + if (DConUp2 == false) DCwaiting2 = true; + else { + event = 2; + DConUp2 = false; + DCwaiting2 = false; + singleOK2 = false; + } + } + } + // Test for normal click event: DCgap expired + if ( buttonVal2 == HIGH && (millis() - upTime2) >= DCgap && DCwaiting2 == true && DConUp2 == false && singleOK2 == true) { + event = 1; + DCwaiting2 = false; + } + // Test for hold + if (buttonVal2 == LOW && (millis() - downTime2) >= holdTime) { + // Trigger "normal" hold + if (not holdEventPast2) { + event = 3; + waitForUp2 = true; + ignoreUp2 = true; + DConUp2 = false; + DCwaiting2 = false; + //downTime2 = millis(); + holdEventPast2 = true; + } + // Trigger "long" hold + if ((millis() - downTime2) >= longHoldTime) { + if (not longholdEventPast2) { + event = 4; + longholdEventPast2 = true; + } + } + } + buttonLast2 = buttonVal2; + return event; +} + +// Wait for user to push button +void wait_btn() { + // Change led to green + if (errorLvl == 0) + rgbLed(green_color); + + while (1) + { + // get input button + int b = checkButton(); + + // Send some clock pulses to the Eeprom in case it locked up + if ((mode == mode_N64_Cart) && ((saveType == 5) || (saveType == 6))) { + pulseClock_N64(1); + } + // if the cart readers input button is pressed shortly + if (b == 1) { + errorLvl = 0; + break; + } + + // if the cart readers input button is pressed long + if (b == 3) { + if (errorLvl) { + // Debug + //ignoreError = 1; + errorLvl = 0; + } + break; + } + } +} + +// Display a question box with selectable answers. Make sure default choice is in (0, num_answers] +unsigned char questionBox_OLED(const char* question, char answers[7][20], int num_answers, int default_choice) { + + //clear the screen + display.clearDisplay(); + display.display(); + display.setCursor(0, 0); + + // change the rgb led to the start menu color + rgbLed(default_choice); + + // print menu + display.println(question); + for (unsigned char i = 0; i < num_answers; i++) { + // Add space for the selection dot + display.print(" "); + // Print menu item + display.println(answers[i]); + } + display.display(); + + // start with the default choice + choice = default_choice; + + // draw selection box + display.drawPixel(0, 8 * choice + 12, WHITE); + display.display(); + + unsigned long idleTime = millis(); + byte currentColor = 0; + + // wait until user makes his choice + while (1) { + // Attract Mode + if (millis() - idleTime > 300000) { + if ((millis() - idleTime) % 4000 == 0) { + if (currentColor < 7) { + currentColor++; + } + else { + currentColor = 0; + } + } + rgbLed(currentColor); + } + + /* Check Button + 1 click + 2 doubleClick + 3 hold + 4 longHold */ + int b = checkButton(); + + if (b == 2) { + idleTime = millis(); + + // remove selection box + display.drawPixel(0, 8 * choice + 12, BLACK); + display.display(); + + if ((choice == 0) && (filebrowse == 1)) { + if (currPage > 1) { + lastPage = currPage; + currPage--; + break; + } + else { + root = 1; + break; + } + } + else if (choice > 0) { + choice--; + } + else { + choice = num_answers - 1; + } + + // draw selection box + display.drawPixel(0, 8 * choice + 12, WHITE); + display.display(); + + // change RGB led to the color of the current menu option + rgbLed(choice); + } + + // go one down in the menu if the Cart Dumpers button is clicked shortly + + if (b == 1) { + idleTime = millis(); + + // remove selection box + display.drawPixel(0, 8 * choice + 12, BLACK); + display.display(); + + if ((choice == num_answers - 1 ) && (numPages > currPage) && (filebrowse == 1)) { + lastPage = currPage; + currPage++; + break; + } + else + choice = (choice + 1) % num_answers; + + // draw selection box + display.drawPixel(0, 8 * choice + 12, WHITE); + display.display(); + + // change RGB led to the color of the current menu option + rgbLed(choice); + } + + // if the Cart Dumpers button is hold continiously leave the menu + // so the currently highlighted action can be executed + + if (b == 3) { + idleTime = millis(); + break; + } + } + + // pass on user choice + rgb.setColor(0, 0, 0); + return choice; +} + +/****************************************** + Filebrowser Module +*****************************************/ +void fileBrowser(const char* browserTitle) { + char fileNames[30][26]; + int currFile; + filebrowse = 1; + + // Empty filePath string + filePath[0] = '\0'; + + // Temporary char array for filename + char nameStr[26]; + +browserstart: + + // Print title + println_Msg(browserTitle); + + // Set currFile back to 0 + currFile = 0; + currPage = 1; + lastPage = 1; + + // Read in File as long as there are files + while (myFile.openNext(sd.vwd(), O_READ)) { + + // Get name of file + myFile.getName(nameStr, 27); + + // Ignore if hidden + if (myFile.isHidden()) { + } + // Indicate a directory. + else if (myFile.isDir()) { + // Copy full dirname into fileNames + sprintf(fileNames[currFile], "%s%s", "/", nameStr); + // Truncate to 19 letters for LCD + nameStr[19] = '\0'; + // Copy short string into fileOptions + sprintf(fileOptions[currFile], "%s%s", "/", nameStr); + currFile++; + } + // It's just a file + else if (myFile.isFile()) { + // Copy full filename into fileNames + sprintf(fileNames[currFile], "%s", nameStr); + // Truncate to 19 letters for LCD + nameStr[19] = '\0'; + // Copy short string into fileOptions + sprintf(fileOptions[currFile], "%s", nameStr); + currFile++; + } + myFile.close(); + } + + // "Calculate number of needed pages" + if (currFile < 8) + numPages = 1; + else if (currFile < 15) + numPages = 2; + else if (currFile < 22) + numPages = 3; + else if (currFile < 29) + numPages = 4; + else if (currFile < 36) + numPages = 5; + + // Fill the array "answers" with 7 options to choose from in the file browser + char answers[7][20]; + +page: + + // If there are less than 7 entries, set count to that number so no empty options appear + byte count; + if (currFile < 8) + count = currFile; + else if (currPage == 1) + count = 7; + else if (currFile < 15) + count = currFile - 7; + else if (currPage == 2) + count = 7; + else if (currFile < 22) + count = currFile - 14; + else if (currPage == 3) + count = 7; + else if (currFile < 29) + count = currFile - 21; + else { + display_Clear(); + + println_Msg(F("Too many files")); + display_Update(); + println_Msg(F("")); + println_Msg(F("Press Button...")); + display_Update(); + wait(); + } + + for (byte i = 0; i < 8; i++ ) { + // Copy short string into fileOptions + sprintf( answers[i], "%s", fileOptions[ ((currPage - 1) * 7 + i)] ); + } + + // Create menu with title and 1-7 options to choose from + unsigned char answer = question_box(browserTitle, answers, count, 0); + + // Check if the page has been switched + if (currPage != lastPage) { + lastPage = currPage; + goto page; + } + + // Check if we are supposed to go back to the root dir + if (root) { + // Empty filePath string + filePath[0] = '\0'; + // Rewind filesystem + //sd.vwd()->rewind(); + // Change working dir to root + sd.chdir("/"); + // Start again + root = 0; + goto browserstart; + } + + // wait for user choice to come back from the question box menu + switch (answer) + { + case 0: + strcpy(fileName, fileNames[0 + ((currPage - 1) * 7)]); + break; + + case 1: + strcpy(fileName, fileNames[1 + ((currPage - 1) * 7)]); + break; + + case 2: + strcpy(fileName, fileNames[2 + ((currPage - 1) * 7)]); + break; + + case 3: + strcpy(fileName, fileNames[3 + ((currPage - 1) * 7)]); + break; + + case 4: + strcpy(fileName, fileNames[4 + ((currPage - 1) * 7)]); + break; + + case 5: + strcpy(fileName, fileNames[5 + ((currPage - 1) * 7)]); + break; + + case 6: + strcpy(fileName, fileNames[6 + ((currPage - 1) * 7)]); + break; + + case 7: + // File import + break; + } + + // Add directory to our filepath if we just entered a new directory + if (fileName[0] == '/') { + // add dirname to path + strcat(filePath, fileName); + // Remove / from dir name + char* dirName = fileName + 1; + // Change working dir + sd.chdir(dirName); + // Start browser in new directory again + goto browserstart; + } + else { + // Afer everything is done change SD working directory back to root + sd.chdir("/"); + } + filebrowse = 0; +} + +/****************************************** + Main loop +*****************************************/ +void loop() { + if (mode == mode_N64_Controller) { + n64ControllerMenu(); + } + else if (mode == mode_N64_Cart) { + n64CartMenu(); + } + else if (mode == mode_SNES) { + snesMenu(); + } + else if (mode == mode_FLASH8) { + flashromMenu8(); + } + else if (mode == mode_FLASH16) { + flashromMenu16(); + } + else if (mode == mode_EPROM) { + epromMenu(); + } + else if (mode == mode_SFM) { + sfmMenu(); + } + else if (mode == mode_GB) { + gbMenu(); + } + else if (mode == mode_GBA) { + gbaMenu(); + } + else if (mode == mode_SFM_Flash) { + sfmFlashMenu(); + } + else if (mode == mode_SFM_Game) { + sfmGameOptions(); + } + else if (mode == mode_GBM) { + gbmMenu(); + } + else if (mode == mode_MD) { + mdMenu(); + } + else if (mode == mode_PCE) { + pceMenu(); + } + else { + display_Clear(); + println_Msg(F("Menu Error")); + println_Msg(""); + println_Msg(""); + print_Msg(F("Mode = ")); + print_Msg(mode); + println_Msg(F("")); + println_Msg(F("Press Button...")); + display_Update(); + wait(); + asm volatile (" jmp 0"); + } +} + +//****************************************** +// End of File //****************************************** diff --git a/Cart_Reader/FLASH.ino b/Cart_Reader/FLASH.ino index 97840dd..ae09325 100644 --- a/Cart_Reader/FLASH.ino +++ b/Cart_Reader/FLASH.ino @@ -1,2062 +1,2092 @@ -//****************************************** -// FLASHROM MODULE -//****************************************** - -/****************************************** - Variables - *****************************************/ -// Flashrom -unsigned long flashSize; -byte flashromType; -byte secondID = 1; -unsigned long time; -unsigned long blank; -unsigned long sectorSize; -byte bufferSize; -boolean hiROM = 1; - -/****************************************** - Menu - *****************************************/ -// Flash start menu -static const char flashMenuItem1[] PROGMEM = "8bit adapter"; -static const char flashMenuItem2[] PROGMEM = "16bit adapter(old)"; -static const char flashMenuItem3[] PROGMEM = "Eprom adapter(beta)"; -static const char* const menuOptionsFlash[] PROGMEM = {flashMenuItem1, flashMenuItem2, flashMenuItem3}; - -// 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 27C322"; -static const char epromMenuItem3[] PROGMEM = "Write 27C322"; -static const char epromMenuItem4[] PROGMEM = "Verify 27C322"; -static const char epromMenuItem5[] PROGMEM = "Reset"; -static const char* const menuOptionsEprom[] PROGMEM = {epromMenuItem1, epromMenuItem2, epromMenuItem3, epromMenuItem4, epromMenuItem5}; - -void flashMenu() { - // create menu with title and 3 options to choose from - unsigned char flashSlot; - // Copy menuOptions out of progmem - convertPgm(menuOptionsFlash, 3); - flashSlot = question_box("Select adapter PCB", menuOptions, 3, 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_Flash16(); - id_Flash16(); - wait(); - mode = mode_FLASH16; - break; - - case 2: - display_Clear(); - display_Update(); - setup_Eprom(); - mode = mode_EPROM; - 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("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(); - if (flashromType == 1) - resetFlash29F032(); - else - resetFlash29F1610(); - blankcheck_Flash(); - break; - - case 1: - display_Clear(); - println_Msg(F("Erasing Flashrom")); - println_Msg(F("Please wait...")); - display_Update(); - time = millis(); - if (flashromType == 1) { - eraseFlash29F032(); - } - else { - eraseFlash29F1610(); - } - println_Msg(F("Flashrom erased")); - display_Update(); - if (flashromType == 1) - resetFlash29F032(); - else - resetFlash29F1610(); - break; - - case 2: - time = millis(); - if (flashromType == 1) - resetFlash29F032(); - else - resetFlash29F1610(); - readFlash(); - break; - - case 3: - filePath[0] = '\0'; - sd.chdir("/"); - fileBrowser("Select file"); - display_Clear(); - time = millis(); - if (flashromType == 1) - writeFlash29F032(); - else if (flashromType == 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); - } - } - delay(100); - // Reset twice just to be sure - if (flashromType == 1) - resetFlash29F032(); - else - resetFlash29F1610(); - if (flashromType == 1) - resetFlash29F032(); - else - resetFlash29F1610(); - verifyFlash(); - break; - - case 4: - time = 0; - display_Clear(); - println_Msg(F("ID Flashrom")); - if (flashromType == 1) - idFlash29F032(); - else - idFlash29F1610(); - - println_Msg(F("")); - printFlash(40); - println_Msg(F("")); - display_Update(); - - if (flashromType == 1) - resetFlash29F032(); - else - resetFlash29F1610(); - break; - - case 5: - time = 0; - display_Clear(); - println_Msg(F("Print first 70Bytes")); - display_Update(); - if (flashromType == 1) - resetFlash29F032(); - else - resetFlash29F1610(); - printFlash(70); - break; - - case 6: - time = 0; - display_Clear(); - display_Update(); - if (flashromType == 1) - resetFlash29F032(); - else - resetFlash29F1610(); - asm volatile (" jmp 0"); - 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("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("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)) { - 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(); - 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(); -} - -void epromMenu() { - // create menu with title "Eprom Writer" and 4 options to choose from - unsigned char mainMenu; - // Copy menuOptions out of progmem - convertPgm(menuOptionsEprom, 5); - mainMenu = question_box("Eprom Writer", menuOptions, 5, 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: - filePath[0] = '\0'; - sd.chdir("/"); - fileBrowser("Verify against"); - display_Clear(); - time = millis(); - verify_Eprom(); - break; - - case 4: - 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"); - println_Msg("Please do a manual"); - println_Msg("powercycle now"); - 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, "04D4") == 0) { - println_Msg(F("MBM29F033C detected")); - flashSize = 4194304; - 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 (secondID) { - // Backup first ID read-out - strncpy(vendorID, flashid, 5); - // Read ID a second time using a different command - idFlash29F1610(); - 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(); - if (flashromType == 1) - resetFlash29F032(); - else - resetFlash29F1610(); -} - -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 { - 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; - - display_Clear(); - println_Msg("This is still a work"); - println_Msg("in progress."); - println_Msg(""); - println_Msg("Sometimes it works..."); - println_Msg("sometimes it blows up"); - println_Msg(""); - println_Msg("Press Button"); - display_Update(); - wait(); -} - -/****************************************** - 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) CE(PH6)LOW - PORTH &= ~((1 << 1) | (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) HIGH - PORTH |= (1 << 1); -} -/****************************************** - 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(); - } -} - -/****************************************** - 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(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)) { - 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(); -} - -/****************************************** - 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(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 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; - // 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 - __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"); - - // Setting CE(PH6) LOW - PORTH &= ~(1 << 6); - - // Wait 1us for Chip Enable Low to Output Valid while program verify - delayMicroseconds(1); - - // Read - word tempWord = ( ( PINA & 0xFF ) << 8 ) | ( PINC & 0xFF ); - - // 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(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); - - // Switch VPP/OE(PH5) to HIGH - PORTH |= (1 << 5); - delay(1000); - - 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 - word checkWord = 0xFFFF; - 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 - checkWord = 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 (checkWord != myWord); - } - d += 2; - } - d = 0; - } - // 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(); - } -} - -//****************************************** -// End of File +//****************************************** +// FLASHROM MODULE +//****************************************** + +/****************************************** + Variables + *****************************************/ +// Flashrom +unsigned long flashSize; +byte flashromType; +byte secondID = 1; +unsigned long time; +unsigned long blank; +unsigned long sectorSize; +byte bufferSize; +boolean hiROM = 1; + +/****************************************** + Menu + *****************************************/ +// Flash start menu +static const char flashMenuItem1[] PROGMEM = "8bit adapter"; +static const char flashMenuItem2[] PROGMEM = "16bit adapter(old)"; +static const char flashMenuItem3[] PROGMEM = "Eprom adapter(beta)"; +static const char* const menuOptionsFlash[] PROGMEM = {flashMenuItem1, flashMenuItem2, flashMenuItem3}; + +// 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, 3); + flashSlot = question_box("Select adapter PCB", menuOptions, 3, 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_Flash16(); + id_Flash16(); + wait(); + mode = mode_FLASH16; + break; + + case 2: + display_Clear(); + display_Update(); + setup_Eprom(); + mode = mode_EPROM; + 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("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(); + if (flashromType == 1) + resetFlash29F032(); + else + resetFlash29F1610(); + blankcheck_Flash(); + break; + + case 1: + display_Clear(); + println_Msg(F("Erasing Flashrom")); + println_Msg(F("Please wait...")); + display_Update(); + time = millis(); + if (flashromType == 1) { + eraseFlash29F032(); + } + else { + eraseFlash29F1610(); + } + println_Msg(F("Flashrom erased")); + display_Update(); + if (flashromType == 1) + resetFlash29F032(); + else + resetFlash29F1610(); + break; + + case 2: + time = millis(); + if (flashromType == 1) + resetFlash29F032(); + else + resetFlash29F1610(); + readFlash(); + break; + + case 3: + filePath[0] = '\0'; + sd.chdir("/"); + fileBrowser("Select file"); + display_Clear(); + time = millis(); + if (flashromType == 1) + writeFlash29F032(); + else if (flashromType == 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); + } + } + delay(100); + // Reset twice just to be sure + if (flashromType == 1) + resetFlash29F032(); + else + resetFlash29F1610(); + if (flashromType == 1) + resetFlash29F032(); + else + resetFlash29F1610(); + verifyFlash(); + break; + + case 4: + time = 0; + display_Clear(); + println_Msg(F("ID Flashrom")); + if (flashromType == 1) + idFlash29F032(); + else + idFlash29F1610(); + + println_Msg(F("")); + printFlash(40); + println_Msg(F("")); + display_Update(); + + if (flashromType == 1) + resetFlash29F032(); + else + resetFlash29F1610(); + break; + + case 5: + time = 0; + display_Clear(); + println_Msg(F("Print first 70Bytes")); + display_Update(); + if (flashromType == 1) + resetFlash29F032(); + else + resetFlash29F1610(); + printFlash(70); + break; + + case 6: + time = 0; + display_Clear(); + display_Update(); + if (flashromType == 1) + resetFlash29F032(); + else + resetFlash29F1610(); + asm volatile (" jmp 0"); + 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("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("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)) { + 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(); + 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(); +} + +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("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("Select file"); + display_Clear(); + time = millis(); + write_Eprom(); + delay(1000); + verify_Eprom(); + break; + + case 3: + filePath[0] = '\0'; + sd.chdir("/"); + fileBrowser("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(); + 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(); +} + +/****************************************** + 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, "04D4") == 0) { + println_Msg(F("MBM29F033C detected")); + flashSize = 4194304; + 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 (secondID) { + // Backup first ID read-out + strncpy(vendorID, flashid, 5); + // Read ID a second time using a different command + idFlash29F1610(); + 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(); + if (flashromType == 1) + resetFlash29F032(); + else + resetFlash29F1610(); +} + +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 { + 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) CE(PH6)LOW + PORTH &= ~((1 << 1) | (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) HIGH + PORTH |= (1 << 1); +} +/****************************************** + 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(); + } +} + +/****************************************** + 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(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)) { + 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(); +} + +/****************************************** + 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(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 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(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); + + // 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("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 (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 //******************************************