Adding EXP0_PULLUP_TEST should probably verify pullup on EXP0 provides

logic 1 if relying on it.  Seems to work fine on NES discrete and
INLXO-ROM boards where planning to utilize it.  SNES can't pull up due to
pulldown and original famicom cart can't either perhaps because of
EXP6 EXP FF output being too much of a load..?
This commit is contained in:
Paul Molloy 2016-11-27 17:47:40 -06:00
parent 8c1eb00e85
commit c6a68c679f
10 changed files with 143 additions and 15 deletions

View File

@ -32,6 +32,28 @@ uint8_t io_opcode_only( uint8_t opcode )
} }
/* Desc:Function takes an opcode which was transmitted via USB
* then decodes it to call designated function.
* shared_dict_io.h is used in both host and fw to ensure opcodes/names align
* Pre: Macros must be defined in firmware pinport.h
* opcode must be defined in shared_dict_io.h
* Post:function call complete.
* 7bytes of return data are contained in *data pointer
* Rtn: SUCCESS if opcode found, ERR_UNKN_IO_OPCODE_RTN if opcode not present.
*/
uint8_t io_opcode_return( uint8_t opcode, uint8_t *data )
{
switch (opcode) {
case EXP0_PULLUP_TEST: exp0_pullup_test(data); break;
default:
//macro doesn't exist
return ERR_UNKN_IO_OPCODE_RTN;
}
return SUCCESS;
}
//pullup as many cart pins as possible //pullup as many cart pins as possible
//goal to be safe state for all hardware //goal to be safe state for all hardware
//doesn't currently contain any checks to report error/success from //doesn't currently contain any checks to report error/success from
@ -62,6 +84,8 @@ void io_reset()
//NES PRG-ROM /OE (with pulldown) on old INL-ROM v1 boards w/pulldown //NES PRG-ROM /OE (with pulldown) on old INL-ROM v1 boards w/pulldown
//NED PRG-ROM /WE (with pullup) on INL-ROM v3 boards w/pullup //NED PRG-ROM /WE (with pullup) on INL-ROM v3 boards w/pullup
//NES CPLD JTAG TDO non-5v tolerant //NES CPLD JTAG TDO non-5v tolerant
//Famicom carts have APU sound (EXP6) shorted to RF sound (EXP0)
// -enabling EXP FF output will drive EXP0 to value of A21/EXP6
_EXP0_FLT(); _EXP0_FLT();
//LED LAST displaying complete.. //LED LAST displaying complete..
@ -139,6 +163,8 @@ void nes_init()
//latch address of $000000 //latch address of $000000
//disable cart memories //disable cart memories
//reset high disables SRAM and puts INL carts in PRGM mode //reset high disables SRAM and puts INL carts in PRGM mode
//Excersize extreme caution calling this while NES/FC cart inserted
//probably won't work if FC inserted due to EXP0-EXP6 short due to audio jumper on cart
void snes_init() void snes_init()
{ {
//start with a reset //start with a reset
@ -189,3 +215,40 @@ void snes_init()
} }
//Test starts by verifying EXP0 can be driven low, if not, will return one byte of AUX_PIN
//followed by alternating 0xAA, 0x55, 0xAA...
//This test pulls up EXP0 and then reads AUX_PIN 6 times in rapid succession returning error code
//plus 6 bytes of read data. If pull up works but is just slow, should see that in return data.
//data[0] marks bit where EXP0 resisdes to provide host with bitmask for EXP0
void exp0_pullup_test(uint8_t *data)
{
//provide host with bit mask of EXP0 for first byte
data[0] = (1<<EXP0);
//first verify EXP0 can be driven low
_EXP0_LO(); //sets O/P and low
NOP(); //give some time to settle
data[1] = AUX_IN; //port where EXP0 resides
_EXP0_FLT(); //sets I/P w/o pullup
if ( (data[1] & data[0]) == data[0]) {
//EXP0 was high, couldn't drive EXP0 low
data[2] = data[4] = data[6] = 0xAA;
data[3] = data[5] = 0x55;
//return this signature as indication EXP0 failed to drive low
return;
}
//Driving EXP0 low was successful, now pullup and read back
_EXP0_PU();
data[1] = AUX_IN;
data[2] = AUX_IN;
data[3] = AUX_IN;
data[4] = AUX_IN;
data[5] = AUX_IN;
data[6] = AUX_IN;
//return EXP0 to floating
_EXP0_FLT();
}

