mirror of
https://github.com/raphnet/4nes4snes
synced 2024-11-14 13:05:03 -05:00
--- 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.
This commit is contained in:
parent
30ded39aad
commit
befc9be7f1
@ -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.
|
||||
|
||||
|
75
Makefile
75
Makefile
@ -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
|
||||
|
||||
|
71
Makefile.atmega168
Normal file
71
Makefile.atmega168
Normal file
@ -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
|
||||
|
77
Makefile.atmega8
Normal file
77
Makefile.atmega8
Normal file
@ -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
|
||||
|
15
Readme.txt
15
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?
|
||||
|
83
main.c
83
main.c
@ -14,7 +14,6 @@
|
||||
#include <string.h>
|
||||
|
||||
#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<<WGM21);
|
||||
TCCR2B=(1<<CS22)|(1<<CS21)|(1<<CS20);
|
||||
OCR2A=196; // for 60 hz
|
||||
#else
|
||||
TCCR2 = (1<<WGM21)|(1<<CS22)|(1<<CS21)|(1<<CS20);
|
||||
OCR2 = 196; // for 60 hz
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(AT168_COMPATIBLE)
|
||||
|
||||
#define mustPollControllers() (TIFR2 & (1<<OCF2A))
|
||||
#define clrPollControllers() do { TIFR2 = 1<<OCF2A; } while(0)
|
||||
|
||||
#else
|
||||
|
||||
#define mustPollControllers() (TIFR & (1<<OCF2))
|
||||
#define clrPollControllers() do { TIFR = 1<<OCF2; } while(0)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static uchar reportBuffer[12]; /* buffer for HID reports */
|
||||
|
||||
|
||||
@ -134,8 +158,6 @@ static uchar reportBuffer[12]; /* buffer for HID reports */
|
||||
/* ----------------------------- USB interface ----------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static uchar idleRates[MAX_REPORTS]; /* in 4 ms units */
|
||||
|
||||
uchar usbFunctionDescriptor(struct usbRequest *rq)
|
||||
{
|
||||
if ((rq->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; i<MAX_REPORTS; i++)
|
||||
idleRates[i] = rq->wValue.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<<OCF2))
|
||||
if (mustPollControllers())
|
||||
{
|
||||
TIFR = 1<<OCF2;
|
||||
|
||||
clrPollControllers();
|
||||
|
||||
curGamepad->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<<TOV0)) { /* 22 ms timer */
|
||||
TIFR = 1<<TOV0;
|
||||
|
||||
for (i=0; i<curGamepad->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<<i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(must_report)
|
||||
{
|
||||
|
19
usbconfig.h
19
usbconfig.h
@ -5,7 +5,7 @@
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: usbconfig.h,v 1.8 2012-04-09 04:05:43 cvs Exp $
|
||||
* This Revision: $Id: usbconfig.h,v 1.9 2013-04-20 17:24:53 cvs Exp $
|
||||
*/
|
||||
|
||||
#ifndef __usbconfig_h_included__
|
||||
@ -129,21 +129,12 @@ rename it to "usbconfig.h". Then edit it accordingly.
|
||||
|
||||
/* -------------------------- Device Description --------------------------- */
|
||||
|
||||
/* This vendor ID comes from "Mecanique" which used to sale
|
||||
* ranges of product IDs. */
|
||||
#define USB_CFG_VENDOR_ID 0x81, 0x17
|
||||
|
||||
/* This product ID is registered to the author. If you change the code
|
||||
* and wish to distribute it, please obtain and use your own VID/PID. Otherwise,
|
||||
* there are serious compatibility and conflict risks, under Windows
|
||||
* in particular.
|
||||
*
|
||||
* See the technical notes in usbdrv/USBID-License.txt for more details.
|
||||
*/
|
||||
#define USB_CFG_DEVICE_ID 0x9d, 0x0a
|
||||
/* This is the Dracal technnologies inc. (Raphnet technologies) VID */
|
||||
#define USB_CFG_VENDOR_ID 0x8B, 0x28
|
||||
#define USB_CFG_DEVICE_ID 0x03, 0x00
|
||||
|
||||
|
||||
#define USB_CFG_DEVICE_VERSION 0x03, 0x01
|
||||
#define USB_CFG_DEVICE_VERSION 0x04, 0x01
|
||||
/* Version number of the device: Minor number first, then major number.
|
||||
*/
|
||||
#define USB_CFG_VENDOR_NAME 'r', 'a', 'p', 'h', 'n', 'e', 't', '.', 'n', 'e', 't'
|
||||
|
Loading…
Reference in New Issue
Block a user