diff --git a/Changelog.txt b/Changelog.txt index 38b26ce..a1d8529 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,3 +1,9 @@ +--- v1.4 (April 20, 2013) +- Support for Atmega168. Use Makefile.atmega168. +- New USB VID/PID +- Simplified main loop by remving setIdle/getIdle implementation. Optional for + joysticks according to HID specification appendix G. + --- v1.3 (April 2012) - Added support for SNES multitaps in 4 player mode. diff --git a/Makefile b/Makefile deleted file mode 100644 index 721d6d6..0000000 --- a/Makefile +++ /dev/null @@ -1,75 +0,0 @@ -# Name: Makefile -# Project: HIDKeys -# Author: Christian Starkjohann -# Creation Date: 2006-02-02 -# Tabsize: 4 -# Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH -# License: Proprietary, free under certain conditions. See Documentation. -# This Revision: $Id: Makefile,v 1.5 2009-05-02 14:02:52 cvs Exp $ - -UISP = uisp -dprog=stk500 -dpart=atmega8 -dserial=/dev/avr -COMPILE = avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega8 -DF_CPU=12000000L #-DDEBUG_LEVEL=1 -COMMON_OBJS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o - -OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o fournsnes.o devdesc.o -HEXFILE=main.hex - -# symbolic targets: -all: $(HEXFILE) - -.c.o: - $(COMPILE) -c $< -o $@ - -.S.o: - $(COMPILE) -x assembler-with-cpp -c $< -o $@ -# "-x assembler-with-cpp" should not be necessary since this is the default -# file type for the .S (with capital S) extension. However, upper case -# characters are not always preserved on Windows. To ensure WinAVR -# compatibility define the file type manually. - -.c.s: - $(COMPILE) -S $< -o $@ - - -clean: - rm -f $(HEXFILE) main.lst main.obj main.cof main.list main.map main.eep.hex main.bin *.o usbdrv/*.o main.s usbdrv/oddebug.s usbdrv/usbdrv.s - -# file targets: -main.bin: $(COMMON_OBJS) fournsnes.o devdesc.o - $(COMPILE) -o main.bin $(OBJECTS) -Wl,-Map=main.map - -$(HEXFILE): main.bin - rm -f $(HEXFILE) main.eep.hex - avr-objcopy -j .text -j .data -O ihex main.bin $(HEXFILE) - ./checksize main.bin - -flash: all - #$(UISP) --erase --upload --verify if=$(HEXFILE) - $(UISP) --erase --upload if=$(HEXFILE) - -flash_usb: - sudo avrdude -p m8 -P usb -c avrispmkII -Uflash:w:$(HEXFILE) -B 1.0 - -# Fuse high byte: -# 0xc9 = 1 1 0 0 1 0 0 1 <-- BOOTRST (boot reset vector at 0x0000) -# ^ ^ ^ ^ ^ ^ ^------ BOOTSZ0 -# | | | | | +-------- BOOTSZ1 -# | | | | + --------- EESAVE (don't preserve EEPROM over chip erase) -# | | | +-------------- CKOPT (full output swing) -# | | +---------------- SPIEN (allow serial programming) -# | +------------------ WDTON (WDT not always on) -# +-------------------- RSTDISBL (reset pin is enabled) -# Fuse low byte: -# 0x9f = 1 0 0 1 1 1 1 1 -# ^ ^ \ / \--+--/ -# | | | +------- CKSEL 3..0 (external >8M crystal) -# | | +--------------- SUT 1..0 (crystal osc, BOD enabled) -# | +------------------ BODEN (BrownOut Detector enabled) -# +-------------------- BODLEVEL (2.7V) -fuse: - $(UISP) --wr_fuse_h=0xc9 --wr_fuse_l=0x9f - -fuse_usb: - sudo avrdude -p m8 -P usb -c avrispmkII -Uhfuse:w:0xc9:m -Ulfuse:w:0x9f:m -B 10.0 - - diff --git a/Makefile.atmega168 b/Makefile.atmega168 new file mode 100644 index 0000000..b15115a --- /dev/null +++ b/Makefile.atmega168 @@ -0,0 +1,71 @@ +CC=avr-gcc +AS=$(CC) +LD=$(CC) +PROGNAME=4nes4snes-m168 +CPU=atmega168 + +CFLAGS=-Wall -Os -Iusbdrv -I. -mmcu=$(CPU) -DF_CPU=12000000L #-DDEBUG_LEVEL=1 +LDFLAGS=-Wl,-Map=$(PROGNAME).map -mmcu=$(CPU) +AVRDUDE=avrdude -p m168 -P usb -c avrispmkII + +OBJS=usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o fournsnes.o devdesc.o + +HEXFILE=$(PROGNAME).hex +ELFFILE=$(PROGNAME).elf + +# symbolic targets: +all: $(HEXFILE) + +.c.o: + $(CC) $(CFLAGS) -c $< -o $@ + +.S.o: + $(CC) $(CFLAGS) -x assembler-with-cpp -c $< -o $@ +# "-x assembler-with-cpp" should not be necessary since this is the default +# file type for the .S (with capital S) extension. However, upper case +# characters are not always preserved on Windows. To ensure WinAVR +# compatibility define the file type manually. + +.c.s: + $(CC) $(CFLAGS) -S $< -o $@ + + +clean: + rm -f $(HEXFILE) main.lst main.obj main.cof main.list main.map main.eep.hex main.bin *.o usbdrv/*.o main.s usbdrv/oddebug.s usbdrv/usbdrv.s + +# file targets: +$(ELFFILE): $(OBJS) + $(LD) $(LDFLAGS) -o $(ELFFILE) $(OBJS) + +$(HEXFILE): $(ELFFILE) + rm -f $(HEXFILE) + avr-objcopy -j .text -j .data -O ihex $(ELFFILE) $(HEXFILE) + ./checksize $(ELFFILE) + + +flash: $(HEXFILE) + $(AVRDUDE) -Uflash:w:$(HEXFILE) -B 1.0 + +# - - - - - BOOTSZ1 BOOTSZ0 BOOTRST +# 0 0 0 0 0 0 0 1 +EFUSE=0x01 + +# RSTDISBL DWEN SPIEN WDTON EESAVE BODLEVEL2 BODLEVEL1 BODLEVEL0 +# 1 1 0 1 1 1 1 1 +HFUSE=0xd5 +# +# CKDIV8 CKOUT SUT1 SUT0 CKSEL3 CKSEL2 CKSEL1 CKSEL0 +# 1 1 0 1 0 1 1 1 +# +# Full swing crystal oscillator, BOD enabled +LFUSE=0xDF + +fuse: + $(AVRDUDE) -e -Uefuse:w:$(EFUSE):m -Uhfuse:w:$(HFUSE):m -Ulfuse:w:$(LFUSE):m -B 20.0 -v + +chip_erase: + $(AVRDUDE) -e -B 1.0 -F + +reset: + $(AVRDUDE) -B 1.0 -F + diff --git a/Makefile.atmega8 b/Makefile.atmega8 new file mode 100644 index 0000000..51255cf --- /dev/null +++ b/Makefile.atmega8 @@ -0,0 +1,77 @@ +CC=avr-gcc +AS=$(CC) +LD=$(CC) +PROGNAME=4nes4snes-m8 +CPU=atmega8 + +CFLAGS=-Wall -Os -Iusbdrv -I. -mmcu=$(CPU) -DF_CPU=12000000L #-DDEBUG_LEVEL=1 +LDFLAGS=-Wl,-Map=$(PROGNAME).map -mmcu=$(CPU) +AVRDUDE=avrdude -p m8 -P usb -c avrispmkII + +OBJS=usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o fournsnes.o devdesc.o + +HEXFILE=$(PROGNAME).hex +ELFFILE=$(PROGNAME).elf + +# symbolic targets: +all: $(HEXFILE) + +.c.o: + $(CC) $(CFLAGS) -c $< -o $@ + +.S.o: + $(CC) $(CFLAGS) -x assembler-with-cpp -c $< -o $@ +# "-x assembler-with-cpp" should not be necessary since this is the default +# file type for the .S (with capital S) extension. However, upper case +# characters are not always preserved on Windows. To ensure WinAVR +# compatibility define the file type manually. + +.c.s: + $(CC) $(CFLAGS) -S $< -o $@ + + +clean: + rm -f $(HEXFILE) main.lst main.obj main.cof main.list main.map main.eep.hex main.bin *.o usbdrv/*.o main.s usbdrv/oddebug.s usbdrv/usbdrv.s + +# file targets: +$(ELFFILE): $(OBJS) + $(LD) $(LDFLAGS) -o $(ELFFILE) $(OBJS) + +$(HEXFILE): $(ELFFILE) + rm -f $(HEXFILE) + avr-objcopy -j .text -j .data -O ihex $(ELFFILE) $(HEXFILE) + ./checksize $(ELFFILE) + + +flash: $(HEXFILE) + $(AVRDUDE) -Uflash:w:$(HEXFILE) -B 1.0 + +# Fuse high byte: +# 0xc9 = 1 1 0 0 1 0 0 1 <-- BOOTRST (boot reset vector at 0x0000) +# ^ ^ ^ ^ ^ ^ ^------ BOOTSZ0 +# | | | | | +-------- BOOTSZ1 +# | | | | + --------- EESAVE (don't preserve EEPROM over chip erase) +# | | | +-------------- CKOPT (full output swing) +# | | +---------------- SPIEN (allow serial programming) +# | +------------------ WDTON (WDT not always on) +# +-------------------- RSTDISBL (reset pin is enabled) +# Fuse low byte: +# 0x9f = 1 0 0 1 1 1 1 1 +# ^ ^ \ / \--+--/ +# | | | +------- CKSEL 3..0 (external >8M crystal) +# | | +--------------- SUT 1..0 (crystal osc, BOD enabled) +# | +------------------ BODEN (BrownOut Detector enabled) +# +-------------------- BODLEVEL (2.7V) + +LFUSE=0x9F +HFUSE=0xC9 + +fuse: + $(AVRDUDE) -e -Uhfuse:w:$(HFUSE):m -Ulfuse:w:$(LFUSE):m -B 20.0 -v + +chip_erase: + $(AVRDUDE) -e -B 1.0 -F + +reset: + $(AVRDUDE) -B 1.0 -F + diff --git a/Readme.txt b/Readme.txt index b872c2e..54b76b3 100644 --- a/Readme.txt +++ b/Readme.txt @@ -12,8 +12,8 @@ Table of contents: 1) What is 4nes4snes? -------------------- - 4nes4snes if a firmware for Atmel ATmega8 which - allows one to connect up to 4 NES and/or SNES + 4nes4snes if a firmware for Atmel ATmega8 and Atmega168* + which allows one to connect up to 4 NES and/or SNES controllers to a PC using a single circuit. The device connects to an USB port and appears to the @@ -21,6 +21,9 @@ Table of contents: that it looks like 4 controllers in Windows's control_panel->game_controllers window. +* Other devices from the same family are probably supported, but +not tested. + 2) USB Implementation ------------------ @@ -48,15 +51,13 @@ Table of contents: 4) License ------- - 4nes4snes is released under Objective Development's extended GPL - license. See License.txt + 4nes4snes is released under the GPLv2 license. See License.txt 5) About the vendor id/product id pair: ------------------------------------ - Please dont re-use them for other projects. Instead, - obtain your own. I got mine from mecanique: - http://www.mecanique.co.uk/products/usb/pid.html + Please do not re-use them for other projects. Instead, + obtain your own. 6) Where can I get more information and updates? diff --git a/main.c b/main.c index 3d7ab18..32284d1 100644 --- a/main.c +++ b/main.c @@ -14,7 +14,6 @@ #include #include "usbdrv.h" -#include "oddebug.h" #include "gamepad.h" #include "fournsnes.h" @@ -27,6 +26,15 @@ static uchar rt_usbHidReportDescriptorSize=0; static uchar *rt_usbDeviceDescriptor=NULL; static uchar rt_usbDeviceDescriptorSize=0; + +#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168A__) || \ + defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328__) || \ + defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88__) || \ + defined(__AVR_ATmega88A__) || defined(__AVR_ATmega88P__) || \ + defined(__AVR_ATmega88PA__) +#define AT168_COMPATIBLE +#endif + /* The maximum number of independent reports that are supported. */ #define MAX_REPORTS 8 @@ -118,14 +126,30 @@ static void hardwareInit(void) while(--i); /* delay >10ms for USB reset */ } DDRD = 0x00; /* 0000 0000 bin: remove USB reset condition */ - /* configure timer 0 for a rate of 12M/(1024 * 256) = 45.78 Hz (~22ms) */ - TCCR0 = 5; /* timer 0 prescaler: 1024 */ +#if defined(AT168_COMPATIBLE) + TCCR2A= (1<bmRequestType & USBRQ_TYPE_MASK) != USBRQ_TYPE_STANDARD) @@ -167,7 +189,6 @@ static uchar reportPos=0; uchar usbFunctionSetup(uchar data[8]) { usbRequest_t *rq = (void *)data; - int i; usbMsgPtr = reportBuffer; @@ -180,24 +201,6 @@ uchar usbFunctionSetup(uchar data[8]) reportPos=0; return curGamepad->buildReport(reportBuffer, rq->wValue.bytes[0]); - case USBRQ_HID_GET_IDLE: - if (rq->wValue.bytes[0] > 0 && rq->wValue.bytes[0] <= MAX_REPORTS) { - usbMsgPtr = idleRates + (rq->wValue.bytes[0] - 1); - return 1; - } - break; - - case USBRQ_HID_SET_IDLE: - if (rq->wValue.bytes[0]==0) { - for (i=0; iwValue.bytes[1]; - } - else { - if (rq->wValue.bytes[0] > 0 && rq->wValue.bytes[0] <= MAX_REPORTS) { - idleRates[rq->wValue.bytes[0]-1] = rq->wValue.bytes[1]; - } - } - break; } } else { /* no vendor specific requests implemented */ @@ -264,14 +267,11 @@ int main(void) //wdt_enable(WDTO_2S); hardwareInit(); curGamepad->init(); - odDebugInit(); usbInit(); curGamepad->update(); sei(); - DBG1(0x00, 0, 0); - for(;;){ /* main event loop */ wdt_reset(); @@ -280,10 +280,10 @@ int main(void) usbPoll(); /* Read the controllers at 60hz */ - if (TIFR & (1<update(); /* Check what will have to be reported */ @@ -294,27 +294,6 @@ int main(void) } } - /* Try to report at the granularity requested by - * the host. */ - if (TIFR & (1<num_reports; i++) - { - // 0 means - if(idleRates[i] != 0){ - if (idleCounters[i] > 4) { - idleCounters[i] -= 5; /* 22 ms in units of 4 ms */ - } else { - // reset the counter and schedule a report for this - idleCounters[i] = idleRates[i]; - must_report |= (1<