From ce2a5aeccaecc412b1b9dc3e59b45264cd494d58 Mon Sep 17 00:00:00 2001 From: Paul Molloy Date: Thu, 24 Nov 2016 07:14:15 -0600 Subject: [PATCH] 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. --- firmware/source/logic.h | 10 +- firmware/source/pinport.c | 214 ++++++++++++++++++++++++++------------ firmware/source/pinport.h | 11 ++ shared/shared_pinport.h | 78 +++++--------- 4 files changed, 193 insertions(+), 120 deletions(-) diff --git a/firmware/source/logic.h b/firmware/source/logic.h index 8e18b5f..0149a87 100644 --- a/firmware/source/logic.h +++ b/firmware/source/logic.h @@ -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 diff --git a/firmware/source/pinport.c b/firmware/source/pinport.c index 15619f1..be7a667 100644 --- a/firmware/source/pinport.c +++ b/firmware/source/pinport.c @@ -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: @@ -326,21 +322,15 @@ uint8_t pinport_opcode_8b_operand( uint8_t opcode, uint8_t operand ) break; //ADDR[15:8] FLIPFLOP - case ADDRH_SET: - _DATA_OP(); - DATA_OUT = operand; - _AHL_CLK(); - _DATA_IP(); + case ADDRH_SET: + _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(); + case ADDRX_SET: + _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; +} diff --git a/firmware/source/pinport.h b/firmware/source/pinport.h index 81dcfe4..5ff6811 100644 --- a/firmware/source/pinport.h +++ b/firmware/source/pinport.h @@ -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 diff --git a/shared/shared_pinport.h b/shared/shared_pinport.h index 1613700..43166d0 100644 --- a/shared/shared_pinport.h +++ b/shared/shared_pinport.h @@ -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