diff --git a/firmware/source/main.c b/firmware/source/main.c index 23fcb1a..61a8d55 100644 --- a/firmware/source/main.c +++ b/firmware/source/main.c @@ -75,13 +75,6 @@ int main(void) //Initialize board/system #endif - //Turn on LED -#ifdef STM_CORE - RCC->AHBENR |= (IOP_LED_EN); -#endif -// PCb_OP_EN(LEDbank, LED); -// PCb_SET_HI(LEDbank, LED); - PCb_IP_PU(LEDbank, LED); //================= //MAIN LOOP diff --git a/firmware/source/pinport_al.h b/firmware/source/pinport_al.h index 824455f..ef9d6a2 100644 --- a/firmware/source/pinport_al.h +++ b/firmware/source/pinport_al.h @@ -28,14 +28,6 @@ // perform an operation on a port that's not present, or not initialized/setup error // codes will be sent back to the host to designate the lack of port presence. // -// --------------------------------------------------------------------------------------- -// CONTROL PORT: 16bits for function -// C15-0 -// Directionality: All pins are able to be toggled between input/output individually -// Driver: All pins indiv selectable pull-up or float for input. Output always push pull. -// Write/Output: Bit access only, no byte/word accesses -// Read/Input: Bit access only, returned byte/word will be zero if clear, non-zero if set -// --------------------------------------------------------------------------------------- // STM32 GPIO registers are quite different than AVR style // they are more flexible/capable, but a little tricky to interface with @@ -59,6 +51,7 @@ // MODER[1] typically leave clear unless using AltFunc // MODER[0] becomes equivalent of AVR DDR #define MODER_OP 0x01 +#define MODER_OP_ALL 0x55555555 #define MODER_AF 0x10 // // GPIOx->OTYPER 16bit registers control driver type @@ -84,7 +77,7 @@ // This ends up being a little cleaner than AVR i/o interfacing // Can probably just enable pull-ups on everything and leave it like that // -only exception being USB pins (PA11/12) better leave those floating -#define PUPDR_FLT 0x00 +//#define PUPDR_FLT 0x00 #define PUPDR_PU 0x01 #define PUPDR_PD 0x10 // @@ -134,288 +127,613 @@ // reading when O/P is of little use, as should be value of PORTx // read only register -//kaz6 is PB1 -//#define LED (1U) -//#define IOP_LED_EN RCC_AHBENR_GPIOBEN -//#define GPIO_LED GPIOB + + + +// --------------------------------------------------------------------------------------- +// CONTROL PORT +// +// This port is present on all devices, however not all pins are present depending on device +// Keeping this port as bit access only makes it so there is no limit to number of pins. +// Directionality: All pins are able to be toggled between input/output individually +// Driver: All pins indiv selectable pull-up or float for input. Output always push pull. +// Write/Output: Bit access only, no byte/word accesses +// Read/Input: Bit access only, returned byte/word will be zero if clear, non-zero if set // -////kaz adapter is PC13 -//#define LED (13U) -//#define IOP_LED_EN RCC_AHBENR_GPIOCEN -//#define GPIO_LED GPIOC +// PORT C pin definitions +// Don't assign one mcu pin to more than one pin in this port! +// mcu pin can be assigned in other ports, as initializing +// those ports will 'disable' the pin in this port. +// if the pin has multiple purposes and would like to give +// it different names based on the cart inserted, just create +// multiple defines/names for the one PCn pin. // -////kaz adapter data0 debug is PB8 -//#define DEBUG (8U) -//#define IOP_DEBUG_EN RCC_AHBENR_GPIOBEN -//#define GPIO_DEBUG GPIOB -// -//#define LED_ON() (GPIO_LED->ODR |= (0x1U<ODR &= ~(0x1U<ODR |= (0x1U<ODR &= ~(0x1U<MODER &= ~(MODER_OP<<(pin*2)); bank->PUPDR |= (PUPDR_PU<<(pin*2)) -#define PCb_IP_FLT(bank, pin) bank->MODER &= ~(MODER_OP<<(pin*2)); bank->PUPDR &= ~(PUPDR_PU<<(pin*2)) -#define PCb_OP_EN(bank, pin) bank->MODER |= (MODER_OP<<(pin*2)) -#define PCb_READ(bank, pin, val) val = (bank->IDR & (1<BSRR = 1<BRR = 1<MODER &= ~(MODER_OP<<(pin*2)); bank->PUPDR |= (PUPDR_PU<<(pin*2)) +#define CTL_IP_FLT(bank, pin) bank->MODER &= ~(MODER_OP<<(pin*2)); bank->PUPDR &= ~(PUPDR_PU<<(pin*2)) +#define CTL_OP(bank, pin) bank->MODER |= (MODER_OP<<(pin*2)) +#define CTL_READ(bank, pin, val) val = (bank->IDR & (1<BSRR = 1<BRR = 1<DDR &= ~(1<PORT |= (1<DDR &= ~(1<PORT &= ~(1<DDR |= (1<PIN & (1<PORT |= (1<PORT &= ~(1<DDR &= ~(1<PORT |= (1<DDR &= ~(1<PORT &= ~(1<DDR |= (1<PIN & (1<PORT |= (1<PORT &= ~(1<MODER &= ~(MODER_OP_ALL & 0x000FFFF0) + #define _DATA_OP() Dbank->MODER |= (MODER_OP_ALL & 0x000FFFF0) + #define _DATA_SET(data) Dbank->ODR = (Dbank->ODR & 0xFC03) | (data<<2) + #define _DATA_RD(data) data = (Dbank->IDR>>2) & 0x00FF + +#endif //STM_INL6 + +#ifdef STM_ADAPTER + + //All 8bits are on GPIOB inorder, but mapped to bits15-8 + #define Dbank GPIOB + + //IP and OP assume MODER[1] is clear (ie not set to Alt Func) + #define _DATA_IP() Dbank->MODER &= ~(MODER_OP_ALL & 0xFFFF0000) + #define _DATA_OP() Dbank->MODER |= (MODER_OP_ALL & 0xFFFF0000) + //TODO create byte wide port structs to grant byte accesses so doesn't need shifted + #define _DATA_SET(data) Dbank->ODR = (Dbank->ODR & 0x00FF) | (data<<8) + #define _DATA_RD(data) data = (Dbank->IDR>>8) & 0x00FF + +#endif //STM_ADAPTER + +#ifdef AVR_KAZZO + + //All 8bits are on GPIOB aligned perfectly + #define Dbank GPIOB + + #define _DATA_IP() Dbank->DDR = 0x00 + #define _DATA_OP() Dbank->DDR = 0xFF + #define _DATA_SET(data) Dbank->PORT = data + #define _DATA_RD(data) data = Dbank->PIN + + +#endif //AVR_KAZZO + + +// --------------------------------------------------------------------------------------- +// ADDRESS PORT 16bit +// +// This port is present on all devices +// Directionality: All pins are forced output +// Driver: All pins are push-pull +// Write/Output: Byte/half word access only, no bit accesses +// Read/Input: Not supported +// +// --------------------------------------------------------------------------------------- + +#ifdef STM_INL6 + + //All 16bits are on GPIOC in perfect alignment + #define Abank GPIOC + + #define _ADDR_IP() Abank->MODER &= ~MODER_OP_ALL + #define _ADDR_OP() Abank->MODER |= MODER_OP_ALL + #define _ADDRL(low) Abank->ODR = (Abank->ODR & 0xFF00) | low + #define _ADDRH(high) Abank->ODR = (Abank->ODR & 0x00FF) | (high<<8) + #define _ADDR(hword) Abank->ODR = hword + +#endif //STM_INL6 + +#ifdef STM_ADAPTER + + // A15-8 are behind AHL flipflop + // A7-6 are on GPIO A9-8 + // A5-0 are on GPIO A7-2 + #define A76bank GPIOA + #define A50bank GPIOB + + #define _ADDR_IP() A76bank->MODER &= ~(MODER_OP_ALL & 0x000F0000); A50bank->MODER &= ~(MODER_OP_ALL & 0x0000FFF0) + #define _ADDR_OP() A76bank->MODER |= (MODER_OP_ALL & 0x000F0000); A50bank->MODER |= (MODER_OP_ALL & 0x0000FFF0) + #define _ADDRL(low) A76bank->ODR = (A76bank->ODR & 0xFCFF) | ((low & 0xC0)<<2);A50bank->ODR = (A50bank->ODR & 0xFF03) | ((low & 0x3F)<<2) +//clocks must be initialized, Data bus clear + #define _ADDRH(high) _DATA_OP(); _DATA_SET(high); _AHL_CLK(); _DATA_IP(); + #define _ADDR(hword) ADDRL(hword); _ADDRH(hword<<8) + +#endif //STM_ADAPTER + +#ifdef AVR_KAZZO + + // A15-8 are behind AHL flipflop + // A7-0 are on GPIOA perfectly aligned + #define _ALbank GPIOA + + #define _ADDRL(low) GPIOA->PORT = low +//clocks must be initialized, Data bus clear + #define _ADDRH(high) _DATA_OP(); _DATA_SET(high); _AHL_CLK(); _DATA_IP(); + +#endif //AVR_KAZZO + + + + #endif diff --git a/firmware/source/pinport_stm.h b/firmware/source/pinport_stm.h new file mode 100644 index 0000000..7edefd7 --- /dev/null +++ b/firmware/source/pinport_stm.h @@ -0,0 +1,581 @@ +#ifndef _pinport_h +#define _pinport_h + +#include "logic.h" +#include "shared_errors.h" +#include "shared_dict_pinport.h" + +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 ); +uint8_t pinport_opcode_8b_return( uint8_t opcode, uint8_t *rvalue ); +void software_AHL_CLK(); +void software_AXL_CLK(); + +//This file contains pinout translations from AVR names to "kazzo" names +//this file also works to make all kazzo versions compatible and "alike" +//There are defines for kazzo version, turns out unique early versions +//can be differentiated by solder mask color. +//Final version is default and doesn't need any defines +//#define PURPLE_KAZZO +//#define GREEN_KAZZO + +//======================================================= +//History of PCB revsisions produced by InfiniteNesLives +//======================================================= +// +// uncomment define if buiding for either of the first two versions +//#define PURPLE_KAZZO + +// First printed circuit board version +// only handful made (less than 10?) +// Purple solder mask +// Labeled "Kazzo PCB rev 3.0" +// Dated 8/22/2011 +// * Only contained NES and Famicom connectors +// * Had bug where USB data lines mixed up +// -manually fixed during component assembly +// * Naruko determined this should have still been v1 board +// -due to it's overall design and conflicting with someother v3 board +// * This was my first ever PCB design and one of the first +// times designing something for the NES/FC. Looking +// back at the design there were some very noob decisions... +// * INPUT/OUTPUT differences: +// EXP9 - PD1/LED jumper +// when closed, PD1 controls NES EXP9 and LED +// when open, EXP9 is floating PD1 only controls LED +// NES EXP9 was connected to GND pin #16 on FC +// -I must have thought that GND pin could serve +// different purpose.. +// -Result is PD1 is shorted to GND when FC cart inserted +// and jumper closed.. +// Believe I closed this jumper on units I shipped +// prob should have left it open.. +// Suggested fix: leave open and ground EXP9 +// -prevents issue with LED when FC cart inserted +// -minor draw back no access to EXP9 +// ALOG - EXP6 - DIGI jumper +// another noob jumper decision... +// ALOG is the MCU AREF pin which should be tied to VCC +// -I thought it was an analog in apparently... +// DIGI is EXP flip flop Q6 output +// Best position for this jumper is EXP6-DIGI +// ALOG pad should be tied to VCC with jumper.. +// Doing that would make it similar to future designs. +// Don't think I shipped any with ALOG jumper closed +// NES EXP6 is tied to Famicom pin 46 (Sound to RF) +// Expansion port FlipFlop /OE - CLK +// Aside from lame jumper design above, biggest difference +// between this PCB version and future ones. +// -EXP FF /OE controlled by MCU PD7 +// -EXP FF CLK controlled by MCU PC3 +// Future versions control both /OE and CLK with PD7 +// -this frees PC3 for user use +// Both FlipFlops D i/p are driven by Data bus (PORT B) +// +// +// Second printed circuit board version +// only handful made (about a dozen?) +// Purple solder mask +// Labeled "Kazzo PCB rev 1.1" +// Dated 8/22/2011 +// * Only contained NES and Famicom connectors +// * Identical to version above aside from the following +// * Corrected bug where USB data lines mixed up +// * Changed silkscreen to v1.1 as suggested by naruko +// * INPUT/OUTPUT differences: +// -Same as version above as far as I know. +// +// +// uncomment define if buiding for this versions +//#define GREEN_KAZZO +// +// Third printed circuit board version +// only handful made (about ten?) used primarily as SNES prototype +// Green solder mask +// Labeled "Retro programmer/dumper v1.2" "Kazzo 1.x" +// Dated Apr 2013 +// * First version to add SNES connector along with NES & FC +// * Removed noob jumpers from purple versions above. +// -grouned FC pin16 as it should have been. +// * INPUT/OUTPUT differences: +// -EXP FF /OE still controlled by MCU PD7 +// -MCU PC7 controls both CLK on both FF's. +// -EXP FF D inputs are PORTA +// all other versions are driven by PORTB +// This means you always have to clock both flipflops +// Place desired value on PORTA/B respectively and clock with PD7 +// -PC3 is free for user use. +// -SNES /RESET pin not controlled by PD0 (EXP0) +// instead it's controlled by A20 (EXPFF Q4) +// prevents putting INL SNES boards in program mode unless A20 is also low +// pretty much makes flashing SNES boards a royal PITA/impossible +// Suggested fix is to have PD0 (EXP0) control SNES /RESET +// would have to free /RESET and wire to EXP0/PD0 to permit flashing/reading INL SNES board. +// +// +// Fourth printed circuit board version +// First volume PCB run ~300 copies +// Yellow solder mask +// Labeled "Retro programmer/dumper v1.2b" "Kazzo 1.x" +// Dated May 2013 +// * Includes NES, Famicom, & SNES connector +// * SNES board must be removed from case and slid all the way to right +// * Pitch offset on SNES connector makes it difficult to connect with original SNES boards. +// -Connector designed to only provide support for INL SNES Hi/Lo-ROM boards. +// * Care must be excersized not to insert SNES board backwards applying reverse power. +// * Effectively Final circuit design after lessons learned on small batches that preceeded. +// * INPUT/OUTPUT differences: +// -EXP FF /OE & CLK controlled by MCU PD7 +// -MCU PC7 only controls CLK on ADDR HIGH FF. +// -EXP & ADDRHI FF D inputs both on Data bus PORTB +// -PC3 is free for user use. +// -SNES /RESET pin controlled by PD0 (EXP0) +// -Retains prev ver fixes, nothing funny going on with jumpers FC GND pin #16 +// +// +// Fifth printed circuit board version +// Second volume PCB run ~500 copies +// Yellow solder mask +// Labeled "Retro programmer/dumper v1.2b" "Kazzo 1.x" +// Dated OCT 2014 +// * Includes NES, Famicom, & SNES connector +// * SNES connector setup/cautions just like the prev version. +// * No significant changes from previous version. +// -Changed MCU clock to Crystal instead of resonator in prev ver. +// -Added screw mount holes, although not very well placed. +// * INPUT/OUTPUT differences: +// -None from previous version +// +// +// Sixth printed circuit board version +// Third volume PCB run in production as of 1NOV2016 +// Orange solder mask +// Labeled "Retro programmer/dumper v1.4" "Kazzo 1.x" +// Dated OCT 2016 +// Addition of fancy INL logo for first time +// * Includes NES, Famicom, & SNES connector +// * SNES connector improvement to correct pitch issue with prev ver. +// * Addition of PCT resettable fuse on incoming power. +// -Provides protection to SNES boards inserted backwards. +// * Rearrangement of BL/RUN switch and screw holes for better case design. +// * Cut out buzzer pads (PD6) from under MCU which was never developed. +// * INPUT/OUTPUT differences: +// -None from previous version +// +// +// STM32F070C6T6 KAZZO USB 2.0 ADAPTER board +// designed to retrofit all previous kazzo versions +// updates to arm cortex M0 core and hardware USB 2.0 +// Green solder mask +// Labeled "KAZZO USB 2.0 ADAPTER" "V1.P" +// Dated JAN 2017 +// Pins out to all DIP-40 pins: +// AVR reset -> STM reset +// AVR BOOTLOADn -> STM BOOT0 (not sure if this actually works...) +// AVR XTAL1/2 -> STM oscOUT/IN (PF1/0) +// +// ascii art board connections setup: +//AVR PIN #40<. .-> AVR PIN #20 +// __|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|_ +// | O O O O O O O O O O O O O O O O O O O O| +// | "KAZZO USB 2.0 ADAPTER" | +// kazzo | programming header /\ 6pin extra port | kazzo +// rst butn | O- /RESET / \ EMPTY -O O- PA6 | AVR PA6 "FREE" +// CIRAM_A10| O- SWD (PA13) CIRAM A10 /STM \ EMPTY -O O- PC15 | nc +// GND | O- GND \ 32 / 3v3 -O O- PC14 | nc +// nc | O- SWC (PA14) \ ./ GND -O O- PA1 | nc +// nc | O- 3v3 \/ 5v -O O- PA0 | EXP0 +// | | +// | O O O O O O O O O O O O O O O O O O O O| +// ------------------------------------------------------------- +// | | | | | | | | | | | | | | | | | | | | +//AVR PIN #1<-` `-> AVR PIN #19 + + + +// STM32 GPIO registers are quite different than AVR style +// they are more flexible/capable, but a little tricky to interface with +// some features present on STM32 pins, but not AVR +// - PULL-DOWN ability (and PULL-UP like AVR) +// - Speed/Slew rate selection +// - Open drain outputs (and push/pull like AVR) +// - Bit set/reset registers to remove necessity of RMW operations +// - Lockability to keep port config bits from changing until reset +// - GPIO blocks must be provided a clock and enabled to "turn on" +// failing to do so will cause hard faults when accessing registers!! +// +// All GPIO registers can be accessed in byte, halfword, or 32bit full words +// unless otherwise noted +// +// GPIOx->MODER[1:0] 32bit registers control direction/type of driver +// 00- Input (default reset state, except SWC-PA15 & SWD-PA13 default AF) +// 01- Gen Purp Output +// 10- Alternate func (SPI, I2C, etc) +// 11- reserved +// MODER[1] typically leave clear unless using AltFunc +// MODER[0] becomes equivalent of AVR DDR +// +// GPIOx->OTYPER 16bit registers control driver type +// 0- Push Pull (default reset state) +// 1- Open Drain +// N/A when MODER is set to "00" INPUT +// we can generally just ignore this register and use pushpull as AVR does +// +// GPIOx->OSPEEDR[1:0] 32bit registers control pin driver speed/slew +// x0- Low speed (default reset state, except SWD-PA13 default High Spd) +// 01- Medium speed +// 11- High speed +// N/A when MODER is set to "00" INPUT +// we can generally just ignore this register and use slow speed +// +// GPIOx->PUPDR[1:0] 32bit registers control pull-up/down resistors +// this register is in effect even when alternate functions are enabled +// 00- floating/disabled, no pull-up/down (default for most pins except below) +// 01- Pull-up enabled (default SWD-PA13) also CIRAM A10 +// 10- Pull-down enabled (default SWC-PA14) +// 11- Reserved, don't use (prob enables both which would be bad...) +// PUPDR[0] is kinda like AVR PORT when DDR is set to INPUT, and PUPDR[1]=0 +// This ends up being a little cleaner than AVR i/o interfacing +// Can probably just enable pull-ups on everything and leave it like that +// -only exception being USB pins (PA11/12) better leave those floating +// +// GPIOx->IDR 16bit register used to read current input level on pin +// this register is read only +// +// GPIOx->ODR 16bit register used to set output of pin if enabled by MODER +// this register is read/writeable +// +// GPIOx->BSSR 32bit register to only set/clear pins +// BR[31:16] upper halfword is will reset/clear pin if written to '1' value +// BS[15:00] lower halfword is will set pin if written to '1' value +// writing 0 to any bit has no effect +// if setting both BS register has priority (bit will be set) +// this register is write only! +// +// GPIO->BRR 16bit register equivalent to upper word of BSSR register above +// provides convinent separate BR register that doesn't need shifted +// +// GPIOx->LCKR 17bit register MUST BE ACCESSED in 32bit full words!!! +// complex sequence needed to set, but once done lock config/altfunc +// bits for that GPIO. I interpret this to mean the registers above +// with exception of IDR, ODR, BSSR registers, plus AF registers +// Good to use this for things than we don't want to accidentally change: +// - USB & XTAL pins come to mind as good candidates +// +// GPIOx->AFRL/H 2 sets of 32bit registers to determine alternate function +// of GPIO if enabled with MODER registers. Default is AF0 at reset +// + +// Following macros are written to be supported on all yellow/orange silk kazzos +// includes rev 1.2b & 1.4 Dated May 2013 and later + + +// used for a very short delay +#define NOP() do { __asm__ __volatile__ ("nop"); } while (0) + +////PORT wide set/clear +//#define LO 0x00 +//#define HI 0xFF +// +////DDR values +//#define IP 0x00 +//#define OP 0xFF +// +////============================ +////ADDR[7:0] PORTA +////============================ +////PORT DEFN +//#define ADDR_OUT PORTA +//#define ADDR_IN PINA +//#define ADDR_DDR DDRA +////DDR-PORT MACROS +//#define _ADDR_IP() ADDR_DDR = IP +//#define _ADDR_OP() ADDR_DDR = OP +//#define _ADDR_LO() ADDR_OUT = LO +//#define _ADDR_HI() ADDR_OUT = HI +// +//Need to rethink these macros.. Curently AVR uses them as values +//But for the stm32 it makes more sense to create function macros +//function macros could be made compatible with AVR as well +//ADDR_OUT = addrL; data[i] = DATA_IN; +//would become: +//ADDR_OUT(addrL); DATA_IN(data[i]); +// +//The port wide HI/LO IP/OP macros don't work either as we can't define values +// +//Firmware macro "functions" have underscore prefix +//opcode macros have identical name but without the prefix +//Haven't decided if PIN/PORT macros should be given underscore as well. +// Good chance I will want them with _ when writing read functions +// Easier to add them than take them out maybe..? +//Current rule is _ goes with () type macro +//Thinking this may as well change too since doing away with value macros... +//Or perhaps leading underscore denotes macros w/o operands + +//PORT wide set/clear +#define AVR_LO 0x00 +#define AVR_HI 0xFF + +//DDR values +#define AVR_IP 0x00 +#define AVR_OP 0xFF + +//============================ +//ADDR[7:0] PORTA +//============================ +//PORT DEFN +#define ADDR_OUT(op) (PORTA = op) +#define ADDR_IN(op) (op = PINA) +#define ADDR_DDR(op) (DDRA = op) +//AND/OR functions +#define ADDR_OUT_OR(op) (PORTA |= op) +#define ADDR_OUT_AND(op) (PORTA &= op) + +//DDR-PORT MACROS +#define ADDR_IP() ADDR_DDR = AVR_IP +#define ADDR_OP() ADDR_DDR = AVR_OP +#define ADDR_LO() ADDR_OUT = AVR_LO +#define ADDR_HI() ADDR_OUT = AVR_HI + +//============================ +//DATA[7:0] PORTB +//============================ +//PORT DEFN +#define DATA_OUT PORTB +#define DATA_IN PINB +#define DATA_DDR DDRB +//DDR-PORT MACROS +#define _DATA_IP() DATA_DDR = IP +#define _DATA_OP() DATA_DDR = OP +#define _DATA_LO() DATA_OUT = LO +#define _DATA_HI() DATA_OUT = HI + + +//============================ +//CTL PORTC +//============================ +//PORT DEFN +#define CTL_OUT PORTC +#define CTL_IN PINC +#define CTL_DDR DDRC +//DDR-PORT MACROS +#define _CTL_IP() CTL_DDR = IP +// No CTL_OP() macro as some of these are inputs or bidir, best to individually assert as output +#define _CTL_LO() CTL_OUT = LO +#define _CTL_HI() CTL_OUT = HI + +//PIN DEFN +#define M2 PC0 //NES, FC, & SNES (SYSCLK) +#define ROMSEL PC1 //(aka PRG/CE) NES, FC, & SNES +#define PRGRW PC2 //PRG R/W on NES & FC + +#ifdef PURPLE_KAZZO +#define p_AXL PC3 //EXP FF CLK on purple boards +#else +#define FREE PC3 //Free pin on all other boards +#endif + +#define CSRD PC4 //NES & FC CHR /RD, SNES /RD +#define CSWR PC5 //NES & FC CHR /WR, SNES /WR +#define CICE PC6 //NES & FC CIRAM /CE, most carts are 2screen tying this to CHR /A13 making this an I/P + +#ifdef GREEN_KAZZO +#define g_AXHL PC7 //Both ADDR_MID & EXP/ADDRHI FF CLK on green prototype +#else +#define AHL PC7 //ADDR MID FF CLK per orig kazzo design +#endif + +//PIN MACROS +#define _M2_IP() CTL_DDR &= ~(1<GND, RUN->float + +#ifdef PURPLE_KAZZO +#define pg_XOE PD7 //EXP/ADDRHI FF /OE pin on purple and green boards +#endif +#ifdef GREEN_KAZZO +#define pg_XOE PD7 //EXP/ADDRHI FF /OE pin on purple and green boards +#endif +#ifndef pg_XOE //FINAL_DESIGN +#define AXLOE PD7 //EXP/ADDRHI FF CLK & /OE pin on final board versions +#endif + +//PIN MACROS +//lower case aren't meant to be called unless certain pin is 5v tolerant +#define _EXP0_ip() AUX_DDR &= ~(1<enable o/p +#define _XOE_hi() AUX_OUT |= (1<disable o/p + +#else //FINAL_DESIGN +#define _AXLOE_IP() AUX_DDR &= ~(1<enable o/p +#define _EXPFF_FLT() AUX_OUT |= (1<disable o/p +//Caution _AXL_CLK() relies on _EXPFF_OP() to be called beforehand +// Think of it like you must enable the output before you can clock it. +// Floating EXPFF also happens to clock it. Think of it like it looses it's value if disabled. +#define _AXL_CLK() _EXPFF_FLT(); _EXPFF_OP(); //same name and convention as purple +#endif + +//Final version ties XOEn and AXL to same pin, we can do this in software to make other ver behave similarly +#ifdef PURPLE_KAZZO +#define _AXLOE_IP() _XOE_ip(); _p_AXL_ip(); +#define _AXLOE_OP() _XOE_op(); _p_AXL_op(); +#define _EXPFF_OP() _XOE_lo(); _p_AXL_lo(); +#define _EXPFF_FLT() _XOE_hi(); _p_AXL_hi(); +#endif +#ifdef GREEN_KAZZO //green can't tie AXL, just don't worry about clocking effect while enabling/disabling +#define _AXLOE_IP() _XOE_ip(); //run risk that AHL isn't O/P because AXL was made O/P instead +#define _AXLOE_OP() _XOE_op(); //sofware AXL/AHL clock covers this case though. +#define _EXPFF_OP() _XOE_lo(); +#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 + +//PPU and CPU +#define A10 0x04 +#define A11 0x08 + +#endif diff --git a/firmware/source/old/types.h b/firmware/source/types.h similarity index 99% rename from firmware/source/old/types.h rename to firmware/source/types.h index e50f33f..5a4b1d5 100644 --- a/firmware/source/old/types.h +++ b/firmware/source/types.h @@ -11,6 +11,8 @@ typedef struct setup_packet{ uint16_t wLength; }setup_packet; +/* + //write function pointers typedef void (*write_funcptr) ( uint8_t addrH, uint8_t addrL, uint8_t data ); typedef uint8_t (*read_funcptr) ( uint8_t addrH, uint8_t addrL ); @@ -72,5 +74,6 @@ typedef struct operation_info { write_funcptr wr_map_func; //function used to write to mapper }operation_info; +*/ #endif diff --git a/firmware/source/usb.c b/firmware/source/usb.c index 6535bde..dfa3a54 100644 --- a/firmware/source/usb.c +++ b/firmware/source/usb.c @@ -41,6 +41,7 @@ //}usbRequest_t; + #ifdef AVR_CORE USB_PUBLIC usbMsgLen_t usbFunctionSetup(uchar data[8]) { #endif @@ -53,15 +54,28 @@ uint16_t usbFunctionSetup(uint8_t data[8]) { // extern buffer *cur_usb_load_buff; //cast incoming data into the the usb setup packet it is -// setup_packet *spacket = (void *)data; + setup_packet *spacket = (void *)data; - //8 Byte buffer to be used for returning error code and return values - //must be static so V-USB driver can still access after function return -// static uint8_t rv[RETURN_BUFF_SIZE]; - static uint8_t rv[8]; - //rv[RV_ERR_IDX] contains opcode success/error code - //rv[1-7] available for return data, start with index 1 - //rv[RETURN_BUFF_FIRST_IDX-RETURN_BUFFER_LAST_IDX] + //default 8 Byte buffer to be used for returning error code and return values + //must be static so USB driver can still access after function return + //static uint8_t rv[RETURN_BUFF_SIZE]; + //need to make sure this return array is aligned on arm core to prevent unaligned access + //best way I can think to do this is instantiate it as a 16bit array, + //then point to it with an 8bit pointer and now it can be accessed as 8bit array. + //without this stm32 was hardfaulting I'm not certain, but I think this is why +#ifdef STM_CORE + static uint16_t rv16[RETURN_BUFF_SIZE/2]; + uint8_t *rv = (uint8_t*)rv16; +#else + static uint8_t rv[RETURN_BUFF_SIZE]; +#endif + //perhaps a better solution for stm32 is just provide a pointer to usb buffer ram + //but that doesn't expand past 8bytes easily, and starts to necessitate special cases + //diverging from V-usb norms.. + rv[RETURN_ERR_IDX] = GEN_FAIL; //default to error till opcode updates. + rv[RETURN_LEN_IDX] = 0; //reset to zero, number of bytes in return data (excluding ERR & LEN) + //now it's the opcode's responsiblity to update these values + //rv[RETURN_DATA] start of return data /* (1) Set the global pointer 'usbMsgPtr' to the base of the static RAM data * block and return the length of the data in 'usbFunctionSetup()'. The driver @@ -72,39 +86,34 @@ uint16_t usbFunctionSetup(uint8_t data[8]) { //buffer. If no return data requested from host rlen = 0, so this wouldn't matter //Some dictionaries/opcodes that want to return larger buffers though //this function will set usbMsgPtr to point to that larger buffer when supported - //avr-gcc doesn't like this and gives warning - //source/usb.c:64: warning: assignment makes integer from pointer without a cast - //tried casting it to usbMsgPtr -// usbMsgPtr = (usbMsgPtr_t)rv; + + //works on avr, broke on stm: + usbMsgPtr = (usbMsgPtr_t)rv; + //usbMsgPtr = rv; + -//#if USB_CFG_LONG_TRANSFERS -// //number of bytes to return to host -// //16bit meets max possible 16KBytes with V-USB long transfers enabled - //uint16_t rlen = 0; //the speed loss doesn't make long transfers worth it for now -//#else -// //8bit is enough for 254 bit non-long xfrs -// //also gives ~0.7KBps speed up compared to 16bit rlen - uint8_t rlen = 0; -//#endif - -/* - //determine endpoint IN/OUT - if ( (spacket->bmRequestType & ENDPOINT_BIT) == ENDPOINT_IN ) { - //read from device request - //send error code and return value - rlen = 1; //min value of error code - } else { - //write to device request - //host doesn't want to waste time with reading back error codes - rlen = 0; - //must also come here if opcode has payload coming in data packets to follow - //in that case host would have to send follow up read request to get error code - } +#if USB_CFG_LONG_TRANSFERS + //number of bytes to return to host + //16bit meets max possible 16KBytes with V-USB long transfers enabled + uint16_t rlen = spacket->wLength; //the speed loss doesn't make long transfers worth it for now +#else + //8bit is enough for 254 bit non-long xfrs + //also gives ~0.7KBps speed up compared to 16bit rlen on V-USB + uint8_t rlen = (uint8_t) spacket->wLength; +#endif switch(spacket->bRequest) { case DICT_PINPORT: switch (spacket->opcode) { + //Turn on LED +#ifdef STM_CORE + RCC->AHBENR |= (IOP_LED_EN); +#endif +// PCb_OP_EN(LEDbank, LED); +// PCb_SET_HI(LEDbank, LED); + CTL_IP_PU(LEDbank, LED); + /* case PP_OPCODE_ONLY_MIN ... PP_OPCODE_ONLY_MAX: rv[RV_ERR_IDX] = pinport_opcode_only( spacket->opcode ); break; @@ -124,62 +133,24 @@ uint16_t usbFunctionSetup(uint8_t data[8]) { rv[RV_ERR_IDX] = pinport_opcode_8b_return( spacket->opcode, &rv[RV_DATA0_IDX]); rlen ++; break; + */ default: //pinport opcode min/max definition error - rv[RV_ERR_IDX] = ERR_BAD_PP_OP_MINMAX; + rv[RETURN_ERR_IDX] = ERR_BAD_PP_OP_MINMAX; } break; //end of PINPORT +/* case DICT_IO: - switch (spacket->opcode) { - case IO_OPCODE_ONLY_MIN ... IO_OPCODE_ONLY_MAX: - rv[RV_ERR_IDX] = io_opcode_only( spacket->opcode ); - break; - case IO_OPCODE_RTN_MIN ... IO_OPCODE_RTN_MAX: - rv[RV_ERR_IDX] = io_opcode_return( - spacket->opcode, &rv[RV_DATA0_IDX] ); - rlen = 8; - break; - default: //io opcode min/max definition error - rv[RV_ERR_IDX] = ERR_BAD_IO_OP_MINMAX; - } - break; //end of IO + //break; //end of IO case DICT_NES: - switch (spacket->opcode) { - case NES_OPCODE_24BOP_MIN ... NES_OPCODE_24BOP_MAX: - rv[RV_ERR_IDX] = nes_opcode_24b_operand( spacket->opcode, - spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); - break; - case NES_OPCODE_16BOP_8BRV_MIN ... NES_OPCODE_16BOP_8BRV_MAX: - rv[RV_ERR_IDX] = nes_opcode_16b_operand_8b_return( spacket->opcode, - spacket->operandMSB, spacket->operandLSB, &rv[RV_DATA0_IDX]); - rlen++; - break; - default: //nes opcode min/max definition error - rv[RV_ERR_IDX] = ERR_BAD_NES_OP_MINMAX; - } - break; //end of NES + //break; //end of NES case DICT_SNES: - switch (spacket->opcode) { - case SNES_OPCODE_24BOP_MIN ... SNES_OPCODE_24BOP_MAX: - rv[RV_ERR_IDX] = snes_opcode_24b_operand( spacket->opcode, - spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); - break; - case SNES_OPCODE_24BOP_8BRV_MIN ... SNES_OPCODE_24BOP_8BRV_MAX: - rv[RV_ERR_IDX] = snes_opcode_24b_operand_8b_return( spacket->opcode, - spacket->miscdata, spacket->operandMSB, spacket->operandLSB, &rv[RV_DATA0_IDX]); - rlen++; - break; - default: //snes opcode min/max definition error - rv[RV_ERR_IDX] = ERR_BAD_SNES_OP_MINMAX; - } - break; //end of SNES + //break; //end of SNES case DICT_BUFFER: - //just give buffer.c the setup packet and let it figure things out for itself - usbMsgPtr = (usbMsgPtr_t)buffer_usb_call( spacket, rv, &rlen ); - break; //end of BUFFER + //break; //end of BUFFER case DICT_USB: //currently just a simple way to read back usbFunctionWrite status SUCCESS/ERROR @@ -195,23 +166,16 @@ uint16_t usbFunctionSetup(uint8_t data[8]) { usbMsgPtr = (usbMsgPtr_t)operation_usb_call( spacket, rv, &rlen ); break; //end of OPER +*/ default: //request (aka dictionary) is unknown - rv[RV_ERR_IDX] = ERR_UNKN_DICTIONARY; + rv[RETURN_ERR_IDX] = ERR_UNKN_DICTIONARY; } -*/ - //TODO add check that verifies rlen == setup packet return lenght request - //current state has error checking somewhat embeded in the fact the host - //will detect when return length differs from requested return rlen; //need to return USB_NO_MSG for OUT transfers to make usbFunctionWrite called - //return USB_NO_MSG; //if want usbFunctionRead called during IN token data packets - //Don't have a use for usbFunctionRead yet.. Not expecting to anytime soon - //probably easier and perhaps faster to send cart dump commands and store rom image - //in a buffer to be returned here. } diff --git a/firmware/source/usb.h b/firmware/source/usb.h index 8d01bd6..cac30b1 100644 --- a/firmware/source/usb.h +++ b/firmware/source/usb.h @@ -22,12 +22,13 @@ //end STM CORE #include "pinport_al.h" +#include "types.h" +#include "shared_usb.h" +#include "shared_errors.h" +#include "shared_dictionaries.h" /* -#include "shared_dictionaries.h" -#include "types.h" #include "logic.h" -#include "shared_errors.h" #include "pinport.h" #include "io.h" #include "nes.h" diff --git a/firmware/source_stm_only/usbstm.c b/firmware/source_stm_only/usbstm.c index 3abf629..c89ad4c 100644 --- a/firmware/source_stm_only/usbstm.c +++ b/firmware/source_stm_only/usbstm.c @@ -445,7 +445,7 @@ static uint16_t num_bytes_sending; static uint16_t num_bytes_expecting; static uint16_t num_bytes_xfrd; static uint8_t req_dir; -uint16_t *usbMsgPtr; +usbMsgPtr_t usbMsgPtr; //function gets called after reception of setup packet for IN transfer, //and each time an interrupt for successful data tx from control EP diff --git a/firmware/source_stm_only/usbstm.h b/firmware/source_stm_only/usbstm.h index a7e1c56..7b621b3 100644 --- a/firmware/source_stm_only/usbstm.h +++ b/firmware/source_stm_only/usbstm.h @@ -234,8 +234,8 @@ typedef struct usbRequest_t{ //4..31 = Reserved -#define usbMsgPtr_t uint16_t -extern uint16_t *usbMsgPtr; +#define usbMsgPtr_t uint16_t * +extern usbMsgPtr_t usbMsgPtr; extern uint16_t usbFunctionSetup(uint8_t data[8]); extern uint8_t usbFunctionWrite(uint8_t *data, uint8_t len); diff --git a/host/scripts/inlretro.lua b/host/scripts/inlretro.lua index 566dee0..603cab7 100644 --- a/host/scripts/inlretro.lua +++ b/host/scripts/inlretro.lua @@ -79,7 +79,7 @@ end -- initial function called from C main function main () -- print dictionary opcode addr miscdata endpt buffer length - print("dict_call ", dict_call( 1, dict["DICT_PINPORT"], op_pinport["LED_OFF"], 0, 0, USB_IN, nil, 1), "\n") + print("dict_call ", dict_call( 1, dict["DICT_PINPORT"], op_pinport["LED_OFF"], 0, 0, USB_IN, nil, 8), "\n") end -- Dictionary table definitions diff --git a/shared/shared_dict_usb.h b/shared/shared_dict_usb.h index 6e432f9..cd13350 100644 --- a/shared/shared_dict_usb.h +++ b/shared/shared_dict_usb.h @@ -6,10 +6,10 @@ //The dictionary number is literally used as usb transfer request field //the opcodes and operands in this dictionary are fed directly into usb setup packet's wValue wIndex fields -#define RETURN_BUFF_SIZE 8 //number of bytes in generic return buffer -#define RV_ERR_IDX 0 //(first) index of buffer that contains SUCCESS/ERROR# -#define RV_DATA0_IDX RV_ERR_IDX + 1 //first index of return data -#define RV_DATA_MAX_IDX RETURN_BUFF_SIZE - 1 //last index available for return data +//#define RETURN_BUFF_SIZE 8 //number of bytes in generic return buffer +//#define RV_ERR_IDX 0 //(first) index of buffer that contains SUCCESS/ERROR# +//#define RV_DATA0_IDX RV_ERR_IDX + 1 //first index of return data +//#define RV_DATA_MAX_IDX RETURN_BUFF_SIZE - 1 //last index available for return data //============================================================================================= //============================================================================================= diff --git a/shared/shared_dictionaries.h b/shared/shared_dictionaries.h index 509e09e..9cebde2 100644 --- a/shared/shared_dictionaries.h +++ b/shared/shared_dictionaries.h @@ -72,8 +72,8 @@ //============================================================================================= //============================================================================================= -#define DICT_IO 2 -#include "shared_dict_io.h" +//#define DICT_IO 2 +//#include "shared_dict_io.h" //io dictionary contains commands //Scope of functions contained is intended to be general and generic not specific //to the cartridge inserted. The closest these operations get to being cart/system @@ -88,8 +88,8 @@ //============================================================================================= //============================================================================================= -#define DICT_NES 3 -#include "shared_dict_nes.h" +//#define DICT_NES 3 +//#include "shared_dict_nes.h" //nes dictionary contains commands //These commands rely on io initialization from io dictionary prior to calling //This library is intended to contain all NES related opcodes/commands @@ -99,8 +99,8 @@ //============================================================================================= //============================================================================================= -#define DICT_SNES 4 -#include "shared_dict_snes.h" +//#define DICT_SNES 4 +//#include "shared_dict_snes.h" //snes dictionary contains commands //These commands rely on io initialization from io dictionary prior to calling //This library is intended to contain all SNES related opcodes/commands @@ -110,8 +110,8 @@ //============================================================================================= //============================================================================================= -#define DICT_BUFFER 5 -#include "shared_dict_buffer.h" +//#define DICT_BUFFER 5 +//#include "shared_dict_buffer.h" //mcu buffer dictionary commands //This library is intended to contain all buffer related opcodes/commands //also contains defines for both host and firmware such as buffer status numbers @@ -121,8 +121,8 @@ //============================================================================================= //============================================================================================= -#define DICT_USB 6 -#include "shared_dict_usb.h" +//#define DICT_USB 6 +//#include "shared_dict_usb.h" //currently no actual dictionary as there are no opcodes. //just used to return status of usbfunctions in event of a transfer error. //contains definitions of data transactions between host and firmware @@ -132,8 +132,8 @@ //============================================================================================= //============================================================================================= -#define DICT_OPER 7 -#include "shared_dict_operation.h" +//#define DICT_OPER 7 +//#include "shared_dict_operation.h" //dictionary used to initialize and control operation_info variables //============================================================================================= //============================================================================================= diff --git a/shared/shared_errors.h b/shared/shared_errors.h index 8213c00..cf0d4a1 100644 --- a/shared/shared_errors.h +++ b/shared/shared_errors.h @@ -1,10 +1,13 @@ -#ifndef _error_codes_h -#define _error_codes_h +#ifndef _shared_errors_h +#define _shared_errors_h #define SUCCESS 0 #define GEN_FAIL 0xFF + +/* #define FALSE 0 #define NILL 0 +*/ //greater than 128 are possible avr return codes #define ERR_UNKN_DICTIONARY 128 @@ -23,6 +26,7 @@ #define ERR_UNKN_PP_OPCODE_24BOP 143 #define ERR_UNKN_PP_OPCODE_8BRV 144 +/* #define ERR_UNKN_IO_OPCODE_ONLY 150 #define ERR_UNKN_IO_OPCODE_RTN 151 @@ -53,4 +57,6 @@ //max error number 255 +*/ + #endif diff --git a/shared/shared_usb.h b/shared/shared_usb.h new file mode 100644 index 0000000..6f1f34d --- /dev/null +++ b/shared/shared_usb.h @@ -0,0 +1,23 @@ +#ifndef _shared_dict_usb_h +#define _shared_dict_usb_h + +//define dictionary's reference number in the shared_dictionaries.h file +//then include this dictionary file in shared_dictionaries.h +//The dictionary number is literally used as usb transfer request field +//the opcodes and operands in this dictionary are fed directly into usb setup packet's wValue wIndex fields + +#define RETURN_BUFF_SIZE 8 //number of bytes in generic return buffer +#define RETURN_ERR_IDX 0 //index of IN DATA stage that contains SUCCESS/ERROR# +#define RETURN_LEN_IDX 1 //index of IN DATA stage that contains length of return value(s) in bytes (0-125) +#define RETURN_DATA 2 //index of IN DATA stage that contains start of return data + +//============================================================================================= +//============================================================================================= +// USB DICTIONARY +// +// opcodes contained in this dictionary must be implemented in firmware/source/io.c +// +//============================================================================================= +//============================================================================================= + +#endif