diff --git a/firmware/Make_stm b/firmware/Make_stm_adapter similarity index 89% rename from firmware/Make_stm rename to firmware/Make_stm_adapter index 235ad5e..13438dd 100644 --- a/firmware/Make_stm +++ b/firmware/Make_stm_adapter @@ -65,8 +65,8 @@ CFLAGS+= $(DEFINE) $(INCLUDE) SOURCES=$(wildcard source/*.c source_stm_only/*.c) OBJECTS=$(patsubst %.c,%.o,$(SOURCES)) -#all: dir $(BUILD)/$(PROJ).axf $(BUILD)/$(PROJ).elf $(BUILD)/$(PROJ).hex $(BUILD)/$(PROJ).bin size -all: dir $(BUILD)/$(PROJ).elf $(BUILD)/$(PROJ).hex $(BUILD)/$(PROJ).bin size +#all: dir shared $(BUILD)/$(PROJ).axf $(BUILD)/$(PROJ).elf $(BUILD)/$(PROJ).hex $(BUILD)/$(PROJ).bin size +all: dir shared $(BUILD)/$(PROJ).elf $(BUILD)/$(PROJ).hex $(BUILD)/$(PROJ).bin size #build axf file output (basically elf with DWARF debug info) # $@ is shortcut for the target, $^ is shortcut for prereqs @@ -86,6 +86,10 @@ $(BUILD)/$(PROJ).bin: $(BUILD)/$(PROJ).elf dir: mkdir -p $(BUILD) +#copy shared .h files which are used in host and firmware +shared: + cp -r ../shared/* source/ + size: $(BUILD)/$(PROJ).elf $(SIZE) -t $^ diff --git a/firmware/Make_stm_inl6 b/firmware/Make_stm_inl6 new file mode 100644 index 0000000..6728912 --- /dev/null +++ b/firmware/Make_stm_inl6 @@ -0,0 +1,104 @@ + +#Build directory +BUILD = build_stm + +#project name +#doesn't need to be associated with any file names +PROJ = inlretro_stm + + +# Selecting Core +CORTEX_M=0 + +# Use newlib-nano. To disable it, specify USE_NANO= +#USE_NANO=--specs=nano.specs +USE_NANO= + +# Use seimhosting or not +USE_SEMIHOST=--specs=rdimon.specs +USE_NOHOST=--specs=nosys.specs + +CORE=CM$(CORTEX_M) +BASE=. + +# Compiler & Linker +CC=arm-none-eabi-gcc +CXX=arm-none-eabi-g++ +OBJCOPY=arm-none-eabi-objcopy +SIZE=arm-none-eabi-size + +# Options for specific architecture +ARCH_FLAGS=-mthumb -mcpu=cortex-m$(CORTEX_M) + +# Startup code +STARTUP=$(BASE)/include_stm/startup_ARM$(CORE).S + +# -Os -flto -ffunction-sections -fdata-sections to compile for code size +CFLAGS=$(ARCH_FLAGS) $(STARTUP_DEFS) -Os -flto -ffunction-sections -fdata-sections -g +CXXFLAGS=$(CFLAGS) + +# Link for code size +GC=-Wl,--gc-sections + +# Create map file +MAP=-Wl,-Map=$(BUILD)/$(PROJ).map + +STARTUP_DEFS=-D__STARTUP_CLEAR_BSS -D__START=main -D__NO_SYSTEM_INIT + +LDSCRIPTS=-L. -L$(BASE)/include_stm -T nokeep.ld +LFLAGS=$(USE_NANO) $(USE_NOHOST) $(LDSCRIPTS) $(GC) $(MAP) + +DEFINE+=\ + -DSTM32F070x6 \ + -DF_CPU=16000000 \ + -DSTM_CORE \ + -DSTM_INL6 #inlretro 6connector +# -DSTM_ADAPTER #stm32 to kazzo adapter board +# -DSTM32F072x8 \ #64KB version of all packages (LQFP-48,64,100) +# -DSTM32F070xB \ #128KB version of both packages (LQFP-48,64) +# -DSTM32F070x6 \ #32KB version of both packages (TSSOP-20,LQFP-48) +# -DF_CPU=8000000 +INCLUDE=-I ./include_stm +CFLAGS+= $(DEFINE) $(INCLUDE) + +#SOURCES=$(wildcard source/**/*.c source/*.c) +SOURCES=$(wildcard source/*.c source_stm_only/*.c) +OBJECTS=$(patsubst %.c,%.o,$(SOURCES)) + +#all: dir shared $(BUILD)/$(PROJ).axf $(BUILD)/$(PROJ).elf $(BUILD)/$(PROJ).hex $(BUILD)/$(PROJ).bin size +all: dir shared $(BUILD)/$(PROJ).elf $(BUILD)/$(PROJ).hex $(BUILD)/$(PROJ).bin size + +#build axf file output (basically elf with DWARF debug info) +# $@ is shortcut for the target, $^ is shortcut for prereqs +# TARGET: PREREQS +$(BUILD)/$(PROJ).axf: $(STARTUP) $(OBJECTS) + $(CC) $^ $(CFLAGS) $(LFLAGS) -o $@ + +$(BUILD)/$(PROJ).elf: $(STARTUP) $(OBJECTS) + $(CC) $^ $(CFLAGS) $(LFLAGS) -o $@ + +$(BUILD)/$(PROJ).hex: $(BUILD)/$(PROJ).elf + $(OBJCOPY) -O ihex $^ $@ + +$(BUILD)/$(PROJ).bin: $(BUILD)/$(PROJ).elf + $(OBJCOPY) -O binary $^ $@ + +dir: + mkdir -p $(BUILD) + +#copy shared .h files which are used in host and firmware +shared: + cp -r ../shared/* source/ + +size: $(BUILD)/$(PROJ).elf + $(SIZE) -t $^ + +program: all + ST-LINK_CLI.exe -c -P $(BUILD)\$(PROJ).hex 0x08000000 -Rst + +disassm: all + arm-none-eabi-objdump $(BUILD)\$(PROJ).elf -d -g + +clean: + rm -rf $(BUILD) + rm -f $(OBJECTS) diff --git a/firmware/Makefile b/firmware/Makefile index a89ecbc..dfc6ada 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -7,5 +7,7 @@ all: avr: make -f Make_avr clean program -stm: - make -f Make_stm clean program +stm6: + make -f Make_stm_inl6 clean program +stmad: + make -f Make_stm_adapter clean program diff --git a/firmware/source/avr_gpio.h b/firmware/source/avr_gpio.h index 036126b..54f1f50 100644 --- a/firmware/source/avr_gpio.h +++ b/firmware/source/avr_gpio.h @@ -1,3 +1,7 @@ +#ifndef _avr_gpio_h +#define _avr_gpio_h + +#include #define __IO volatile /*!< Defines 'read / write' permissions */ @@ -30,3 +34,4 @@ typedef struct //#define GPIO_MODER_MODER0_Msk (0x3U << GPIO_MODER_MODER0_Pos) /*!< 0x00000003 */ //#define GPIO_MODER_MODER0 GPIO_MODER_MODER0_Msk +#endif diff --git a/firmware/source/io.c b/firmware/source/io.c new file mode 100644 index 0000000..a0feba5 --- /dev/null +++ b/firmware/source/io.c @@ -0,0 +1,226 @@ +#include "io.h" + +//================================================================================================= +// +// I/O operations +// This file includes all the io functions possible to be called from the io dictionary. +// +// See description of the commands contained here in shared/shared_dictionaries.h +// +//================================================================================================= + +/* Desc:Function takes an opcode which was transmitted via USB + * then decodes it to call designated function. + * shared_dict_io.h is used in both host and fw to ensure opcodes/names align + * Pre: Macros must be defined in firmware pinport.h + * opcode must be defined in shared_dict_io.h + * Post:function call complete. + * Rtn: SUCCESS if opcode found, error if opcode not present or other problem. + */ +uint8_t io_call( uint8_t opcode, uint8_t miscdata, uint16_t operand, uint8_t *rdata ) +{ + switch (opcode) { + case IO_RESET: io_reset(); break; + case NES_INIT: nes_init(); break; +// case SNES_INIT: snes_init(); break; +// case EXP0_PULLUP_TEST: exp0_pullup_test(data); break; + default: + //opcode doesn't exist + return ERR_UNKN_IO_OPCODE; + } + + return SUCCESS; + +} + + +//pullup as many cart pins as possible +//goal to be safe state for all hardware +//doesn't currently contain any checks to report error/success from +//this is intended to be the "reset" safest condition for the kazzo +void io_reset() +{ + +#ifdef STM_CORE + //reset GPIO perif blocks to default state + RCC->AHBRSTR |= ( RCC_AHBRSTR_GPIOARST | RCC_AHBRSTR_GPIOBRST | RCC_AHBRSTR_GPIOCRST | RCC_AHBRSTR_GPIODRST | RCC_AHBRSTR_GPIOFRST ); + RCC->AHBRSTR &= ~( RCC_AHBRSTR_GPIOARST | RCC_AHBRSTR_GPIOBRST | RCC_AHBRSTR_GPIOCRST | RCC_AHBRSTR_GPIODRST | RCC_AHBRSTR_GPIOFRST ); +#endif + + //pull up addr[7:0] bus + ADDR_ENABLE(); + ADDR_IP(); + ADDR_PU(); + + //pull up data bus + DATA_ENABLE(); + DATA_IP_PU(); + + //pull up control port + CTL_ENABLE(); + MCO_IP_PU(); + ROMSEL_IP_PU(); + PRGRW_IP_PU(); + CSRD_IP_PU(); + CSWR_IP_PU(); + CICE_IP_PU(); + IRQ_IP_PU(); + CIA10_IP_PU(); +#ifndef C3nodef + FREE_IP_PU(); +#endif + + //pull up on FF /OE should disable FF ouput +#ifndef C7nodef + AHL_IP_PU(); +#endif +#ifndef C13nodef + EXP_DISABLE(); +#endif +#ifndef C19nodef + AFL_IP_PU(); +#endif + + //EXP0 input no pullup + //Lots of possibilities, ~safe bet it will have it's own pull-up/down if needed. + //SNES /RESET pin disables SRAM on first few pcb versions + //NES PRG-ROM /OE (with pulldown) on old INL-ROM v1 boards w/pulldown + //NED PRG-ROM /WE (with pullup) on INL-ROM v3 boards w/pullup + //NES CPLD JTAG TDO non-5v tolerant + //Famicom carts have APU sound (EXP6) shorted to RF sound (EXP0) + // -enabling EXP FF output will drive EXP0 to value of A21/EXP6 + EXP0_IP_FL(); + + //LED LAST displaying complete.. + //planning to have LED DIM at power on to signify kazzo is in default + //mostly all pins pulled up state. + //gives some insight to current state of kazzo since it doesn't reset itself + //or if kazzo does reset itself due to WDT dim LED can help detect that. + LED_IP_PU(); //DIM pulled up + +} + +//NES cartridge interfacing setup +//set outputs as required +//latch address of $0000 +//disable NES cart memories +void nes_init() +{ + //start with a reset + //expecting user to do this but just to be sure + io_reset(); + + //enable control outputs and disable memories + //PRG-ROM + ROMSEL_OP(); + ROMSEL_HI(); + //WRAM (and state of m2 during first half of CPU cycle) + MCO_OP(); + MCO_LO(); + //CPU RD + PRGRW_OP(); + PRGRW_HI(); + + //other control pins are inputs, leave as IP pullup from reset + + //disable any CHR/VRAM memories with CHR /RD /WR + //prior to setting PPU A13 & /A13 which are /CE pins + //doing this helps ensure data bus is clear before + //using it for AHL clocking + CSRD_OP(); + CSRD_HI(); + CSWR_OP(); + CSWR_HI(); + + //memories are now disabled Data bus should be clear + + + //now meet conditions to call other macros + //setup address $0000 + ADDR_ENABLE(); + ADDR_SET(0x0000); + +} + +/* + +//SNES cartridge interfacing setup +//set outputs as required +//latch address of $000000 +//disable cart memories +//reset high disables SRAM and puts INL carts in PRGM mode +//Excersize extreme caution calling this while NES/FC cart inserted +//probably won't work if FC inserted due to EXP0-EXP6 short due to audio jumper on cart +void snes_init() +{ + //start with a reset + //expecting user to do this but just to be sure + io_reset(); + + //enable control outputs and disable memories + //ROM + ROMSEL_OP(); + ROMSEL_HI(); + CSRD_OP(); + CSRD_HI(); + CSWR_OP(); + CSWR_HI(); + + //disable SRAM and put cart in PRGM mode + EXP0_OP(); + EXP0_HI(); + + //other control pins are inputs or unused, leave as IP pullup from reset + + //memories are now disabled Data bus should be clear + + //setup AHL FF + AHL_OP(); + AHL_CLK(); + //setup AXL FF + AXL_OP(); + AXL_CLK(); + + //now meet conditions to call other macros + //setup address $000000 + ADDR_SET(0x0000); + ADDRX_SET(0x00); + +} + +//Test starts by verifying EXP0 can be driven low, if not, will return one byte of AUX_PIN +//followed by alternating 0xAA, 0x55, 0xAA... +//This test pulls up EXP0 and then reads AUX_PIN 6 times in rapid succession returning error code +//plus 6 bytes of read data. If pull up works but is just slow, should see that in return data. +//data[0] marks bit where EXP0 resisdes to provide host with bitmask for EXP0 +void exp0_pullup_test(uint8_t *data) +{ + + //first verify EXP0 can be driven low + _EXP0_LO(); //sets O/P and low + NOP(); //give some time to settle + data[1] = AUX_IN; //port where EXP0 resides + _EXP0_FLT(); //sets I/P w/o pullup + + if ( (data[1] & data[0]) == data[0]) { + //EXP0 was high, couldn't drive EXP0 low + data[2] = data[4] = data[6] = 0xAA; + data[3] = data[5] = 0x55; + //return this signature as indication EXP0 failed to drive low + return; + } + + //Driving EXP0 low was successful, now pullup and read back + _EXP0_PU(); + data[1] = AUX_IN; + data[2] = AUX_IN; + data[3] = AUX_IN; + data[4] = AUX_IN; + data[5] = AUX_IN; + data[6] = AUX_IN; + + //return EXP0 to floating + _EXP0_FLT(); + +} +*/ diff --git a/firmware/source/io.h b/firmware/source/io.h new file mode 100644 index 0000000..5894ced --- /dev/null +++ b/firmware/source/io.h @@ -0,0 +1,15 @@ +#ifndef _io_h +#define _io_h + +#include "pinport.h" +#include "shared_dictionaries.h" +#include "shared_errors.h" + +uint8_t io_call( uint8_t opcode, uint8_t miscdata, uint16_t operand, uint8_t *rdata ); + +void io_reset(); +void nes_init(); +//void snes_init(); +//void exp0_pullup_test(uint8_t *data); + +#endif diff --git a/firmware/source/main.c b/firmware/source/main.c index 61a8d55..0c4a8b5 100644 --- a/firmware/source/main.c +++ b/firmware/source/main.c @@ -1,5 +1,6 @@ #include "usb.h" +#include "io.h" #ifdef AVR_CORE #include @@ -44,8 +45,6 @@ int main(void) //reconnect to host usbDeviceConnect(); - //intialize i/o and LED to pullup state -// io_reset(); //enable interrupts sei(); @@ -75,6 +74,8 @@ int main(void) //Initialize board/system #endif + //intialize i/o and LED to pullup state + io_reset(); //================= //MAIN LOOP diff --git a/firmware/source/pinport.c b/firmware/source/pinport.c new file mode 100644 index 0000000..d084bcb --- /dev/null +++ b/firmware/source/pinport.c @@ -0,0 +1,483 @@ +#include "pinport.h" + +//This file was created based on pinport.h +//the close relationship between these two files must be kept in mind when making changes. +//This file is also very dependent on shared_dict_pinport.h +//the shared_dict_pinport.h was generated from this file, so any changes here must be forwarded. + +/* Desc:Decode pinport dictionary calls transmitted via USB and call requested operation + * shared_dict_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_dict_pinport.h + * Post:opcode command complete, return data & length stored if used. + * Rtn: SUCCESS if opcode found and completed, error code if not. + */ +uint8_t pinport_call( uint8_t opcode, uint8_t miscdata, uint16_t operand, uint8_t *rdata ) +{ + +#define RD_LEN 0 +#define RD0 1 +#define RD1 2 + +#define BYTE_LEN 1 +#define HWORD_LEN 2 + + //create pointer to first two bytes of return data array + uint16_t *ret_hword = (uint16_t*) &rdata[RD0]; + + switch (opcode) { + + //============================ + //CONTROL PORT INDIVIDUAL PIN ACCESS + //opcode: type of pin operation + //operand: pin number to act on + //============================ + case CTL_ENABLE_: CTL_ENABLE(); break; + case CTL_IP_PU_: + switch ( operand ) { + case 0: CTL_IP_PU(C0bank, C0); break; + case 1: CTL_IP_PU(C1bank, C1); break; + case 2: CTL_IP_PU(C2bank, C2); break; + #ifndef C3nodef + case 3: CTL_IP_PU(C3bank, C3); break; + #endif + case 4: CTL_IP_PU(C4bank, C4); break; + case 5: CTL_IP_PU(C5bank, C5); break; + case 6: CTL_IP_PU(C6bank, C6); break; + #ifndef C7nodef + case 7: CTL_IP_PU(C7bank, C7); break; + #endif + case 8: CTL_IP_PU(C8bank, C8); break; + case 9: CTL_IP_PU(C9bank, C9); break; + case 10: CTL_IP_PU(C10bank,C10); break; + case 11: CTL_IP_PU(C11bank,C11); break; + #ifndef C12nodef + case 12: CTL_IP_PU(C12bank,C12); break; + #endif + #ifndef C13nodef + case 13: CTL_IP_PU(C13bank,C13); + #ifdef PURPLE_KAZZO + CTL_IP_PU(C3bank,C3); + #endif + break; + #endif + #ifndef C14nodef + case 14: CTL_IP_PU(C14bank,C14); break; + #endif + #ifndef C15nodef + case 15: CTL_IP_PU(C15bank,C15); break; + #endif + #ifndef C16nodef + case 16: CTL_IP_PU(C16bank,C16); break; + #endif + #ifndef C17nodef + case 17: CTL_IP_PU(C17bank,C17); break; + #endif + #ifndef C18nodef + case 18: CTL_IP_PU(C18bank,C18); break; + #endif + #ifndef C19nodef + case 19: CTL_IP_PU(C19bank,C19); break; + #endif + #ifndef C20nodef + case 20: CTL_IP_PU(C20bank,C20); break; + #endif + case 21: CTL_IP_PU(C21bank,C21); break; + default: return ERR_CTL_PIN_NOT_PRESENT; + } + break; + case CTL_IP_FL_: + switch ( operand ) { + case 0: CTL_IP_FL(C0bank, C0); break; + case 1: CTL_IP_FL(C1bank, C1); break; + case 2: CTL_IP_FL(C2bank, C2); break; + #ifndef C3nodef + case 3: CTL_IP_FL(C3bank, C3); break; + #endif + case 4: CTL_IP_FL(C4bank, C4); break; + case 5: CTL_IP_FL(C5bank, C5); break; + case 6: CTL_IP_FL(C6bank, C6); break; + #ifndef C7nodef + case 7: CTL_IP_FL(C7bank, C7); break; + #endif + case 8: CTL_IP_FL(C8bank, C8); break; + case 9: CTL_IP_FL(C9bank, C9); break; + case 10: CTL_IP_FL(C10bank,C10); break; + case 11: CTL_IP_FL(C11bank,C11); break; + #ifndef C12nodef + case 12: CTL_IP_FL(C12bank,C12); break; + #endif + #ifndef C13nodef + case 13: CTL_IP_FL(C13bank,C13); + #ifdef PURPLE_KAZZO + CTL_IP_FL(C3bank,C3); + #endif + break; + #endif + #ifndef C14nodef + case 14: CTL_IP_FL(C14bank,C14); break; + #endif + #ifndef C15nodef + case 15: CTL_IP_FL(C15bank,C15); break; + #endif + #ifndef C16nodef + case 16: CTL_IP_FL(C16bank,C16); break; + #endif + #ifndef C17nodef + case 17: CTL_IP_FL(C17bank,C17); break; + #endif + #ifndef C18nodef + case 18: CTL_IP_FL(C18bank,C18); break; + #endif + #ifndef C19nodef + case 19: CTL_IP_FL(C19bank,C19); break; + #endif + #ifndef C20nodef + case 20: CTL_IP_FL(C20bank,C20); break; + #endif + case 21: CTL_IP_FL(C21bank,C21); break; + default: return ERR_CTL_PIN_NOT_PRESENT; + } + break; + case CTL_OP_: + switch ( operand ) { + case 0: CTL_OP(C0bank, C0); break; + case 1: CTL_OP(C1bank, C1); break; + case 2: CTL_OP(C2bank, C2); break; + #ifndef C3nodef + case 3: CTL_OP(C3bank, C3); break; + #endif + case 4: CTL_OP(C4bank, C4); break; + case 5: CTL_OP(C5bank, C5); break; + case 6: CTL_OP(C6bank, C6); break; + #ifndef C7nodef + case 7: CTL_OP(C7bank, C7); break; + #endif + case 8: CTL_OP(C8bank, C8); break; + case 9: CTL_OP(C9bank, C9); break; + case 10: CTL_OP(C10bank,C10); break; + case 11: CTL_OP(C11bank,C11); break; + #ifndef C12nodef + case 12: CTL_OP(C12bank,C12); break; + #endif + #ifndef C13nodef + case 13: CTL_OP(C13bank,C13); + #ifdef PURPLE_KAZZO + CTL_OP(C3bank,C3); + #endif + break; + #endif + #ifndef C14nodef + case 14: CTL_OP(C14bank,C14); break; + #endif + #ifndef C15nodef + case 15: CTL_OP(C15bank,C15); break; + #endif + #ifndef C16nodef + case 16: CTL_OP(C16bank,C16); break; + #endif + #ifndef C17nodef + case 17: CTL_OP(C17bank,C17); break; + #endif + #ifndef C18nodef + case 18: CTL_OP(C18bank,C18); break; + #endif + #ifndef C19nodef + case 19: CTL_OP(C19bank,C19); break; + #endif + #ifndef C20nodef + case 20: CTL_OP(C20bank,C20); break; + #endif + case 21: CTL_OP(C21bank,C21); break; + default: return ERR_CTL_PIN_NOT_PRESENT; + } + break; + case CTL_SET_LO_: + switch ( operand ) { + case 0: CTL_SET_LO(C0bank, C0); break; + case 1: CTL_SET_LO(C1bank, C1); break; + case 2: CTL_SET_LO(C2bank, C2); break; + #ifndef C3nodef + case 3: CTL_SET_LO(C3bank, C3); break; + #endif + case 4: CTL_SET_LO(C4bank, C4); break; + case 5: CTL_SET_LO(C5bank, C5); break; + case 6: CTL_SET_LO(C6bank, C6); break; + #ifndef C7nodef + case 7: CTL_SET_LO(C7bank, C7); break; + #endif + case 8: CTL_SET_LO(C8bank, C8); break; + case 9: CTL_SET_LO(C9bank, C9); break; + case 10: CTL_SET_LO(C10bank,C10); break; + case 11: CTL_SET_LO(C11bank,C11); break; + #ifndef C12nodef + case 12: CTL_SET_LO(C12bank,C12); break; + #endif + #ifndef C13nodef + case 13: CTL_SET_LO(C13bank,C13); + #ifdef PURPLE_KAZZO + CTL_SET_LO(C3bank,C3); + #endif + break; + #endif + #ifndef C14nodef + case 14: CTL_SET_LO(C14bank,C14); break; + #endif + #ifndef C15nodef + case 15: CTL_SET_LO(C15bank,C15); break; + #endif + #ifndef C16nodef + case 16: CTL_SET_LO(C16bank,C16); break; + #endif + #ifndef C17nodef + case 17: CTL_SET_LO(C17bank,C17); break; + #endif + #ifndef C18nodef + case 18: CTL_SET_LO(C18bank,C18); break; + #endif + #ifndef C19nodef + case 19: CTL_SET_LO(C19bank,C19); break; + #endif + #ifndef C20nodef + case 20: CTL_SET_LO(C20bank,C20); break; + #endif + case 21: CTL_SET_LO(C21bank,C21); break; + default: return ERR_CTL_PIN_NOT_PRESENT; + } + break; + case CTL_SET_HI_: + switch ( operand ) { + case 0: CTL_SET_HI(C0bank, C0); break; + case 1: CTL_SET_HI(C1bank, C1); break; + case 2: CTL_SET_HI(C2bank, C2); break; + #ifndef C3nodef + case 3: CTL_SET_HI(C3bank, C3); break; + #endif + case 4: CTL_SET_HI(C4bank, C4); break; + case 5: CTL_SET_HI(C5bank, C5); break; + case 6: CTL_SET_HI(C6bank, C6); break; + #ifndef C7nodef + case 7: CTL_SET_HI(C7bank, C7); break; + #endif + case 8: CTL_SET_HI(C8bank, C8); break; + case 9: CTL_SET_HI(C9bank, C9); break; + case 10: CTL_SET_HI(C10bank,C10); break; + case 11: CTL_SET_HI(C11bank,C11); break; + #ifndef C12nodef + case 12: CTL_SET_HI(C12bank,C12); break; + #endif + #ifndef C13nodef + case 13: CTL_SET_HI(C13bank,C13); + #ifdef PURPLE_KAZZO + CTL_SET_HI(C3bank,C3); + #endif + break; + #endif + #ifndef C14nodef + case 14: CTL_SET_HI(C14bank,C14); break; + #endif + #ifndef C15nodef + case 15: CTL_SET_HI(C15bank,C15); break; + #endif + #ifndef C16nodef + case 16: CTL_SET_HI(C16bank,C16); break; + #endif + #ifndef C17nodef + case 17: CTL_SET_HI(C17bank,C17); break; + #endif + #ifndef C18nodef + case 18: CTL_SET_HI(C18bank,C18); break; + #endif + #ifndef C19nodef + case 19: CTL_SET_HI(C19bank,C19); break; + #endif + #ifndef C20nodef + case 20: CTL_SET_HI(C20bank,C20); break; + #endif + case 21: CTL_SET_HI(C21bank,C21); break; + default: return ERR_CTL_PIN_NOT_PRESENT; + } + break; + case CTL_RD_: + rdata[RD_LEN] = HWORD_LEN; + switch ( operand ) { + case 0: CTL_RD(C0bank, C0, *ret_hword); break; + case 1: CTL_RD(C1bank, C1, *ret_hword); break; + case 2: CTL_RD(C2bank, C2, *ret_hword); break; + #ifndef C3nodef + case 3: CTL_RD(C3bank, C3, *ret_hword); break; + #endif + case 4: CTL_RD(C4bank, C4, *ret_hword); break; + case 5: CTL_RD(C5bank, C5, *ret_hword); break; + case 6: CTL_RD(C6bank, C6, *ret_hword); break; + #ifndef C7nodef + case 7: CTL_RD(C7bank, C7, *ret_hword); break; + #endif + case 8: CTL_RD(C8bank, C8, *ret_hword); break; + case 9: CTL_RD(C9bank, C9, *ret_hword); break; + case 10: CTL_RD(C10bank,C10, *ret_hword); break; + case 11: CTL_RD(C11bank,C11, *ret_hword); break; + #ifndef C12nodef + case 12: CTL_RD(C12bank,C12, *ret_hword); break; + #endif + #ifndef C13nodef + case 13: CTL_RD(C13bank,C13, *ret_hword); break; + #endif + #ifndef C14nodef + case 14: CTL_RD(C14bank,C14, *ret_hword); break; + #endif + #ifndef C15nodef + case 15: CTL_RD(C15bank,C15, *ret_hword); break; + #endif + #ifndef C16nodef + case 16: CTL_RD(C16bank,C16, *ret_hword); break; + #endif + #ifndef C17nodef + case 17: CTL_RD(C17bank,C17, *ret_hword); break; + #endif + #ifndef C18nodef + case 18: CTL_RD(C18bank,C18, *ret_hword); break; + #endif + #ifndef C19nodef + case 19: CTL_RD(C19bank,C19, *ret_hword); break; + #endif + #ifndef C20nodef + case 20: CTL_RD(C20bank,C20, *ret_hword); break; + #endif + case 21: CTL_RD(C21bank,C21, *ret_hword); break; + default: rdata[RD_LEN] = 0; + return ERR_CTL_PIN_NOT_PRESENT; + } + break; + + //============================ + //DATA PORT BYTE WIDE ACCESS + //opcode: type of operation + //operand: value to place on bus + //============================ + case DATA_ENABLE_: DATA_ENABLE(); break; + case DATA_IP_PU_: DATA_IP_PU(); break; + case DATA_IP_: DATA_IP(); break; + case DATA_OP_: DATA_OP(); break; + case DATA_SET_: DATA_SET(operand); break; + case DATA_RD_: DATA_RD(rdata[RD0]); + rdata[RD_LEN] = 1; break; + + //============================ + //ADDR PORT 16bit WIDE ACCESS + //opcode: type of operation + //operand: value to place on bus + //============================ + case ADDR_ENABLE_: ADDR_ENABLE(); break; + case ADDR_PU_: ADDR_PU(); break; + case ADDR_IP_: ADDR_IP(); break; + case ADDR_OP_: ADDR_OP(); break; + case ADDR_SET_: ADDR_SET(operand); break; + + //============================ + //EXP PORT 8bit ACCESS (bits1-8) + //opcode: type of operation + //operand: value to place on bus + //============================ + case EXP_ENABLE_: EXP_ENABLE(); break; + case EXP_DISABLE_: EXP_DISABLE(); break; + case EXP_SET_: EXP_SET(operand); break; + + default: + //macro doesn't exist or isn't on this PCB version + return ERR_UNKN_PP_OPCODE; + } + + return SUCCESS; +} + +#ifdef GREEN_KAZZO + +/* Desc: + * other board versions have PORTB "DATA" feed into both FF's + * this board feeds EXP FF with PORTA "ADDR" instead + * goal is to make board versions 'identical' + * to do this we assume higher level functions will have already + * placed desired latch value on PORTB "Dbank->PORT" + * we need to juggle this data around and not stomp on anything + * Pre: DATA_OP() set + * curAHLaddr set by software_AHL_CLK + * Dbank->PORT contains desired value to be latched by EXP FF + * AXHL might not be set as O/P + * AXHL might not be low ready for AXHL_CLK + * Post:Both FF's have desired value latched + * ADDR_OP() left set + * curAXLaddr updated for use by software_AHL_CLK + * Dbank->PORT and ALbank->PORT replaced with original values + * AXHL left as O/P and ready for subsequent CLK + */ + +//these variables are updated each time the FF's are clocked +//that way we can retain the value of other FF as both must be clocked at once +static uint8_t curAHLaddr; +static uint8_t curAXLaddr; + +void software_AXL_CLK() +{ + //first store current DATA & ADDR values + curAXLaddr = Dbank->PORT; //This is desired AXL value + uint8_t orig_addr = ALbank->PORT; //PORTA + + //Put current AHL latched value on DATA as that's where it'll be relatched + //software_AHL_CLK function is one to maintain this value + Dbank->PORT = curAHLaddr; + + //set ADDR as O/P and place desired value on bus + ADDR_OP(); //prob already be set, but in case not + ALbank->PORT = curAXLaddr; + + //Clock both latches + AHL_OP(); //can't be sure "AHL" is OP as assumption is AXL will be used as latch + AHL_LO(); //can't be sure it's low either + //_AXHL_CLK(); //clock values + CTL_SET_HI(AHLbank, AHL); CTL_SET_LO(AHLbank, AHL); + + //finally restore original DATA & ADDR values + Dbank->PORT = curAXLaddr; + ALbank->PORT = orig_addr; + +} + +/* Desc: Same premise as software_AXL_CLK above. + * this is a little simpler as data has already been feed with AHL value. + * just need to make sure AXL latch doesn't get corrupted. + * Pre: DATA_OP() set + * curAXLaddr set by software_AXL_CLK + * Dbank->PORT contains desired value to be latched by ADDRMID FF + * AXHL is already set to O/P + * AXHL already low ready for AXHL_CLK + * Post:Both FF's have desired value latched + * curAHLaddr updated for use by software_AXL_CLK + * Dbank->PORT and ALbank->PORT replaced with original values + * AXHL left as O/P and ready for subsequent CLK + */ +void software_AHL_CLK() +{ + //first store current DATA & ADDR values + curAHLaddr = Dbank->PORT; //This is desired AHL value (store it for other function's use) + uint8_t orig_addr = ALbank->PORT; //PORTA + + //Desired AHL latch value should have already been placed on Dbank->PORT. + + //set ADDR as O/P and place curAXLaddr on bus other function should have updated it last latch + ADDR_OP(); //should already be set, but in case not + ALbank->PORT = curAXLaddr; + + //Clock both latches + //Can assume AHL is OP as other versions would require it to latch AHL + //Can also assume it was left low, if not causes issues in all board versions + //_AXHL_CLK(); //clock values + CTL_SET_HI(AHLbank, AHL); CTL_SET_LO(AHLbank, AHL); + + //finally restore original DATA & ADDR values + //never changed: Dbank->PORT = curAHLaddr; + ALbank->PORT = orig_addr; + +} + +#endif //GREEN_KAZZO diff --git a/firmware/source/pinport.h b/firmware/source/pinport.h new file mode 100644 index 0000000..8eb72b6 --- /dev/null +++ b/firmware/source/pinport.h @@ -0,0 +1,164 @@ +#ifndef _pinport_h +#define _pinport_h + +#include "pinport_al.h" +#include "shared_errors.h" +#include "shared_dict_pinport.h" + +uint8_t pinport_call( uint8_t opcode, uint8_t miscdata, uint16_t operand, uint8_t *rdata ); + + +// used for a very short delay +//#define NOP() do { __asm__ __volatile__ ("nop"); } while (0) + + +//PIN MACROS + +// PC0 "MCO" +#define MCO_IP_PU() CTL_IP_PU(MCObank, MCO) +#define MCO_IP_FL() CTL_IP_FL(MCObank, MCO) +#define MCO_OP() CTL_OP(MCObank, MCO) +#define MCO_LO() CTL_SET_LO(MCObank, MCO) +#define MCO_HI() CTL_SET_HI(MCObank, MCO) +#define MCO_RD(val) CTL_RD(MCObank, MCO, val) + +// PC1 "ROMSEL" +#define ROMSEL_IP_PU() CTL_IP_PU(ROMSELbank, ROMSEL) +#define ROMSEL_IP_FL() CTL_IP_FL(ROMSELbank, ROMSEL) +#define ROMSEL_OP() CTL_OP(ROMSELbank, ROMSEL) +#define ROMSEL_LO() CTL_SET_LO(ROMSELbank, ROMSEL) +#define ROMSEL_HI() CTL_SET_HI(ROMSELbank, ROMSEL) +#define ROMSEL_RD(val) CTL_RD(ROMSELbank, ROMSEL, val) + +// PC2 "PRGRW" +#define PRGRW_IP_PU() CTL_IP_PU(PRGRWbank, PRGRW) +#define PRGRW_IP_FL() CTL_IP_FL(PRGRWbank, PRGRW) +#define PRGRW_OP() CTL_OP(PRGRWbank, PRGRW) +#define PRGRW_LO() CTL_SET_LO(PRGRWbank, PRGRW) +#define PRGRW_HI() CTL_SET_HI(PRGRWbank, PRGRW) +#define PRGRW_RD(val) CTL_RD(PRGRWbank, PRGRW, val) + +// PC3 "FREE" +#ifndef C3nodef +#define FREE_IP_PU() CTL_IP_PU(FREEbank, FREE) +#define FREE_IP_FL() CTL_IP_FL(FREEbank, FREE) +#define FREE_OP() CTL_OP(FREEbank, FREE) +#define FREE_LO() CTL_SET_LO(FREEbank, FREE) +#define FREE_HI() CTL_SET_HI(FREEbank, FREE) +#define FREE_RD(val) CTL_RD(FREEbank, FREE, val) +#endif + +// PC4 "CSRD" +#define CSRD_IP_PU() CTL_IP_PU(CSRDbank, CSRD) +#define CSRD_IP_FL() CTL_IP_FL(CSRDbank, CSRD) +#define CSRD_OP() CTL_OP(CSRDbank, CSRD) +#define CSRD_LO() CTL_SET_LO(CSRDbank, CSRD) +#define CSRD_HI() CTL_SET_HI(CSRDbank, CSRD) +#define CSRD_RD(val) CTL_RD(CSRDbank, CSRD, val) + +// PC5 "CSWR" +#define CSWR_IP_PU() CTL_IP_PU(CSWRbank, CSWR) +#define CSWR_IP_FL() CTL_IP_FL(CSWRbank, CSWR) +#define CSWR_OP() CTL_OP(CSWRbank, CSWR) +#define CSWR_LO() CTL_SET_LO(CSWRbank, CSWR) +#define CSWR_HI() CTL_SET_HI(CSWRbank, CSWR) +#define CSWR_RD(val) CTL_RD(CSWRbank, CSWR, val) + +// PC6 "CICE" +#define CICE_IP_PU() CTL_IP_PU(CICEbank, CICE) +#define CICE_IP_FL() CTL_IP_FL(CICEbank, CICE) +#define CICE_OP() CTL_OP(CICEbank, CICE) +#define CICE_LO() CTL_SET_LO(CICEbank, CICE) +#define CICE_HI() CTL_SET_HI(CICEbank, CICE) +#define CICE_RD(val) CTL_RD(CICEbank, CICE, val) + +// PC7 "AHL" +#ifndef C7nodef +#define AHL_IP_PU() CTL_IP_PU(AHLbank, AHL) +#define AHL_IP_FL() CTL_IP_FL(AHLbank, AHL) +#define AHL_OP() CTL_OP(AHLbank, AHL) +#define AHL_LO() CTL_SET_LO(AHLbank, AHL) +#define AHL_HI() CTL_SET_HI(AHLbank, AHL) +#define AHL_RD(val) CTL_RD(AHLbank, AHL, val) +#endif + +// PC8 "EXP0" +#define EXP0_IP_PU() CTL_IP_PU(EXP0bank, EXP0) +#define EXP0_IP_FL() CTL_IP_FL(EXP0bank, EXP0) +#define EXP0_OP() CTL_OP(EXP0bank, EXP0) +#define EXP0_LO() CTL_SET_LO(EXP0bank, EXP0) +#define EXP0_HI() CTL_SET_HI(EXP0bank, EXP0) +#define EXP0_RD(val) CTL_RD(EXP0bank, EXP0, val) + +// PC9 "LED" +#define LED_IP_PU() CTL_IP_PU(LEDbank, LED) +#define LED_IP_FL() CTL_IP_FL(LEDbank, LED) +#define LED_OP() CTL_OP(LEDbank, LED) +#define LED_LO() CTL_SET_LO(LEDbank, LED) +#define LED_HI() CTL_SET_HI(LEDbank, LED) +#define LED_RD(val) CTL_RD(LEDbank, LED, val) + +// PC10 "IRQ" +#define IRQ_IP_PU() CTL_IP_PU(IRQbank, IRQ) +#define IRQ_IP_FL() CTL_IP_FL(IRQbank, IRQ) +#define IRQ_OP() CTL_OP(IRQbank, IRQ) +#define IRQ_LO() CTL_SET_LO(IRQbank, IRQ) +#define IRQ_HI() CTL_SET_HI(IRQbank, IRQ) +#define IRQ_RD(val) CTL_RD(IRQbank, IRQ, val) + +// PC11 "CIA10" +#define CIA10_IP_PU() CTL_IP_PU(CIA10bank, CIA10) +#define CIA10_IP_FL() CTL_IP_FL(CIA10bank, CIA10) +#define CIA10_OP() CTL_OP(CIA10bank, CIA10) +#define CIA10_LO() CTL_SET_LO(CIA10bank, CIA10) +#define CIA10_HI() CTL_SET_HI(CIA10bank, CIA10) +#define CIA10_RD(val) CTL_RD(CIA10bank, CIA10, val + +// PC12 "BL" + +// PC13 "AXL" +#ifndef C13nodef + +#ifdef PURPLE_KAZZO //tie two pins together via software +#define AXL_IP_PU() CTL_IP_PU(AXLbank, AXL) CTL_IP_PU(FREEbank, FREE) +#define AXL_IP_FL() CTL_IP_FL(AXLbank, AXL) CTL_IP_FL(FREEbank, FREE) +#define AXL_OP() CTL_OP(AXLbank, AXL) CTL_OP(FREEbank, FREE) +#define AXL_LO() CTL_SET_LO(AXLbank, AXL) CTL_SET_LO(FREEbank, FREE) +#define AXL_HI() CTL_SET_HI(AXLbank, AXL) CTL_SET_HI(FREEbank, FREE) +#define AXL_RD(val) CTL_RD(AXLbank, AXL, val) +#else //not PURPLE_KAZZO +#define AXL_IP_PU() CTL_IP_PU(AXLbank, AXL) +#define AXL_IP_FL() CTL_IP_FL(AXLbank, AXL) +#define AXL_OP() CTL_OP(AXLbank, AXL) +#define AXL_LO() CTL_SET_LO(AXLbank, AXL) +#define AXL_HI() CTL_SET_HI(AXLbank, AXL) +#define AXL_RD(val) CTL_RD(AXLbank, AXL, val) +#endif + +#endif + +// PC14 "AUDL" + +// PC15 "AUDR" + +// PC16 "CIN" + +// PC17 "SWD" + +// PC18 "SWC" + +// PC19 "AFL" +#ifndef C19nodef +#define AFL_IP_PU() CTL_IP_PU(AFLbank, AFL) +#define AFL_IP_FL() CTL_IP_FL(AFLbank, AFL) +#define AFL_OP() CTL_OP(AFLbank, AFL) +#define AFL_LO() CTL_SET_LO(AFLbank, AFL) +#define AFL_HI() CTL_SET_HI(AFLbank, AFL) +#define AFL_RD(val) CTL_RD(AFLbank, AFL, val) +#endif + +// PC20 "COUT" + +// PC21 "FCAPU" + +#endif diff --git a/firmware/source/pinport_al.h b/firmware/source/pinport_al.h index f03ec95..a020a40 100644 --- a/firmware/source/pinport_al.h +++ b/firmware/source/pinport_al.h @@ -12,6 +12,206 @@ #include #endif +//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 //GREEN needs PURPLE defined at same time + +#ifdef GREEN_KAZZO +void software_AHL_CLK(); +void software_AXL_CLK(); +#endif + +//======================================================= +//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 prototype +// 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 +// +// +// +// STM32F070RBT6 "INL RETRO 6" prototype +// completely new design with 6 connectors: +// GBA/DMG, SNES/SFC, NES, N64, Sega gen, Famicom +// updates to arm cortex M0 core and hardware USB 2.0 +// Green solder mask +// Labeled "INL RETRO PROGRAMMER DUMPER V2.0P" +// Dated MAY 2017 +// Unlike all previous version above this has direct access to most pins +// Only exception is one Flipflop for SegaGen A17-18, 20-23, #LO_MEM, & #TIME +// flipflop also drives SNES PA0-7 + + + //============================================================================================= // // PINPORT ABSTRACTION LAYER @@ -77,9 +277,10 @@ // 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_FL 0x00 #define PUPDR_PU 0x01 #define PUPDR_PD 0x10 +#define PUPDR_PU_ALL 0x55555555 // // GPIOx->IDR 16bit register used to read current input level on pin // this register is read only @@ -141,12 +342,22 @@ // Read/Input: Bit access only, returned byte/word will be zero if clear, non-zero if set // // PORT C pin definitions -// Don't assign one mcu pin to more than one pin in this port! +// Try not to 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. +// If a ctl pin is needed that's mapped to different mcu pins based on the board, +// create a new control port pin and violate the first rule with caution. +// +// Creation of new signals: +// 1) Create PC# -> mcupin assignment below +// 2) map pin name to PC# which follows assignments below +// 3) add applicable macro calls to pinport.c +// 4) add pin name to shared_dict_pinport.h operands for simple calling from host +// 5) add shortcut macros to pinport.h if desired +// 6) ensure CTL PORT ENABLE macro enables new pin adequately // // --------------------------------------------------------------------------------------- @@ -164,8 +375,9 @@ #define C2bank GPIOA #define C2 (1U) - // PC3 "PAXL" - // Not defined + // PC3 "FREE" + // Not defined + #define C3nodef // PC4 "CSRD" mcupinA2 #define C4bank GPIOA @@ -181,6 +393,7 @@ // PC7 "AHL" // Not defined + #define C7nodef // PC8 "EXP0" mcupinA6 #define C8bank GPIOA @@ -200,9 +413,11 @@ // PC12 "BL" // Not defined + #define C12nodef // PC13 "AXL" // Not defined + #define C13nodef // PC14 "AUDL" mcupinA4 #define C14bank GPIOA @@ -232,10 +447,14 @@ #define C20bank GPIOD #define C20 (2U) + // PC21 "FCAPU" double mapping of AUDR + #define C21bank C15bank + #define C21 C15 + /* NEED MORE UNIQUE names for these pins to not conflict with Data port definitions... - // PC21 "D8" mcupinB10 - #define C21bank GPIOB - #define C21 (10U) + // PCxx "D8" mcupinB10 + #define Cxxbank GPIOB + #define Cxx (10U) // PC22 "D9" mcupinB11 #define C22bank GPIOB @@ -258,10 +477,11 @@ #define C26 (15U) */ - #define IOP_LED_EN RCC_AHBENR_GPIOBEN - - - + +#define RCC_AHBENR_CTL (RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIODEN) +#define RCC_AHBENR_ADDR RCC_AHBENR_GPIOCEN +#define RCC_AHBENR_DATA RCC_AHBENR_GPIOBEN +#define RCC_AHBENR_EXP (RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOBEN) #endif //STM_INL6 @@ -280,8 +500,12 @@ #define C2bank GPIOA #define C2 (5U) - // PC3 "PAXL" - // Not defined + // PC3 "FREE" mcupinA6 + #define C3bank GPIOA + #define C3 (6U) +#ifdef PURPLE_KAZZO + #define C3nodef //assigned to PAXL instead which is tied to AXL /OE in software +#endif // PC4 "CSRD" mcupinA7 #define C4bank GPIOA @@ -317,6 +541,7 @@ // PC12 "BL" // Not defined + #define C12nodef // PC13 "AXL" mcupinA2 #define C13bank GPIOA @@ -324,15 +549,19 @@ // PC14 "AUDL" // Not defined + #define C14nodef // PC15 "AUDR" // Not defined + #define C15nodef // PC16 "CIN" // Not defined + #define C16nodef // PC17 "SWD" mcupinA13 // Not defined due to shared with CIRAM A10 + #define C17nodef // PC18 "SWC" mcupinA14 #define C18bank GPIOA @@ -340,29 +569,20 @@ // PC19 "AFL" // Not defined + #define C19nodef // PC20 "COUT" // Not defined + #define C20nodef - // PC21 "D8" - // Not defined + // PC21 "FCAPU" double mapping of EXP0 + #define C21bank C8bank + #define C21 C8 - // PC22 "D9" - // Not defined - // PC23 "D10" - // Not defined - - // PC24 "D11" - // Not defined - - // PC25 "D12" - // Not defined - - // PC26 "D13" - // Not defined - -#define IOP_LED_EN RCC_AHBENR_GPIOCEN +#define RCC_AHBENR_CTL (RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN) +#define RCC_AHBENR_ADDR (RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN) +#define RCC_AHBENR_DATA RCC_AHBENR_GPIOBEN #endif //STM_ADAPTER @@ -381,8 +601,12 @@ #define C2bank GPIOC #define C2 (2U) - // PC3 "PAXL" mcupinC3 - // Not defined + // PC3 "FREE" mcupinC3 + #define C3bank GPIOC + #define C3 (3U) +#ifdef PURPLE_KAZZO + #define C3nodef //assigned to PAXL instead which is tied to AXL /OE in software +#endif // PC4 "CSRD" mcupinC4 #define C4bank GPIOC @@ -420,48 +644,42 @@ #define C12bank GPIOD #define C12 (6U) - // PC13 "AXL" mcupinD7 + // PC13 "AXL" mcupinD7 //PURPLE KAZZO uses this for /OE only #define C13bank GPIOD #define C13 (7U) // PC14 "AUDL" // not defined + #define C14nodef // PC15 "AUDR" // not defined + #define C15nodef // PC16 "CIN" // not defined + #define C16nodef // PC17 "SWD" // not defined + #define C17nodef // PC18 "SWC" // not defined + #define C18nodef // PC19 "AFL" // not defined + #define C19nodef // PC20 "COUT" // not defined + #define C20nodef - // PC21 "D8" - // not defined + // PC21 "FCAPU" double mapping of EXP0 + #define C21bank C8bank + #define C21 C8 - // PC22 "D9" - // not defined - - // PC23 "D10" - // not defined - - // PC24 "D11" - // not defined - - // PC25 "D12" - // not defined - - // PC26 "D13" - // not defined #endif //AVR_KAZZO @@ -474,8 +692,6 @@ // PC0 "MCO" mcu clock out M2/phi2, Sysclk, etc #define MCO C0 #define MCObank C0bank -#define M2 C0 -#define M2bank C0bank // PC1 "ROMSEL" Cartridge rom enable #define ROMSEL C1 @@ -485,9 +701,9 @@ #define PRGRW C2 #define PRGRWbank C2bank -// PC3 "PAXL" purple kazzo EXP flipflop latch, FREE on most kazzos -#define PAXL C3 -#define PAXLbank C3bank +// PC3 "FREE" purple kazzo EXP flipflop latch, FREE on most kazzos +#define FREE C3 +#define FREEbank C3bank // PC4 "CSRD" NES CHR/SNES /RD #define CSRD C4 @@ -505,7 +721,7 @@ #define AHL C7 #define AHLbank C7bank -// PC8 "EXP0" NES EXP0, cart-console /RESET +// PC8 "EXP0" NES EXP0, FC APU sound, cart-console /RESET #define EXP0 C8 #define EXP0bank C8bank @@ -558,11 +774,15 @@ #define COUT C20 #define COUTbank C20bank +// PC21 "FCAPU" cart audio in +#define FCAPU C21 +#define FCAPUbank C21bank + // INLretro6 gains direct control over NES EXP port and is used for N64 control pins: /* -// PC21 "D8" -#define D8 C21 -#define D8bank C21bank +// PCxx "D8" +#define D8 Cxx +#define D8bank Cxxbank // PC22 "D9" #define D9 C22 @@ -594,22 +814,28 @@ #ifdef STM_CORE #define CTL_IP_PU(bank, pin) bank->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_IP_FL(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<BSRR = 1<IDR & (1<AHBENR |= RCC_AHBENR_CTL #endif //STM_CORE #ifdef AVR_CORE #define CTL_IP_PU(bank, pin) bank->DDR &= ~(1<PORT |= (1<DDR &= ~(1<PORT &= ~(1<DDR &= ~(1<PORT &= ~(1<DDR |= (1<PIN & (1<PORT |= (1<PORT &= ~(1<PORT |= (1<PIN & (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 + //also assume PUPDR is reset default floating + #define DATA_IP_PU() Dbank->MODER &= ~(MODER_OP_ALL & 0x000FFFF0); Dbank->PUPDR |= (PUPDR_PU_ALL & 0x000FFFF0) + #define DATA_IP() Dbank->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 + + #define DATA_EN_CLK() RCC->AHBENR |= RCC_AHBENR_DATA + #define DATA_ENABLE() DATA_EN_CLK(); DATA_IP_PU(); + #endif //STM_INL6 #ifdef STM_ADAPTER - //All 8bits are on GPIOB inorder, but mapped to bits15-8 + //All 8bits are on GPIOB in order, 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) + //also assume PUPDR is reset default floating + #define DATA_IP_PU() Dbank->MODER &= ~(MODER_OP_ALL & 0xFFFF0000); Dbank->PUPDR |= (PUPDR_PU_ALL & 0xFFFF0000) + #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 + #define DATA_SET(data) Dbank->ODR = (Dbank->ODR & 0x00FF) | (data<<8) + #define DATA_RD(data) data = (Dbank->IDR>>8) & 0x00FF + + #define DATA_EN_CLK() RCC->AHBENR |= RCC_AHBENR_DATA + #define DATA_ENABLE() DATA_EN_CLK(); DATA_IP_PU() #endif //STM_ADAPTER @@ -671,11 +921,13 @@ //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 + #define DATA_SET(data) Dbank->PORT = data + #define DATA_IP_PU() Dbank->DDR = 0x00; DATA_SET(0xFF) + #define DATA_IP() Dbank->DDR = 0x00 + #define DATA_OP() Dbank->DDR = 0xFF + #define DATA_RD(data) data = Dbank->PIN + #define DATA_ENABLE() DATA_IP_PU() #endif //AVR_KAZZO @@ -696,11 +948,15 @@ //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 + #define ADDR_PU() Abank->PUPDR |= PUPDR_PU_ALL + #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_SET(hword) Abank->ODR = hword + + #define ADDR_EN_CLK() RCC->AHBENR |= RCC_AHBENR_ADDR + #define ADDR_ENABLE() ADDR_EN_CLK(); ADDR_OP() #endif //STM_INL6 @@ -712,12 +968,17 @@ #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) + #define ADDR_PU() A76bank->PUPDR |= (PUPDR_PU_ALL & 0x000F0000); A50bank->PUPDR |= (PUPDR_PU_ALL & 0x0000FFF0) + #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) + #define ADDRH(high) DATA_OP(); DATA_SET(high); AHL_CLK(); DATA_IP() + #define ADDR_SET(hword) ADDRL(hword); ADDRH(hword>>8) + + #define ADDR_EN_CLK() RCC->AHBENR |= RCC_AHBENR_ADDR + #define ADDR_EN_FF() CTL_OP(AHLbank, AHL); CTL_SET_LO(AHLbank, AHL) + #define ADDR_ENABLE() ADDR_EN_CLK(); ADDR_EN_FF(); ADDR_OP() #endif //STM_ADAPTER @@ -725,16 +986,86 @@ // A15-8 are behind AHL flipflop // A7-0 are on GPIOA perfectly aligned - #define _ALbank GPIOA + #define ALbank GPIOA - #define _ADDRL(low) GPIOA->PORT = low + #define ADDR_PU() ALbank->PORT = 0xFF + #define ADDR_IP() ALbank->DDR = 0x00 + #define ADDR_OP() ALbank->DDR = 0xFF + #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(); - #define _ADDR(hword) ADDRL(hword); _ADDRH(hword>>8) + #define ADDRH(high) DATA_OP(); DATA_SET(high); AHL_CLK(); DATA_IP(); + #define ADDR_SET(hword) ADDRL(hword); ADDRH(hword>>8) + + #define ADDR_EN_FF() CTL_OP(AHLbank, AHL); CTL_SET_LO(AHLbank, AHL) + #define ADDR_ENABLE() ADDR_EN_FF(); ADDR_OP(); #endif //AVR_KAZZO +// --------------------------------------------------------------------------------------- +// EXPANSION PORT 8bit pins #1-8 +// +// This port is present on all devices but implemented differently. +// This port is primarily targeted as a NES cartridge port to connect to EXP1-8 +// EXP0 has it's own dedicated pin in CTL PORT, EXP9 is dual purposed with LED on AVR/adapters +// AVR & ADAPTER connect EXP6 to Famicom RF audio (cart output) +// INL6 dual purposes EXP6, 8, & 9 with CLT PORT AUDL, SWCLK, & AUDR respectively +// Need some sort of interlock to ensure CTL PORT & EXP PORT don't stop on eachother's shared pins +// Extra macros are needed to make this port compatible on early versions of AVR KAZZO +// AVR & Adapter have access via 8x Flipflop +// -these devices also map these pins to A16-23 +// INL6 has direct pin access +// -these pins also act as Data8-15 for Sega Genesis +// -has separate pins dedicated to A16-23 +// Directionality: All pins are forced output, or tristate. This maintains compatability +// between all devices +// Driver: All pins are push-pull, AVR & STM ADAPTER drive with 5v signals, INL6 drives with 3.3v +// Write/Output: Byte access only, no bit accesses +// Read/Input: Not supported +// +// --------------------------------------------------------------------------------------- + +#ifdef STM_INL6 + + //pins1-5 = GPIOB10-14 (D8-12), pin6 = GPIOA4 (AUDL), pin7 = GPIOB15 (D13), pin8 = GPIOA14 (SWCLK) + //these defines are quite the mess currently due to pins all over the place + //there is no real benefit to defining this port as byte wide but defining them this way 'degrades' + //them to the same quality as AVR making all devices mostly compatible. + //These can be redefined as CONTROL PORT for simpler pin granuarity access + #define E157bank GPIOB + #define E68bank GPIOA + + #define EXP_PU() E157bank->PUPDR |= (PUPDR_PU_ALL & 0xFFF00000); E68bank->PUPDR |= (PUPDR_PU_ALL & 0x30000300) + #define EXP_IP() E157bank->MODER &=~(MODER_OP_ALL & 0xFFF00000); E68bank->MODER &=~(MODER_OP_ALL & 0x30000300) + #define EXP_OP() E157bank->MODER |= (MODER_OP_ALL & 0xFFF00000); E68bank->MODER |= (MODER_OP_ALL & 0x30000300) + //not sure these bit shift accesses will work if the value passed in is a uint8_t variable... + #define EXP_SET(val) E157bank->ODR = ((E157bank->ODR & 0x03FF) | (val<<10 & 0x7C00) | (val<<9 & 0x8000)); E68bank->ODR = ((E68bank->ODR & 0xBFEF) | (val>>1 & 0x0010) | (val<<7 & 0x4000)) + + #define EXP_EN_CLK() RCC->AHBENR |= RCC_AHBENR_EXP + #define EXP_ENABLE() ADDR_EN_CLK(); EXP_OP() + #define EXP_DISABLE() EXP_PU(); EXP_IP() + +//STM_INL6 +#else //AVR_KAZZO or STM_ADAPTER + + + // EXP1-8 are behind AXL flipflop + + //clocks must be initialized, Data bus clear + #define EXP_SET(val) DATA_OP(); DATA_SET(val); AXL_CLK(); DATA_IP() + +#ifdef PURPLE_KAZZO + #define EXP_EN_FF() CTL_OP(AXLbank, AXL); CTL_SET_LO(AXLbank, AXL); CTL_OP(FREEbank, FREE); CTL_SET_LO(FREEbank, FREE); + #define EXP_DISABLE() CTL_IP_PU(AXLbank, AXL); CTL_IP_PU(FREEbank, FREE) +#else + #define EXP_EN_FF() CTL_OP(AXLbank, AXL); CTL_SET_LO(AXLbank, AXL) + #define EXP_DISABLE() CTL_IP_PU(AXLbank, AXL) +#endif + + #define EXP_ENABLE() DATA_ENABLE(); CTL_ENABLE(); EXP_EN_FF() + +#endif //AVR_KAZZO or STM_ADAPTER + #endif diff --git a/firmware/source/pinport_stm.h b/firmware/source/pinport_stm.h deleted file mode 100644 index 7edefd7..0000000 --- a/firmware/source/pinport_stm.h +++ /dev/null @@ -1,581 +0,0 @@ -#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/types.h b/firmware/source/types.h index 5a4b1d5..83a2795 100644 --- a/firmware/source/types.h +++ b/firmware/source/types.h @@ -6,8 +6,7 @@ typedef struct setup_packet{ uint8_t bRequest; //designates dictionary of opcode uint8_t opcode; //wValueLSB (little endian) uint8_t miscdata; //wValueMSB - uint8_t operandLSB; //wIndexLSB - uint8_t operandMSB; //wIndexMSB + uint16_t operand; //16bit operand "wIndex" uint16_t wLength; }setup_packet; diff --git a/firmware/source/usb.c b/firmware/source/usb.c index 2c94ccd..7f8a720 100644 --- a/firmware/source/usb.c +++ b/firmware/source/usb.c @@ -77,16 +77,6 @@ uint16_t usbFunctionSetup(uint8_t data[8]) { //now it's the opcode's responsiblity to update these values //rv[RETURN_DATA] start of return data - //fake some return data - rv[RETURN_ERR_IDX] = SUCCESS; - rv[RETURN_LEN_IDX] = 3; - rv[RETURN_DATA] = 0xAA; - rv[RETURN_DATA+1] = 0xDE; - rv[RETURN_DATA+2] = 0xAD; - rv[RETURN_DATA+3] = 0xBE; - rv[RETURN_DATA+4] = 0xEF; - rv[RETURN_DATA+5] = 0xCC; - /* (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 * will handle the rest. Or (2) return USB_NO_MSG in 'usbFunctionSetup()'. The @@ -96,10 +86,7 @@ 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 - - //works on avr, broke on stm: usbMsgPtr = (usbMsgPtr_t)rv; - //usbMsgPtr = rv; #if USB_CFG_LONG_TRANSFERS @@ -115,48 +102,14 @@ uint16_t usbFunctionSetup(uint8_t data[8]) { switch(spacket->bRequest) { case DICT_PINPORT: - - //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); - - - - switch (spacket->opcode) { - /* - case PP_OPCODE_ONLY_MIN ... PP_OPCODE_ONLY_MAX: - rv[RV_ERR_IDX] = pinport_opcode_only( spacket->opcode ); - break; - case PP_OPCODE_8BOP_MIN ... PP_OPCODE_8BOP_MAX: - rv[RV_ERR_IDX] = pinport_opcode_8b_operand( - spacket->opcode, spacket->operandLSB ); - break; - case PP_OPCODE_16BOP_MIN ... PP_OPCODE_16BOP_MAX: - rv[RV_ERR_IDX] = pinport_opcode_16b_operand( - spacket->opcode, spacket->operandMSB, spacket->operandLSB ); - break; - case PP_OPCODE_24BOP_MIN ... PP_OPCODE_24BOP_MAX: - rv[RV_ERR_IDX] = pinport_opcode_24b_operand( spacket->opcode, - spacket->miscdata, spacket->operandMSB, spacket->operandLSB ); - break; - case PP_OPCODE_8BRV_MIN ... PP_OPCODE_8BRV_MAX: - rv[RV_ERR_IDX] = pinport_opcode_8b_return( spacket->opcode, &rv[RV_DATA0_IDX]); - rlen ++; - break; - default: //pinport opcode min/max definition error - rv[RETURN_ERR_IDX] = ERR_BAD_PP_OP_MINMAX; - */ - } + rv[RETURN_ERR_IDX] = pinport_call( spacket->opcode, spacket->miscdata, spacket->operand, &rv[RETURN_LEN_IDX] ); break; //end of PINPORT -/* case DICT_IO: - //break; //end of IO + rv[RETURN_ERR_IDX] = io_call( spacket->opcode, spacket->miscdata, spacket->operand, &rv[RETURN_LEN_IDX] ); + break; //end of IO +/* case DICT_NES: //break; //end of NES diff --git a/firmware/source/usb.h b/firmware/source/usb.h index cac30b1..54a0203 100644 --- a/firmware/source/usb.h +++ b/firmware/source/usb.h @@ -4,24 +4,16 @@ //Define the target core, only define one of these //these defines are made in Makefile -//#define AVR_CORE -//#define STM_CORE - -//== AVR CORE == AVR CORE == AVR CORE == AVR CORE == AVR CORE #ifdef AVR_CORE -// #include - #include "usbdrv.h" #endif -//end AVR CORE -//== STM CORE == STM CORE == STM CORE == STM CORE == STM CORE #ifdef STM_CORE #include "..\source_stm_only\usbstm.h" #endif -//end STM CORE -#include "pinport_al.h" +#include "pinport.h" +#include "io.h" #include "types.h" #include "shared_usb.h" #include "shared_errors.h" @@ -29,8 +21,6 @@ /* #include "logic.h" -#include "pinport.h" -#include "io.h" #include "nes.h" #include "snes.h" #include "buffer.h" diff --git a/host/scripts/app/blank.lua b/host/scripts/app/blank.lua new file mode 100644 index 0000000..aca1074 --- /dev/null +++ b/host/scripts/app/blank.lua @@ -0,0 +1,26 @@ + +-- create the module's table +local blank = {} + +-- import required modules +local dict = require "scripts.app.dict" + +-- file constants + +-- local functions +local function func() + +end + + +-- global variables so other modules can use them + + +-- call functions desired to run when script is called/imported + + +-- functions other modules are able to call +blank.func = func + +-- return the module's table +return blank diff --git a/host/scripts/app/cart.lua b/host/scripts/app/cart.lua new file mode 100644 index 0000000..83de657 --- /dev/null +++ b/host/scripts/app/cart.lua @@ -0,0 +1,109 @@ + +-- create the module's table +local cart = {} + +-- import required modules +local dict = require "scripts.app.dict" +local nes = require "scripts.app.nes" + +-- file constants + +-- local functions +local function detect( debug ) + + print("attempting to detect cartridge..."); +-- //always start with resetting i/o + dict.io("IO_RESET") + +-- //TODO check if can detect a cart inserted backwards before continuing + +-- //check if NES/Famicom cart + dict.io("NES_INIT") + +-- //if PPU /A13 is tied to CIRAM /CE we know it's NES/Famicom + if nes.jumper_ciramce_ppuA13n(debug) then +-- //NES with 2 screen mirroring + if debug then print("CIRAM /CE is jumpered to PPU /A13") end +-- cart->console = NES_CART; + elseif nes.ciramce_inv_ppuA13(debug) then +-- //some boards including INLXO-ROM boards drive CIRAM /CE with inverse of PPU A13 + if debug then print("CIRAM /CE is inverse of PPU A13") end +-- cart->console = NES_CART; + end +-- TODO check if CIRAM on cartridge or NT CHR-ROM +-- +-- if NES/FC determine which if possible +-- also possible that this could catch failed detections above which is current case with VRC6 +-- Famicom has audio in and audio out pins connected to each other +-- For this to pass with a NES cart EXP6 would have to be jumpered to EXP0 for some strange reason +-- might fail if expansion audio mixing circuitry foils the check above +-- but worst case we detected NES when famicom which isn't big deal.. + if nes.jumper_famicom_sound(debug) then + if debug then print("Famicom audio jumper found") end +-- cart->console = FC_CART; + end + +-- //if couldn't detect NES/FC check for SNES cartridge +-- //want to keep from outputting on EXP bus if NES cart was found +-- if ( cart->console == UNKNOWN ) { +-- //only way I can think of is if memory is enabled by certain addresses and control signals +-- snes_init( transfer ); +-- if ( snes_mem_visible( transfer, 0x00, 0xFFFC )) { +-- //CHECK for memory visible near NES reset vector +-- debug("SNES memories detected"); +-- cart->console = SNES_CART; +-- } +-- //now it's possible that rom is there, but data is 0xFF so above test would fail +-- //one option would be to drive bus low for short period and see if bus can be +-- //driven low. This could damage pin drivers though, best to create command in +-- //firmware to perform this to limit to one CPU cycle instead of USB xfr times +-- +-- //Prob best to check if able to read flash ID's if reset vector data is 0xFF +-- //Since reset vector being 0xFF prob means it's blank flash cart.. +-- +-- //playable SNES carts should have data somewhere in reset vector... +-- } +-- +-- //always end with resetting i/o +-- io_reset( transfer ); +-- +-- switch (cart->console) { +-- case NES_CART: printf("NES cartridge detected!\n"); +-- break; +-- case FC_CART: printf("Famicom cartridge detected!\n"); +-- break; +-- case SNES_CART: printf("SNES cartridge detected!\n"); +-- break; +-- case BKWD_CART: log_err("CARTRIDGE INSERTED BACKWARDS!!!\n"); +-- //TODO detection not yet implemented need to look over connector pinouts +-- break; +-- case UNKNOWN: printf("Unable to detect cartridge...\n"); +-- //TODO error out properly +-- break; +-- default: +-- sentinel("cartridge console element got set to something unsupported."); +-- } +-- +-- return SUCCESS; +-- +--error: +-- //always end with resetting i/o +-- io_reset( transfer ); +-- return -1; +-- +--} + +end + + +-- global variables so other modules can use them + + +-- call functions desired to run when script is called/imported + + +-- functions other modules are able to call +cart.detect = detect + +-- return the module's table +return cart diff --git a/host/scripts/app/dict.lua b/host/scripts/app/dict.lua new file mode 100644 index 0000000..b310b6b --- /dev/null +++ b/host/scripts/app/dict.lua @@ -0,0 +1,297 @@ +-- dictionary module +-- creates tables with dictionary entries from shared\shared_dict*.h files +-- performs usb transfer when making dictionary call and returns device data + +-- create the module's table +local dict = {} + +-- file constants +local USB_IN = 0x80 --device to host +local USB_OUT = 0x00 --host to device + +-- read all the C shared_dict*.h files and create tables with all values +-- This isn't 'Nam there are rules! +-- dictionary #define that start with underscore are skipped this skips over header and special cases +-- currently only finds lowercase #define statements (seems C does too!) +-- multiline comments /* comment */ are not permitted, will throw error! +-- #define statements must have a numeric value such as: #define FOO 4 +-- #define without number will error like this: "#define FOO BAR" or "#define FOO BAR - 100" is bad too! +-- fills passed in table with keys and values to be used for making usb dictionary calls +-- accepts decimal or hex when 0x00 format +-- trailing underscores are trimmed, this allows firmware macro defines to match dictionary defines +-- sets "opcode_rlen" when RL= (ie RL = 5) in the comments following the opcode +local function create_dict_tables( table, file ) + assert(io.input(file, "r")) + + local count = 0 + local define = 0 + local define_end = 0 + local slash = 0 + local line + local comment + for line in io.lines() do + count = count + 1 + comment = nil --needs cleared for each pass + --search for multiline comment opening, starting at index 1, plain search = true + if string.find( line, "/*", 1, true) then + print("\n\n!!!ERROR!!!\nmultiline comment found line number", count) + print("while parsing file:", file, "\nonly inline comments are permitted!!!\n") + error("multiline comments not allowed in dictionary files!") + end + define, define_end = string.find( line, "#define") + if define then + slash = string.find(line, "//") + --check for comment following define, if present cut out comment + if slash and (slash>define) then + --store comment contents for later parsing + comment = string.sub(line, slash, -1) + line = string.sub(line, 1, slash-1 ) + end + --check for comment prior to define, skip if present + if not (slash and (slash CIRAM /CE jumper present +-- Does NOT check if PPU A13 is inverted and then drives CIRAM /CE +-- Pre: nes_init() been called to setup i/o +-- Post:PPU /A13 left high (disabled), all other ADDRH signals low +-- Rtn: true if jumper is set +local function jumper_ciramce_ppuA13n( debug ) + + --check that we can clear CIRAM /CE with PPU /A13 + dict.pinport( "ADDR_SET", 0x0000 ) + --read CIRAM /CE pin + if dict.pinport( "CTL_RD", "CICE" ) ~= 0 then + if debug then print("CIRAM /CE high when /A13 low ") end + return false + end + + --set PPU /A13 high + dict.pinport( "ADDR_SET", PPU_A13N_HI ) + --read CIRAM /CE pin + if dict.pinport( "CTL_RD", "CICE" ) == 0 then + if debug then print("CIRAM /CE low when /A13 high") end + return false + end + + --CICE low jumper appears to be present + if debug then print("CIRAM /CE <- PPU /A13 jumper present") end + return true +end + +-- Desc:check if PPU A13 is inverted then drives CIRAM /CE +-- Some mappers may do this including INLXO-ROM boards +-- Does NOT check if PPU /A13 is drives CIRAM /CE +-- Pre: nes_init() been called to setup i/o +-- Post:PPU A13 left disabled (hi) +-- Rtn: true if inverted PPU A13 drives CIRAM /CE +local function ciramce_inv_ppuA13 (debug) + + --set PPU A13 low + dict.pinport( "ADDR_SET", 0x0000 ) + -- CIRAM /CE should be high if inverted A13 is what drives it + if dict.pinport( "CTL_RD", "CICE" ) == 0 then + if debug then print("CIRAM /CE low when A13 low") end + return false + end + + --check that we can clear CIRAM /CE with PPU A13 high + dict.pinport( "ADDR_SET", PPU_A13_HI ) + -- CIRAM /CE should be low if inverted A13 is what drives it + if dict.pinport( "CTL_RD", "CICE" ) ~= 0 then + if debug then print("CIRAM /CE high when A13 high") end + return false + end + + --CICE low jumper appears to be present + if debug then print("CIRAM /CE <- inverse PPU A13") end + return true +end + +-- Desc:check for famicom audio in->out jumper +-- This drives EXP6 (RF out) -> EXP0 (APU in) which is backwards.. +-- not much can do about that for old avr kazzo designs +-- There are probably caps/resistors for synth carts anyway +-- but to be safe only apply short pulses. +-- While we typically don't want to apply 5v to EXP port on NES carts, +-- this only does so for EXP6 which is safe on current designs. +-- All other EXP1-8 pins are only driven low. +-- Pre: nes_init() been called to setup i/o +-- which makes EXP0 floating i/p +-- Post:EXP FF left disabled and EXP0 floating +-- AXLOE pin returned to input with pullup +-- Rtn: true if jumper/connection is present +-- Test:Works on non-expansion sound carts obviously +-- Works on VRC6 and VRC7 +-- Others untested +local function jumper_famicom_sound (debug) + + --EXP0 should be floating input + --AXLOE pin needs to be set as output and + --EXP FF needs enabled before we can clock it, + --but don't leave it enabled before exiting function +-- + --set AXLOE to output + dict.pinport("EXP_ENABLE") + --Latch low first + dict.pinport("EXP_SET", 0x00) +-- pull up FCAPU + dict.pinport("CTL_IP_PU", "FCAPU") + --read EXP0 Famicom APU audio pin + if dict.pinport( "CTL_RD", "FCAPU" ) ~= 0 then + if debug then print("RF audio out (EXP6) didn't drive APU audio in (EXP0) low") end + dict.pinport("EXP_DISABLE") + dict.pinport("CTL_IP_FL", "EXP0") + return false + end + + --Latch RF audio sound pin high + dict.pinport("EXP_SET", FC_RF_HI) + --read Famicom APU audio pin + if dict.pinport( "CTL_RD", "FCAPU" ) == 0 then + if debug then print("RF audio out (EXP6) didn't drive APU audio in (EXP0) high") end + dict.pinport("EXP_DISABLE") + dict.pinport("CTL_IP_FL", "EXP0") + return false + end + + --Famicom audio jumper appears to be present + if debug then print("RF audio out (EXP6) is connected to APU audio in") end + --disable EXP PORT and return EXP0 to floating if it was used + dict.pinport("EXP_DISABLE") + dict.pinport("CTL_IP_FL", "EXP0") + return true +end + +-- global variables so other modules can use them + + +-- call functions desired to run when script is called/imported + + +-- functions other modules are able to call +nes.jumper_ciramce_ppuA13n = jumper_ciramce_ppuA13n +nes.ciramce_inv_ppuA13 = ciramce_inv_ppuA13 +nes.jumper_famicom_sound = jumper_famicom_sound + +-- return the module's table +return nes + +-- old C file: +-- +--/* Desc:PRG-ROM flash manf/prod ID sense test +-- * Using EXP0 /WE writes +-- * Only senses SST flash ID's +-- * Assumes that isn't getting tricked by having manf/prodID at $8000/8001 +-- * could add check and increment read address to ensure doesn't get tricked.. +-- * Pre: nes_init() been called to setup i/o +-- * exp0 pullup test must pass +-- * if ROM A14 is mapper controlled it must be low when CPU A14 is low +-- * controlling A14 outside of this function acts as a means of bank size detection +-- * Post:memory manf/prod ID set to read values if passed +-- * memory wr_dict and wr_opcode set if successful +-- * Software mode exited if entered successfully +-- * Rtn: SUCCESS if flash sensed, GEN_FAIL if not, neg if error +-- */ +--int read_flashID_prgrom_exp0( USBtransfer *transfer, memory *flash ) { +-- +-- uint8_t rv[RV_DATA0_IDX]; +-- + --enter software mode + --ROMSEL controls PRG-ROM /OE which needs to be low for flash writes + --So unlock commands need to be addressed below $8000 + --DISCRETE_EXP0_PRGROM_WR doesn't toggle /ROMSEL by definition though, so A15 is unused + -- 15 14 13 12 + -- 0x5 = 0b 0 1 0 1 -> $5555 + -- 0x2 = 0b 0 0 1 0 -> $2AAA +-- dictionary_call( transfer, DICT_NES, DISCRETE_EXP0_PRGROM_WR, 0x5555, 0xAA, +-- USB_IN, NULL, 1); +-- dictionary_call( transfer, DICT_NES, DISCRETE_EXP0_PRGROM_WR, 0x2AAA, 0x55, +-- USB_IN, NULL, 1); +-- dictionary_call( transfer, DICT_NES, DISCRETE_EXP0_PRGROM_WR, 0x5555, 0x90, +-- USB_IN, NULL, 1); + --read manf ID +-- dictionary_call( transfer, DICT_NES, NES_CPU_RD, 0x8000, NILL, +-- USB_IN, rv, RV_DATA0_IDX+1); +-- debug("manf id: %x", rv[RV_DATA0_IDX]); +-- if ( rv[RV_DATA0_IDX] != SST_MANF_ID ) { +-- return GEN_FAIL; +-- //no need for software exit since failed to enter +-- } +-- + --read prod ID +-- dictionary_call( transfer, DICT_NES, NES_CPU_RD, 0x8001, NILL, +-- USB_IN, rv, RV_DATA0_IDX+1); +-- debug("prod id: %x", rv[RV_DATA0_IDX]); +-- if ( (rv[RV_DATA0_IDX] == SST_PROD_128) +-- || (rv[RV_DATA0_IDX] == SST_PROD_256) +-- || (rv[RV_DATA0_IDX] == SST_PROD_512) ) { +-- //found expected manf and prod ID +-- flash->manf = SST_MANF_ID; +-- flash->part = rv[RV_DATA0_IDX]; +-- flash->wr_dict = DICT_NES; +-- flash->wr_opcode = DISCRETE_EXP0_PRGROM_WR; +-- } +-- + --exit software +-- dictionary_call( transfer, DICT_NES, DISCRETE_EXP0_PRGROM_WR, 0x8000, 0xF0, +-- USB_IN, NULL, 1); +-- + --verify exited + --dictionary_call( transfer, DICT_NES, NES_CPU_RD, 0x8000, NILL, + -- USB_IN, rv, RV_DATA0_IDX+1); + --debug("prod id: %x", rv[RV_DATA0_IDX]); +-- +-- return SUCCESS; +--} +-- +-- +--/* Desc:PRG-ROM flash manf/prod ID sense test +-- * Using mapper 30 defined PRG-ROM flash writes +-- * Only senses SST flash ID's +-- * Assumes that isn't getting tricked by having manf/prodID at $8000/8001 +-- * could add check and increment read address to ensure doesn't get tricked.. +-- * Pre: nes_init() been called to setup i/o +-- * Post:memory manf/prod ID set to read values if passed +-- * memory wr_dict and wr_opcode set if successful +-- * Software mode exited if entered successfully +-- * Rtn: SUCCESS if flash sensed, GEN_FAIL if not, neg if error +-- */ +--int read_flashID_prgrom_map30( USBtransfer *transfer, memory *flash ) { +-- +-- uint8_t rv[RV_DATA0_IDX]; +-- + --enter software mode + --$8000-BFFF writes to flash + --$C000-FFFF writes to mapper + -- 15 14 13 12 + -- 0x5 = 0b 0 1 0 1 -> $9555 + -- 0x2 = 0b 0 0 1 0 -> $2AAA + --set A14 in mapper reg for $5555 command +-- dictionary_call( transfer, DICT_NES, NES_CPU_WR, 0xC000, 0x01, +-- USB_IN, NULL, 1); + --write $5555 0xAA +-- dictionary_call( transfer, DICT_NES, NES_CPU_WR, 0x9555, 0xAA, +-- USB_IN, NULL, 1); + --clear A14 in mapper reg for $2AAA command +-- dictionary_call( transfer, DICT_NES, NES_CPU_WR, 0xC000, 0x00, +-- USB_IN, NULL, 1); + --write $2AAA 0x55 +-- dictionary_call( transfer, DICT_NES, NES_CPU_WR, 0xAAAA, 0x55, +-- USB_IN, NULL, 1); + --set A14 in mapper reg for $5555 command +-- dictionary_call( transfer, DICT_NES, NES_CPU_WR, 0xC000, 0x01, +-- USB_IN, NULL, 1); + --write $5555 0x90 for software mode +-- dictionary_call( transfer, DICT_NES, NES_CPU_WR, 0x9555, 0x90, +-- USB_IN, NULL, 1); +-- + --read manf ID +-- dictionary_call( transfer, DICT_NES, NES_CPU_RD, 0x8000, NILL, +-- USB_IN, rv, RV_DATA0_IDX+1); +-- debug("manf id: %x", rv[RV_DATA0_IDX]); +-- if ( rv[RV_DATA0_IDX] != SST_MANF_ID ) { +-- return GEN_FAIL; +-- //no need for software exit since failed to enter +-- } +-- + --read prod ID +-- dictionary_call( transfer, DICT_NES, NES_CPU_RD, 0x8001, NILL, +-- USB_IN, rv, RV_DATA0_IDX+1); +-- debug("prod id: %x", rv[RV_DATA0_IDX]); +-- if ( (rv[RV_DATA0_IDX] == SST_PROD_128) +-- || (rv[RV_DATA0_IDX] == SST_PROD_256) +-- || (rv[RV_DATA0_IDX] == SST_PROD_512) ) { +-- //found expected manf and prod ID +-- flash->manf = SST_MANF_ID; +-- flash->part = rv[RV_DATA0_IDX]; +-- flash->wr_dict = DICT_NES; +-- flash->wr_opcode = NES_CPU_WR; +-- } +-- + --exit software +-- dictionary_call( transfer, DICT_NES, NES_CPU_WR, 0x8000, 0xF0, +-- USB_IN, NULL, 1); +-- + --verify exited +-- dictionary_call( transfer, DICT_NES, NES_CPU_RD, 0x8000, NILL, +-- USB_IN, rv, RV_DATA0_IDX+1); +-- debug("prod id: %x", rv[RV_DATA0_IDX]); +-- +-- return SUCCESS; +--} +-- +-- +--/* Desc:CHR-ROM flash manf/prod ID sense test +-- * Only senses SST flash ID's +-- * Does not make CHR bank writes so A14-A13 must be made valid outside of this funciton +-- * An NROM board does this by tieing A14:13 to A12:11 +-- * Other mappers will pass this function if PT0 has A14:13=01, PT1 has A14:13=10 +-- * Assumes that isn't getting tricked by having manf/prodID at $0000/0001 +-- * could add check and increment read address to ensure doesn't get tricked.. +-- * Pre: nes_init() been called to setup i/o +-- * Post:memory manf/prod ID set to read values if passed +-- * memory wr_dict and wr_opcode set if successful +-- * Software mode exited if entered successfully +-- * Rtn: SUCCESS if flash sensed, GEN_FAIL if not, neg if error +-- */ +--int read_flashID_chrrom_8K( USBtransfer *transfer, memory *flash ) { +-- +-- uint8_t rv[RV_DATA0_IDX]; +-- + --enter software mode + --NROM has A13 tied to A11, and A14 tied to A12. + --So only A0-12 needs to be valid + --A13 needs to be low to address CHR-ROM + -- 15 14 13 12 + -- 0x5 = 0b 0 1 0 1 -> $1555 + -- 0x2 = 0b 0 0 1 0 -> $0AAA +-- dictionary_call( transfer, DICT_NES, NES_PPU_WR, 0x1555, 0xAA, +-- USB_IN, NULL, 1); +-- dictionary_call( transfer, DICT_NES, NES_PPU_WR, 0x0AAA, 0x55, +-- USB_IN, NULL, 1); +-- dictionary_call( transfer, DICT_NES, NES_PPU_WR, 0x1555, 0x90, +-- USB_IN, NULL, 1); + --read manf ID +-- dictionary_call( transfer, DICT_NES, NES_PPU_RD, 0x0000, NILL, +-- USB_IN, rv, RV_DATA0_IDX+1); +-- debug("manf id: %x", rv[RV_DATA0_IDX]); +-- if ( rv[RV_DATA0_IDX] != SST_MANF_ID ) { +-- return GEN_FAIL; +-- //no need for software exit since failed to enter +-- } +-- + --read prod ID +-- dictionary_call( transfer, DICT_NES, NES_PPU_RD, 0x0001, NILL, +-- USB_IN, rv, RV_DATA0_IDX+1); +-- debug("prod id: %x", rv[RV_DATA0_IDX]); +-- if ( (rv[RV_DATA0_IDX] == SST_PROD_128) +-- || (rv[RV_DATA0_IDX] == SST_PROD_256) +-- || (rv[RV_DATA0_IDX] == SST_PROD_512) ) { +-- //found expected manf and prod ID +-- flash->manf = SST_MANF_ID; +-- flash->part = rv[RV_DATA0_IDX]; +-- flash->wr_dict = DICT_NES; +-- flash->wr_opcode = NES_PPU_WR; +-- } +-- + --exit software +-- dictionary_call( transfer, DICT_NES, NES_PPU_WR, 0x0000, 0xF0, +-- USB_IN, NULL, 1); +-- + --verify exited + --dictionary_call( transfer, DICT_NES, NES_PPU_RD, 0x0000, NILL, + -- USB_IN, rv, RV_DATA0_IDX+1); + --debug("prod id: %x", rv[RV_DATA0_IDX]); +-- +-- return SUCCESS; +--} +-- +--/* Desc:Simple CHR-RAM sense test +-- * A more thourough test should be implemented in firmware +-- * This one simply tests one address in PPU address space +-- * Pre: nes_init() been called to setup i/o +-- * Post: +-- * Rtn: SUCCESS if ram sensed, GEN_FAIL if not, neg if error +-- */ +--int ppu_ram_sense( USBtransfer *transfer, uint16_t addr ) { +-- +-- uint8_t rv[RV_DATA0_IDX]; +-- + --write 0xAA to addr +-- dictionary_call( transfer, DICT_NES, NES_PPU_WR, addr, 0xAA, +-- USB_IN, NULL, 1); + --try to read it back +-- dictionary_call( transfer, DICT_NES, NES_PPU_RD, addr, NILL, +-- USB_IN, rv, RV_DATA0_IDX+1); +-- debug("reading back 0xAA: %x", rv[RV_DATA0_IDX]); +-- if ( rv[RV_DATA0_IDX] != 0xAA ) { +-- return GEN_FAIL; +-- } +-- + --write 0x55 to addr +-- dictionary_call( transfer, DICT_NES, NES_PPU_WR, addr, 0x55, +-- USB_IN, NULL, 1); + --try to read it back +-- dictionary_call( transfer, DICT_NES, NES_PPU_RD, addr, NILL, +-- USB_IN, rv, RV_DATA0_IDX+1); +-- debug("reading back 0x55: %x", rv[RV_DATA0_IDX]); +-- if ( rv[RV_DATA0_IDX] != 0x55 ) { +-- return GEN_FAIL; +-- } +-- +-- return SUCCESS; +--} +-- +-- +--/* Desc:Just calls CIRAM_A10_MIRROR opcode and returns result. +-- * result will be return value of opcode +-- * Pre: nes_init() been called to setup i/o +-- * Post:address bus left assigned +-- * Rtn: VERT/HORIZ/1SCNA/1SCNB +-- */ +--int ciram_A10_mirroring( USBtransfer *transfer ) +--{ +-- uint8_t rv[RV_DATA0_IDX]; +-- +-- dictionary_call( transfer, DICT_NES, CIRAM_A10_MIRROR, NILL, NILL, +-- USB_IN, rv, RV_DATA0_IDX+1); +-- debug("mirroring detected: %x", rv[RV_DATA0_IDX]); +-- return rv[RV_DATA0_IDX]; +--} diff --git a/host/scripts/usb_device.lua b/host/scripts/app/usb_device.lua similarity index 100% rename from host/scripts/usb_device.lua rename to host/scripts/app/usb_device.lua diff --git a/host/scripts/inlretro.lua b/host/scripts/inlretro.lua index 7266527..674814f 100644 --- a/host/scripts/inlretro.lua +++ b/host/scripts/inlretro.lua @@ -1,235 +1,35 @@ -- main script that runs application logic and flow -USB_IN = 0x80 --device to host -USB_OUT = 0x00 --host to device - --- read all the C shared_dict*.h files and create tables with all values --- This isn't 'Nam there are rules! --- dictionary #define that start with underscore are skipped this skips over header and special cases --- currently only finds lowercase #define statements (seems C does too!) --- multiline comments /* comment */ are not permitted, will throw error! --- #define statements must have a numeric value such as: #define FOO 4 --- #define without number will error like this: "#define FOO BAR" or "#define FOO BAR - 100" is bad too! --- fills passed in table with keys and values to be used for making usb dictionary calls --- accepts decimal or hex when 0x00 format - -function create_dict_tables( table, file ) - assert(io.input(file, "r")) - - local count = 0 - local define = 0 - local define_end = 0 - local slash = 0 - local line - local comment - for line in io.lines() do - count = count + 1 - --search for multiline comment opening, starting at index 1, plain search = true - if string.find( line, "/*", 1, true) then - print("\n\n!!!ERROR!!!\nmultiline comment found line number", count) - print("while parsing file:", file, "\nonly inline comments are permitted!!!\n") - error("multiline comments not allowed in dictionary files!") - end - define, define_end = string.find( line, "#define") - if define then - slash = string.find(line, "//") - --check for comment following define, if present cut out comment - if slash and (slash>define) then - --store comment contents for later parsing - comment = string.sub(line, slash, -1) - line = string.sub(line, 1, slash-1 ) - end - --check for comment prior to define, skip if present - if not (slash and (slashenable o/p -#define EXPFF_FLT 88 //FF /OE pin high->disable o/p - -//AXL_CLK this is similar between purple and green versions, just on a different pin. -//green boards don't have an AXL_CLK nor a AHL_CLK, as the two are combined. -//green boards must resolve this in software storing value of FF's so can have the effect -//of only clocking one of them. -//#ifdef GREEN_KAZZO -//case XX: AXHL_CLK(); break; //don't want to call this as software AXL/AHL don't track -//case 87: software_AXL_CLK(); break; -//case 88: software_AHL_CLK(); break; -//#else -//these two cases covers all designs with macro calling sofware versions for green board. -#define AXL_CLK 89 -#define AHL_CLK 90 -//#endif -//these work fine in hardware for purple and final. -//green had to separate these two with software. - - - -//============================================================================================= -//============================================================================================= -// CAUTION!!! CAUTION!!! CAUTION!!! CAUTION!!! CAUTION!!! -// -// The opcodes that follow operate under some rules that you must adhere to if calling -// 1) Data bus should be free and clear when possible -// -DATA_IP() is default state -// -Be cognizant if you're driving the data bus -// many of these opcodes use the data bus to function. -// -Many of these opcodes will end up driving the data bus -// know when that'll happen and free bus when data retreived -// -// -Flipflops must be initialized -// this primarily means CLK pin must be OP and LO ready for CLK command -// -output of FF must be enabled to actually feed latched value on cart -// final pcb version will enable EXP FF after clocking. -// early pcb versions have FF /OE on separate pin not so automatic. -// -// -control pins must be initialized -// -enable OP on pins necessary to perform desire of command -// ie M2 and /ROMSEL must be OP if you're trying to change them with a command. -// -// -be cognizant of what pins are inputs and which are outputs -// 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 -// -// -//============================================================================================= -//============================================================================================= - - - - -//============================================================================================= -// OPCODES WITH OPERAND and no return value besides SUCCESS/ERROR_CODE -//============================================================================================= -// -#define PP_OPCODE_8BOP_MIN 0x80 -#define PP_OPCODE_8BOP_MAX 0x9F -// 0x80-0x9F: opcodes with 8bit operand -// 0x80-8A are only ones currently in use -// -#define PP_OPCODE_16BOP_MIN 0xA0 -#define PP_OPCODE_16BOP_MAX 0xAF -// 0xA0-0xAF: opcodes with 16bit operand -// 0xA0-A2 are only ones currently in use -// -#define PP_OPCODE_24BOP_MIN 0xB0 -#define PP_OPCODE_24BOP_MAX 0xBF -// 0xB0-0xBF: opcodes with 24bit operand -// 0xA0 is currently only one in use -// -// Current limit for these types of opcodes is 128-191 (0x80-0xBF) -// This allows for the MSBs' to be used for decoding pinport opcode to this type -// -// -//============================================================================================= -//============================================================================================= - - -//================================= -//8bit operand -//================================= - -//ADDR[7:0] PORTA -#define ADDR_SET 0x80 - -//DATA[7:0] PORTB -#define DATA_SET 0x81 -//conveinent/safe yet slower function that sets ADDR as OP then sets value -#define DATA_OPnSET 0x82 - -//ADDR[15:8] FLIPFLOP -//NES CPU: ADDRH[6:0] -> CPU A[14:8] -// ADDRH[7] -> NC on CPU side -//NES PPU: ADDRH[5:0] -> PPU A[13:8] -// 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 0x83 - -//EXPANSION FLIPFLOP -//NES: ADDRX[7:0] -> EXP PORT [8:1] -//SNES: ADDRX[7:0] -> CPU A[23:16] -#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 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 0x87 -#define aux_ddr_set 0x88 -#define ctl_port_set 0x89 -#define aux_port_set 0x8A - - - -//================================= -//16bit operand -//================================= - -//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] -#define ADDR16_SET 0xA0 - -//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 -#define NCPU_ADDR_ROMSEL 0xA1 - -//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.. -// But should be able to do this with CHR /RD in same manner CHR-ROM is kept silent.. - -//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. -#define NPPU_ADDR_SET 0xA2 - - -//================================= -//24bit operand -//================================= - -//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 -//wIndex contains lower 16bits -//wValue upper (miscdata) contains upper 8bits -#define ADDR24_SET 0xB0 - - - -//============================================================================================= -// OPCODES with NO OPERAND but have RETURN VALUE plus SUCCESS/ERROR_CODE -//============================================================================================= -// -#define PP_OPCODE_8BRV_MIN 0xC0 -#define PP_OPCODE_8BRV_MAX 0xFF -// 0xC0-0xFF: opcodes with 8bit return value (plus SuCCESS/ERROR) -// 0xC0-CB are only ones currently in use -// -// 0x??-0xFF: larger return values perhaps? -// -// -// Current limit for these types of opcodes is 192-255 (0xC0-0xFF) -// This allows for the MSBs' to be used for decoding pinport opcode to this type -// Detect this opcode/operand setup with opcode between the following defines: -// -// Detect this opcode/operand setup with opcode between the following defines: -// -//============================================================================================= -//============================================================================================= - - -//READ MCU I/O PORT INPUT 'PIN' REGISTERS -//This is what's used to read bus after setting DDR register to input with IP() command/macro -//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 -//DATA[7:0] PINB -#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 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 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 0xC4 -//DATA[7:0] PORTB -#define DATA_PORT_RD 0xC5 -//CTL PORTC -#define CTL_PORT_RD 0xC6 -//AUX PORTD -#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 0xC8 -//DATA[7:0] DDRB -#define DATA_DDR_RD 0xC9 -//CTL DDRC -#define CTL_DDR_RD 0xCA -//AUX DDRD -#define AUX_DDR_RD 0xCB - - - -//============================================================================================= -// OPCODES with OPERAND and RETURN VALUE plus SUCCESS/ERROR_CODE -//============================================================================================= -//Not sure if want these or not... #endif diff --git a/shared/shared_dictionaries.h b/shared/shared_dictionaries.h index 9cebde2..094fd3e 100644 --- a/shared/shared_dictionaries.h +++ b/shared/shared_dictionaries.h @@ -30,50 +30,16 @@ #define DICT_PINPORT 1 #include "shared_dict_pinport.h" //pinport dictionary has various commands giving low and mid level access to retro prog's i/o pins. -//It also contains internal avr registers associated with the avr's io. -//Access to other internal avr registers should be placed in other associated dictionaries. -//The opcodes in this dictionary should not have any cyclic effect such as pulsing /ROMSEL -//low to read data and then disabling taking /ROMSEL high again. These commands are intended -//to appear as a single change/edge to cartridge hardware. Only potential exception to this -//is AHL/AXL clocking which is used to latch values to FF's, that effectively is only one -//state change for the cartridge hardware. -// -// Many of the opcodes in the second half of this dictionary have the following rules: -// -// The opcodes that follow operate under some rules that you must adhere to if calling -// 1) Data bus should be free and clear when possible -// -DATA_IP() is default state -// -Be cognizant if you're driving the data bus -// many of these opcodes use the data bus to function. -// -Many of these opcodes will end up driving the data bus -// know when that'll happen and free bus when data retreived -// -// -Flipflops must be initialized -// this primarily means CLK pin must be OP and LO ready for CLK command -// -output of FF must be enabled to actually feed latched value on cart -// final pcb version will enable EXP FF after clocking. -// early pcb versions have FF /OE on separate pin not so automatic. -// -// -control pins must be initialized -// -enable OP on pins necessary to perform desire of command -// ie M2 and /ROMSEL must be OP if you're trying to change them with a command. -// -// -be cognizant of what pins are inputs and which are outputs -// 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 -// -// +//See abstraction layer port definitions in firmware pinport_al.h file for more details. +//An effort has been made to make opcodes in this dictionary hardware independent. //============================================================================================= //============================================================================================= //============================================================================================= //============================================================================================= -//#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 +54,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 diff --git a/shared/shared_errors.h b/shared/shared_errors.h index 0e22bbb..d40d19e 100644 --- a/shared/shared_errors.h +++ b/shared/shared_errors.h @@ -4,29 +4,16 @@ #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 -#define ERR_BAD_PP_OP_MINMAX 129 -#define ERR_BAD_IO_OP_MINMAX 130 -#define ERR_BAD_NES_OP_MINMAX 131 -#define ERR_BAD_SNES_OP_MINMAX 132 -#define ERR_BAD_BUFF_OP_MINMAX 133 -#define ERR_BUFN_DOES_NOT_EXIST 134 -#define ERR_BAD_OPER_OP_MINMAX 135 -//#define ERR_UNKN_PP_OPCODE_ONLY 140 -//#define ERR_UNKN_PP_OPCODE_8BOP 141 -//#define ERR_UNKN_PP_OPCODE_16BOP 142 -//#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 -// +#define ERR_UNKN_PP_OPCODE 140 +#define ERR_CTL_PIN_NOT_PRESENT 141 + +#define ERR_UNKN_IO_OPCODE 150 + //#define ERR_UNKN_NES_OPCODE_24BOP 160 //#define ERR_UNKN_NES_OPCODE_16BOP_8BRV 161 //