modified: logic.h

modified:   pinport.c
modified:   pinport.h
	-completing implementation of remaining shared_pinport opcodes
modified:   ../../shared/shared_pinport.h
	-few opcodes deleted because I decided they were stupid when got
	around to implementing them.  Set user up for errors and not
	useful generally.
This commit is contained in:
Paul Molloy 2016-11-24 07:14:15 -06:00
parent 0af7bb3b16
commit ce2a5aecca
4 changed files with 193 additions and 120 deletions

View File

@ -6,10 +6,10 @@
#define IP 0x00
#define OP 0xFF
//FALSE is ANYTHING but TRUE, the value signifies the error number
#define TRUE 0x00
#define SUCCESS 0x00
#define ERR_UNKN_PP_OPCODE_ONLY 1
#define ERR_UNKN_PP_OPCODE_8BOP 2
#define ERR_UNKN_PP_OPCODE_16BOP 2
#define ERR_UNKN_PP_OPCODE_ONLY 1
#define ERR_UNKN_PP_OPCODE_8BOP 2
#define ERR_UNKN_PP_OPCODE_16BOP 3
#define ERR_UNKN_PP_OPCODE_24BOP 4
#define ERR_UNKN_PP_OPCODE_8BRV 5

View File

@ -295,6 +295,7 @@ void software_AHL_CLK()
* -FF latch /OE pins set as outputs
* -FF CLK pins low ready for CLK
* See big CAUTION on shared_pinport.h for more details
* ADDR_OP() expected to be set
* Post:Macro/function called with operand
* data bus left free and clear when possible
* -DATA_OPnSET diliberately drive the bus
@ -309,11 +310,6 @@ uint8_t pinport_opcode_8b_operand( uint8_t opcode, uint8_t operand )
case ADDR_SET:
ADDR_OUT = operand;
break;
//convienent/safer sets OP then value
case ADDR_OPnSET:
_ADDR_OP();
ADDR_OUT = operand;
break;
//DATA[7:0] PORTB
case DATA_SET:
@ -327,20 +323,14 @@ uint8_t pinport_opcode_8b_operand( uint8_t opcode, uint8_t operand )
//ADDR[15:8] FLIPFLOP
case ADDRH_SET:
_DATA_OP();
DATA_OUT = operand;
_AHL_CLK();
_DATA_IP();
_ADDRH_SET(operand);
break;
//EXPANSION FLIPFLOP
//NES: ADDRX[7:0] -> EXP PORT [8:1]
//SNES: ADDRX[7:0] -> CPU A[23:16]
case ADDRX_SET:
_DATA_OP();
DATA_OUT = operand;
_AXL_CLK();
_DATA_IP();
_ADDRX_SET(operant);
break;
//Set ADDR/DATA bus DDR registers with bit granularity
@ -381,8 +371,8 @@ uint8_t pinport_opcode_8b_operand( uint8_t opcode, uint8_t operand )
/* Desc:Function takes an opcode and 16bit operand which was transmitted via USB
* operand_MS is most significant byte, operand_LS is least significant
* then decodes it to call designated macro/function.
* operandMSB is most significant byte, operandLSB is least significant
* shared_pinport.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_pinport.h
@ -390,68 +380,61 @@ uint8_t pinport_opcode_8b_operand( uint8_t opcode, uint8_t operand )
* control pins must be initialized
* -FF latch /OE pins set as outputs
* -FF CLK pins low ready for CLK
* ADDR_OP() is expected to be set.
* /ROMSEL and M2 expected to be OP.
* See big CAUTION on shared_pinport.h for more details
* Post:Macro/function called with operand
* data bus left free and clear when possible
* -some opcodes diliberately drive the bus
* ADDR_OP() is left set as default state
* Rtn: SUCCESS if opcode found, ERR_UNKN_PP_OPCODE_16BOP if opcode not present.
*/
uint8_t pinport_opcode_16b_operand( uint8_t opcode, uint8_t operand_MS, uint8_t operand_LS )
uint8_t pinport_opcode_16b_operand( uint8_t opcode, uint8_t operandMSB, uint8_t operandLSB )
{
switch (opcode) {
//ADDR[15:0] (ADDRH:ADDR)
//Doesn't affect control signals
//bits[13:0] are applied to NES CPU, NES PPU, and SNES address bus
//bit[14] is only applied to CPU A14 on NES
//bit[15] is only applied to PPU /A13 on NES
//bit[15:14] are applied to SNES A[15:14]
//ADDR[15:0] (ADDRH:ADDR)
//Doesn't affect control signals
//bits[13:0] are applied to NES CPU, NES PPU, and SNES address bus
//bit[14] is only applied to CPU A14 on NES
//bit[15] is only applied to PPU /A13 on NES
//bit[15:14] are applied to SNES A[15:14]
case ADDR16_SET:
_DATA_OP();
DATA_OUT =
_ADDRH_SET(operandMSB);
ADDR_OUT = operandLSB;
break;
//Set NES CPU ADDRESS BUS SET with /ROMSEL
//bit 15 is decoded to enable /ROMSEL properly (aka PRG /CE)
//bit15 is actually inverted then applied to /ROMSEL since /ROMSEL is low when NES CPU A15 is high
//NOTE! This does NOT affect M2 (aka phi2), so carts using M2 to decode things like WRAM is dependent on last value of M2
//This will also stop current value of PPU /A13 with bit15
//Set NES CPU ADDRESS BUS SET with /ROMSEL
//bit 15 is decoded to enable /ROMSEL properly (aka PRG /CE)
//bit15 is actually inverted then applied to /ROMSEL since /ROMSEL is low when NES CPU A15 is high
//NOTE! This does NOT affect M2 (aka phi2), so carts using M2 to decode things like WRAM is dependent on last value of M2
//This will also stop current value of PPU /A13 with bit15
case NCPU_ADDR_ROMSEL:
_ADDRH_SET(operandMSB);
ADDR_OUT = operandLSB;
//if $8000 or higher
if (operandMSB >= 0x80) _ROMSEL_LO();
//else $7FFF or lower
else _ROMSEL_HI();
break;
//Set NES CPU ADDRESS BUS SET with M2
//Identical to NCPU_ADDR_ROMSEL above, but M2 (aka phi2) affected instead of /ROMSEL
//bit 15 is decoded to assert M2 properly
//bit15 is actually applied directly to M2 since carts use M2 being high as part of A15=1 detection
//NOTE! This does NOT affect /ROMSEL, so /ROMSEL is whatever value it was previously
//This will also stop current value of PPU /A13 with bit15
case NCPU_ADDR_M2:
break;
//Set NES CPU ADDRESS BUS SET with M2 & /ROMSEL
//Combination of opcodes above, but M2 and /ROMSEL will be asserted
//bit 15 is decoded to assert M2 & /ROMSEL properly
//bit15 is actually applied directly to M2 since carts use M2 being high as part of A15=1 detection
//NOTE! This does NOT affect /ROMSEL, so /ROMSEL is whatever value it was previously
//This will also stop current value of PPU /A13 with bit15
case NCPU_ADDR_M2ROMSEL:
break;
//Set NES PPU ADDRESS BUS with /A13
//PPU address bus is 14bits wide A[13:0] so operand bits [15:14] are ignored.
//bit 13 is inverted and applied to PPU /A13
//PPU control signals CHR /RD and CHR /WR are unaffected
//Note: since PPU /A13 is tied to ADDRH[7] could perform this faster by using ADDR16_SET
// but this opcode is convienent and ensures PPU /A13 is always inverse of PPU A13
// This is important for NES carts with on board CHR-ROM and VRAM for 4screen mirroring.
//Set NES PPU ADDRESS BUS with /A13
//PPU address bus is 14bits wide A[13:0] so operand bits [15:14] are ignored.
//bit 13 is inverted and applied to PPU /A13
//PPU control signals CHR /RD and CHR /WR are unaffected
//Note: since PPU /A13 is tied to ADDRH[7] could perform this faster by using ADDR16_SET
// but this opcode is convienent and ensures PPU /A13 is always inverse of PPU A13
// This is important for NES carts with on board CHR-ROM and VRAM for 4screen mirroring.
case NPPU_ADDR_SET:
ADDR_OUT = operandLSB;
// below PPU $2000, A13 clear, SET PPU /A13
if (operandMSB < 0x20) _ADDRH_SET(operandMSB & PPU_A13N);
// above PPU $1FFF, A13 set, PPU /A13 already clear in operandMSB
else _ADDRH_SET(operandMSB);
break;
default:
//macro doesn't exist
return ERR_UNKN_PP_OPCODE_16BOP;
@ -460,11 +443,112 @@ uint8_t pinport_opcode_16b_operand( uint8_t opcode, uint8_t operand_MS, uint8_t
return SUCCESS;
}
//=================================
//24bit operand
//=================================
/* Desc:Function takes an opcode and 24bit operand which was transmitted via USB
* then decodes it to call designated macro/function.
* operandMSB is most signf byte, operandMID is center, operandLSB is least significant
* shared_pinport.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_pinport.h
* data bus must be free and clear
* control pins must be initialized
* -FF latch /OE pins set as outputs
* -FF CLK pins low ready for CLK
* ADDR_OP() is expected to be set.
* See big CAUTION on shared_pinport.h for more details
* Post:Macro/function called with operand
* data bus left free and clear when possible
* -some opcodes may diliberately drive the bus
* ADDR_OP() is left set as default state
* Rtn: SUCCESS if opcode found, ERR_UNKN_PP_OPCODE_24BOP if opcode not present.
*/
uint8_t pinport_opcode_24b_operand( uint8_t opcode, uint8_t operandMSB, uint8_t operandMID, uint8_t operandLSB )
{
//ADDR[23:0] (ADDRX:ADDRH:ADDR) SNES full address bus
//Sets SNES 24 bit address but to value of 24bit operand
//No control signals are modified
//#define ADDR24_SET 0xB0
switch (opcode) {
//ADDR[23:0] (ADDRX:ADDRH:ADDR) SNES full address bus
//Sets SNES 24 bit address but to value of 24bit operand
//No control signals are modified
case ADDR24_SET:
ADDR_OUT = operandLSB;
_DATA_OP();
DATA_OUT = operandMID;
_CLK_AHL();
DATA_OUT = operandMSB;
_CLK_AXL();
DATA_IP();
break;
default:
//macro doesn't exist
return ERR_UNKN_PP_OPCODE_24BOP;
}
return SUCCESS;
}
/* Desc:Function takes an opcode and pointer to return value byte
* then decodes it to retreive value.
* shared_pinport.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_pinport.h
* See big CAUTION on shared_pinport.h for more details
* Post:pointer updated to value designated by opcode.
* Rtn: SUCCESS if opcode found, ERR_UNKN_PP_OPCODE_8BRV if opcode not present.
*/
uint8_t pinport_opcode_8b_return( uint8_t opcode, uint8_t *rvalue )
{
switch (opcode) {
//READ MCU I/O PORT INPUT 'PIN' REGISTERS
//ADDR[7:0] PINA
case ADDR_RD:
rvalue = ADDR_IN;
//DATA[7:0] PINB
case DATA_RD:
rvalue = DATA_IN;
//CTL PINC
case CTL_RD:
rvalue = CTL_IN;
//AUX PIND
case AUX_RD:
rvalue = AUX_IN;
//READ MCU I/O PORT OUTPUT 'PORT' REGISTERS
//ADDR[7:0] PORTA
case ADDR_PORT_RD:
rvalue = ADDR_OUT;
//DATA[7:0] PORTB
case DATA_PORT_RD:
rvalue = DATA_OUT;
//CTL PORTC
case CTL_PORT_RD:
rvalue = CTL_OUT;
//AUX PORTD
case AUX_PORT_RD:
rvalue = AUX_OUT;
//READ MCU I/O PORT DIRECTION 'DDR' REGISTERS
//ADDR[7:0] DDRA
case ADDR_DDR_RD:
rvalue = ADDR_DDR;
//DATA[7:0] DDRB
case DATA_DDR_RD:
rvalue = DATA_DDR:
//CTL DDRC
case CTL_DDR_RD:
rvalue = CTL_DDR;
//AUX DDRD
case AUX_DDR_RD:
rvalue = AUX_DDR;
default:
//macro doesn't exist
return ERR_UNKN_PP_OPCODE_8BRV;
}
return SUCCESS;
}

View File

@ -6,6 +6,8 @@
uint8_t pinport_opcode_only( uint8_t opcode );
uint8_t pinport_opcode_8b_operand( uint8_t opcode, uint8_t operand );
uint8_t pinport_opcode_16b_operand( uint8_t opcode, uint8_t operandMSB, uint8_t operandLSB )
uint8_t pinport_opcode_24b_operand( uint8_t opcode, uint8_t operandMSB, uint8_t operandMID, uint8_t operandLSB )
void software_AHL_CLK();
void software_AXL_CLK();
@ -400,5 +402,14 @@ void software_AXL_CLK();
#define _EXPFF_FLT() _XOE_hi();
#endif
//clocks must be initialized, Data bus clear
#define _ADDRH_SET(oper) _DATA_OP(); DATA_OUT = oper; _AHL_CLK(); _DATA_IP();
#define _ADDRX_SET(oper) _DATA_OP(); DATA_OUT = oper; _AXL_CLK(); _DATA_IP();
//PPU A13 is ADDRH bit 5
#define PPU_A13 0x20
//PPU /A13 is ADDRH bit 7
#define PPU_A13N 0x80
#endif

View File

@ -217,6 +217,9 @@
// ie driving PPU /A13 will be fed back to CIRAM /CE so it needs to be IP
// -if in doubt, leave it as input with pull up, atleast that shouldn't break anything
//
// -ADDR_OP is default state, these opcodes assume it to be set as it shouldn't conflict
// -/ROMSEL & M2 expected to be set as outputs
//
//
//=============================================================================================
//=============================================================================================
@ -228,9 +231,9 @@
// OPCODES WITH OPERAND and no return value besides SUCCESS/ERROR_CODE
//=============================================================================================
// 0x80-0x9F: opcodes with 8bit operand
// 0x80-8B are only ones currently in use
// 0x80-8A are only ones currently in use
// 0xA0-0xAF: opcodes with 16bit operand
// 0xA0-A4 are only ones currently in use
// 0xA0-A2 are only ones currently in use
// 0xB0-0xBF: opcodes with 24bit operand
// 0xA0 is currently only one in use
//
@ -249,13 +252,11 @@
//ADDR[7:0] PORTA
#define ADDR_SET 0x80
//conveinent/safe yet slower function that sets ADDR as OP then sets value
#define ADDR_OPnSET 0x81
//DATA[7:0] PORTB
#define DATA_SET 0x82
#define DATA_SET 0x81
//conveinent/safe yet slower function that sets ADDR as OP then sets value
#define DATA_OPnSET 0x83
#define DATA_OPnSET 0x82
//ADDR[15:8] FLIPFLOP
//NES CPU: ADDRH[6:0] -> CPU A[14:8]
@ -264,27 +265,27 @@
// ADDRH[6] -> NC on PPU side
// ADDRH[7] -> PPU /A13 (which drives CIRAM /CE on most carts "2-screen mirroring")
//SNES: ADDRH[7:0] -> CPU A[15:8]
#define ADDRH_SET 0x84
#define ADDRH_SET 0x83
//EXPANSION FLIPFLOP
//NES: ADDRX[7:0] -> EXP PORT [8:1]
//SNES: ADDRX[7:0] -> CPU A[23:16]
#define ADDRX_SET 0x85
#define ADDRX_SET 0x84
//Set ADDR/DATA bus DDR registers with bit granularity
// OP() IP() macros affect entire 8bit port's direction
// Each pin can be controlled individually though
// This could be useful for advanced feature that doesn't treat DATA/ADDR as byte wide port.
#define ADDR_DDR_SET 0x86
#define DATA_DDR_SET 0x87
#define ADDR_DDR_SET 0x85
#define DATA_DDR_SET 0x86
//Perhaps it will be useful to have this function on other ports as well
//But probably wouldn't be very useful if standard carts are plugged in..
//AUX port operations will shield USB pins from being affected
//defined as lower case because you shouldn't call these unless you *Really* know what you're doing..
#define ctl_ddr_set 0x88
#define aux_ddr_set 0x89
#define ctl_port_set 0x8A
#define aux_port_set 0x8B
#define ctl_ddr_set 0x87
#define aux_ddr_set 0x88
#define ctl_port_set 0x89
#define aux_port_set 0x8A
//TODO consider listing AVR internal registers here..?
//could be useful when utilizing SPI/I2C communications etc
@ -310,22 +311,6 @@
//This will also stop current value of PPU /A13 with bit15
#define NCPU_ADDR_ROMSEL 0xA1
//Set NES CPU ADDRESS BUS SET with M2
//Identical to NCPU_ADDR_ROMSEL above, but M2 (aka phi2) affected instead of /ROMSEL
//bit 15 is decoded to assert M2 properly
//bit15 is actually applied directly to M2 since carts use M2 being high as part of A15=1 detection
//NOTE! This does NOT affect /ROMSEL, so /ROMSEL is whatever value it was previously
//This will also stop current value of PPU /A13 with bit15
#define NCPU_ADDR_M2 0xA2
//Set NES CPU ADDRESS BUS SET with M2 & /ROMSEL
//Combination of opcodes above, but M2 and /ROMSEL will be asserted
//bit 15 is decoded to assert M2 & /ROMSEL properly
//bit15 is actually applied directly to M2 since carts use M2 being high as part of A15=1 detection
//NOTE! This does NOT affect /ROMSEL, so /ROMSEL is whatever value it was previously
//This will also stop current value of PPU /A13 with bit15
#define NCPU_ADDR_M2ROMSEL 0xA3
//TODO consider opcode that preserves PPU /A13 instead of stomping it like the opcodes above.
//Can't think of why this would be useful so ignoring for now
//One reason might be to keep VRAM silent on a NES board with 4screen mirroring..
@ -338,10 +323,8 @@
//Note: since PPU /A13 is tied to ADDRH[7] could perform this faster by using ADDR16_SET
// but this opcode is convienent and ensures PPU /A13 is always inverse of PPU A13
// This is important for NES carts with on board CHR-ROM and VRAM for 4screen mirroring.
#define NPPU_ADDR_SET 0xA4
#define NPPU_ADDR_SET 0xA2
//TODO consider opcode that sets PPU A[12:0] and maintains previous value of A13 & /A13
//might be useful if trying to latch/clock CHR memory with it's /CE pin instead of /OE /WE
//=================================
//24bit operand
@ -358,7 +341,7 @@
// OPCODES with NO OPERAND but have RETURN VALUE plus SUCCESS/ERROR_CODE
//=============================================================================================
// 0xC0-0xFF: opcodes with 8bit return value (plus SuCCESS/ERROR)
// 0xC0-CD are only ones currently in use
// 0xC0-CB are only ones currently in use
//
// 0x??-0xFF: larger return values perhaps?
//
@ -375,45 +358,40 @@
//Current value of PORT Determines if pullups are activated or not, pull up with HI() macro, and float with LO() macro
//ADDR[7:0] PINA
#define ADDR_RD 0xC0
//conveinence fucntion sets as input then reads
#define ADDR_INnRD 0xC1
//DATA[7:0] PINB
#define DATA_RD 0xC2
//conveinence fucntion sets as input then reads
#define DATA_INnRD 0xC3
#define DATA_RD 0xC1
//CTL PINC
//Should set pin of interest to input with IP with macros prior to reading
//you're still allowed to read value even if some/all pins are output though
#define CTL_RD 0xC4
#define CTL_RD 0xC2
//AUX PIND
//Should set pin of interest to input with IP with macros prior to reading
//you're still allowed to read value even if some/all pins are output though
#define AUX_RD 0xC5
#define AUX_RD 0xC3
//READ MCU I/O PORT OUTPUT 'PORT' REGISTERS
//Gives means to see what pins are currently being driven (or pulled up) to.
//ADDR[7:0] PORTA
#define ADDR_PORT_RD 0xC6
#define ADDR_PORT_RD 0xC4
//DATA[7:0] PORTB
#define DATA_PORT_RD 0xC7
#define DATA_PORT_RD 0xC5
//CTL PORTC
#define CTL_PORT_RD 0xC8
#define CTL_PORT_RD 0xC6
//AUX PORTD
#define AUX_PORT_RD 0xC9
#define AUX_PORT_RD 0xC7
//READ MCU I/O PORT DIRECTION 'DDR' REGISTERS
//Gives means to see what pins are currently set to I/P or O/P.
//ADDR[7:0] DDRA
#define ADDR_DDR_RD 0xCA
#define ADDR_DDR_RD 0xC8
//DATA[7:0] DDRB
#define DATA_DDR_RD 0xCB
#define DATA_DDR_RD 0xC9
//CTL DDRC
#define CTL_DDR_RD 0xCC
#define CTL_DDR_RD 0xCA
//AUX DDRD
#define AUX_DDR_RD 0xCD
#define AUX_DDR_RD 0xCB