View File

@ -7,8 +7,11 @@
#include "shared_errors.h" #include "shared_errors.h"
uint8_t io_opcode_only( uint8_t opcode ); uint8_t io_opcode_only( uint8_t opcode );
uint8_t io_opcode_return( uint8_t opcode, uint8_t *data );
void io_reset(); void io_reset();
void nes_init(); void nes_init();
void snes_init(); void snes_init();
void exp0_pullup_test(uint8_t *data);
#endif #endif

View File

@ -302,7 +302,7 @@ uint8_t nes_ppu_rd( uint8_t addrH, uint8_t addrL )
* data bus left clear * data bus left clear
* Rtn: None * Rtn: None
*/ */
uint8_t nes_ppu_wr( uint8_t addrH, uint8_t addrL, uint8_t data ) void nes_ppu_wr( uint8_t addrH, uint8_t addrL, uint8_t data )
{ {
//will need output whole function //will need output whole function
_DATA_OP(); _DATA_OP();

View File

@ -14,6 +14,6 @@ uint8_t emulate_nes_cpu_rd( uint8_t addrH, uint8_t addrL );
uint8_t nes_cpu_rd( uint8_t addrH, uint8_t addrL ); uint8_t nes_cpu_rd( uint8_t addrH, uint8_t addrL );
void nes_cpu_wr( uint8_t addrH, uint8_t addrL, uint8_t data ); void nes_cpu_wr( uint8_t addrH, uint8_t addrL, uint8_t data );
uint8_t nes_ppu_rd( uint8_t addrH, uint8_t addrL ); uint8_t nes_ppu_rd( uint8_t addrH, uint8_t addrL );
uint8_t nes_ppu_wr( uint8_t addrH, uint8_t addrL, uint8_t data ); void nes_ppu_wr( uint8_t addrH, uint8_t addrL, uint8_t data );
#endif #endif

View File

@ -113,6 +113,11 @@ USB_PUBLIC usbMsgLen_t usbFunctionSetup(uchar data[8]) {
case IO_OPCODE_ONLY_MIN ... IO_OPCODE_ONLY_MAX: case IO_OPCODE_ONLY_MIN ... IO_OPCODE_ONLY_MAX:
rv[0] = io_opcode_only( spacket->opcode ); rv[0] = io_opcode_only( spacket->opcode );
break; break;
case IO_OPCODE_RTN_MIN ... IO_OPCODE_RTN_MAX:
rv[0] = io_opcode_return(
spacket->opcode, &rv[1] );
rlen = 8;
break;
default: //io opcode min/max definition error default: //io opcode min/max definition error
rv[0] = ERR_BAD_IO_OP_MINMAX; rv[0] = ERR_BAD_IO_OP_MINMAX;
} }

View File

@ -10,6 +10,7 @@
#include "pinport.h" #include "pinport.h"
#include "io.h" #include "io.h"
#include "nes.h" #include "nes.h"
#include "snes.h"
#endif #endif

View File

@ -72,6 +72,10 @@ int dictionary_call( USBtransfer *transfer, uint8_t dictionary, uint8_t opcode,
case IO_OPCODE_ONLY_MIN ... IO_OPCODE_ONLY_MAX: case IO_OPCODE_ONLY_MIN ... IO_OPCODE_ONLY_MAX:
debug("IO_OPCODE_ONLY"); debug("IO_OPCODE_ONLY");
break; break;
case IO_OPCODE_RTN_MIN ... IO_OPCODE_RTN_MAX:
debug("IO_OPCODE_RTN");
transfer->wLength = 8;
break;
default: //io opcode min/max definition error default: //io opcode min/max definition error
sentinel("bad IO opcode min/max err:%d",ERR_BAD_IO_OP_MINMAX); sentinel("bad IO opcode min/max err:%d",ERR_BAD_IO_OP_MINMAX);
} }

