From 1e5ea8cc7e3c291939a071c83ff996712ef53638 Mon Sep 17 00:00:00 2001 From: Paul Molloy Date: Mon, 24 Jul 2017 21:56:34 -0500 Subject: [PATCH] Have USB drivers successfully calling usbFunctionSetup when vendor setup packet arrives. Had issue with return data on STM32 not being properly aligned when the rv array was only 8bit. So defining it as a 16bit array and then pointing a 8bit pointer to it seems to be an easy fix for now. Ready to start working on pinport dictionary. Need to get lua code working on a lower level handling the dictionary calls. Need it do do things like fill out the wLength and everything for me so one doesn't have to remember every detail about an opcode/dictionary before calling it. Realizing code was heavily segmented based on how big/many operands there were and how big the return data was. This is hard to maintain, need lua to resolve this issue, and make everything easier to script. Thinking opcode/dictionary calls need to be more like a function call. Passing in necessary args only, and returning data instead of succeed/fail. --- firmware/source/main.c | 7 - firmware/source/pinport_al.h | 776 +++++++++++++++++++++--------- firmware/source/pinport_stm.h | 581 ++++++++++++++++++++++ firmware/source/{old => }/types.h | 3 + firmware/source/usb.c | 142 ++---- firmware/source/usb.h | 7 +- firmware/source_stm_only/usbstm.c | 2 +- firmware/source_stm_only/usbstm.h | 4 +- host/scripts/inlretro.lua | 2 +- shared/shared_dict_usb.h | 8 +- shared/shared_dictionaries.h | 24 +- shared/shared_errors.h | 10 +- shared/shared_usb.h | 23 + 13 files changed, 1239 insertions(+), 350 deletions(-) create mode 100644 firmware/source/pinport_stm.h rename firmware/source/{old => }/types.h (99%) create mode 100644 shared/shared_usb.h 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