mirror of
https://github.com/sanni/cartreader.git
synced 2024-11-24 05:29:17 +01:00
V4.0: Add complete N64 Controller Test
This commit is contained in:
parent
f6f442f47a
commit
1fe0b53a0d
@ -2,8 +2,8 @@
|
|||||||
Cartridge Reader for Arduino Mega2560
|
Cartridge Reader for Arduino Mega2560
|
||||||
|
|
||||||
Author: sanni
|
Author: sanni
|
||||||
Date: 20-09-2019
|
Date: 27-09-2019
|
||||||
Version: 3.9
|
Version: 4.0
|
||||||
|
|
||||||
SD lib: https://github.com/greiman/SdFat
|
SD lib: https://github.com/greiman/SdFat
|
||||||
LCD lib: https://github.com/adafruit/Adafruit_SSD1306
|
LCD lib: https://github.com/adafruit/Adafruit_SSD1306
|
||||||
@ -43,7 +43,7 @@
|
|||||||
**********************************************************************************/
|
**********************************************************************************/
|
||||||
#include <SdFat.h>
|
#include <SdFat.h>
|
||||||
|
|
||||||
char ver[5] = "3.9";
|
char ver[5] = "4.0";
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
Options
|
Options
|
||||||
@ -373,9 +373,9 @@ static const char modeItem7[] PROGMEM = "Reset";
|
|||||||
static const char* const modeOptions[] PROGMEM = {modeItem1, modeItem2, modeItem3, modeItem4, modeItem5, modeItem6, modeItem7};
|
static const char* const modeOptions[] PROGMEM = {modeItem1, modeItem2, modeItem3, modeItem4, modeItem5, modeItem6, modeItem7};
|
||||||
|
|
||||||
// Add-ons submenu
|
// Add-ons submenu
|
||||||
static const char addonsItem1[] PROGMEM = "PC Engine/TG16";
|
static const char addonsItem1[] PROGMEM = "NES/Famicom";
|
||||||
static const char addonsItem2[] PROGMEM = "Flashrom Programmer";
|
static const char addonsItem2[] PROGMEM = "Flashrom Programmer";
|
||||||
static const char addonsItem3[] PROGMEM = "NES/Famicom";
|
static const char addonsItem3[] PROGMEM = "PC Engine/TG16";
|
||||||
static const char addonsItem4[] PROGMEM = "Sega Master System";
|
static const char addonsItem4[] PROGMEM = "Sega Master System";
|
||||||
static const char addonsItem5[] PROGMEM = "Reset";
|
static const char addonsItem5[] PROGMEM = "Reset";
|
||||||
static const char* const addonsOptions[] PROGMEM = {addonsItem1, addonsItem2, addonsItem3, addonsItem4, addonsItem5};
|
static const char* const addonsOptions[] PROGMEM = {addonsItem1, addonsItem2, addonsItem3, addonsItem4, addonsItem5};
|
||||||
@ -483,7 +483,7 @@ void addonsMenu() {
|
|||||||
switch (addonsMenu)
|
switch (addonsMenu)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
pcsMenu();
|
nesMenu();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
@ -491,7 +491,7 @@ void addonsMenu() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
nesMenu();
|
pcsMenu();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
|
@ -25,7 +25,7 @@ static const char gbSmartGameMenuItem4[] PROGMEM = "Switch Game";
|
|||||||
static const char gbSmartGameMenuItem5[] PROGMEM = "Reset";
|
static const char gbSmartGameMenuItem5[] PROGMEM = "Reset";
|
||||||
static const char* const menuOptionsGBSmartGame[] PROGMEM = {gbSmartGameMenuItem1, gbSmartGameMenuItem2, gbSmartGameMenuItem3, gbSmartGameMenuItem4, gbSmartGameMenuItem5};
|
static const char* const menuOptionsGBSmartGame[] PROGMEM = {gbSmartGameMenuItem1, gbSmartGameMenuItem2, gbSmartGameMenuItem3, gbSmartGameMenuItem4, gbSmartGameMenuItem5};
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint8_t start_bank;
|
uint8_t start_bank;
|
||||||
uint8_t rom_type;
|
uint8_t rom_type;
|
||||||
@ -87,7 +87,7 @@ void setup_GBSmart()
|
|||||||
gameMenuStartBank = 0x02;
|
gameMenuStartBank = 0x02;
|
||||||
hasMenu = true;
|
hasMenu = true;
|
||||||
numGames = 0;
|
numGames = 0;
|
||||||
|
|
||||||
display_Clear();
|
display_Clear();
|
||||||
display_Update();
|
display_Update();
|
||||||
}
|
}
|
||||||
@ -95,7 +95,7 @@ void setup_GBSmart()
|
|||||||
void gbSmartMenu()
|
void gbSmartMenu()
|
||||||
{
|
{
|
||||||
uint8_t mainMenu;
|
uint8_t mainMenu;
|
||||||
|
|
||||||
// Copy menuOptions out of progmem
|
// Copy menuOptions out of progmem
|
||||||
convertPgm(menuOptionsGBSmart, 3);
|
convertPgm(menuOptionsGBSmart, 3);
|
||||||
mainMenu = question_box(F("GB Smart"), menuOptions, 3, 0);
|
mainMenu = question_box(F("GB Smart"), menuOptions, 3, 0);
|
||||||
@ -104,20 +104,20 @@ void gbSmartMenu()
|
|||||||
switch (mainMenu)
|
switch (mainMenu)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
gbSmartGameMenu();
|
gbSmartGameMenu();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
mode = mode_GB_GBSmart_Flash;
|
mode = mode_GB_GBSmart_Flash;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
asm volatile (" jmp 0");
|
asm volatile (" jmp 0");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,51 +131,51 @@ void gbSmartGameOptions()
|
|||||||
switch (gameSubMenu)
|
switch (gameSubMenu)
|
||||||
{
|
{
|
||||||
case 0: // Read Game
|
case 0: // Read Game
|
||||||
{
|
{
|
||||||
display_Clear();
|
display_Clear();
|
||||||
sd.chdir("/");
|
sd.chdir("/");
|
||||||
readROM_GB();
|
readROM_GB();
|
||||||
compare_checksum_GB();
|
compare_checksum_GB();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1: // Read SRAM
|
case 1: // Read SRAM
|
||||||
{
|
{
|
||||||
display_Clear();
|
display_Clear();
|
||||||
sd.chdir("/");
|
sd.chdir("/");
|
||||||
readSRAM_GB();
|
readSRAM_GB();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2: // Write SRAM
|
case 2: // Write SRAM
|
||||||
{
|
|
||||||
display_Clear();
|
|
||||||
sd.chdir("/");
|
|
||||||
writeSRAM_GB();
|
|
||||||
uint32_t wrErrors = verifySRAM_GB();
|
|
||||||
if (wrErrors == 0)
|
|
||||||
{
|
{
|
||||||
println_Msg(F("Verified OK"));
|
display_Clear();
|
||||||
display_Update();
|
sd.chdir("/");
|
||||||
|
writeSRAM_GB();
|
||||||
|
uint32_t wrErrors = verifySRAM_GB();
|
||||||
|
if (wrErrors == 0)
|
||||||
|
{
|
||||||
|
println_Msg(F("Verified OK"));
|
||||||
|
display_Update();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
print_Msg(F("Error: "));
|
||||||
|
print_Msg(wrErrors);
|
||||||
|
println_Msg(F(" bytes"));
|
||||||
|
print_Error(F("did not verify."), false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
print_Msg(F("Error: "));
|
|
||||||
print_Msg(wrErrors);
|
|
||||||
println_Msg(F(" bytes"));
|
|
||||||
print_Error(F("did not verify."), false);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3: // Switch Game
|
case 3: // Switch Game
|
||||||
{
|
{
|
||||||
gameMenuStartBank = 0x02;
|
gameMenuStartBank = 0x02;
|
||||||
gbSmartGameMenu();
|
gbSmartGameMenu();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
asm volatile (" jmp 0");
|
asm volatile (" jmp 0");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gameSubMenu != 3)
|
if (gameSubMenu != 3)
|
||||||
@ -193,7 +193,7 @@ void gbSmartGameMenu()
|
|||||||
gb_smart_load_more_games:
|
gb_smart_load_more_games:
|
||||||
if (gameMenuStartBank > 0xfe)
|
if (gameMenuStartBank > 0xfe)
|
||||||
gameMenuStartBank = 0x02;
|
gameMenuStartBank = 0x02;
|
||||||
|
|
||||||
gbSmartGetGames();
|
gbSmartGetGames();
|
||||||
|
|
||||||
if (hasMenu)
|
if (hasMenu)
|
||||||
@ -216,11 +216,11 @@ gb_smart_load_more_games:
|
|||||||
|
|
||||||
// copy romname
|
// copy romname
|
||||||
strcpy(romName, gbSmartGames[gameSubMenu].title);
|
strcpy(romName, gbSmartGames[gameSubMenu].title);
|
||||||
|
|
||||||
// select a game
|
// select a game
|
||||||
gbSmartRemapStartBank(gbSmartGames[gameSubMenu].start_bank, gbSmartGames[gameSubMenu].rom_size, gbSmartGames[gameSubMenu].sram_size);
|
gbSmartRemapStartBank(gbSmartGames[gameSubMenu].start_bank, gbSmartGames[gameSubMenu].rom_size, gbSmartGames[gameSubMenu].sram_size);
|
||||||
getCartInfo_GB();
|
getCartInfo_GB();
|
||||||
|
|
||||||
mode = mode_GB_GBSmart_Game;
|
mode = mode_GB_GBSmart_Game;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,49 +234,49 @@ void gbSmartFlashMenu()
|
|||||||
switch (flashSubMenu)
|
switch (flashSubMenu)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
// read flash
|
// read flash
|
||||||
display_Clear();
|
display_Clear();
|
||||||
sd.chdir("/");
|
sd.chdir("/");
|
||||||
|
|
||||||
EEPROM_readAnything(10, foldern);
|
EEPROM_readAnything(10, foldern);
|
||||||
sprintf(fileName, "GBS%d.bin", foldern);
|
sprintf(fileName, "GBS%d.bin", foldern);
|
||||||
sd.mkdir("GB/GBS", true);
|
sd.mkdir("GB/GBS", true);
|
||||||
sd.chdir("GB/GBS");
|
sd.chdir("GB/GBS");
|
||||||
foldern = foldern + 1;
|
foldern = foldern + 1;
|
||||||
EEPROM_writeAnything(10, foldern);
|
EEPROM_writeAnything(10, foldern);
|
||||||
|
|
||||||
gbSmartReadFlash();
|
gbSmartReadFlash();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
// write flash
|
// write flash
|
||||||
display_Clear();
|
display_Clear();
|
||||||
|
|
||||||
println_Msg(F("Attention"));
|
println_Msg(F("Attention"));
|
||||||
println_Msg(F("This will erase your"));
|
println_Msg(F("This will erase your"));
|
||||||
println_Msg(F("GB Smart Cartridge."));
|
println_Msg(F("GB Smart Cartridge."));
|
||||||
println_Msg(F(""));
|
println_Msg(F(""));
|
||||||
println_Msg(F("Press Button"));
|
println_Msg(F("Press Button"));
|
||||||
println_Msg(F("to continue"));
|
println_Msg(F("to continue"));
|
||||||
display_Update();
|
display_Update();
|
||||||
wait();
|
wait();
|
||||||
|
|
||||||
display_Clear();
|
display_Clear();
|
||||||
filePath[0] = '\0';
|
filePath[0] = '\0';
|
||||||
sd.chdir("/");
|
sd.chdir("/");
|
||||||
fileBrowser(F("Select 4MB file"));
|
fileBrowser(F("Select 4MB file"));
|
||||||
|
|
||||||
sprintf(filePath, "%s/%s", filePath, fileName);
|
sprintf(filePath, "%s/%s", filePath, fileName);
|
||||||
gbSmartWriteFlash();
|
gbSmartWriteFlash();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
mode = mode_GB_GBSmart;
|
mode = mode_GB_GBSmart;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println_Msg(F(""));
|
println_Msg(F(""));
|
||||||
@ -288,13 +288,13 @@ void gbSmartFlashMenu()
|
|||||||
void gbSmartGetGames()
|
void gbSmartGetGames()
|
||||||
{
|
{
|
||||||
static const byte menu_title[] = {0x47, 0x42, 0x31, 0x36, 0x4d};
|
static const byte menu_title[] = {0x47, 0x42, 0x31, 0x36, 0x4d};
|
||||||
|
|
||||||
// reset remap setting
|
// reset remap setting
|
||||||
gbSmartRemapStartBank(0x00, gbSmartRomSizeGB, gbSmartSramSizeGB);
|
gbSmartRemapStartBank(0x00, gbSmartRomSizeGB, gbSmartSramSizeGB);
|
||||||
|
|
||||||
uint16_t i;
|
uint16_t i;
|
||||||
uint8_t myByte, myLength;
|
uint8_t myByte, myLength;
|
||||||
|
|
||||||
// check if contain menu
|
// check if contain menu
|
||||||
hasMenu = true;
|
hasMenu = true;
|
||||||
dataIn_GB();
|
dataIn_GB();
|
||||||
@ -306,13 +306,13 @@ void gbSmartGetGames()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasMenu)
|
if (hasMenu)
|
||||||
{
|
{
|
||||||
for (i = gameMenuStartBank, numGames = 0; i < gbSmartBanks && numGames < GB_SMART_GAMES_PER_PAGE; )
|
for (i = gameMenuStartBank, numGames = 0; i < gbSmartBanks && numGames < GB_SMART_GAMES_PER_PAGE; )
|
||||||
{
|
{
|
||||||
myLength = 0;
|
myLength = 0;
|
||||||
|
|
||||||
// switch bank
|
// switch bank
|
||||||
dataOut();
|
dataOut();
|
||||||
writeByte_GB(0x2100, i);
|
writeByte_GB(0x2100, i);
|
||||||
@ -331,7 +331,7 @@ void gbSmartGetGames()
|
|||||||
for (uint8_t j = 0; j < 15; j++)
|
for (uint8_t j = 0; j < 15; j++)
|
||||||
{
|
{
|
||||||
myByte = readByte_GB(0x4134 + j);
|
myByte = readByte_GB(0x4134 + j);
|
||||||
|
|
||||||
if (((char(myByte) >= 0x30 && char(myByte) <= 0x39) ||
|
if (((char(myByte) >= 0x30 && char(myByte) <= 0x39) ||
|
||||||
(char(myByte) >= 0x41 && char(myByte) <= 0x7a)))
|
(char(myByte) >= 0x41 && char(myByte) <= 0x7a)))
|
||||||
gbSmartGames[numGames].title[myLength++] = char(myByte);
|
gbSmartGames[numGames].title[myLength++] = char(myByte);
|
||||||
@ -346,7 +346,7 @@ void gbSmartGetGames()
|
|||||||
myByte = (2 << gbSmartGames[numGames].rom_size);
|
myByte = (2 << gbSmartGames[numGames].rom_size);
|
||||||
i += myByte;
|
i += myByte;
|
||||||
numGames++;
|
numGames++;
|
||||||
gb_smart_get_game_loop_end:;
|
gb_smart_get_game_loop_end:;
|
||||||
}
|
}
|
||||||
|
|
||||||
gameMenuStartBank = i;
|
gameMenuStartBank = i;
|
||||||
@ -357,7 +357,7 @@ gb_smart_get_game_loop_end:;
|
|||||||
for (uint8_t j = 0; j < 15; j++)
|
for (uint8_t j = 0; j < 15; j++)
|
||||||
{
|
{
|
||||||
myByte = readByte_GB(0x0134 + j);
|
myByte = readByte_GB(0x0134 + j);
|
||||||
|
|
||||||
if (((char(myByte) >= 0x30 && char(myByte) <= 0x39) ||
|
if (((char(myByte) >= 0x30 && char(myByte) <= 0x39) ||
|
||||||
(char(myByte) >= 0x41 && char(myByte) <= 0x7a)))
|
(char(myByte) >= 0x41 && char(myByte) <= 0x7a)))
|
||||||
gbSmartGames[0].title[myLength++] = char(myByte);
|
gbSmartGames[0].title[myLength++] = char(myByte);
|
||||||
@ -380,14 +380,14 @@ void gbSmartReadFlash()
|
|||||||
print_Msg(fileName);
|
print_Msg(fileName);
|
||||||
println_Msg(F("..."));
|
println_Msg(F("..."));
|
||||||
display_Update();
|
display_Update();
|
||||||
|
|
||||||
if (!myFile.open(fileName, O_RDWR | O_CREAT))
|
if (!myFile.open(fileName, O_RDWR | O_CREAT))
|
||||||
print_Error(F("Can't create file on SD"), true);
|
print_Error(F("Can't create file on SD"), true);
|
||||||
|
|
||||||
// reset flash to read array state
|
// reset flash to read array state
|
||||||
for (int i = 0x00; i < gbSmartBanks; i += gbSmartBanksPerFlashChip)
|
for (int i = 0x00; i < gbSmartBanks; i += gbSmartBanksPerFlashChip)
|
||||||
gbSmartResetFlash(i);
|
gbSmartResetFlash(i);
|
||||||
|
|
||||||
// remaps mmc to full access
|
// remaps mmc to full access
|
||||||
gbSmartRemapStartBank(0x00, gbSmartRomSizeGB, gbSmartSramSizeGB);
|
gbSmartRemapStartBank(0x00, gbSmartRomSizeGB, gbSmartSramSizeGB);
|
||||||
|
|
||||||
@ -414,7 +414,7 @@ void gbSmartReadFlash()
|
|||||||
sdBuffer[c] = readByte_GB(addr + c);
|
sdBuffer[c] = readByte_GB(addr + c);
|
||||||
|
|
||||||
myFile.write(sdBuffer, 512);
|
myFile.write(sdBuffer, 512);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// back to initial state
|
// back to initial state
|
||||||
@ -431,10 +431,10 @@ void gbSmartWriteFlash()
|
|||||||
for (int bank = 0x00; bank < gbSmartBanks; bank += gbSmartBanksPerFlashChip)
|
for (int bank = 0x00; bank < gbSmartBanks; bank += gbSmartBanksPerFlashChip)
|
||||||
{
|
{
|
||||||
display_Clear();
|
display_Clear();
|
||||||
|
|
||||||
print_Msg(F("Erasing..."));
|
print_Msg(F("Erasing..."));
|
||||||
display_Update();
|
display_Update();
|
||||||
|
|
||||||
gbSmartEraseFlash(bank);
|
gbSmartEraseFlash(bank);
|
||||||
gbSmartResetFlash(bank);
|
gbSmartResetFlash(bank);
|
||||||
|
|
||||||
@ -443,7 +443,7 @@ void gbSmartWriteFlash()
|
|||||||
display_Update();
|
display_Update();
|
||||||
|
|
||||||
if (!gbSmartBlankCheckingFlash(bank))
|
if (!gbSmartBlankCheckingFlash(bank))
|
||||||
print_Error(F("Could not erase flash"), true);
|
print_Error(F("Could not erase flash"), true);
|
||||||
|
|
||||||
println_Msg(F("Passed"));
|
println_Msg(F("Passed"));
|
||||||
display_Update();
|
display_Update();
|
||||||
@ -466,7 +466,7 @@ void gbSmartWriteFlash()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
print_Msg(F("Error: "));
|
print_Msg(F("Error: "));
|
||||||
print_Msg(writeErrors);
|
print_Msg(writeErrors);
|
||||||
println_Msg(F(" bytes "));
|
println_Msg(F(" bytes "));
|
||||||
print_Error(F("did not verify."), true);
|
print_Error(F("did not verify."), true);
|
||||||
@ -487,7 +487,7 @@ void gbSmartWriteFlash(uint32_t start_bank)
|
|||||||
print_Msg(start_bank, HEX);
|
print_Msg(start_bank, HEX);
|
||||||
print_Msg(F("..."));
|
print_Msg(F("..."));
|
||||||
display_Update();
|
display_Update();
|
||||||
|
|
||||||
// handle bank 0x00 on 0x0000
|
// handle bank 0x00 on 0x0000
|
||||||
gbSmartWriteFlashFromMyFile(0x0000);
|
gbSmartWriteFlashFromMyFile(0x0000);
|
||||||
|
|
||||||
@ -496,7 +496,7 @@ void gbSmartWriteFlash(uint32_t start_bank)
|
|||||||
{
|
{
|
||||||
dataOut();
|
dataOut();
|
||||||
writeByte_GB(0x2100, bank);
|
writeByte_GB(0x2100, bank);
|
||||||
|
|
||||||
gbSmartWriteFlashFromMyFile(0x4000);
|
gbSmartWriteFlashFromMyFile(0x4000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -524,10 +524,10 @@ void gbSmartWriteFlashFromMyFile(uint32_t addr)
|
|||||||
gbSmartWriteFlashByte(addr, 0x0c);
|
gbSmartWriteFlashByte(addr, 0x0c);
|
||||||
gbSmartWriteFlashByte(addr, 0xff);
|
gbSmartWriteFlashByte(addr, 0xff);
|
||||||
gbSmartWriteFlashByte(addr + i, 0x00); // BCH should be 0x00
|
gbSmartWriteFlashByte(addr + i, 0x00); // BCH should be 0x00
|
||||||
|
|
||||||
// waiting for finishing
|
// waiting for finishing
|
||||||
dataIn_GB();
|
dataIn_GB();
|
||||||
while ((readByte_GB(addr + i) & 0x80) == 0x00);
|
while ((readByte_GB(addr + i) & 0x80) == 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
// blink LED
|
// blink LED
|
||||||
@ -553,7 +553,7 @@ uint32_t gbSmartVerifyFlash()
|
|||||||
for (uint16_t addr = 0x0000; addr <= 0x3fff; addr += 512)
|
for (uint16_t addr = 0x0000; addr <= 0x3fff; addr += 512)
|
||||||
{
|
{
|
||||||
myFile.read(sdBuffer, 512);
|
myFile.read(sdBuffer, 512);
|
||||||
|
|
||||||
for (uint16_t c = 0; c < 512; c++)
|
for (uint16_t c = 0; c < 512; c++)
|
||||||
{
|
{
|
||||||
if (readByte_GB(addr + c) != sdBuffer[c])
|
if (readByte_GB(addr + c) != sdBuffer[c])
|
||||||
@ -571,13 +571,13 @@ uint32_t gbSmartVerifyFlash()
|
|||||||
for (uint16_t addr = 0x4000; addr <= 0x7fff; addr += 512)
|
for (uint16_t addr = 0x4000; addr <= 0x7fff; addr += 512)
|
||||||
{
|
{
|
||||||
myFile.read(sdBuffer, 512);
|
myFile.read(sdBuffer, 512);
|
||||||
|
|
||||||
for (uint16_t c = 0; c < 512; c++)
|
for (uint16_t c = 0; c < 512; c++)
|
||||||
{
|
{
|
||||||
if (readByte_GB(addr + c) != sdBuffer[c])
|
if (readByte_GB(addr + c) != sdBuffer[c])
|
||||||
verified++;
|
verified++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// back to initial state
|
// back to initial state
|
||||||
@ -637,22 +637,22 @@ void gbSmartEraseFlash(uint8_t flash_start_bank)
|
|||||||
|
|
||||||
dataIn_GB();
|
dataIn_GB();
|
||||||
while ((readByte_GB(0x0000) & 0x80) == 0x00);
|
while ((readByte_GB(0x0000) & 0x80) == 0x00);
|
||||||
|
|
||||||
// blink LED
|
// blink LED
|
||||||
PORTB ^= (1 << 4);
|
PORTB ^= (1 << 4);
|
||||||
|
|
||||||
// rest of flash block
|
// rest of flash block
|
||||||
for (uint32_t ba = gbSmartBanksPerFlashBlock; ba < gbSmartBanksPerFlashChip; ba += gbSmartBanksPerFlashBlock)
|
for (uint32_t ba = gbSmartBanksPerFlashBlock; ba < gbSmartBanksPerFlashChip; ba += gbSmartBanksPerFlashBlock)
|
||||||
{
|
{
|
||||||
dataOut();
|
dataOut();
|
||||||
writeByte_GB(0x2100, ba);
|
writeByte_GB(0x2100, ba);
|
||||||
|
|
||||||
gbSmartWriteFlashByte(0x4000, 0x20);
|
gbSmartWriteFlashByte(0x4000, 0x20);
|
||||||
gbSmartWriteFlashByte(0x4000, 0xd0);
|
gbSmartWriteFlashByte(0x4000, 0xd0);
|
||||||
|
|
||||||
dataIn_GB();
|
dataIn_GB();
|
||||||
while ((readByte_GB(0x4000) & 0x80) == 0x00);
|
while ((readByte_GB(0x4000) & 0x80) == 0x00);
|
||||||
|
|
||||||
// blink LED
|
// blink LED
|
||||||
PORTB ^= (1 << 4);
|
PORTB ^= (1 << 4);
|
||||||
}
|
}
|
||||||
@ -674,10 +674,10 @@ void gbSmartWriteFlashByte(uint32_t myAddress, uint8_t myData)
|
|||||||
__asm__("nop\n\tnop\n\tnop\n\tnop\n\t");
|
__asm__("nop\n\tnop\n\tnop\n\tnop\n\t");
|
||||||
|
|
||||||
// Pull FLASH_WE (PH4) high
|
// Pull FLASH_WE (PH4) high
|
||||||
PORTH |= (1 << 4);
|
PORTH |= (1 << 4);
|
||||||
|
|
||||||
// pull high for another 250ns
|
// pull high for another 250ns
|
||||||
__asm__("nop\n\tnop\n\tnop\n\tnop\n\t");
|
__asm__("nop\n\tnop\n\tnop\n\tnop\n\t");
|
||||||
}
|
}
|
||||||
|
|
||||||
// rom_start_bank = 0x00 means back to original state
|
// rom_start_bank = 0x00 means back to original state
|
||||||
@ -686,7 +686,7 @@ void gbSmartRemapStartBank(uint8_t rom_start_bank, uint8_t rom_size, uint8_t sra
|
|||||||
rom_start_bank &= 0xfe;
|
rom_start_bank &= 0xfe;
|
||||||
|
|
||||||
dataOut();
|
dataOut();
|
||||||
|
|
||||||
// clear base bank setting
|
// clear base bank setting
|
||||||
writeByte_GB(0x1000, 0xa5);
|
writeByte_GB(0x1000, 0xa5);
|
||||||
writeByte_GB(0x7000, 0x00);
|
writeByte_GB(0x7000, 0x00);
|
||||||
|
@ -42,12 +42,15 @@ unsigned long romBase = 0x10000000;
|
|||||||
byte flashramType = 1;
|
byte flashramType = 1;
|
||||||
boolean MN63F81MPN = false;
|
boolean MN63F81MPN = false;
|
||||||
|
|
||||||
|
//ControllerTest
|
||||||
|
bool quit = 1;
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
Menu
|
Menu
|
||||||
*****************************************/
|
*****************************************/
|
||||||
// N64 start menu
|
// N64 start menu
|
||||||
static const char n64MenuItem1[] PROGMEM = "Game Cartridge";
|
static const char n64MenuItem1[] PROGMEM = "Game Cartridge";
|
||||||
static const char n64MenuItem2[] PROGMEM = "Controller Pak";
|
static const char n64MenuItem2[] PROGMEM = "Controller";
|
||||||
static const char n64MenuItem3[] PROGMEM = "Flash Repro";
|
static const char n64MenuItem3[] PROGMEM = "Flash Repro";
|
||||||
static const char n64MenuItem4[] PROGMEM = "Flash Gameshark";
|
static const char n64MenuItem4[] PROGMEM = "Flash Gameshark";
|
||||||
static const char n64MenuItem5[] PROGMEM = "Reset";
|
static const char n64MenuItem5[] PROGMEM = "Reset";
|
||||||
@ -155,7 +158,8 @@ void n64ControllerMenu() {
|
|||||||
case 0:
|
case 0:
|
||||||
display_Clear();
|
display_Clear();
|
||||||
display_Update();
|
display_Update();
|
||||||
readController();
|
controllerTest();
|
||||||
|
quit = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
@ -830,35 +834,533 @@ void get_button()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void readController() {
|
|
||||||
bool quit = 1;
|
/******************************************
|
||||||
|
N64 Controller Test
|
||||||
|
*****************************************/
|
||||||
|
#define CENTER 64
|
||||||
|
|
||||||
|
void oledPrint(const char string[], int x, int y) {
|
||||||
|
|
||||||
|
if (x == CENTER)
|
||||||
|
x = 64 - (strlen(string) / 2) * 6;
|
||||||
|
display.setCursor(x, y);
|
||||||
|
display.print(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
void oledPrint(int number, int x, int y) {
|
||||||
|
display.setCursor(x, y);
|
||||||
|
display.print(number);
|
||||||
|
}
|
||||||
|
|
||||||
|
void printSTR(String st, int x, int y)
|
||||||
|
{
|
||||||
|
char buf[st.length() + 1];
|
||||||
|
|
||||||
|
st.toCharArray(buf, st.length() + 1);
|
||||||
|
oledPrint(buf, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void controllerTest() {
|
||||||
|
// on which screens do we start
|
||||||
|
int startscreen = 1;
|
||||||
|
int mode = 0;
|
||||||
|
int test = 1;
|
||||||
|
|
||||||
|
//name of the current displayed result
|
||||||
|
String anastick = "";
|
||||||
|
int prevStickX = 0;
|
||||||
|
|
||||||
|
// Graph
|
||||||
|
int xax = 22 + 24; // midpoint x
|
||||||
|
int yax = 24; // midpoint y
|
||||||
|
int zax = 24; // size
|
||||||
|
|
||||||
|
// variables to display test data of different sticks
|
||||||
|
int upx = 0;
|
||||||
|
int upy = 0;
|
||||||
|
int uprightx = 0;
|
||||||
|
int uprighty = 0;
|
||||||
|
int rightx = 0;
|
||||||
|
int righty = 0;
|
||||||
|
int downrightx = 0;
|
||||||
|
int downrighty = 0;
|
||||||
|
int downx = 0;
|
||||||
|
int downy = 0;
|
||||||
|
int downleftx = 0;
|
||||||
|
int downlefty = 0;
|
||||||
|
int leftx = 0;
|
||||||
|
int lefty = 0;
|
||||||
|
int upleftx = 0;
|
||||||
|
int uplefty = 0;
|
||||||
|
|
||||||
|
// variables to save test data
|
||||||
|
int bupx = 0;
|
||||||
|
int bupy = 0;
|
||||||
|
int buprightx = 0;
|
||||||
|
int buprighty = 0;
|
||||||
|
int brightx = 0;
|
||||||
|
int brighty = 0;
|
||||||
|
int bdownrightx = 0;
|
||||||
|
int bdownrighty = 0;
|
||||||
|
int bdownx = 0;
|
||||||
|
int bdowny = 0;
|
||||||
|
int bdownleftx = 0;
|
||||||
|
int bdownlefty = 0;
|
||||||
|
int bleftx = 0;
|
||||||
|
int blefty = 0;
|
||||||
|
int bupleftx = 0;
|
||||||
|
int buplefty = 0;
|
||||||
|
int results = 0;
|
||||||
|
|
||||||
while (quit) {
|
while (quit) {
|
||||||
display_Clear();
|
|
||||||
|
|
||||||
// Get Button and analog stick
|
// Get Button and analog stick
|
||||||
get_button();
|
get_button();
|
||||||
|
|
||||||
println_Msg(F("Controller Test"));
|
switch (startscreen)
|
||||||
println_Msg("");
|
{
|
||||||
println_Msg(button);
|
case 1:
|
||||||
println_Msg("");
|
{
|
||||||
String stickx = String("X: " + String(N64_status.stick_x, DEC) + " ");
|
display.clearDisplay();
|
||||||
println_Msg(stickx);
|
oledPrint("Button Test", CENTER, 0);
|
||||||
String sticky = String("Y: " + String(N64_status.stick_y, DEC) + " ");
|
display.drawLine(22 + 0, 10, 22 + 84, 10, WHITE);
|
||||||
println_Msg(sticky);
|
|
||||||
println_Msg("");
|
|
||||||
println_Msg(F("Press START to quit"));
|
|
||||||
|
|
||||||
display_Update();
|
// Print Button
|
||||||
delay(100);
|
printSTR(" " + button + " ", CENTER, 20);
|
||||||
|
|
||||||
if (button == F("START")) {
|
// Print Stick X Value
|
||||||
quit = 0;
|
String stickx = String("X: " + String(N64_status.stick_x, DEC) + " ");
|
||||||
|
printSTR(stickx, 22 + 0, 38);
|
||||||
|
|
||||||
|
// Print Stick Y Value
|
||||||
|
String sticky = String("Y: " + String(N64_status.stick_y, DEC) + " ");
|
||||||
|
printSTR(sticky, 22 + 60, 38);
|
||||||
|
|
||||||
|
printSTR("(Continue with START)", 0, 55);
|
||||||
|
//Update LCD
|
||||||
|
display.display();
|
||||||
|
|
||||||
|
// go to next screen
|
||||||
|
if (button == "Press a button" && lastbutton == "START")
|
||||||
|
{
|
||||||
|
// reset button
|
||||||
|
lastbutton = "N/A";
|
||||||
|
|
||||||
|
display.clearDisplay();
|
||||||
|
if (startscreen != 4)
|
||||||
|
startscreen = startscreen + 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
startscreen = 1;
|
||||||
|
test = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (button == "Press a button" && lastbutton == "Z" && startscreen == 4)
|
||||||
|
{
|
||||||
|
// Quit
|
||||||
|
quit = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
oledPrint("Range Test", CENTER, 55);
|
||||||
|
display.drawLine(22 + 0, 50, 22 + 84, 50, WHITE);
|
||||||
|
|
||||||
|
// Print Stick X Value
|
||||||
|
String stickx = String("X:" + String(N64_status.stick_x, DEC) + " ");
|
||||||
|
printSTR(stickx, 22 + 54, 8);
|
||||||
|
|
||||||
|
// Print Stick Y Value
|
||||||
|
String sticky = String("Y:" + String(N64_status.stick_y, DEC) + " ");
|
||||||
|
printSTR(sticky, 22 + 54, 18);
|
||||||
|
|
||||||
|
// Draw Axis
|
||||||
|
//display.drawLine(xax - zax, yax, xax + zax, yax, WHITE);
|
||||||
|
//display.drawLine(xax, yax - zax, xax, yax + zax, WHITE);
|
||||||
|
display.drawPixel(xax, yax, WHITE);
|
||||||
|
display.drawPixel(xax, yax - 80 / 4, WHITE);
|
||||||
|
display.drawPixel(xax, yax + 80 / 4, WHITE);
|
||||||
|
display.drawPixel(xax + 80 / 4, yax, WHITE);
|
||||||
|
display.drawPixel(xax - 80 / 4, yax, WHITE);
|
||||||
|
|
||||||
|
// Draw corners
|
||||||
|
display.drawPixel(xax - 68 / 4, yax - 68 / 4, WHITE);
|
||||||
|
display.drawPixel(xax + 68 / 4, yax + 68 / 4, WHITE);
|
||||||
|
display.drawPixel(xax + 68 / 4, yax - 68 / 4, WHITE);
|
||||||
|
display.drawPixel(xax - 68 / 4, yax + 68 / 4, WHITE);
|
||||||
|
|
||||||
|
//Draw Analog Stick
|
||||||
|
if (mode == 1)
|
||||||
|
{
|
||||||
|
display.drawPixel(xax + N64_status.stick_x / 4, yax - N64_status.stick_y / 4, WHITE);
|
||||||
|
//Update LCD
|
||||||
|
display.display();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
display.drawCircle(xax + N64_status.stick_x / 4, yax - N64_status.stick_y / 4, 2, WHITE);
|
||||||
|
//Update LCD
|
||||||
|
display.display();
|
||||||
|
display.clearDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
// switch mode
|
||||||
|
if (button == "Press a button" && lastbutton == "Z")
|
||||||
|
{
|
||||||
|
if (mode == 0)
|
||||||
|
{
|
||||||
|
mode = 1;
|
||||||
|
display.clearDisplay();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mode = 0;
|
||||||
|
display.clearDisplay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// go to next screen
|
||||||
|
if (button == "Press a button" && lastbutton == "START")
|
||||||
|
{
|
||||||
|
// reset button
|
||||||
|
lastbutton = "N/A";
|
||||||
|
|
||||||
|
display.clearDisplay();
|
||||||
|
if (startscreen != 4)
|
||||||
|
startscreen = startscreen + 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
startscreen = 1;
|
||||||
|
test = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (button == "Press a button" && lastbutton == "Z" && startscreen == 4)
|
||||||
|
{
|
||||||
|
// Quit
|
||||||
|
quit = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
display.drawPixel(22 + prevStickX, 40, BLACK);
|
||||||
|
oledPrint("Skipping Test", CENTER, 0);
|
||||||
|
display.drawLine(22 + 0, 10, 22 + 83, 10, WHITE);
|
||||||
|
display.drawRect(22 + 0, 15, 22 + 59, 21, WHITE);
|
||||||
|
if (N64_status.stick_x > 0) {
|
||||||
|
display.drawLine(22 + N64_status.stick_x, 15, 22 + N64_status.stick_x, 35, WHITE);
|
||||||
|
display.drawPixel(22 + N64_status.stick_x, 40, WHITE);
|
||||||
|
prevStickX = N64_status.stick_x;
|
||||||
|
}
|
||||||
|
|
||||||
|
printSTR("Try to fill box by", 0, 45);
|
||||||
|
printSTR("slowly moving right", 0, 55);
|
||||||
|
//Update LCD
|
||||||
|
display.display();
|
||||||
|
|
||||||
|
if (button == "Press a button" && lastbutton == "Z")
|
||||||
|
{
|
||||||
|
// reset button
|
||||||
|
lastbutton = "N/A";
|
||||||
|
|
||||||
|
display.clearDisplay();
|
||||||
|
}
|
||||||
|
// go to next screen
|
||||||
|
if (button == "Press a button" && lastbutton == "START")
|
||||||
|
{
|
||||||
|
// reset button
|
||||||
|
lastbutton = "N/A";
|
||||||
|
|
||||||
|
display.clearDisplay();
|
||||||
|
if (startscreen != 4)
|
||||||
|
startscreen = startscreen + 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
startscreen = 1;
|
||||||
|
test = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (button == "Press a button" && lastbutton == "Z" && startscreen == 4)
|
||||||
|
{
|
||||||
|
// Quit
|
||||||
|
quit = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
switch ( test )
|
||||||
|
{
|
||||||
|
case 0: // Display results
|
||||||
|
{
|
||||||
|
switch (results)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
anastick = "YOURS";
|
||||||
|
upx = bupx;
|
||||||
|
upy = bupy;
|
||||||
|
uprightx = buprightx;
|
||||||
|
uprighty = buprighty;
|
||||||
|
rightx = brightx;
|
||||||
|
righty = brighty;
|
||||||
|
downrightx = bdownrightx;
|
||||||
|
downrighty = bdownrighty;
|
||||||
|
downx = bdownx;
|
||||||
|
downy = bdowny;
|
||||||
|
downleftx = bdownleftx;
|
||||||
|
downlefty = bdownlefty;
|
||||||
|
leftx = bleftx;
|
||||||
|
lefty = blefty;
|
||||||
|
upleftx = bupleftx;
|
||||||
|
uplefty = buplefty;
|
||||||
|
|
||||||
|
if (button == "Press a button" && lastbutton == "A")
|
||||||
|
{
|
||||||
|
// reset button
|
||||||
|
lastbutton = "N/A";
|
||||||
|
results = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
anastick = "ORIG";
|
||||||
|
upx = 1;
|
||||||
|
upy = 84;
|
||||||
|
uprightx = 67;
|
||||||
|
uprighty = 68;
|
||||||
|
rightx = 83;
|
||||||
|
righty = -2;
|
||||||
|
downrightx = 67;
|
||||||
|
downrighty = -69;
|
||||||
|
downx = 3;
|
||||||
|
downy = -85;
|
||||||
|
downleftx = -69;
|
||||||
|
downlefty = -70;
|
||||||
|
leftx = -85;
|
||||||
|
lefty = 0;
|
||||||
|
upleftx = -68;
|
||||||
|
uplefty = 68;
|
||||||
|
|
||||||
|
if (button == "Press a button" && lastbutton == "A")
|
||||||
|
{
|
||||||
|
// reset button
|
||||||
|
lastbutton = "N/A";
|
||||||
|
results = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} //results
|
||||||
|
display.clearDisplay();
|
||||||
|
|
||||||
|
printSTR(anastick, 22 + 50, 0);
|
||||||
|
|
||||||
|
oledPrint("U:", 22 + 50, 10);
|
||||||
|
oledPrint(upy, 100, 10);
|
||||||
|
oledPrint("D:", 22 + 50, 20);
|
||||||
|
oledPrint(downy, 100, 20);
|
||||||
|
oledPrint("L:", 22 + 50, 30);
|
||||||
|
oledPrint(leftx, 100, 30);
|
||||||
|
oledPrint("R:", 22 + 50, 40);
|
||||||
|
oledPrint(rightx, 100, 40);
|
||||||
|
|
||||||
|
display.drawLine(xax + upx / 4, yax - upy / 4, xax + uprightx / 4, yax - uprighty / 4, WHITE);
|
||||||
|
display.drawLine(xax + uprightx / 4, yax - uprighty / 4, xax + rightx / 4, yax - righty / 4, WHITE);
|
||||||
|
display.drawLine(xax + rightx / 4, yax - righty / 4, xax + downrightx / 4, yax - downrighty / 4, WHITE);
|
||||||
|
display.drawLine(xax + downrightx / 4, yax - downrighty / 4, xax + downx / 4, yax - downy / 4, WHITE);
|
||||||
|
display.drawLine(xax + downx / 4, yax - downy / 4, xax + downleftx / 4, yax - downlefty / 4, WHITE);
|
||||||
|
display.drawLine(xax + downleftx / 4, yax - downlefty / 4, xax + leftx / 4, yax - lefty / 4, WHITE);
|
||||||
|
display.drawLine(xax + leftx / 4, yax - lefty / 4, xax + upleftx / 4, yax - uplefty / 4, WHITE);
|
||||||
|
display.drawLine(xax + upleftx / 4, yax - uplefty / 4, xax + upx / 4, yax - upy / 4, WHITE);
|
||||||
|
|
||||||
|
display.drawPixel(xax, yax, WHITE);
|
||||||
|
|
||||||
|
printSTR("(Quit with Z)", 25, 55);
|
||||||
|
//Update LCD
|
||||||
|
display.display();
|
||||||
|
break;
|
||||||
|
} //display results
|
||||||
|
|
||||||
|
case 1:// +y Up
|
||||||
|
{
|
||||||
|
oledPrint("Hold Stick Up", CENTER, 18);
|
||||||
|
oledPrint("then press A", CENTER, 28);
|
||||||
|
//myOLED.drawBitmap(110, 60, ana1);
|
||||||
|
|
||||||
|
if (button == "Press a button" && lastbutton == "A")
|
||||||
|
{
|
||||||
|
bupx = N64_status.stick_x;
|
||||||
|
bupy = N64_status.stick_y;
|
||||||
|
// reset button
|
||||||
|
lastbutton = "N/A";
|
||||||
|
|
||||||
|
display.clearDisplay();
|
||||||
|
test = 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 2:// +y+x Up-Right
|
||||||
|
{
|
||||||
|
oledPrint("Up-Right", CENTER, 22 );
|
||||||
|
//myOLED.drawBitmap(110, 60, ana2);
|
||||||
|
|
||||||
|
if (button == "Press a button" && lastbutton == "A")
|
||||||
|
{
|
||||||
|
buprightx = N64_status.stick_x;
|
||||||
|
buprighty = N64_status.stick_y;
|
||||||
|
test = 3;
|
||||||
|
// reset button
|
||||||
|
lastbutton = "N/A";
|
||||||
|
|
||||||
|
display.clearDisplay();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 3:// +x Right
|
||||||
|
{
|
||||||
|
oledPrint("Right", CENTER, 22 );
|
||||||
|
//myOLED.drawBitmap(110, 60, ana3);
|
||||||
|
|
||||||
|
if (button == "Press a button" && lastbutton == "A")
|
||||||
|
{
|
||||||
|
brightx = N64_status.stick_x;
|
||||||
|
brighty = N64_status.stick_y;
|
||||||
|
test = 4;
|
||||||
|
// reset button
|
||||||
|
lastbutton = "N/A";
|
||||||
|
|
||||||
|
display.clearDisplay();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 4:// -y+x Down-Right
|
||||||
|
{
|
||||||
|
oledPrint("Down-Right", CENTER, 22 );
|
||||||
|
//myOLED.drawBitmap(110, 60, ana4);
|
||||||
|
|
||||||
|
if (button == "Press a button" && lastbutton == "A")
|
||||||
|
{
|
||||||
|
bdownrightx = N64_status.stick_x;
|
||||||
|
bdownrighty = N64_status.stick_y;
|
||||||
|
test = 5;
|
||||||
|
// reset button
|
||||||
|
lastbutton = "N/A";
|
||||||
|
|
||||||
|
display.clearDisplay();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 5:// -y Down
|
||||||
|
{
|
||||||
|
oledPrint("Down", CENTER, 22 );
|
||||||
|
//myOLED.drawBitmap(110, 60, ana5);
|
||||||
|
|
||||||
|
if (button == "Press a button" && lastbutton == "A")
|
||||||
|
{
|
||||||
|
bdownx = N64_status.stick_x;
|
||||||
|
bdowny = N64_status.stick_y;
|
||||||
|
test = 6;
|
||||||
|
// reset button
|
||||||
|
lastbutton = "N/A";
|
||||||
|
|
||||||
|
display.clearDisplay();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 6:// -y-x Down-Left
|
||||||
|
{
|
||||||
|
oledPrint("Down-Left", CENTER, 22 );
|
||||||
|
//myOLED.drawBitmap(110, 60, ana6);
|
||||||
|
|
||||||
|
if (button == "Press a button" && lastbutton == "A")
|
||||||
|
{
|
||||||
|
bdownleftx = N64_status.stick_x;
|
||||||
|
bdownlefty = N64_status.stick_y;
|
||||||
|
test = 7;
|
||||||
|
// reset button
|
||||||
|
lastbutton = "N/A";
|
||||||
|
|
||||||
|
display.clearDisplay();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 7:// -x Left
|
||||||
|
{
|
||||||
|
oledPrint("Left", CENTER, 22 );
|
||||||
|
//myOLED.drawBitmap(110, 60, ana7);
|
||||||
|
|
||||||
|
if (button == "Press a button" && lastbutton == "A")
|
||||||
|
{
|
||||||
|
bleftx = N64_status.stick_x;
|
||||||
|
blefty = N64_status.stick_y;
|
||||||
|
test = 8;
|
||||||
|
// reset button
|
||||||
|
lastbutton = "N/A";
|
||||||
|
|
||||||
|
display.clearDisplay();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 8:// +y+x Up-Left
|
||||||
|
{
|
||||||
|
oledPrint("Up-Left", CENTER, 22);
|
||||||
|
//myOLED.drawBitmap(110, 60, ana8);
|
||||||
|
|
||||||
|
if (button == "Press a button" && lastbutton == "A")
|
||||||
|
{
|
||||||
|
bupleftx = N64_status.stick_x;
|
||||||
|
buplefty = N64_status.stick_y;
|
||||||
|
test = 0;
|
||||||
|
// reset button
|
||||||
|
lastbutton = "N/A";
|
||||||
|
|
||||||
|
display.clearDisplay();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (test != 0)
|
||||||
|
{
|
||||||
|
oledPrint("Benchmark", CENTER, 0);
|
||||||
|
display.drawLine(22 + 0, 9, 22 + 83, 9, WHITE);
|
||||||
|
printSTR("(Quit with Z)", 25, 55);
|
||||||
|
}
|
||||||
|
display.display();
|
||||||
|
// go to next screen
|
||||||
|
if (button == "Press a button" && lastbutton == "START")
|
||||||
|
{
|
||||||
|
// reset button
|
||||||
|
lastbutton = "N/A";
|
||||||
|
|
||||||
|
display.clearDisplay();
|
||||||
|
if (startscreen != 4)
|
||||||
|
startscreen = startscreen + 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
startscreen = 1;
|
||||||
|
test = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (button == "Press a button" && lastbutton == "Z" && startscreen == 4)
|
||||||
|
{
|
||||||
|
// Quit
|
||||||
|
quit = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
N64 Controller Pak Functions
|
N64 Controller Pak Functions
|
||||||
(connected via Controller)
|
(connected via Controller)
|
||||||
@ -1189,7 +1691,7 @@ static const uint32_t crc_32_tab[] PROGMEM = { /* CRC polynomial 0xedb88320 */
|
|||||||
};
|
};
|
||||||
|
|
||||||
// improved strcmp function that ignores case to prevent checksum comparison issues
|
// improved strcmp function that ignores case to prevent checksum comparison issues
|
||||||
int strcicmp(char const *a, char const *b)
|
int strcicmp(char const * a, char const * b)
|
||||||
{
|
{
|
||||||
for (;; a++, b++) {
|
for (;; a++, b++) {
|
||||||
int d = tolower((unsigned char) * a) - tolower((unsigned char) * b);
|
int d = tolower((unsigned char) * a) - tolower((unsigned char) * b);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//******************************************
|
//******************************************
|
||||||
// NINTENDO POWER MODULE
|
// NINTENDO POWER MODULE
|
||||||
//******************************************
|
//******************************************
|
||||||
// (GB Memory starts at around line 1743)
|
// (GB Memory starts at around line 1740)
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
SF Memory Cassette
|
SF Memory Cassette
|
||||||
|
@ -1,812 +0,0 @@
|
|||||||
/**********************************************************************************
|
|
||||||
Nintendo 64 Controller Test for Arduino Mega
|
|
||||||
|
|
||||||
Author: sanni
|
|
||||||
Date: 2016-04-15
|
|
||||||
Version: V2
|
|
||||||
|
|
||||||
OLED lib: http://www.rinkydinkelectronics.com/library.php?id=79
|
|
||||||
|
|
||||||
Thanks to:
|
|
||||||
Andrew Brown/Peter Den Hartog - N64 send/get functions
|
|
||||||
|
|
||||||
**********************************************************************************/
|
|
||||||
|
|
||||||
#include <OLED_I2C.h>
|
|
||||||
extern uint8_t SmallFont[];
|
|
||||||
|
|
||||||
// define LCD pins
|
|
||||||
OLED myOLED(SDA, SCL, 8);
|
|
||||||
|
|
||||||
//define LED pin
|
|
||||||
int ledPin = 10;
|
|
||||||
|
|
||||||
// These two macros toggle the eepDataPin/ControllerDataPin between input and output
|
|
||||||
// External 1K pull-up resistor from eepDataPin to VCC required
|
|
||||||
// 0x10 = 00010000 -> Port H Pin 4
|
|
||||||
#define N64_HIGH DDRH &= ~0x10
|
|
||||||
#define N64_LOW DDRH |= 0x10
|
|
||||||
// Read the current state(0/1) of the eepDataPin
|
|
||||||
#define N64_QUERY (PINH & 0x10)
|
|
||||||
|
|
||||||
// received Controller data
|
|
||||||
char N64_raw_dump[33]; // 1 received bit per byte
|
|
||||||
String rawStr = ""; // above char array read into a string
|
|
||||||
struct {
|
|
||||||
char stick_x;
|
|
||||||
char stick_y;
|
|
||||||
}
|
|
||||||
N64_status;
|
|
||||||
|
|
||||||
// on which screens do we start
|
|
||||||
int startscreen = 0;
|
|
||||||
int mode = 0;
|
|
||||||
int test = 1;
|
|
||||||
|
|
||||||
//stings that hold the buttons
|
|
||||||
String button = "N/A";
|
|
||||||
String lastbutton = "N/A";
|
|
||||||
|
|
||||||
//name of the current displayed result
|
|
||||||
String anastick = "";
|
|
||||||
|
|
||||||
// Graph
|
|
||||||
int xax = 22 + 24; // midpoint x
|
|
||||||
int yax = 24; // midpoint y
|
|
||||||
int zax = 24; // size
|
|
||||||
|
|
||||||
// variables to display test data of different sticks
|
|
||||||
int upx = 0;
|
|
||||||
int upy = 0;
|
|
||||||
int uprightx = 0;
|
|
||||||
int uprighty = 0;
|
|
||||||
int rightx = 0;
|
|
||||||
int righty = 0;
|
|
||||||
int downrightx = 0;
|
|
||||||
int downrighty = 0;
|
|
||||||
int downx = 0;
|
|
||||||
int downy = 0;
|
|
||||||
int downleftx = 0;
|
|
||||||
int downlefty = 0;
|
|
||||||
int leftx = 0;
|
|
||||||
int lefty = 0;
|
|
||||||
int upleftx = 0;
|
|
||||||
int uplefty = 0;
|
|
||||||
|
|
||||||
// variables to save test data
|
|
||||||
int bupx = 0;
|
|
||||||
int bupy = 0;
|
|
||||||
int buprightx = 0;
|
|
||||||
int buprighty = 0;
|
|
||||||
int brightx = 0;
|
|
||||||
int brighty = 0;
|
|
||||||
int bdownrightx = 0;
|
|
||||||
int bdownrighty = 0;
|
|
||||||
int bdownx = 0;
|
|
||||||
int bdowny = 0;
|
|
||||||
int bdownleftx = 0;
|
|
||||||
int bdownlefty = 0;
|
|
||||||
int bleftx = 0;
|
|
||||||
int blefty = 0;
|
|
||||||
int bupleftx = 0;
|
|
||||||
int buplefty = 0;
|
|
||||||
int results = 0;
|
|
||||||
|
|
||||||
void N64_send(unsigned char *buffer, char length);
|
|
||||||
void N64_get();
|
|
||||||
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
// Communication with controller on this pin
|
|
||||||
// Don't remove these lines, we don't want to push +5V to the controller
|
|
||||||
// Output a low signal
|
|
||||||
PORTH &= ~(1 << 4);
|
|
||||||
// Set Controller Data Pin(PH4) to Input
|
|
||||||
DDRH &= ~(1 << 4);
|
|
||||||
|
|
||||||
// Led
|
|
||||||
pinMode(ledPin, OUTPUT);
|
|
||||||
|
|
||||||
// OLED
|
|
||||||
myOLED.begin();
|
|
||||||
myOLED.setFont(SmallFont);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This sends the given byte sequence to the controller
|
|
||||||
// length must be at least 1
|
|
||||||
// Oh, it destroys the buffer passed in as it writes it
|
|
||||||
|
|
||||||
void N64_send(unsigned char *buffer, char length)
|
|
||||||
{
|
|
||||||
// Send these bytes
|
|
||||||
char bits;
|
|
||||||
|
|
||||||
bool bit;
|
|
||||||
|
|
||||||
// This routine is very carefully timed by examining the assembly output.
|
|
||||||
// Do not change any statements, it could throw the timings off
|
|
||||||
//
|
|
||||||
// We get 16 cycles per microsecond, which should be plenty, but we need to
|
|
||||||
// be conservative. Most assembly ops take 1 cycle, but a few take 2
|
|
||||||
//
|
|
||||||
// I use manually constructed for-loops out of gotos so I have more control
|
|
||||||
// over the outputted assembly. I can insert nops where it was impossible
|
|
||||||
// with a for loop
|
|
||||||
|
|
||||||
asm volatile (";Starting outer for loop");
|
|
||||||
outer_loop:
|
|
||||||
{
|
|
||||||
asm volatile (";Starting inner for loop");
|
|
||||||
bits = 8;
|
|
||||||
inner_loop:
|
|
||||||
{
|
|
||||||
// Starting a bit, set the line low
|
|
||||||
asm volatile (";Setting line to low");
|
|
||||||
N64_LOW; // 1 op, 2 cycles
|
|
||||||
|
|
||||||
asm volatile (";branching");
|
|
||||||
if (*buffer >> 7) {
|
|
||||||
asm volatile (";Bit is a 1");
|
|
||||||
// 1 bit
|
|
||||||
// remain low for 1us, then go high for 3us
|
|
||||||
// nop block 1
|
|
||||||
asm volatile ("nop\nnop\nnop\nnop\nnop\n");
|
|
||||||
|
|
||||||
asm volatile (";Setting line to high");
|
|
||||||
N64_HIGH;
|
|
||||||
|
|
||||||
// nop block 2
|
|
||||||
// we'll wait only 2us to sync up with both conditions
|
|
||||||
// at the bottom of the if statement
|
|
||||||
asm volatile ("nop\nnop\nnop\nnop\nnop\n"
|
|
||||||
"nop\nnop\nnop\nnop\nnop\n"
|
|
||||||
"nop\nnop\nnop\nnop\nnop\n"
|
|
||||||
"nop\nnop\nnop\nnop\nnop\n"
|
|
||||||
"nop\nnop\nnop\nnop\nnop\n"
|
|
||||||
"nop\nnop\nnop\nnop\nnop\n"
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
asm volatile (";Bit is a 0");
|
|
||||||
// 0 bit
|
|
||||||
// remain low for 3us, then go high for 1us
|
|
||||||
// nop block 3
|
|
||||||
asm volatile ("nop\nnop\nnop\nnop\nnop\n"
|
|
||||||
"nop\nnop\nnop\nnop\nnop\n"
|
|
||||||
"nop\nnop\nnop\nnop\nnop\n"
|
|
||||||
"nop\nnop\nnop\nnop\nnop\n"
|
|
||||||
"nop\nnop\nnop\nnop\nnop\n"
|
|
||||||
"nop\nnop\nnop\nnop\nnop\n"
|
|
||||||
"nop\nnop\nnop\nnop\nnop\n"
|
|
||||||
"nop\n");
|
|
||||||
|
|
||||||
asm volatile (";Setting line to high");
|
|
||||||
N64_HIGH;
|
|
||||||
|
|
||||||
// wait for 1us
|
|
||||||
asm volatile ("; end of conditional branch, need to wait 1us more before next bit");
|
|
||||||
|
|
||||||
}
|
|
||||||
// end of the if, the line is high and needs to remain
|
|
||||||
// high for exactly 16 more cycles, regardless of the previous
|
|
||||||
// branch path
|
|
||||||
|
|
||||||
asm volatile (";finishing inner loop body");
|
|
||||||
--bits;
|
|
||||||
if (bits != 0) {
|
|
||||||
// nop block 4
|
|
||||||
// this block is why a for loop was impossible
|
|
||||||
asm volatile ("nop\nnop\nnop\nnop\nnop\n"
|
|
||||||
"nop\nnop\nnop\nnop\n");
|
|
||||||
// rotate bits
|
|
||||||
asm volatile (";rotating out bits");
|
|
||||||
*buffer <<= 1;
|
|
||||||
|
|
||||||
goto inner_loop;
|
|
||||||
} // fall out of inner loop
|
|
||||||
}
|
|
||||||
asm volatile (";continuing outer loop");
|
|
||||||
// In this case: the inner loop exits and the outer loop iterates,
|
|
||||||
// there are /exactly/ 16 cycles taken up by the necessary operations.
|
|
||||||
// So no nops are needed here (that was lucky!)
|
|
||||||
--length;
|
|
||||||
if (length != 0) {
|
|
||||||
++buffer;
|
|
||||||
goto outer_loop;
|
|
||||||
} // fall out of outer loop
|
|
||||||
}
|
|
||||||
|
|
||||||
// send a single stop (1) bit
|
|
||||||
// nop block 5
|
|
||||||
asm volatile ("nop\nnop\nnop\nnop\n");
|
|
||||||
N64_LOW;
|
|
||||||
// wait 1 us, 16 cycles, then raise the line
|
|
||||||
// 16-2=14
|
|
||||||
// nop block 6
|
|
||||||
asm volatile ("nop\nnop\nnop\nnop\nnop\n"
|
|
||||||
"nop\nnop\nnop\nnop\nnop\n"
|
|
||||||
"nop\nnop\nnop\nnop\n");
|
|
||||||
N64_HIGH;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void N64_get()
|
|
||||||
{
|
|
||||||
// listen for the expected 8 bytes of data back from the controller and
|
|
||||||
// blast it out to the N64_raw_dump array, one bit per byte for extra speed.
|
|
||||||
// Afterwards, call translate_raw_data() to interpret the raw data and pack
|
|
||||||
// it into the N64_status struct.
|
|
||||||
asm volatile (";Starting to listen");
|
|
||||||
unsigned char timeout;
|
|
||||||
char bitcount = 32;
|
|
||||||
char *bitbin = N64_raw_dump;
|
|
||||||
|
|
||||||
// Again, using gotos here to make the assembly more predictable and
|
|
||||||
// optimization easier (please don't kill me)
|
|
||||||
read_loop:
|
|
||||||
timeout = 0x3f;
|
|
||||||
// wait for line to go low
|
|
||||||
while (N64_QUERY) {
|
|
||||||
if (!--timeout)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// wait approx 2us and poll the line
|
|
||||||
asm volatile (
|
|
||||||
"nop\nnop\nnop\nnop\nnop\n"
|
|
||||||
"nop\nnop\nnop\nnop\nnop\n"
|
|
||||||
"nop\nnop\nnop\nnop\nnop\n"
|
|
||||||
"nop\nnop\nnop\nnop\nnop\n"
|
|
||||||
"nop\nnop\nnop\nnop\nnop\n"
|
|
||||||
"nop\nnop\nnop\nnop\nnop\n"
|
|
||||||
);
|
|
||||||
*bitbin = N64_QUERY;
|
|
||||||
++bitbin;
|
|
||||||
--bitcount;
|
|
||||||
if (bitcount == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// wait for line to go high again
|
|
||||||
// it may already be high, so this should just drop through
|
|
||||||
timeout = 0x3f;
|
|
||||||
while (!N64_QUERY) {
|
|
||||||
if (!--timeout)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
goto read_loop;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void get_button()
|
|
||||||
{
|
|
||||||
// Command to send to the gamecube
|
|
||||||
// The last bit is rumble, flip it to rumble
|
|
||||||
// yes this does need to be inside the loop, the
|
|
||||||
// array gets mutilated when it goes through N64_send
|
|
||||||
unsigned char command[] = {
|
|
||||||
0x01
|
|
||||||
};
|
|
||||||
|
|
||||||
// don't want interrupts getting in the way
|
|
||||||
noInterrupts();
|
|
||||||
// send those 3 bytes
|
|
||||||
N64_send(command, 1);
|
|
||||||
// read in data and dump it to N64_raw_dump
|
|
||||||
N64_get();
|
|
||||||
// end of time sensitive code
|
|
||||||
interrupts();
|
|
||||||
|
|
||||||
// The get_N64_status function sloppily dumps its data 1 bit per byte
|
|
||||||
// into the get_status_extended char array. It's our job to go through
|
|
||||||
// that and put each piece neatly into the struct N64_status
|
|
||||||
int i;
|
|
||||||
memset(&N64_status, 0, sizeof(N64_status));
|
|
||||||
|
|
||||||
// bits: joystick x value
|
|
||||||
// These are 8 bit values centered at 0x80 (128)
|
|
||||||
for (i = 0; i < 8; i++) {
|
|
||||||
N64_status.stick_x |= N64_raw_dump[16 + i] ? (0x80 >> i) : 0;
|
|
||||||
}
|
|
||||||
for (i = 0; i < 8; i++) {
|
|
||||||
N64_status.stick_y |= N64_raw_dump[24 + i] ? (0x80 >> i) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read char array N64_raw_dump into string rawStr
|
|
||||||
rawStr = "";
|
|
||||||
for (i = 0; i < 16; i++) {
|
|
||||||
rawStr = rawStr + String(N64_raw_dump[i], DEC);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Buttons (A,B,Z,S,DU,DD,DL,DR,0,0,L,R,CU,CD,CL,CR)
|
|
||||||
if (rawStr.substring(0, 16) == "0000000000000000") {
|
|
||||||
lastbutton = button;
|
|
||||||
button = "Press a button";
|
|
||||||
digitalWrite(ledPin, LOW);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
digitalWrite(ledPin, HIGH);
|
|
||||||
for (int i = 0; i < 16; i++)
|
|
||||||
{
|
|
||||||
// seems to be 16, 8 or 4 depending on what pin is used
|
|
||||||
if (N64_raw_dump[i] == 16)
|
|
||||||
{
|
|
||||||
switch (i)
|
|
||||||
{
|
|
||||||
case 7:
|
|
||||||
button = "D-Right";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 6:
|
|
||||||
button = "D-Left";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 5:
|
|
||||||
button = "D-Down";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
button = "D-Up";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
button = "START";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
button = "Z";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
button = "B";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0:
|
|
||||||
button = "A";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 15:
|
|
||||||
button = "C-Right";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 14:
|
|
||||||
button = "C-Left";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 13:
|
|
||||||
button = "C-Down";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 12:
|
|
||||||
button = "C-Up";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 11:
|
|
||||||
button = "R";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 10:
|
|
||||||
button = "L";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void printSTR(String st, int x, int y)
|
|
||||||
{
|
|
||||||
char buf[st.length() + 1];
|
|
||||||
|
|
||||||
st.toCharArray(buf, st.length() + 1);
|
|
||||||
myOLED.print(buf, x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nextscreen()
|
|
||||||
{
|
|
||||||
if (button == "Press a button" && lastbutton == "START")
|
|
||||||
{
|
|
||||||
// reset button
|
|
||||||
lastbutton = "N/A";
|
|
||||||
|
|
||||||
myOLED.clrScr();
|
|
||||||
if (startscreen != 4)
|
|
||||||
startscreen = startscreen + 1;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
startscreen = 1;
|
|
||||||
test = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
// Get Button and analog stick
|
|
||||||
get_button();
|
|
||||||
|
|
||||||
switch (startscreen)
|
|
||||||
{
|
|
||||||
case 0: // Logo Screen
|
|
||||||
{
|
|
||||||
myOLED.print("ControllerTest", CENTER, 8);
|
|
||||||
myOLED.print("V1.0", CENTER, 18);
|
|
||||||
myOLED.drawLine(22 + 0, 28, 22 + 84, 28);
|
|
||||||
myOLED.print("2013 sanni", CENTER, 32);
|
|
||||||
myOLED.update();
|
|
||||||
|
|
||||||
delay(1500);
|
|
||||||
startscreen = 1;
|
|
||||||
myOLED.clrScr();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
myOLED.print("Button Test", CENTER, 0);
|
|
||||||
myOLED.drawLine(22 + 0, 10, 22 + 84, 10);
|
|
||||||
|
|
||||||
// Print Button
|
|
||||||
printSTR(" " + button + " ", CENTER, 20);
|
|
||||||
|
|
||||||
// Print Stick X Value
|
|
||||||
String stickx = String("X: " + String(N64_status.stick_x, DEC) + " ");
|
|
||||||
printSTR(stickx, 22 + 0, 38);
|
|
||||||
|
|
||||||
// Print Stick Y Value
|
|
||||||
String sticky = String("Y: " + String(N64_status.stick_y, DEC) + " ");
|
|
||||||
printSTR(sticky, 22 + 42, 38);
|
|
||||||
|
|
||||||
//Update LCD
|
|
||||||
myOLED.update();
|
|
||||||
|
|
||||||
// go to next screen
|
|
||||||
nextscreen();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
myOLED.print("Range", 22 + 52, 5);
|
|
||||||
myOLED.print("Test", 22 + 52, 15);
|
|
||||||
myOLED.drawRect(22 + 50, 0, 22 + 83, 25);
|
|
||||||
|
|
||||||
// Print Stick X Value
|
|
||||||
String stickx = String("X:" + String(N64_status.stick_x, DEC) + " ");
|
|
||||||
printSTR(stickx, 22 + 50, 28);
|
|
||||||
|
|
||||||
// Print Stick Y Value
|
|
||||||
String sticky = String("Y:" + String(N64_status.stick_y, DEC) + " ");
|
|
||||||
printSTR(sticky, 22 + 50, 38);
|
|
||||||
|
|
||||||
// Draw Axis
|
|
||||||
myOLED.drawLine(xax - zax, yax, xax + zax, yax);
|
|
||||||
myOLED.drawLine(xax, yax - zax, xax, yax + zax);
|
|
||||||
myOLED.clrPixel(xax, yax - 80 / 4);
|
|
||||||
myOLED.clrPixel(xax, yax + 80 / 4);
|
|
||||||
myOLED.clrPixel(xax + 80 / 4, yax);
|
|
||||||
myOLED.clrPixel(xax - 80 / 4, yax);
|
|
||||||
|
|
||||||
//Draw Analog Stick
|
|
||||||
if (mode == 1)
|
|
||||||
{
|
|
||||||
myOLED.setPixel(xax + N64_status.stick_x / 4, yax - N64_status.stick_y / 4);
|
|
||||||
//Update LCD
|
|
||||||
myOLED.update();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
myOLED.drawCircle(xax + N64_status.stick_x / 4, yax - N64_status.stick_y / 4, 2);
|
|
||||||
//Update LCD
|
|
||||||
myOLED.update();
|
|
||||||
myOLED.clrScr();
|
|
||||||
}
|
|
||||||
|
|
||||||
// switch mode
|
|
||||||
if (button == "Press a button" && lastbutton == "Z")
|
|
||||||
{
|
|
||||||
if (mode == 0)
|
|
||||||
{
|
|
||||||
mode = 1;
|
|
||||||
myOLED.clrScr();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mode = 0;
|
|
||||||
myOLED.clrScr();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// go to next screen
|
|
||||||
nextscreen();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3:
|
|
||||||
{
|
|
||||||
myOLED.print("Skipping Test", CENTER, 0);
|
|
||||||
myOLED.drawLine(22 + 0, 10, 22 + 83, 10);
|
|
||||||
myOLED.drawRect(22 + 0, 20, 22 + 83, 44);
|
|
||||||
if (N64_status.stick_x > 0)
|
|
||||||
myOLED.drawLine(22 + N64_status.stick_x, 20, 22 + N64_status.stick_x, 44);
|
|
||||||
|
|
||||||
//Update LCD
|
|
||||||
myOLED.update();
|
|
||||||
|
|
||||||
if (button == "Press a button" && lastbutton == "Z")
|
|
||||||
{
|
|
||||||
// reset button
|
|
||||||
lastbutton = "N/A";
|
|
||||||
|
|
||||||
myOLED.clrScr();
|
|
||||||
}
|
|
||||||
// go to next screen
|
|
||||||
nextscreen();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 4:
|
|
||||||
{
|
|
||||||
switch ( test )
|
|
||||||
{
|
|
||||||
case 0: // Display results
|
|
||||||
{
|
|
||||||
switch (results)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
{
|
|
||||||
anastick = "YOURS";
|
|
||||||
upx = bupx;
|
|
||||||
upy = bupy;
|
|
||||||
uprightx = buprightx;
|
|
||||||
uprighty = buprighty;
|
|
||||||
rightx = brightx;
|
|
||||||
righty = brighty;
|
|
||||||
downrightx = bdownrightx;
|
|
||||||
downrighty = bdownrighty;
|
|
||||||
downx = bdownx;
|
|
||||||
downy = bdowny;
|
|
||||||
downleftx = bdownleftx;
|
|
||||||
downlefty = bdownlefty;
|
|
||||||
leftx = bleftx;
|
|
||||||
lefty = blefty;
|
|
||||||
upleftx = bupleftx;
|
|
||||||
uplefty = buplefty;
|
|
||||||
|
|
||||||
if (button == "Press a button" && lastbutton == "A")
|
|
||||||
{
|
|
||||||
// reset button
|
|
||||||
lastbutton = "N/A";
|
|
||||||
results = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
anastick = "ORIG";
|
|
||||||
upx = 1;
|
|
||||||
upy = 84;
|
|
||||||
uprightx = 67;
|
|
||||||
uprighty = 68;
|
|
||||||
rightx = 83;
|
|
||||||
righty = -2;
|
|
||||||
downrightx = 67;
|
|
||||||
downrighty = -69;
|
|
||||||
downx = 3;
|
|
||||||
downy = -85;
|
|
||||||
downleftx = -69;
|
|
||||||
downlefty = -70;
|
|
||||||
leftx = -85;
|
|
||||||
lefty = 0;
|
|
||||||
upleftx = -68;
|
|
||||||
uplefty = 68;
|
|
||||||
|
|
||||||
if (button == "Press a button" && lastbutton == "A")
|
|
||||||
{
|
|
||||||
// reset button
|
|
||||||
lastbutton = "N/A";
|
|
||||||
results = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
} //results
|
|
||||||
myOLED.clrScr();
|
|
||||||
|
|
||||||
printSTR(anastick, 22 + 50, 0);
|
|
||||||
|
|
||||||
myOLED.print("U:", 22 + 50, 10);
|
|
||||||
myOLED.printNumI(upy, RIGHT, 10);
|
|
||||||
myOLED.print("D:", 22 + 50, 20);
|
|
||||||
myOLED.printNumI(downy, RIGHT, 20);
|
|
||||||
myOLED.print("L:", 22 + 50, 30);
|
|
||||||
myOLED.printNumI(leftx, RIGHT, 30);
|
|
||||||
myOLED.print("R:", 22 + 50, 40);
|
|
||||||
myOLED.printNumI(rightx, RIGHT, 40);
|
|
||||||
|
|
||||||
myOLED.drawLine(xax + upx / 4, yax - upy / 4, xax + uprightx / 4, yax - uprighty / 4);
|
|
||||||
myOLED.drawLine(xax + uprightx / 4, yax - uprighty / 4, xax + rightx / 4, yax - righty / 4);
|
|
||||||
myOLED.drawLine(xax + rightx / 4, yax - righty / 4, xax + downrightx / 4, yax - downrighty / 4);
|
|
||||||
myOLED.drawLine(xax + downrightx / 4, yax - downrighty / 4, xax + downx / 4, yax - downy / 4);
|
|
||||||
myOLED.drawLine(xax + downx / 4, yax - downy / 4, xax + downleftx / 4, yax - downlefty / 4);
|
|
||||||
myOLED.drawLine(xax + downleftx / 4, yax - downlefty / 4, xax + leftx / 4, yax - lefty / 4);
|
|
||||||
myOLED.drawLine(xax + leftx / 4, yax - lefty / 4, xax + upleftx / 4, yax - uplefty / 4);
|
|
||||||
myOLED.drawLine(xax + upleftx / 4, yax - uplefty / 4, xax + upx / 4, yax - upy / 4);
|
|
||||||
|
|
||||||
myOLED.setPixel(xax, yax);
|
|
||||||
|
|
||||||
//Update LCD
|
|
||||||
myOLED.update();
|
|
||||||
break;
|
|
||||||
} //display results
|
|
||||||
|
|
||||||
case 1:// +y Up
|
|
||||||
{
|
|
||||||
myOLED.print("Hold Stick Up", CENTER, 18);
|
|
||||||
myOLED.print("then press A", CENTER, 28);
|
|
||||||
//myOLED.drawBitmap(110, 60, ana1);
|
|
||||||
|
|
||||||
if (button == "Press a button" && lastbutton == "A")
|
|
||||||
{
|
|
||||||
bupx = N64_status.stick_x;
|
|
||||||
bupy = N64_status.stick_y;
|
|
||||||
// reset button
|
|
||||||
lastbutton = "N/A";
|
|
||||||
|
|
||||||
myOLED.clrScr();
|
|
||||||
test = 2;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 2:// +y+x Up-Right
|
|
||||||
{
|
|
||||||
myOLED.print("Up-Right", CENTER, 22 );
|
|
||||||
//myOLED.drawBitmap(110, 60, ana2);
|
|
||||||
|
|
||||||
if (button == "Press a button" && lastbutton == "A")
|
|
||||||
{
|
|
||||||
buprightx = N64_status.stick_x;
|
|
||||||
buprighty = N64_status.stick_y;
|
|
||||||
test = 3;
|
|
||||||
// reset button
|
|
||||||
lastbutton = "N/A";
|
|
||||||
|
|
||||||
myOLED.clrScr();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 3:// +x Right
|
|
||||||
{
|
|
||||||
myOLED.print("Right", CENTER, 22 );
|
|
||||||
//myOLED.drawBitmap(110, 60, ana3);
|
|
||||||
|
|
||||||
if (button == "Press a button" && lastbutton == "A")
|
|
||||||
{
|
|
||||||
brightx = N64_status.stick_x;
|
|
||||||
brighty = N64_status.stick_y;
|
|
||||||
test = 4;
|
|
||||||
// reset button
|
|
||||||
lastbutton = "N/A";
|
|
||||||
|
|
||||||
myOLED.clrScr();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 4:// -y+x Down-Right
|
|
||||||
{
|
|
||||||
myOLED.print("Down-Right", CENTER, 22 );
|
|
||||||
//myOLED.drawBitmap(110, 60, ana4);
|
|
||||||
|
|
||||||
if (button == "Press a button" && lastbutton == "A")
|
|
||||||
{
|
|
||||||
bdownrightx = N64_status.stick_x;
|
|
||||||
bdownrighty = N64_status.stick_y;
|
|
||||||
test = 5;
|
|
||||||
// reset button
|
|
||||||
lastbutton = "N/A";
|
|
||||||
|
|
||||||
myOLED.clrScr();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 5:// -y Down
|
|
||||||
{
|
|
||||||
myOLED.print("Down", CENTER, 22 );
|
|
||||||
//myOLED.drawBitmap(110, 60, ana5);
|
|
||||||
|
|
||||||
if (button == "Press a button" && lastbutton == "A")
|
|
||||||
{
|
|
||||||
bdownx = N64_status.stick_x;
|
|
||||||
bdowny = N64_status.stick_y;
|
|
||||||
test = 6;
|
|
||||||
// reset button
|
|
||||||
lastbutton = "N/A";
|
|
||||||
|
|
||||||
myOLED.clrScr();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 6:// -y-x Down-Left
|
|
||||||
{
|
|
||||||
myOLED.print("Down-Left", CENTER, 22 );
|
|
||||||
//myOLED.drawBitmap(110, 60, ana6);
|
|
||||||
|
|
||||||
if (button == "Press a button" && lastbutton == "A")
|
|
||||||
{
|
|
||||||
bdownleftx = N64_status.stick_x;
|
|
||||||
bdownlefty = N64_status.stick_y;
|
|
||||||
test = 7;
|
|
||||||
// reset button
|
|
||||||
lastbutton = "N/A";
|
|
||||||
|
|
||||||
myOLED.clrScr();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 7:// -x Left
|
|
||||||
{
|
|
||||||
myOLED.print("Left", CENTER, 22 );
|
|
||||||
//myOLED.drawBitmap(110, 60, ana7);
|
|
||||||
|
|
||||||
if (button == "Press a button" && lastbutton == "A")
|
|
||||||
{
|
|
||||||
bleftx = N64_status.stick_x;
|
|
||||||
blefty = N64_status.stick_y;
|
|
||||||
test = 8;
|
|
||||||
// reset button
|
|
||||||
lastbutton = "N/A";
|
|
||||||
|
|
||||||
myOLED.clrScr();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 8:// +y+x Up-Left
|
|
||||||
{
|
|
||||||
myOLED.print("Up-Left", CENTER, 22);
|
|
||||||
//myOLED.drawBitmap(110, 60, ana8);
|
|
||||||
|
|
||||||
if (button == "Press a button" && lastbutton == "A")
|
|
||||||
{
|
|
||||||
bupleftx = N64_status.stick_x;
|
|
||||||
buplefty = N64_status.stick_y;
|
|
||||||
test = 0;
|
|
||||||
// reset button
|
|
||||||
lastbutton = "N/A";
|
|
||||||
|
|
||||||
myOLED.clrScr();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (test != 0)
|
|
||||||
{
|
|
||||||
myOLED.print("Benchmark", CENTER, 0);
|
|
||||||
myOLED.drawLine(22 + 0, 9, 22 + 83, 9);
|
|
||||||
}
|
|
||||||
myOLED.update();
|
|
||||||
// go to next screen
|
|
||||||
nextscreen();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
|||||||
This is my portable N64 Controller Tester edited to run on the Cart Reader Shield.
|
|
||||||
The N64 controller's data line is connected to Arduino Mega Pin 7.
|
|
Binary file not shown.
@ -1,4 +0,0 @@
|
|||||||
Unzip and copy those into your Arduino library folder e.g. C:\Users\sanni\Documents\Arduino\libraries
|
|
||||||
|
|
||||||
You can also get the latest versions from their creators page:
|
|
||||||
Oled lib: http://www.rinkydinkelectronics.com/library.php?id=79
|
|
Loading…
Reference in New Issue
Block a user