View File

@ -8,18 +8,27 @@ int erase_nes( USBtransfer *transfer )
//dict opcode addr data //dict opcode addr data
dictionary_call( transfer, IO, IO_RESET, 0, 0); dictionary_call( transfer, IO, IO_RESET, 0, 0);
dictionary_call( transfer, IO, NES_INIT, 0, 0); dictionary_call( transfer, IO, NES_INIT, 0, 0);
//software mode dictionary_call( transfer, IO, EXP0_PULLUP_TEST, 0, 0);
dictionary_call( transfer, NES, DISCRETE_EXP0_PRGROM_WR, 0x5555, 0xAA); dictionary_call( transfer, PINPORT, AUX_RD, 0, 0);
dictionary_call( transfer, NES, DISCRETE_EXP0_PRGROM_WR, 0x2AAA, 0x55); dictionary_call( transfer, PINPORT, AUX_RD, 0, 0);
dictionary_call( transfer, NES, DISCRETE_EXP0_PRGROM_WR, 0x5555, 0x90); dictionary_call( transfer, PINPORT, AUX_RD, 0, 0);
dictionary_call( transfer, NES, NES_CPU_RD, 0x8000, 0); dictionary_call( transfer, PINPORT, AUX_RD, 0, 0);
dictionary_call( transfer, NES, NES_CPU_RD, 0x8001, 0); dictionary_call( transfer, PINPORT, AUX_RD, 0, 0);
dictionary_call( transfer, NES, NES_CPU_RD, 0x8000, 0); dictionary_call( transfer, PINPORT, AUX_RD, 0, 0);
dictionary_call( transfer, NES, NES_CPU_RD, 0x8001, 0); dictionary_call( transfer, PINPORT, AUX_RD, 0, 0);
//exit software
dictionary_call( transfer, NES, DISCRETE_EXP0_PRGROM_WR, 0x8000, 0xF0); ////software mode
dictionary_call( transfer, NES, NES_CPU_RD, 0x8000, 0); // dictionary_call( transfer, NES, DISCRETE_EXP0_PRGROM_WR, 0x5555, 0xAA);
dictionary_call( transfer, NES, NES_CPU_RD, 0x8001, 0); // dictionary_call( transfer, NES, DISCRETE_EXP0_PRGROM_WR, 0x2AAA, 0x55);
// dictionary_call( transfer, NES, DISCRETE_EXP0_PRGROM_WR, 0x5555, 0x90);
// dictionary_call( transfer, NES, NES_CPU_RD, 0x8000, 0);
// dictionary_call( transfer, NES, NES_CPU_RD, 0x8001, 0);
// dictionary_call( transfer, NES, NES_CPU_RD, 0x8000, 0);
// dictionary_call( transfer, NES, NES_CPU_RD, 0x8001, 0);
////exit software
// dictionary_call( transfer, NES, DISCRETE_EXP0_PRGROM_WR, 0x8000, 0xF0);
// dictionary_call( transfer, NES, NES_CPU_RD, 0x8000, 0);
// dictionary_call( transfer, NES, NES_CPU_RD, 0x8001, 0);
//erase //erase
// dictionary_call( transfer, NES, DISCRETE_EXP0_PRGROM_WR, 0x5555, 0xAA); // dictionary_call( transfer, NES, DISCRETE_EXP0_PRGROM_WR, 0x5555, 0xAA);

View File

@ -26,7 +26,7 @@
// 0x00-0xFF // 0x00-0xFF
// Detect this opcode/operand setup with opcode between the following defines: // Detect this opcode/operand setup with opcode between the following defines:
#define IO_OPCODE_ONLY_MIN 0x00 #define IO_OPCODE_ONLY_MIN 0x00
#define IO_OPCODE_ONLY_MAX 0xFF #define IO_OPCODE_ONLY_MAX 0x7F
// //
//============================================================================================= //=============================================================================================
//============================================================================================= //=============================================================================================
@ -53,4 +53,46 @@
//reset high disables SRAM and puts INL carts in PRGM mode //reset high disables SRAM and puts INL carts in PRGM mode
#define SNES_INIT 0x02 #define SNES_INIT 0x02
//=============================================================================================
// OPCODES with no operand but have RETRUN VALUE plus SUCCESS/ERROR_CODE
//=============================================================================================
// 0x00-0xFF
// Detect this opcode/operand setup with opcode between the following defines:
#define IO_OPCODE_RTN_MIN 0x80
#define IO_OPCODE_RTN_MAX 0xFF
//
//=============================================================================================
//=============================================================================================
//Test EXP0 drive with pull up
//This is an important test if reling on pulling up EXP0 pin to drive the cart's pin.
//EXP0 is used for various things and may have pull up/down of it's own or significant load
//Test that programmer can drive EXP0 with a pull up before reling on commands that only pullup
//If this fails, can resort to driving EXP0 with SNES /RESET commands but excersize caution
//as some NES cart's have CPLD JTAG TDO pin placed on EXP0 that may not be 5v tolerant.
//FC also has APU audio placed on EXP0, carts without exp sound short RF sound (EXP6) to EXP0
//So if EXP FF's output is enabled, driving the mcu EXP0 pin could cause damage to the pin.
//that's why it's best in general to only pull up EXP0 instead of driving it high.
//Have to drive it low however to get logic 0 most times. If famicom cart is inserted,
//it's probably safer to drive EXP0 through EXP6 sound jumper and leave EXP0 floating/pulledup.
//
//Test starts by verifying EXP0 can be driven low, if not, will return one byte of AUX_PIN
//followed by alternating 0xAA, 0x55, 0xAA...
//This test pulls up EXP0 and then reads AUX_PIN 6 times in rapid succession returning error code
//plus 6 bytes of read data. If pull up works but is just slow, should see that in return data.
//data[0] marks bit where EXP0 resisdes to provide host with bitmask for EXP0
#define EXP0_PULLUP_TEST 0x80
//testing results:
//without any cart inserted takes 5 cycles for EXP0 to settle high
//er: 0 rv: 1, b8, b8, b8, b8, b9, b9
//with discrete NROM board inserted (has pullup on EXP0) settled immediately
//er: 0 rv: 1, 99, 99, 99, 99, 99, 99
//SNES board inserted never settled
//er: 0 rv: 1, b8, b8, b8, b8, b8, b8
//famicom NROM choplifter cart inserted never settled
//er: 0 rv: 1, 98, 98, 98, 98, 98, 98
//INLXO-ROM board JTAG TDO (non-5v tolerant) tied to EXP0 settled immediately
//er: 0 rv: 1, 99, 99, 99, 99, 99, 99
#endif #endif

View File

@ -18,6 +18,7 @@
#define ERR_UNKN_PP_OPCODE_8BRV 144 #define ERR_UNKN_PP_OPCODE_8BRV 144
#define ERR_UNKN_IO_OPCODE_ONLY 150 #define ERR_UNKN_IO_OPCODE_ONLY 150
#define ERR_UNKN_IO_OPCODE_RTN 151
#define ERR_UNKN_NES_OPCODE_24BOP 160 #define ERR_UNKN_NES_OPCODE_24BOP 160
#define ERR_UNKN_NES_OPCODE_16BOP_8BRV 161 #define ERR_UNKN_NES_OPCODE_16BOP_8BRV 161