├── .gitignore ├── README.md ├── n64.h ├── gc_kb.h ├── gamecube.h ├── calibration_fixer ├── src │ ├── gc_calfix_ng.exe │ ├── changelog.txt │ ├── Makefile │ └── gc_cal_fix.cpp └── readme.txt ├── schematics └── readme.txt ├── Makefile ├── devdesc.h ├── reportdesc.h ├── leds.h ├── gamepad.h ├── usbdrv ├── usbdrvasm.asm ├── oddebug.c ├── oddebug.h ├── usbportability.h ├── USB-ID-FAQ.txt ├── USB-IDs-for-free.txt ├── CommercialLicense.txt ├── asmcommon.inc ├── Readme.txt ├── usbdrvasm.S ├── usbdrvasm16.inc ├── Changelog.txt ├── usbdrvasm20.inc ├── usbdrvasm12.inc └── usbdrvasm165.inc ├── devdesc.c ├── Makefile.atmega88 ├── Makefile.atmega168 ├── Makefile.atmega88p ├── Makefile.atmega8 ├── hid_keycodes.h ├── Changelog.txt ├── gamecube.c ├── gcn64_protocol.h ├── gc_kb.c ├── n64.c └── gcn64_protocol.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.hex 3 | *.bin 4 | *.elf 5 | *.map 6 | *.swp 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raphnet/gc_n64_usb/HEAD/README.md -------------------------------------------------------------------------------- /n64.h: -------------------------------------------------------------------------------- 1 | #include "gamepad.h" 2 | 3 | Gamepad *n64GetGamepad(void); 4 | 5 | -------------------------------------------------------------------------------- /gc_kb.h: -------------------------------------------------------------------------------- 1 | #include "gamepad.h" 2 | 3 | Gamepad *gc_kb_getGamepad(void); 4 | 5 | -------------------------------------------------------------------------------- /gamecube.h: -------------------------------------------------------------------------------- 1 | #include "gamepad.h" 2 | 3 | Gamepad *gamecubeGetGamepad(void); 4 | 5 | -------------------------------------------------------------------------------- /calibration_fixer/src/gc_calfix_ng.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raphnet/gc_n64_usb/HEAD/calibration_fixer/src/gc_calfix_ng.exe -------------------------------------------------------------------------------- /schematics/readme.txt: -------------------------------------------------------------------------------- 1 | For the latest schematics, please visit: 2 | http://www.raphnet.net/electronique/gc_n64_usb/index_en.php 3 | 4 | 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | @echo "Please use Makefile.atmega8 or Makefile.atmega168." 3 | @echo 4 | @echo "Example: make -f Makefile.atmega168" 5 | 6 | clean: 7 | make -f Makefile.atmega168 clean 8 | make -f Makefile.atmega8 clean 9 | -------------------------------------------------------------------------------- /devdesc.h: -------------------------------------------------------------------------------- 1 | #ifndef _devdesc_h__ 2 | #define _devdesc_h__ 3 | 4 | #include 5 | 6 | extern const char usbDescrDevice[] PROGMEM; 7 | int getUsbDescrDevice_size(void); 8 | 9 | #endif // _devdesc_h__ 10 | 11 | -------------------------------------------------------------------------------- /calibration_fixer/src/changelog.txt: -------------------------------------------------------------------------------- 1 | - Versino 1.3 (2013-11-24) 2 | * Added support for GCN64-USB v2.9 3 | * Exit after displaying help (-h) 4 | 5 | - Version 1.2 (2013-06-24) 6 | * Added support for GCN64-USB v2.3 7 | 8 | 9 | -------------------------------------------------------------------------------- /reportdesc.h: -------------------------------------------------------------------------------- 1 | #ifndef _reportdesc_h__ 2 | #define _reportdesc_h__ 3 | 4 | #include 5 | 6 | #define GCN64_REPORT_SIZE 9 7 | 8 | extern const char gcn64_usbHidReportDescriptor[] PROGMEM; 9 | int getUsbHidReportDescriptor_size(void); 10 | 11 | #endif // _reportdesc_h__ 12 | 13 | -------------------------------------------------------------------------------- /calibration_fixer/src/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CPP=g++ 3 | LD=$(CPP) 4 | 5 | DX_INCLUDE_PATH=/c/dx9sdk/Include 6 | DX_LIBS=/c/dx9sdk/Lib/x86/dinput8.lib /c/dx9sdk/Lib/x86/dxguid.lib 7 | 8 | CFLAGS=-Wall -I$(DX_INCLUDE_PATH) 9 | CPPFLAGS=$(CFLAGS) 10 | LDFLAGS=$(DX_LIBS) -static 11 | 12 | gc_calfix_ng: gc_cal_fix.o 13 | $(LD) $^ -o $@ $(LDFLAGS) 14 | 15 | clean: 16 | rm gc_calfix_ng.exe 17 | -------------------------------------------------------------------------------- /leds.h: -------------------------------------------------------------------------------- 1 | #ifndef _leds_h__ 2 | #define _leds_h__ 3 | 4 | #ifndef PORTD 5 | #include 6 | #endif 7 | 8 | 9 | #define LED_OFF() 10 | #define LED_ON(); 11 | #define LED_TOGGLE(); 12 | 13 | //#define LED_OFF() do { PORTD |= 0x20; } while(0) 14 | //#define LED_ON() do { PORTD &= ~0x20; } while(0) 15 | //#define LED_TOGGLE() do { PORTD ^= 0x20; } while(0) 16 | 17 | #endif 18 | 19 | -------------------------------------------------------------------------------- /calibration_fixer/readme.txt: -------------------------------------------------------------------------------- 1 | The L and R sliders don't have a central resting position. This 2 | will cause many games to think they are active, which causes 3 | problem when performing button assignments. 4 | 5 | The tool provided here patches the calibration data in a way 6 | that makes the idle position appear central to the computer. 7 | Execute it _after_ completing the normal windows calibration 8 | procdure. 9 | 10 | You need to run the patch again every time you recalibrate 11 | using the windows tool. 12 | -------------------------------------------------------------------------------- /gamepad.h: -------------------------------------------------------------------------------- 1 | #ifndef _gamepad_h__ 2 | #define _gamepad_h__ 3 | 4 | typedef struct { 5 | int num_reports; 6 | 7 | int reportDescriptorSize; 8 | void *reportDescriptor; // must be in flash 9 | 10 | int deviceDescriptorSize; // if 0, use default 11 | void *deviceDescriptor; // must be in flash 12 | 13 | void (*init)(void); 14 | char (*update)(void); 15 | char (*changed)(int id); 16 | int (*buildReport)(unsigned char *buf, int id); 17 | void (*setVibration)(int value); 18 | 19 | /* Check for the controller */ 20 | char (*probe)(void); /* return true if found */ 21 | } Gamepad; 22 | 23 | #endif // _gamepad_h__ 24 | 25 | 26 | -------------------------------------------------------------------------------- /usbdrv/usbdrvasm.asm: -------------------------------------------------------------------------------- 1 | /* Name: usbdrvasm.asm 2 | * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers 3 | * Author: Christian Starkjohann 4 | * Creation Date: 2006-03-01 5 | * Tabsize: 4 6 | * Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH 7 | * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) 8 | */ 9 | 10 | /* 11 | General Description: 12 | The IAR compiler/assembler system prefers assembler files with file extension 13 | ".asm". We simply provide this file as an alias for usbdrvasm.S. 14 | 15 | Thanks to Oleg Semyonov for his help with the IAR tools port! 16 | */ 17 | 18 | #include "usbdrvasm.S" 19 | 20 | end 21 | -------------------------------------------------------------------------------- /devdesc.c: -------------------------------------------------------------------------------- 1 | #include "devdesc.h" 2 | #include "usbconfig.h" 3 | 4 | #define USBDESCR_DEVICE 1 5 | 6 | const char usbDescrDevice[] PROGMEM = { /* USB device descriptor */ 7 | 18, /* sizeof(usbDescrDevice): length of descriptor in bytes */ 8 | USBDESCR_DEVICE, /* descriptor type */ 9 | 0x01, 0x01, /* USB version supported */ 10 | USB_CFG_DEVICE_CLASS, 11 | USB_CFG_DEVICE_SUBCLASS, 12 | 0, /* protocol */ 13 | 8, /* max packet size */ 14 | USB_CFG_VENDOR_ID, /* 2 bytes */ 15 | USB_CFG_DEVICE_ID, /* 2 bytes */ 16 | USB_CFG_DEVICE_VERSION, /* 2 bytes */ 17 | 1, /* manufacturer string index */ 18 | 2, /* product string index */ 19 | 3, /* serial number string index */ 20 | 1, /* number of configurations */ 21 | }; 22 | 23 | int getUsbDescrDevice_size(void) { return sizeof(usbDescrDevice); } 24 | 25 | -------------------------------------------------------------------------------- /usbdrv/oddebug.c: -------------------------------------------------------------------------------- 1 | /* Name: oddebug.c 2 | * Project: AVR library 3 | * Author: Christian Starkjohann 4 | * Creation Date: 2005-01-16 5 | * Tabsize: 4 6 | * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH 7 | * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) 8 | */ 9 | 10 | #include "oddebug.h" 11 | 12 | #if DEBUG_LEVEL > 0 13 | 14 | #warning "Never compile production devices with debugging enabled" 15 | 16 | static void uartPutc(char c) 17 | { 18 | while(!(ODDBG_USR & (1 << ODDBG_UDRE))); /* wait for data register empty */ 19 | ODDBG_UDR = c; 20 | } 21 | 22 | static uchar hexAscii(uchar h) 23 | { 24 | h &= 0xf; 25 | if(h >= 10) 26 | h += 'a' - (uchar)10 - '0'; 27 | h += '0'; 28 | return h; 29 | } 30 | 31 | static void printHex(uchar c) 32 | { 33 | uartPutc(hexAscii(c >> 4)); 34 | uartPutc(hexAscii(c)); 35 | } 36 | 37 | void odDebug(uchar prefix, uchar *data, uchar len) 38 | { 39 | printHex(prefix); 40 | uartPutc(':'); 41 | while(len--){ 42 | uartPutc(' '); 43 | printHex(*data++); 44 | } 45 | uartPutc('\r'); 46 | uartPutc('\n'); 47 | } 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /Makefile.atmega88: -------------------------------------------------------------------------------- 1 | CC=avr-gcc 2 | AS=$(CC) 3 | LD=$(CC) 4 | PROGNAME=gc_n64_usb-m88 5 | CPU=atmega88 6 | 7 | CFLAGS=-Wall -Os -Iusbdrv -I. -mmcu=$(CPU) -DF_CPU=12000000L #-DDEBUG_LEVEL=1 8 | LDFLAGS=-Wl,-Map=$(PROGNAME).map -mmcu=$(CPU) 9 | AVRDUDE=avrdude -p m88 -P usb -c avrispmkII 10 | 11 | OBJS=usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o gcn64_protocol.o gamecube.o n64.o devdesc.o reportdesc.o gc_kb.o 12 | 13 | HEXFILE=$(PROGNAME).hex 14 | ELFFILE=$(PROGNAME).elf 15 | 16 | # symbolic targets: 17 | all: $(HEXFILE) 18 | 19 | .c.o: 20 | $(CC) $(CFLAGS) -c $< -o $@ 21 | 22 | .S.o: 23 | $(CC) $(CFLAGS) -x assembler-with-cpp -c $< -o $@ 24 | # "-x assembler-with-cpp" should not be necessary since this is the default 25 | # file type for the .S (with capital S) extension. However, upper case 26 | # characters are not always preserved on Windows. To ensure WinAVR 27 | # compatibility define the file type manually. 28 | 29 | .c.s: 30 | $(CC) $(CFLAGS) -S $< -o $@ 31 | 32 | 33 | clean: 34 | 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 35 | 36 | # file targets: 37 | $(ELFFILE): $(OBJS) 38 | $(LD) $(LDFLAGS) -o $(ELFFILE) $(OBJS) 39 | 40 | $(HEXFILE): $(ELFFILE) 41 | rm -f $(HEXFILE) 42 | avr-objcopy -j .text -j .data -O ihex $(ELFFILE) $(HEXFILE) 43 | avr-size $(ELFFILE) 44 | 45 | 46 | flash: $(HEXFILE) 47 | $(AVRDUDE) -Uflash:w:$(HEXFILE) -B 1.0 48 | 49 | # Extended fuse byte (Datasheet Table 28-5) 50 | # 51 | # - - - - - BOOTSZ1 BOOTSZ0 BOOTRST 52 | # 0 0 0 0 0 0 0 1 53 | # 54 | EFUSE=0x01 55 | 56 | # Fuse high byte (Datasheet Table 28-6) 57 | # 58 | # RSTDISBL DWEN SPIEN WDTON EESAVE BODLEVEL2 BODLEVEL1 BODLEVEL0 59 | # 1 1 0 1 0 1 0 1 60 | # 61 | HFUSE=0xd5 62 | 63 | # Fuse low byte (Datasheet Table 28-7) 64 | # 65 | # CKDIV8 CKOUT SUT1 SUT0 CKSEL3 CKSEL2 CKSEL1 CKSEL0 66 | # 1 1 0 1 0 1 1 1 67 | # 68 | # Full swing crystal oscillator 69 | # 0.4 - 20 MHz : CKSEL3..1 011 70 | # 71 | # Crystal Oscillator, BOD enabled (Table 9-6) 72 | # CKSEL0 : 1 73 | # SUT1..0 : 01 74 | # 75 | LFUSE=0xD7 76 | 77 | fuse: 78 | $(AVRDUDE) -e -Uefuse:w:$(EFUSE):m -Uhfuse:w:$(HFUSE):m -Ulfuse:w:$(LFUSE):m -B 20.0 -v 79 | 80 | chip_erase: 81 | $(AVRDUDE) -e -B 1.0 -F 82 | 83 | reset: 84 | $(AVRDUDE) -B 1.0 -F 85 | 86 | -------------------------------------------------------------------------------- /Makefile.atmega168: -------------------------------------------------------------------------------- 1 | CC=avr-gcc 2 | AS=$(CC) 3 | LD=$(CC) 4 | PROGNAME=gc_n64_usb-m168 5 | CPU=atmega168 6 | 7 | CFLAGS=-Wall -Os -Iusbdrv -I. -mmcu=$(CPU) -DF_CPU=12000000L #-DDEBUG_LEVEL=1 8 | LDFLAGS=-Wl,-Map=$(PROGNAME).map -mmcu=$(CPU) 9 | AVRDUDE=avrdude -p m168 -P usb -c avrispmkII 10 | 11 | OBJS=usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o gcn64_protocol.o gamecube.o n64.o devdesc.o reportdesc.o gc_kb.o 12 | 13 | HEXFILE=$(PROGNAME).hex 14 | ELFFILE=$(PROGNAME).elf 15 | 16 | # symbolic targets: 17 | all: $(HEXFILE) 18 | 19 | .c.o: 20 | $(CC) $(CFLAGS) -c $< -o $@ 21 | 22 | .S.o: 23 | $(CC) $(CFLAGS) -x assembler-with-cpp -c $< -o $@ 24 | # "-x assembler-with-cpp" should not be necessary since this is the default 25 | # file type for the .S (with capital S) extension. However, upper case 26 | # characters are not always preserved on Windows. To ensure WinAVR 27 | # compatibility define the file type manually. 28 | 29 | .c.s: 30 | $(CC) $(CFLAGS) -S $< -o $@ 31 | 32 | 33 | clean: 34 | 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 35 | 36 | # file targets: 37 | $(ELFFILE): $(OBJS) 38 | $(LD) $(LDFLAGS) -o $(ELFFILE) $(OBJS) 39 | 40 | $(HEXFILE): $(ELFFILE) 41 | rm -f $(HEXFILE) 42 | avr-objcopy -j .text -j .data -O ihex $(ELFFILE) $(HEXFILE) 43 | avr-size $(ELFFILE) 44 | 45 | 46 | flash: $(HEXFILE) 47 | $(AVRDUDE) -Uflash:w:$(HEXFILE) -B 1.0 48 | 49 | # Extended fuse byte (Datasheet Table 28-5) 50 | # 51 | # - - - - - BOOTSZ1 BOOTSZ0 BOOTRST 52 | # 0 0 0 0 0 0 0 1 53 | # 54 | EFUSE=0x01 55 | 56 | # Fuse high byte (Datasheet Table 28-6) 57 | # 58 | # RSTDISBL DWEN SPIEN WDTON EESAVE BODLEVEL2 BODLEVEL1 BODLEVEL0 59 | # 1 1 0 1 0 1 0 1 60 | # 61 | HFUSE=0xd5 62 | 63 | # Fuse low byte (Datasheet Table 28-7) 64 | # 65 | # CKDIV8 CKOUT SUT1 SUT0 CKSEL3 CKSEL2 CKSEL1 CKSEL0 66 | # 1 1 0 1 0 1 1 1 67 | # 68 | # Full swing crystal oscillator 69 | # 0.4 - 20 MHz : CKSEL3..1 011 70 | # 71 | # Crystal Oscillator, BOD enabled (Table 9-6) 72 | # CKSEL0 : 1 73 | # SUT1..0 : 01 74 | # 75 | LFUSE=0xD7 76 | 77 | fuse: 78 | $(AVRDUDE) -e -Uefuse:w:$(EFUSE):m -Uhfuse:w:$(HFUSE):m -Ulfuse:w:$(LFUSE):m -B 20.0 -v 79 | 80 | chip_erase: 81 | $(AVRDUDE) -e -B 1.0 -F 82 | 83 | reset: 84 | $(AVRDUDE) -B 1.0 -F 85 | 86 | -------------------------------------------------------------------------------- /Makefile.atmega88p: -------------------------------------------------------------------------------- 1 | CC=avr-gcc 2 | AS=$(CC) 3 | LD=$(CC) 4 | PROGNAME=gc_n64_usb-m88p 5 | CPU=atmega88p 6 | 7 | CFLAGS=-Wall -Os -Iusbdrv -I. -mmcu=$(CPU) -DF_CPU=12000000L #-DDEBUG_LEVEL=1 8 | LDFLAGS=-Wl,-Map=$(PROGNAME).map -mmcu=$(CPU) 9 | AVRDUDE=avrdude -p m88p -P usb -c avrispmkII 10 | 11 | OBJS=usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o gcn64_protocol.o gamecube.o n64.o devdesc.o reportdesc.o gc_kb.o 12 | 13 | HEXFILE=$(PROGNAME).hex 14 | ELFFILE=$(PROGNAME).elf 15 | 16 | # symbolic targets: 17 | all: $(HEXFILE) 18 | 19 | .c.o: 20 | $(CC) $(CFLAGS) -c $< -o $@ 21 | 22 | .S.o: 23 | $(CC) $(CFLAGS) -x assembler-with-cpp -c $< -o $@ 24 | # "-x assembler-with-cpp" should not be necessary since this is the default 25 | # file type for the .S (with capital S) extension. However, upper case 26 | # characters are not always preserved on Windows. To ensure WinAVR 27 | # compatibility define the file type manually. 28 | 29 | .c.s: 30 | $(CC) $(CFLAGS) -S $< -o $@ 31 | 32 | 33 | clean: 34 | 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 35 | 36 | # file targets: 37 | $(ELFFILE): $(OBJS) 38 | $(LD) $(LDFLAGS) -o $(ELFFILE) $(OBJS) 39 | 40 | $(HEXFILE): $(ELFFILE) 41 | rm -f $(HEXFILE) 42 | avr-objcopy -j .text -j .data -O ihex $(ELFFILE) $(HEXFILE) 43 | avr-size $(ELFFILE) 44 | 45 | 46 | flash: $(HEXFILE) 47 | $(AVRDUDE) -Uflash:w:$(HEXFILE) -B 1.0 48 | 49 | # Extended fuse byte (Datasheet Table 28-5) 50 | # 51 | # - - - - - BOOTSZ1 BOOTSZ0 BOOTRST 52 | # 0 0 0 0 0 0 0 1 53 | # 54 | EFUSE=0x01 55 | 56 | # Fuse high byte (Datasheet Table 28-6) 57 | # 58 | # RSTDISBL DWEN SPIEN WDTON EESAVE BODLEVEL2 BODLEVEL1 BODLEVEL0 59 | # 1 1 0 1 0 1 0 1 60 | # 61 | HFUSE=0xd5 62 | 63 | # Fuse low byte (Datasheet Table 28-7) 64 | # 65 | # CKDIV8 CKOUT SUT1 SUT0 CKSEL3 CKSEL2 CKSEL1 CKSEL0 66 | # 1 1 0 1 0 1 1 1 67 | # 68 | # Full swing crystal oscillator 69 | # 0.4 - 20 MHz : CKSEL3..1 011 70 | # 71 | # Crystal Oscillator, BOD enabled (Table 9-6) 72 | # CKSEL0 : 1 73 | # SUT1..0 : 01 74 | # 75 | LFUSE=0xD7 76 | 77 | fuse: 78 | $(AVRDUDE) -e -Uefuse:w:$(EFUSE):m -Uhfuse:w:$(HFUSE):m -Ulfuse:w:$(LFUSE):m -B 20.0 -v 79 | 80 | chip_erase: 81 | $(AVRDUDE) -e -B 1.0 -F 82 | 83 | reset: 84 | $(AVRDUDE) -B 1.0 -F 85 | 86 | -------------------------------------------------------------------------------- /Makefile.atmega8: -------------------------------------------------------------------------------- 1 | # Name: Makefile 2 | # Project: HIDKeys 3 | # Author: Christian Starkjohann 4 | # Creation Date: 2006-02-02 5 | # Tabsize: 4 6 | # Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH 7 | # License: Proprietary, free under certain conditions. See Documentation. 8 | # This Revision: $Id: Makefile.atmega8,v 1.2 2013-11-09 15:20:06 cvs Exp $ 9 | 10 | UISP = uisp -dprog=stk500 -dpart=atmega8 -dserial=/dev/avr 11 | COMPILE = avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega8 -DF_CPU=12000000L #-DDEBUG_LEVEL=1 12 | OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o devdesc.o gamecube.o n64.o reportdesc.o gcn64_protocol.o gc_kb.o 13 | 14 | 15 | # symbolic targets: 16 | all: gc_n64_usb.hex 17 | 18 | .c.o: 19 | $(COMPILE) -c $< -o $@ 20 | 21 | .S.o: 22 | $(COMPILE) -x assembler-with-cpp -c $< -o $@ 23 | # "-x assembler-with-cpp" should not be necessary since this is the default 24 | # file type for the .S (with capital S) extension. However, upper case 25 | # characters are not always preserved on Windows. To ensure WinAVR 26 | # compatibility define the file type manually. 27 | 28 | .c.s: 29 | $(COMPILE) -S $< -o $@ 30 | 31 | 32 | clean: 33 | rm -f gc_n64_usb.hex gc_n64_usb.lst gc_n64_usb.obj gc_n64_usb.cof gc_n64_usb.list gc_n64_usb.map gc_n64_usb.eep.hex gc_n64_usb.bin *.o usbdrv/*.o gc_n64_usb.s usbdrv/oddebug.s usbdrv/usbdrv.s 34 | 35 | # file targets: 36 | gc_n64_usb.bin: $(OBJECTS) gamecube.o devdesc.o 37 | $(COMPILE) -o gc_n64_usb.bin $(OBJECTS) -Wl,-Map=gc_n64_usb.map 38 | 39 | gc_n64_usb.hex: gc_n64_usb.bin 40 | rm -f gc_n64_usb.hex gc_n64_usb.eep.hex 41 | avr-objcopy -j .text -j .data -O ihex gc_n64_usb.bin gc_n64_usb.hex 42 | avr-size gc_n64_usb.bin 43 | @echo -n "Report descriptor size:" 44 | @nm -S reportdesc.o | grep gcn64_usbHidReportDescriptor | cut -d ' ' -f 2 45 | 46 | flash: all 47 | #$(UISP) --erase --upload --verify if=gc_n64_usb.hex 48 | $(UISP) --erase --upload if=gc_n64_usb.hex 49 | 50 | flash_usb: all 51 | avrdude -p m8 -P usb -c avrispmkII -Uflash:w:gc_n64_usb.hex -B 1.0 52 | 53 | # Fuse high byte: 54 | # 0xc9 = 1 1 0 0 1 0 0 1 <-- BOOTRST (boot reset vector at 0x0000) 55 | # ^ ^ ^ ^ ^ ^ ^------ BOOTSZ0 56 | # | | | | | +-------- BOOTSZ1 57 | # | | | | + --------- EESAVE (don't preserve EEPROM over chip erase) 58 | # | | | +-------------- CKOPT (full output swing) 59 | # | | +---------------- SPIEN (allow serial programming) 60 | # | +------------------ WDTON (WDT not always on) 61 | # +-------------------- RSTDISBL (reset pin is enabled) 62 | # Fuse low byte: 63 | # 0x9f = 1 0 0 1 1 1 1 1 64 | # ^ ^ \ / \--+--/ 65 | # | | | +------- CKSEL 3..0 (external >8M crystal) 66 | # | | +--------------- SUT 1..0 (crystal osc, BOD enabled) 67 | # | +------------------ BODEN (BrownOut Detector enabled) 68 | # +-------------------- BODLEVEL (2.7V) 69 | fuse: 70 | $(UISP) --wr_fuse_h=0xc9 --wr_fuse_l=0x9f 71 | 72 | fuse_usb: 73 | avrdude -p m8 -P usb -c avrispmkII -Uhfuse:w:0xc9:m -Ulfuse:w:0x9f:m -B 10.0 74 | 75 | 76 | -------------------------------------------------------------------------------- /hid_keycodes.h: -------------------------------------------------------------------------------- 1 | #ifndef _hid_keycodes_h__ 2 | #define _hid_keycodes_h__ 3 | 4 | /* From Hut1_12.pdf : Universal Serial Bus HID Usage Tables, 5 | * section 10 Keyboard/Keypad Page (0x07) */ 6 | 7 | #define HID_KB_NOEVENT 0x00 8 | 9 | #define HID_KB_A 0x04 10 | #define HID_KB_B 0x05 11 | #define HID_KB_C 0x06 12 | #define HID_KB_D 0x07 13 | #define HID_KB_E 0x08 14 | #define HID_KB_F 0x09 15 | #define HID_KB_G 0x0a 16 | #define HID_KB_H 0x0b 17 | #define HID_KB_I 0x0c 18 | #define HID_KB_J 0x0d 19 | #define HID_KB_K 0x0e 20 | #define HID_KB_L 0x0f 21 | #define HID_KB_M 0x10 22 | #define HID_KB_N 0x11 23 | #define HID_KB_O 0x12 24 | #define HID_KB_P 0x13 25 | #define HID_KB_Q 0x14 26 | #define HID_KB_R 0x15 27 | #define HID_KB_S 0x16 28 | #define HID_KB_T 0x17 29 | #define HID_KB_U 0x18 30 | #define HID_KB_V 0x19 31 | #define HID_KB_W 0x1a 32 | #define HID_KB_X 0x1b 33 | #define HID_KB_Y 0x1c 34 | #define HID_KB_Z 0x1d 35 | 36 | #define HID_KB_1 0x1e 37 | #define HID_KB_2 0x1f 38 | #define HID_KB_3 0x20 39 | #define HID_KB_4 0x21 40 | #define HID_KB_5 0x22 41 | #define HID_KB_6 0x23 42 | #define HID_KB_7 0x24 43 | #define HID_KB_8 0x25 44 | #define HID_KB_9 0x26 45 | #define HID_KB_0 0x27 46 | 47 | #define HID_KB_ESCAPE 0x29 48 | #define HID_KB_BACKSPACE 0x2a 49 | #define HID_KB_TAB 0x2b 50 | 51 | #define HID_KB_SPACE 0x2c 52 | #define HID_KB_DASH_UNDERSCORE 0x2d 53 | #define HID_KB_EQUAL_PLUS 0x2e 54 | #define HID_KB_OPEN_BRKT_BRACE 0x2f 55 | 56 | #define HID_KB_CLOSE_BRKT_BRACE 0x30 57 | #define HID_KB_NONUS_HASH_TILDE 0x32 58 | #define HID_KB_SEMI_COLON_COLON 0x33 59 | #define HID_KB_QUOTES 0x34 60 | #define HID_KB_GRAVE_ACCENT_AND_TILDE 0x35 61 | #define HID_KB_COMMA_SMALLER_THAN 0x36 62 | #define HID_KB_PERIOD_GREATER_THAN 0x37 63 | #define HID_KB_SLASH_QUESTION 0x38 64 | #define HID_KB_CAPS_LOCK 0x39 65 | 66 | #define HID_KB_F1 0x3a 67 | #define HID_KB_F2 0x3b 68 | #define HID_KB_F3 0x3c 69 | #define HID_KB_F4 0x3d 70 | #define HID_KB_F5 0x3e 71 | #define HID_KB_F6 0x3f 72 | #define HID_KB_F7 0x40 73 | #define HID_KB_F8 0x41 74 | #define HID_KB_F9 0x42 75 | #define HID_KB_F10 0x43 76 | #define HID_KB_F11 0x44 77 | #define HID_KB_F12 0x45 78 | 79 | #define HID_KB_SCROLL_LOCK 0x47 80 | #define HID_KB_INSERT 0x49 81 | #define HID_KB_HOME 0x4a 82 | #define HID_KB_PGUP 0x4b 83 | #define HID_KB_DELETE_FORWARD 0x4c 84 | #define HID_KB_END 0x4d 85 | #define HID_KB_PGDN 0x4e 86 | 87 | #define HID_KB_RIGHT_ARROW 0x4f 88 | #define HID_KB_LEFT_ARROW 0x50 89 | #define HID_KB_DOWN_ARROW 0x51 90 | #define HID_KB_UP_ARROW 0x52 91 | 92 | #define HID_KB_ENTER 0x58 93 | 94 | #define HID_KB_INTERNATIONAL1 0x87 95 | #define HID_KB_INTERNATIONAL2 0x88 96 | #define HID_KB_INTERNATIONAL3 0x89 97 | #define HID_KB_INTERNATIONAL4 0x8a 98 | #define HID_KB_INTERNATIONAL5 0x8b 99 | 100 | #define HID_KB_LEFT_CONTROL 0xe0 101 | #define HID_KB_LEFT_SHIFT 0xe1 102 | #define HID_KB_LEFT_ALT 0xe2 103 | #define HID_KB_LEFT_GUI 0xe3 104 | #define HID_KB_RIGHT_CONTROL 0xe4 105 | #define HID_KB_RIGHT_SHIFT 0xe5 106 | #define HID_KB_RIGHT_ALT 0xe6 107 | #define HID_KB_RIGHT_GUI 0xe7 108 | 109 | #endif // _hid_keycodes_h__ 110 | 111 | -------------------------------------------------------------------------------- /usbdrv/oddebug.h: -------------------------------------------------------------------------------- 1 | /* Name: oddebug.h 2 | * Project: AVR library 3 | * Author: Christian Starkjohann 4 | * Creation Date: 2005-01-16 5 | * Tabsize: 4 6 | * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH 7 | * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) 8 | */ 9 | 10 | #ifndef __oddebug_h_included__ 11 | #define __oddebug_h_included__ 12 | 13 | /* 14 | General Description: 15 | This module implements a function for debug logs on the serial line of the 16 | AVR microcontroller. Debugging can be configured with the define 17 | 'DEBUG_LEVEL'. If this macro is not defined or defined to 0, all debugging 18 | calls are no-ops. If it is 1, DBG1 logs will appear, but not DBG2. If it is 19 | 2, DBG1 and DBG2 logs will be printed. 20 | 21 | A debug log consists of a label ('prefix') to indicate which debug log created 22 | the output and a memory block to dump in hex ('data' and 'len'). 23 | */ 24 | 25 | 26 | #ifndef F_CPU 27 | # define F_CPU 12000000 /* 12 MHz */ 28 | #endif 29 | 30 | /* make sure we have the UART defines: */ 31 | #include "usbportability.h" 32 | 33 | #ifndef uchar 34 | # define uchar unsigned char 35 | #endif 36 | 37 | #if DEBUG_LEVEL > 0 && !(defined TXEN || defined TXEN0) /* no UART in device */ 38 | # warning "Debugging disabled because device has no UART" 39 | # undef DEBUG_LEVEL 40 | #endif 41 | 42 | #ifndef DEBUG_LEVEL 43 | # define DEBUG_LEVEL 0 44 | #endif 45 | 46 | /* ------------------------------------------------------------------------- */ 47 | 48 | #if DEBUG_LEVEL > 0 49 | # define DBG1(prefix, data, len) odDebug(prefix, data, len) 50 | #else 51 | # define DBG1(prefix, data, len) 52 | #endif 53 | 54 | #if DEBUG_LEVEL > 1 55 | # define DBG2(prefix, data, len) odDebug(prefix, data, len) 56 | #else 57 | # define DBG2(prefix, data, len) 58 | #endif 59 | 60 | /* ------------------------------------------------------------------------- */ 61 | 62 | #if DEBUG_LEVEL > 0 63 | extern void odDebug(uchar prefix, uchar *data, uchar len); 64 | 65 | /* Try to find our control registers; ATMEL likes to rename these */ 66 | 67 | #if defined UBRR 68 | # define ODDBG_UBRR UBRR 69 | #elif defined UBRRL 70 | # define ODDBG_UBRR UBRRL 71 | #elif defined UBRR0 72 | # define ODDBG_UBRR UBRR0 73 | #elif defined UBRR0L 74 | # define ODDBG_UBRR UBRR0L 75 | #endif 76 | 77 | #if defined UCR 78 | # define ODDBG_UCR UCR 79 | #elif defined UCSRB 80 | # define ODDBG_UCR UCSRB 81 | #elif defined UCSR0B 82 | # define ODDBG_UCR UCSR0B 83 | #endif 84 | 85 | #if defined TXEN 86 | # define ODDBG_TXEN TXEN 87 | #else 88 | # define ODDBG_TXEN TXEN0 89 | #endif 90 | 91 | #if defined USR 92 | # define ODDBG_USR USR 93 | #elif defined UCSRA 94 | # define ODDBG_USR UCSRA 95 | #elif defined UCSR0A 96 | # define ODDBG_USR UCSR0A 97 | #endif 98 | 99 | #if defined UDRE 100 | # define ODDBG_UDRE UDRE 101 | #else 102 | # define ODDBG_UDRE UDRE0 103 | #endif 104 | 105 | #if defined UDR 106 | # define ODDBG_UDR UDR 107 | #elif defined UDR0 108 | # define ODDBG_UDR UDR0 109 | #endif 110 | 111 | static inline void odDebugInit(void) 112 | { 113 | ODDBG_UCR |= (1< 38 | #ifndef __IAR_SYSTEMS_ASM__ 39 | # include 40 | #endif 41 | 42 | #define __attribute__(arg) /* not supported on IAR */ 43 | 44 | #ifdef __IAR_SYSTEMS_ASM__ 45 | # define __ASSEMBLER__ /* IAR does not define standard macro for asm */ 46 | #endif 47 | 48 | #ifdef __HAS_ELPM__ 49 | # define PROGMEM __farflash 50 | #else 51 | # define PROGMEM __flash 52 | #endif 53 | 54 | #define USB_READ_FLASH(addr) (*(PROGMEM char *)(addr)) 55 | 56 | /* The following definitions are not needed by the driver, but may be of some 57 | * help if you port a gcc based project to IAR. 58 | */ 59 | #define cli() __disable_interrupt() 60 | #define sei() __enable_interrupt() 61 | #define wdt_reset() __watchdog_reset() 62 | #define _BV(x) (1 << (x)) 63 | 64 | /* assembler compatibility macros */ 65 | #define nop2 rjmp $+2 /* jump to next instruction */ 66 | #define XL r26 67 | #define XH r27 68 | #define YL r28 69 | #define YH r29 70 | #define ZL r30 71 | #define ZH r31 72 | #define lo8(x) LOW(x) 73 | #define hi8(x) (((x)>>8) & 0xff) /* not HIGH to allow XLINK to make a proper range check */ 74 | 75 | /* Depending on the device you use, you may get problems with the way usbdrv.h 76 | * handles the differences between devices. Since IAR does not use #defines 77 | * for MCU registers, we can't check for the existence of a particular 78 | * register with an #ifdef. If the autodetection mechanism fails, include 79 | * definitions for the required USB_INTR_* macros in your usbconfig.h. See 80 | * usbconfig-prototype.h and usbdrv.h for details. 81 | */ 82 | 83 | /* ------------------------------------------------------------------------- */ 84 | #elif __CODEVISIONAVR__ /* check for CodeVision AVR */ 85 | /* ------------------------------------------------------------------------- */ 86 | /* This port is not working (yet) */ 87 | 88 | /* #define F_CPU _MCU_CLOCK_FREQUENCY_ seems to be defined automatically */ 89 | 90 | #include 91 | #include 92 | 93 | #define __attribute__(arg) /* not supported on IAR */ 94 | 95 | #define PROGMEM __flash 96 | #define USB_READ_FLASH(addr) (*(PROGMEM char *)(addr)) 97 | 98 | #ifndef __ASSEMBLER__ 99 | static inline void cli(void) 100 | { 101 | #asm("cli"); 102 | } 103 | static inline void sei(void) 104 | { 105 | #asm("sei"); 106 | } 107 | #endif 108 | #define _delay_ms(t) delay_ms(t) 109 | #define _BV(x) (1 << (x)) 110 | #define USB_CFG_USE_SWITCH_STATEMENT 1 /* macro for if() cascase fails for unknown reason */ 111 | 112 | #define macro .macro 113 | #define endm .endmacro 114 | #define nop2 rjmp .+0 /* jump to next instruction */ 115 | 116 | /* ------------------------------------------------------------------------- */ 117 | #else /* default development environment is avr-gcc/avr-libc */ 118 | /* ------------------------------------------------------------------------- */ 119 | 120 | #include 121 | #ifdef __ASSEMBLER__ 122 | # define _VECTOR(N) __vector_ ## N /* io.h does not define this for asm */ 123 | #else 124 | # include 125 | #endif 126 | 127 | #if USB_CFG_DRIVER_FLASH_PAGE 128 | # define USB_READ_FLASH(addr) pgm_read_byte_far(((long)USB_CFG_DRIVER_FLASH_PAGE << 16) | (long)(addr)) 129 | #else 130 | # define USB_READ_FLASH(addr) pgm_read_byte(addr) 131 | #endif 132 | 133 | #define macro .macro 134 | #define endm .endm 135 | #define nop2 rjmp .+0 /* jump to next instruction */ 136 | 137 | #endif /* development environment */ 138 | 139 | /* for conveniecne, ensure that PRG_RDB exists */ 140 | #ifndef PRG_RDB 141 | # define PRG_RDB(addr) USB_READ_FLASH(addr) 142 | #endif 143 | #endif /* __usbportability_h_INCLUDED__ */ 144 | -------------------------------------------------------------------------------- /gamecube.c: -------------------------------------------------------------------------------- 1 | /* gc_n64_usb : Gamecube or N64 controller to USB firmware 2 | Copyright (C) 2007-2015 Raphael Assenat 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "gamepad.h" 22 | #include "leds.h" 23 | #include "gamecube.h" 24 | #include "reportdesc.h" 25 | #include "gcn64_protocol.h" 26 | 27 | /*********** prototypes *************/ 28 | static void gamecubeInit(void); 29 | static char gamecubeUpdate(void); 30 | static char gamecubeChanged(int rid); 31 | 32 | 33 | /* What was most recently read from the controller */ 34 | static unsigned char last_built_report[GCN64_REPORT_SIZE]; 35 | 36 | /* What was most recently sent to the host */ 37 | static unsigned char last_sent_report[GCN64_REPORT_SIZE]; 38 | 39 | static int gc_rumbling = 0; 40 | static int gc_analog_lr_disable = 0; 41 | 42 | static void gamecubeInit(void) 43 | { 44 | if (0 == gamecubeUpdate()) { 45 | unsigned char btns2; 46 | 47 | btns2 = gcn64_protocol_getByte(8); 48 | 49 | //if (gcn64_workbuf[GC_BTN_L] && gcn64_workbuf[GC_BTN_R]) { 50 | if ((btns2 & 0x06) == 0x06) { // L + R 51 | gc_analog_lr_disable = 1; 52 | } else { 53 | gc_analog_lr_disable = 0; 54 | } 55 | } 56 | } 57 | 58 | static char gamecubeUpdate(void) 59 | { 60 | int i; 61 | unsigned char tmp=0; 62 | unsigned char tmpdata[8]; 63 | unsigned char count; 64 | unsigned char x,y,cx,cy,rtrig,ltrig,btns1,btns2,rb1,rb2; 65 | 66 | #if 1 67 | /* Get ID command. 68 | * 69 | * If we don't do that, the wavebird does not work. 70 | * 71 | * 2015-12-08: RA: 72 | * In fact, calling gcn64_detectController at least 73 | * once is enough to "enable" the wavebird receiver. In any case, 74 | * the GET_STATUS commands below get answered. This means 75 | * this GET_ID command is in fact optional. Removing it 76 | * does not seem to do harm with my receiver at least. But 77 | * I will not risk changing what has been there for years. 78 | */ 79 | tmp = GC_GETID; 80 | count = gcn64_transaction(&tmp, 1); 81 | if (count != GC_GETID_REPLY_LENGTH) { 82 | return 1; 83 | } 84 | #endif 85 | 86 | tmpdata[0] = GC_GETSTATUS1; 87 | tmpdata[1] = GC_GETSTATUS2; 88 | tmpdata[2] = GC_GETSTATUS3(gc_rumbling); 89 | 90 | count = gcn64_transaction(tmpdata, 3); 91 | if (count != GC_GETSTATUS_REPLY_LENGTH) { 92 | return 1; // failure 93 | } 94 | 95 | /* 96 | (Source: Nintendo Gamecube Controller Protocol 97 | updated 8th March 2004, by James.) 98 | 99 | Bit Function 100 | 0-2 Always 0 101 | 3 Start 102 | 4 Y 103 | 5 X 104 | 6 B 105 | 7 A 106 | 8 Always 1 107 | 9 L 108 | 10 R 109 | 11 Z 110 | 12-15 Up,Down,Right,Left 111 | 16-23 Joy X 112 | 24-31 Joy Y 113 | 32-39 C Joystick X 114 | 40-47 C Joystick Y 115 | 48-55 Left Btn Val 116 | 56-63 Right Btn Val 117 | */ 118 | 119 | btns1 = gcn64_protocol_getByte(0); 120 | btns2 = gcn64_protocol_getByte(8); 121 | x = gcn64_protocol_getByte(16); 122 | y = gcn64_protocol_getByte(24); 123 | cx = gcn64_protocol_getByte(32); 124 | cy = gcn64_protocol_getByte(40); 125 | ltrig = gcn64_protocol_getByte(48); 126 | rtrig = gcn64_protocol_getByte(56); 127 | 128 | /* Prepare button bits */ 129 | rb1 = rb2 = 0; 130 | for (i=0; i<5; i++) // St Y X B A 131 | rb1 |= (btns1 & (0x10 >> i)) ? (0x01<> i)) ? (0x20<> i)) ? (0x01< 119 | #define GC_KEY_SLASH_QUESTION 0x3E // /? 120 | 121 | // (The extra key before right-shift on japanese keyboards. 122 | // HID code International 1 [HID usage tables Footnote 15-20]). 123 | #define GC_KEY_INTERNATIONAL1 0x3F 124 | #define GC_KEY_F1 0x40 125 | #define GC_KEY_F2 0x41 126 | #define GC_KEY_F3 0x42 127 | #define GC_KEY_F4 0x43 128 | #define GC_KEY_F5 0x44 129 | #define GC_KEY_F6 0x45 130 | #define GC_KEY_F7 0x46 131 | #define GC_KEY_F8 0x47 132 | #define GC_KEY_F9 0x48 133 | #define GC_KEY_F10 0x49 134 | #define GC_KEY_F11 0x4A 135 | #define GC_KEY_F12 0x4B 136 | #define GC_KEY_ESC 0x4C 137 | #define GC_KEY_INSERT 0x4D 138 | #define GC_KEY_DELETE 0x4E 139 | 140 | // (Hankaku/zenkaku/kanji button). Also known as `~ 141 | #define GC_KEY_HANKAKU 0x4F 142 | #define GC_KEY_BACKSPACE 0x50 143 | #define GC_KEY_TAB 0x51 144 | 145 | #define GC_KEY_CAPS_LOCK 0x53 146 | #define GC_KEY_LEFT_SHIFT 0x54 147 | #define GC_KEY_RIGHT_SHIFT 0x55 148 | #define GC_KEY_LEFT_CTRL 0x56 149 | #define GC_KEY_LEFT_ALT 0x57 150 | #define GC_KEY_MUHENKAN 0x58 // HID international 5 151 | #define GC_KEY_SPACE 0x59 152 | #define GC_KEY_HENKAN 0x5A // HID international 4 153 | #define GC_KEY_KANA 0x5B // HID international 2 154 | #define GC_KEY_LEFT 0x5C 155 | #define GC_KEY_DOWN 0x5D 156 | #define GC_KEY_UP 0x5E 157 | #define GC_KEY_RIGHT 0x5F 158 | 159 | #define GC_KEY_ENTER 0x61 160 | 161 | void gcn64protocol_hwinit(void); 162 | int gcn64_detectController(void); 163 | int gcn64_transaction(unsigned char *data_out, int data_out_len); 164 | 165 | unsigned char gcn64_protocol_getByte(int offset); 166 | void gcn64_protocol_getBytes(int offset, int n_bytes, unsigned char *dstbuf); 167 | 168 | #endif // _gcn64_protocol_h__ 169 | -------------------------------------------------------------------------------- /calibration_fixer/src/gc_cal_fix.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | #define DIRECTINPUT_VERSION 0x0800 9 | 10 | #include 11 | #include 12 | 13 | LPDIRECTINPUT8 g_pDI = NULL; 14 | LPDIRECTINPUTDEVICE8 g_pJoystick = NULL; 15 | 16 | static int g_num_fixed = 0; 17 | static int g_only_list = 0; 18 | static int g_show_unsigned = 0; 19 | static int g_saturn_3d = 0; 20 | 21 | int fixJoystickCalibration(void) 22 | { 23 | HRESULT hr; 24 | DIPROPCAL cpoints; 25 | DIDEVCAPS devcaps; 26 | int x; 27 | int axes[6] = { DIJOFS_X, DIJOFS_Y, 28 | DIJOFS_RX, DIJOFS_RY, 29 | DIJOFS_RZ, DIJOFS_SLIDER(0) }; 30 | 31 | if( FAILED( hr = g_pJoystick->SetDataFormat( &c_dfDIJoystick ) ) ) 32 | return -1; 33 | 34 | //g_pJoystick->Acquire(); 35 | 36 | devcaps.dwSize = sizeof(devcaps); 37 | hr = g_pJoystick->GetCapabilities(&devcaps); 38 | if (FAILED(hr)) { 39 | //MessageBox(NULL, _com_error(GetLastError()).ErrorMessage(), L"asd", MB_ICONWARNING | MB_OK); 40 | printf("*** ERROR ****\n"); 41 | } 42 | else { 43 | printf(" Axes: %lu, Buttons: %lu\n", devcaps.dwAxes, devcaps.dwButtons); 44 | } 45 | 46 | printf(" Min. Center Max.\n"); 47 | 48 | cpoints.diph.dwSize = sizeof(cpoints); 49 | cpoints.diph.dwHeaderSize = sizeof(DIPROPHEADER); 50 | cpoints.diph.dwHow = DIPH_BYOFFSET; 51 | 52 | for (x=0; x<8; x++) { 53 | cpoints.diph.dwObj = axes[x]; 54 | 55 | hr = g_pJoystick->GetProperty(DIPROP_CALIBRATION, &cpoints.diph); 56 | if (FAILED(hr)) { 57 | continue; 58 | } 59 | 60 | if (g_show_unsigned) { 61 | printf(" %d: %3ld %3ld %3ld", x, 62 | cpoints.lMin, cpoints.lCenter, cpoints.lMax); 63 | } else { 64 | printf(" %d: %3ld %3ld %3ld", x, 65 | cpoints.lMin - 127, cpoints.lCenter - 127, cpoints.lMax - 127); 66 | } 67 | 68 | if (!g_only_list) { 69 | if (g_saturn_3d) { 70 | if (x==5 || x==6) { 71 | cpoints.lCenter = 0; 72 | cpoints.lMax = 0xff; 73 | cpoints.lMin = -1; 74 | g_pJoystick->SetProperty(DIPROP_CALIBRATION, &cpoints.diph); 75 | printf(" (Modified)"); 76 | } 77 | } else { 78 | if (x==4 || x==5) { 79 | cpoints.lCenter = cpoints.lMax; 80 | cpoints.lMax = 0xff; 81 | 82 | g_pJoystick->SetProperty(DIPROP_CALIBRATION, &cpoints.diph); 83 | printf(" (Modified)"); 84 | } 85 | } 86 | } 87 | printf("\n"); 88 | } 89 | 90 | g_num_fixed++; 91 | 92 | return 0; 93 | } 94 | 95 | 96 | BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* 97 | pdidInstance, VOID* pContext) 98 | { 99 | HRESULT hr; 100 | DIPROPDWORD vidpid; 101 | WORD vid, pid; 102 | 103 | // Obtain an interface to the enumerated joystick. 104 | hr = g_pDI->CreateDevice(pdidInstance->guidInstance, 105 | &g_pJoystick, NULL); 106 | if(FAILED(hr)) 107 | return DIENUM_CONTINUE; 108 | 109 | /* Test */ 110 | vidpid.diph.dwSize = sizeof(vidpid); 111 | vidpid.diph.dwHeaderSize = sizeof(DIPROPHEADER); 112 | vidpid.diph.dwHow = DIPH_DEVICE; 113 | vidpid.diph.dwObj = 0; 114 | hr = g_pJoystick->GetProperty(DIPROP_VIDPID, &vidpid.diph); 115 | if (FAILED(hr)) { 116 | return DIENUM_CONTINUE; 117 | } 118 | 119 | vid = vidpid.dwData & 0xffff; 120 | pid = vidpid.dwData >> 16; 121 | 122 | g_saturn_3d = 0; 123 | 124 | if (vid==0x1781 && pid==0x0a9a) { 125 | printf("Found Device ID : VID=%04x PID=%04x (ADAP-GCN64 v1.x)\n", vid, pid); 126 | fixJoystickCalibration(); // uses global 127 | } 128 | else if (vid==0x1740 && pid==0x057f) { 129 | printf("Found Device ID : VID=%04x PID=%04x (ADAP-GCN64 v2.1)\n", vid, pid); 130 | fixJoystickCalibration(); // uses global 131 | } 132 | else if (vid==0x289b && pid==0x0001) { 133 | printf("Found Device ID : VID=%04x PID=%04x (ADAP-GCN64 v2.2)\n", vid, pid); 134 | fixJoystickCalibration(); // uses global 135 | } 136 | else if (vid==0x289b && pid==0x0004) { 137 | printf("Found Device ID : VID=%04x PID=%04x (ADAP-GCN64 v2.3)\n", vid, pid); 138 | fixJoystickCalibration(); // uses global 139 | } 140 | else if (vid==0x289b && pid==0x000c) { 141 | printf("Found Device ID : VID=%04x PID=%04x (ADAP-GCN64 v2.9)\n", vid, pid); 142 | fixJoystickCalibration(); // uses global 143 | } 144 | else if (vid==0X289B && pid==0X0005) { 145 | printf("Found Device ID : VID=%04x PID=%04x (Saturn joystick)\n", vid, pid); 146 | g_saturn_3d = 1; 147 | fixJoystickCalibration(); // uses global 148 | } 149 | else { 150 | printf("Ignoring Device ID : VID=%04x PID=%04x\n", vid, pid); 151 | 152 | } 153 | 154 | return DIENUM_CONTINUE; 155 | } 156 | 157 | int main(int argc, char * argv[]) 158 | { 159 | HRESULT res; 160 | int opt; 161 | int run_calibration = 0; 162 | 163 | printf("raphnet.net Gamecube adapter L/R buttons calibration fixer v1.4\n"); 164 | printf("Copyright (C) 2009-2014, Raphael Assenat\n\n"); 165 | 166 | while(-1 != (opt = getopt(argc, argv, "hlcu"))) { 167 | switch (opt) 168 | { 169 | case 'h': 170 | printf("Usage: ./gc_calfix_ng \n\n"); 171 | printf("By default, this tool adjusts the calibration data for all supported joysticks.\n"); 172 | printf("The following options can be used to perform other tasks.\n\n"); 173 | printf("Options:\n"); 174 | printf(" -h Show help\n"); 175 | printf(" -l Only list and display supported joystick calibration settings\n"); 176 | printf(" -c Open the windows calibration dialog before exiting\n"); 177 | printf(" -u Show unsigned calibration values.\n"); 178 | return 0; 179 | 180 | case 'u': 181 | g_show_unsigned = 1; 182 | break; 183 | 184 | case 'l': 185 | g_only_list = 1; 186 | break; 187 | 188 | case 'c': 189 | run_calibration = 1; 190 | break; 191 | 192 | default: 193 | fprintf(stderr, "Unknown option passed. See -h\n"); 194 | break; 195 | } 196 | } 197 | 198 | 199 | res = DirectInput8Create(GetModuleHandle( NULL ), DIRECTINPUT_VERSION, IID_IDirectInput8, 200 | (VOID **)&g_pDI, NULL); 201 | 202 | if (FAILED(res)) { 203 | printf("DirectInput8Create failed\n"); 204 | return -1; 205 | } 206 | 207 | g_pDI->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, 208 | NULL, DIEDFL_ATTACHEDONLY); 209 | 210 | if (!g_num_fixed) { 211 | printf("No supported joysticks found."); 212 | } 213 | else { 214 | printf("Found %d supported joystick(s).\n", g_num_fixed);\ 215 | if (run_calibration) { 216 | g_pJoystick->RunControlPanel(0,0); 217 | } 218 | } 219 | 220 | printf("\n -- Press ENTER to exit --\n"); 221 | 222 | getchar(); 223 | 224 | return 0; 225 | } 226 | 227 | -------------------------------------------------------------------------------- /usbdrv/USB-ID-FAQ.txt: -------------------------------------------------------------------------------- 1 | Version 2012-07-09 2 | 3 | ========================== 4 | WHY DO WE NEED THESE IDs? 5 | ========================== 6 | 7 | USB is more than a low level protocol for data transport. It also defines a 8 | common set of requests which must be understood by all devices. And as part 9 | of these common requests, the specification defines data structures, the 10 | USB Descriptors, which are used to describe the properties of the device. 11 | 12 | From the perspective of an operating system, it is therefore possible to find 13 | out basic properties of a device (such as e.g. the manufacturer and the name 14 | of the device) without a device-specific driver. This is essential because 15 | the operating system can choose a driver to load based on this information 16 | (Plug-And-Play). 17 | 18 | Among the most important properties in the Device Descriptor are the USB 19 | Vendor- and Product-ID. Both are 16 bit integers. The most simple form of 20 | driver matching is based on these IDs. The driver announces the Vendor- and 21 | Product-IDs of the devices it can handle and the operating system loads the 22 | appropriate driver when the device is connected. 23 | 24 | It is obvious that this technique only works if the pair Vendor- plus 25 | Product-ID is unique: Only devices which require the same driver can have the 26 | same pair of IDs. 27 | 28 | 29 | ===================================================== 30 | HOW DOES THE USB STANDARD ENSURE THAT IDs ARE UNIQUE? 31 | ===================================================== 32 | 33 | Since it is so important that USB IDs are unique, the USB Implementers Forum, 34 | Inc. (usb.org) needs a way to enforce this legally. It is not forbidden by 35 | law to build a device and assign it any random numbers as IDs. Usb.org 36 | therefore needs an agreement to regulate the use of USB IDs. The agreement 37 | binds only parties who agreed to it, of course. Everybody else is free to use 38 | any numbers for their IDs. 39 | 40 | So how can usb.org ensure that every manufacturer of USB devices enters into 41 | an agreement with them? They do it via trademark licensing. Usb.org has 42 | registered the trademark "USB", all associated logos and related terms. If 43 | you want to put an USB logo on your product or claim that it is USB 44 | compliant, you must license these trademarks from usb.org. And this is where 45 | you enter into an agreement. See the "USB-IF Trademark License Agreement and 46 | Usage Guidelines for the USB-IF Logo" at 47 | http://www.usb.org/developers/logo_license/. 48 | 49 | Licensing the USB trademarks requires that you buy a USB Vendor-ID from 50 | usb.org (one-time fee of ca. 2,000 USD), that you become a member of usb.org 51 | (yearly fee of ca. 4,000 USD) and that you meet all the technical 52 | specifications from the USB spec. 53 | 54 | This means that most hobbyists and small companies will never be able to 55 | become USB compliant, just because membership is so expensive. And you can't 56 | be compliant with a driver based on V-USB anyway, because the AVR's port pins 57 | don't meet the electrical specifications for USB. So, in principle, all 58 | hobbyists and small companies are free to choose any random numbers for their 59 | IDs. They have nothing to lose... 60 | 61 | There is one exception worth noting, though: If you use a sub-component which 62 | implements USB, the vendor of the sub-components may guarantee USB 63 | compliance. This might apply to some or all of FTDI's solutions. 64 | 65 | 66 | ======================================================================= 67 | WHY SHOULD YOU OBTAIN USB IDs EVEN IF YOU DON'T LICENSE USB TRADEMARKS? 68 | ======================================================================= 69 | 70 | You have learned in the previous section that you are free to choose any 71 | numbers for your IDs anyway. So why not do exactly this? There is still the 72 | technical issue. If you choose IDs which are already in use by somebody else, 73 | operating systems will load the wrong drivers and your device won't work. 74 | Even if you choose IDs which are not currently in use, they may be in use in 75 | the next version of the operating system or even after an automatic update. 76 | 77 | So what you need is a pair of Vendor- and Product-IDs for which you have the 78 | guarantee that no USB compliant product uses them. This implies that no 79 | operating system will ever ship with drivers responsible for these IDs. 80 | 81 | 82 | ============================================== 83 | HOW DOES OBJECTIVE DEVELOPMENT HANDLE USB IDs? 84 | ============================================== 85 | 86 | Objective Development gives away pairs of USB-IDs with their V-USB licenses. 87 | In order to ensure that these IDs are unique, Objective Development has an 88 | agreement with the company/person who has bought the USB Vendor-ID from 89 | usb.org. This agreement ensures that a range of USB Product-IDs is reserved 90 | for assignment by Objective Development and that the owner of the Vendor-ID 91 | won't give it to anybody else. 92 | 93 | This means that you have to trust three parties to ensure uniqueness of 94 | your IDs: 95 | 96 | - Objective Development, that they don't give the same PID to more than 97 | one person. 98 | - The owner of the Vendor-ID that they don't assign PIDs from the range 99 | assigned to Objective Development to anybody else. 100 | - Usb.org that they don't assign the same Vendor-ID a second time. 101 | 102 | 103 | ================================== 104 | WHO IS THE OWNER OF THE VENDOR-ID? 105 | ================================== 106 | 107 | Objective Development has obtained ranges of USB Product-IDs under two 108 | Vendor-IDs: Under Vendor-ID 5824 from Wouter van Ooijen (Van Ooijen 109 | Technische Informatica, www.voti.nl) and under Vendor-ID 8352 from Jason 110 | Kotzin (now flirc.tv, Inc.). Both VID owners have received their Vendor-ID 111 | directly from usb.org. 112 | 113 | 114 | ========================================================================= 115 | CAN I USE USB-IDs FROM OBJECTIVE DEVELOPMENT WITH OTHER DRIVERS/HARDWARE? 116 | ========================================================================= 117 | 118 | The short answer is: Yes. All you get is a guarantee that the IDs are never 119 | assigned to anybody else. What more do you need? 120 | 121 | 122 | ============================ 123 | WHAT ABOUT SHARED ID PAIRS? 124 | ============================ 125 | 126 | Objective Development has reserved some PID/VID pairs for shared use. You 127 | have no guarantee of uniqueness for them, except that no USB compliant device 128 | uses them. In order to avoid technical problems, we must ensure that all 129 | devices with the same pair of IDs use the same driver on kernel level. For 130 | details, see the file USB-IDs-for-free.txt. 131 | 132 | 133 | ====================================================== 134 | I HAVE HEARD THAT SUB-LICENSING OF USB-IDs IS ILLEGAL? 135 | ====================================================== 136 | 137 | A 16 bit integer number cannot be protected by copyright laws. It is not 138 | sufficiently complex. And since none of the parties involved entered into the 139 | USB-IF Trademark License Agreement, we are not bound by this agreement. So 140 | there is no reason why it should be illegal to sub-license USB-IDs. 141 | 142 | 143 | ============================================= 144 | WHO IS LIABLE IF THERE ARE INCOMPATIBILITIES? 145 | ============================================= 146 | 147 | Objective Development disclaims all liabilities which might arise from the 148 | assignment of IDs. If you guarantee product features to your customers 149 | without proper disclaimer, YOU are liable for that. 150 | -------------------------------------------------------------------------------- /usbdrv/USB-IDs-for-free.txt: -------------------------------------------------------------------------------- 1 | Version 2009-08-22 2 | 3 | =========================== 4 | FREE USB-IDs FOR SHARED USE 5 | =========================== 6 | 7 | Objective Development has reserved a set of USB Product-IDs for use according 8 | to the guidelines outlined below. For more information about the concept of 9 | USB IDs please see the file USB-ID-FAQ.txt. Objective Development guarantees 10 | that the IDs listed below are not used by any USB compliant devices. 11 | 12 | 13 | ==================== 14 | MECHANISM OF SHARING 15 | ==================== 16 | 17 | From a technical point of view, two different devices can share the same USB 18 | Vendor- and Product-ID if they require the same driver on operating system 19 | level. We make use of this fact by assigning separate IDs for various device 20 | classes. On application layer, devices must be distinguished by their textual 21 | name or serial number. We offer separate sets of IDs for discrimination by 22 | textual name and for serial number. 23 | 24 | Examples for shared use of USB IDs are included with V-USB in the "examples" 25 | subdirectory. 26 | 27 | 28 | ====================================== 29 | IDs FOR DISCRIMINATION BY TEXTUAL NAME 30 | ====================================== 31 | 32 | If you use one of the IDs listed below, your device and host-side software 33 | must conform to these rules: 34 | 35 | (1) The USB device MUST provide a textual representation of the manufacturer 36 | and product identification. The manufacturer identification MUST be available 37 | at least in USB language 0x0409 (English/US). 38 | 39 | (2) The textual manufacturer identification MUST contain either an Internet 40 | domain name (e.g. "mycompany.com") registered and owned by you, or an e-mail 41 | address under your control (e.g. "myname@gmx.net"). You can embed the domain 42 | name or e-mail address in any string you like, e.g. "Objective Development 43 | http://www.obdev.at/vusb/". 44 | 45 | (3) You are responsible for retaining ownership of the domain or e-mail 46 | address for as long as any of your products are in use. 47 | 48 | (4) You may choose any string for the textual product identification, as long 49 | as this string is unique within the scope of your textual manufacturer 50 | identification. 51 | 52 | (5) Application side device look-up MUST be based on the textual manufacturer 53 | and product identification in addition to VID/PID matching. The driver 54 | matching MUST be a comparison of the entire strings, NOT a sub-string match. 55 | 56 | (6) For devices which implement a particular USB device class (e.g. HID), the 57 | operating system's default class driver MUST be used. If an operating system 58 | driver for Vendor Class devices is needed, this driver must be libusb or 59 | libusb-win32 (see http://libusb.org/ and 60 | http://libusb-win32.sourceforge.net/). 61 | 62 | Table if IDs for discrimination by textual name: 63 | 64 | PID dec (hex) | VID dec (hex) | Description of use 65 | ==============+===============+============================================ 66 | 1500 (0x05dc) | 5824 (0x16c0) | For Vendor Class devices with libusb 67 | --------------+---------------+-------------------------------------------- 68 | 1503 (0x05df) | 5824 (0x16c0) | For generic HID class devices (which are 69 | | | NOT mice, keyboards or joysticks) 70 | --------------+---------------+-------------------------------------------- 71 | 1505 (0x05e1) | 5824 (0x16c0) | For CDC-ACM class devices (modems) 72 | --------------+---------------+-------------------------------------------- 73 | 1508 (0x05e4) | 5824 (0x16c0) | For MIDI class devices 74 | --------------+---------------+-------------------------------------------- 75 | 76 | Note that Windows caches the textual product- and vendor-description for 77 | mice, keyboards and joysticks. Name-bsed discrimination is therefore not 78 | recommended for these device classes. 79 | 80 | 81 | ======================================= 82 | IDs FOR DISCRIMINATION BY SERIAL NUMBER 83 | ======================================= 84 | 85 | If you use one of the IDs listed below, your device and host-side software 86 | must conform to these rules: 87 | 88 | (1) The USB device MUST provide a textual representation of the serial 89 | number, unless ONLY the operating system's default class driver is used. 90 | The serial number string MUST be available at least in USB language 0x0409 91 | (English/US). 92 | 93 | (2) The serial number MUST start with either an Internet domain name (e.g. 94 | "mycompany.com") registered and owned by you, or an e-mail address under your 95 | control (e.g. "myname@gmx.net"), both terminated with a colon (":") character. 96 | You MAY append any string you like for further discrimination of your devices. 97 | 98 | (3) You are responsible for retaining ownership of the domain or e-mail 99 | address for as long as any of your products are in use. 100 | 101 | (5) Application side device look-up MUST be based on the serial number string 102 | in addition to VID/PID matching. The matching must start at the first 103 | character of the serial number string and include the colon character 104 | terminating your domain or e-mail address. It MAY stop anywhere after that. 105 | 106 | (6) For devices which implement a particular USB device class (e.g. HID), the 107 | operating system's default class driver MUST be used. If an operating system 108 | driver for Vendor Class devices is needed, this driver must be libusb or 109 | libusb-win32 (see http://libusb.org/ and 110 | http://libusb-win32.sourceforge.net/). 111 | 112 | (7) If ONLY the operating system's default class driver is used, e.g. for 113 | mice, keyboards, joysticks, CDC or MIDI devices and no discrimination by an 114 | application is needed, the serial number may be omitted. 115 | 116 | 117 | Table if IDs for discrimination by serial number string: 118 | 119 | PID dec (hex) | VID dec (hex) | Description of use 120 | ===============+===============+=========================================== 121 | 10200 (0x27d8) | 5824 (0x16c0) | For Vendor Class devices with libusb 122 | ---------------+---------------+------------------------------------------- 123 | 10201 (0x27d9) | 5824 (0x16c0) | For generic HID class devices (which are 124 | | | NOT mice, keyboards or joysticks) 125 | ---------------+---------------+------------------------------------------- 126 | 10202 (0x27da) | 5824 (0x16c0) | For USB Mice 127 | ---------------+---------------+------------------------------------------- 128 | 10203 (0x27db) | 5824 (0x16c0) | For USB Keyboards 129 | ---------------+---------------+------------------------------------------- 130 | 10204 (0x27dc) | 5824 (0x16c0) | For USB Joysticks 131 | ---------------+---------------+------------------------------------------- 132 | 10205 (0x27dd) | 5824 (0x16c0) | For CDC-ACM class devices (modems) 133 | ---------------+---------------+------------------------------------------- 134 | 10206 (0x27de) | 5824 (0x16c0) | For MIDI class devices 135 | ---------------+---------------+------------------------------------------- 136 | 137 | 138 | ================= 139 | ORIGIN OF USB-IDs 140 | ================= 141 | 142 | OBJECTIVE DEVELOPMENT Software GmbH has obtained all VID/PID pairs listed 143 | here from Wouter van Ooijen (see www.voti.nl) for exclusive disposition. 144 | Wouter van Ooijen has obtained the VID from the USB Implementers Forum, Inc. 145 | (see www.usb.org). The VID is registered for the company name "Van Ooijen 146 | Technische Informatica". 147 | 148 | 149 | ========== 150 | DISCLAIMER 151 | ========== 152 | 153 | OBJECTIVE DEVELOPMENT Software GmbH disclaims all liability for any 154 | problems which are caused by the shared use of these VID/PID pairs. 155 | -------------------------------------------------------------------------------- /usbdrv/CommercialLicense.txt: -------------------------------------------------------------------------------- 1 | V-USB Driver Software License Agreement 2 | Version 2012-07-09 3 | 4 | THIS LICENSE AGREEMENT GRANTS YOU CERTAIN RIGHTS IN A SOFTWARE. YOU CAN 5 | ENTER INTO THIS AGREEMENT AND ACQUIRE THE RIGHTS OUTLINED BELOW BY PAYING 6 | THE AMOUNT ACCORDING TO SECTION 4 ("PAYMENT") TO OBJECTIVE DEVELOPMENT. 7 | 8 | 9 | 1 DEFINITIONS 10 | 11 | 1.1 "OBJECTIVE DEVELOPMENT" shall mean OBJECTIVE DEVELOPMENT Software GmbH, 12 | Grosse Schiffgasse 1A/7, 1020 Wien, AUSTRIA. 13 | 14 | 1.2 "You" shall mean the Licensee. 15 | 16 | 1.3 "V-USB" shall mean all files included in the package distributed under 17 | the name "vusb" by OBJECTIVE DEVELOPMENT (http://www.obdev.at/vusb/) 18 | unless otherwise noted. This includes the firmware-only USB device 19 | implementation for Atmel AVR microcontrollers, some simple device examples 20 | and host side software examples and libraries. 21 | 22 | 23 | 2 LICENSE GRANTS 24 | 25 | 2.1 Source Code. OBJECTIVE DEVELOPMENT shall furnish you with the source 26 | code of V-USB. 27 | 28 | 2.2 Distribution and Use. OBJECTIVE DEVELOPMENT grants you the 29 | non-exclusive right to use, copy and distribute V-USB with your hardware 30 | product(s), restricted by the limitations in section 3 below. 31 | 32 | 2.3 Modifications. OBJECTIVE DEVELOPMENT grants you the right to modify 33 | the source code and your copy of V-USB according to your needs. 34 | 35 | 2.4 USB IDs. OBJECTIVE DEVELOPMENT furnishes you with one or two USB 36 | Product ID(s), sent to you in e-mail. These Product IDs are reserved 37 | exclusively for you. OBJECTIVE DEVELOPMENT has obtained USB Product ID 38 | ranges under the Vendor ID 5824 from Wouter van Ooijen (Van Ooijen 39 | Technische Informatica, www.voti.nl) and under the Vendor ID 8352 from 40 | Jason Kotzin (now flirc.tv, Inc.). Both owners of the Vendor IDs have 41 | obtained these IDs from the USB Implementers Forum, Inc. (www.usb.org). 42 | OBJECTIVE DEVELOPMENT disclaims all liability which might arise from the 43 | assignment of USB IDs. 44 | 45 | 2.5 USB Certification. Although not part of this agreement, we want to make 46 | it clear that you cannot become USB certified when you use V-USB or a USB 47 | Product ID assigned by OBJECTIVE DEVELOPMENT. AVR microcontrollers don't 48 | meet the electrical specifications required by the USB specification and 49 | the USB Implementers Forum certifies only members who bought a Vendor ID of 50 | their own. 51 | 52 | 53 | 3 LICENSE RESTRICTIONS 54 | 55 | 3.1 Number of Units. Only one of the following three definitions is 56 | applicable. Which one is determined by the amount you pay to OBJECTIVE 57 | DEVELOPMENT, see section 4 ("Payment") below. 58 | 59 | Hobby License: You may use V-USB according to section 2 above in no more 60 | than 5 hardware units. These units must not be sold for profit. 61 | 62 | Entry Level License: You may use V-USB according to section 2 above in no 63 | more than 150 hardware units. 64 | 65 | Professional License: You may use V-USB according to section 2 above in 66 | any number of hardware units, except for large scale production ("unlimited 67 | fair use"). Quantities below 10,000 units are not considered large scale 68 | production. If your reach quantities which are obviously large scale 69 | production, you must pay a license fee of 0.10 EUR per unit for all units 70 | above 10,000. 71 | 72 | 3.2 Rental. You may not rent, lease, or lend V-USB or otherwise encumber 73 | any copy of V-USB, or any of the rights granted herein. 74 | 75 | 3.3 Transfer. You may not transfer your rights under this Agreement to 76 | another party without OBJECTIVE DEVELOPMENT's prior written consent. If 77 | such consent is obtained, you may permanently transfer this License to 78 | another party. The recipient of such transfer must agree to all terms and 79 | conditions of this Agreement. 80 | 81 | 3.4 Reservation of Rights. OBJECTIVE DEVELOPMENT retains all rights not 82 | expressly granted. 83 | 84 | 3.5 Non-Exclusive Rights. Your license rights under this Agreement are 85 | non-exclusive. 86 | 87 | 3.6 Third Party Rights. This Agreement cannot grant you rights controlled 88 | by third parties. In particular, you are not allowed to use the USB logo or 89 | other trademarks owned by the USB Implementers Forum, Inc. without their 90 | consent. Since such consent depends on USB certification, it should be 91 | noted that V-USB will not pass certification because it does not 92 | implement checksum verification and the microcontroller ports do not meet 93 | the electrical specifications. 94 | 95 | 96 | 4 PAYMENT 97 | 98 | The payment amount depends on the variation of this agreement (according to 99 | section 3.1) into which you want to enter. Concrete prices are listed on 100 | OBJECTIVE DEVELOPMENT's web site, usually at 101 | http://www.obdev.at/vusb/license.html. You agree to pay the amount listed 102 | there to OBJECTIVE DEVELOPMENT or OBJECTIVE DEVELOPMENT's payment processor 103 | or reseller. 104 | 105 | 106 | 5 COPYRIGHT AND OWNERSHIP 107 | 108 | V-USB is protected by copyright laws and international copyright 109 | treaties, as well as other intellectual property laws and treaties. V-USB 110 | is licensed, not sold. 111 | 112 | 113 | 6 TERM AND TERMINATION 114 | 115 | 6.1 Term. This Agreement shall continue indefinitely. However, OBJECTIVE 116 | DEVELOPMENT may terminate this Agreement and revoke the granted license and 117 | USB-IDs if you fail to comply with any of its terms and conditions. 118 | 119 | 6.2 Survival of Terms. All provisions regarding secrecy, confidentiality 120 | and limitation of liability shall survive termination of this agreement. 121 | 122 | 123 | 7 DISCLAIMER OF WARRANTY AND LIABILITY 124 | 125 | LIMITED WARRANTY. V-USB IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 126 | KIND. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, OBJECTIVE 127 | DEVELOPMENT AND ITS SUPPLIERS HEREBY DISCLAIM ALL WARRANTIES, EITHER 128 | EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 129 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND 130 | NON-INFRINGEMENT, WITH REGARD TO V-USB, AND THE PROVISION OF OR FAILURE 131 | TO PROVIDE SUPPORT SERVICES. THIS LIMITED WARRANTY GIVES YOU SPECIFIC LEGAL 132 | RIGHTS. YOU MAY HAVE OTHERS, WHICH VARY FROM STATE/JURISDICTION TO 133 | STATE/JURISDICTION. 134 | 135 | LIMITATION OF LIABILITY. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, 136 | IN NO EVENT SHALL OBJECTIVE DEVELOPMENT OR ITS SUPPLIERS BE LIABLE FOR ANY 137 | SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER 138 | (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, 139 | BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY 140 | LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE V-USB OR THE 141 | PROVISION OF OR FAILURE TO PROVIDE SUPPORT SERVICES, EVEN IF OBJECTIVE 142 | DEVELOPMENT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN ANY 143 | CASE, OBJECTIVE DEVELOPMENT'S ENTIRE LIABILITY UNDER ANY PROVISION OF THIS 144 | AGREEMENT SHALL BE LIMITED TO THE AMOUNT ACTUALLY PAID BY YOU FOR V-USB. 145 | 146 | 147 | 8 MISCELLANEOUS TERMS 148 | 149 | 8.1 Marketing. OBJECTIVE DEVELOPMENT has the right to mention for marketing 150 | purposes that you entered into this agreement. 151 | 152 | 8.2 Entire Agreement. This document represents the entire agreement between 153 | OBJECTIVE DEVELOPMENT and you. It may only be modified in writing signed by 154 | an authorized representative of both, OBJECTIVE DEVELOPMENT and you. 155 | 156 | 8.3 Severability. In case a provision of these terms and conditions should 157 | be or become partly or entirely invalid, ineffective, or not executable, 158 | the validity of all other provisions shall not be affected. 159 | 160 | 8.4 Applicable Law. This agreement is governed by the laws of the Republic 161 | of Austria. 162 | 163 | 8.5 Responsible Courts. The responsible courts in Vienna/Austria will have 164 | exclusive jurisdiction regarding all disputes in connection with this 165 | agreement. 166 | 167 | -------------------------------------------------------------------------------- /gc_kb.c: -------------------------------------------------------------------------------- 1 | /* gc_n64_usb : Gamecube or N64 controller to USB firmware 2 | Copyright (C) 2007-2013 Raphael Assenat 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "usbdrv/usbdrv.h" 22 | #include "gamepad.h" 23 | #include "leds.h" 24 | #include "gc_kb.h" 25 | #include "gcn64_protocol.h" 26 | #include "hid_keycodes.h" 27 | 28 | /*********** prototypes *************/ 29 | static void gamecubeInit(void); 30 | static char gamecubeUpdate(void); 31 | static char gamecubeChanged(int rid); 32 | 33 | #define GC_KB_REPORT_SIZE 3 34 | 35 | /* What was most recently read from the controller */ 36 | static unsigned char last_built_report[GC_KB_REPORT_SIZE]; 37 | 38 | /* What was most recently sent to the host */ 39 | static unsigned char last_sent_report[GC_KB_REPORT_SIZE]; 40 | 41 | /* [0] Modifier byte 42 | * [1] Key array 43 | * [2] Key array 44 | * [3] Key array 45 | * 46 | * See Universal Serial Bus HID Tables - 10 Keyboard/Keypad Page (0x07) 47 | * for key codes. 48 | * 49 | */ 50 | static const unsigned char gcKeyboardReport[] PROGMEM = { 51 | 0x05, 0x01, // Usage page : Generic Desktop 52 | 0x09, 0x06, // Usage (Keyboard) 53 | 0xA1, 0x01, // Collection (Application) 54 | 0x05, 0x07, // Usage Page (Key Codes) 55 | /* 0x19, 0xE0, // Usage Minimum (224) 56 | 0x29, 0xE7, // Usage Maximum (231) 57 | 0x15, 0x00, // Logical Minimum (0) 58 | 0x25, 0x01, // Logical Maximum (1) 59 | 60 | // Modifier Byte 61 | 0x75, 0x01, // Report Size(1) 62 | 0x95, 0x08, // Report Count(8) 63 | 0x81, 0x02, // Input (Data, Variable, Absolute)*/ 64 | 65 | // Reserved Byte 66 | // 0x95, 0x01, // Report Count(1) 67 | // 0x75, 0x08, // Report Size(8) 68 | 69 | 0x95, 0x03, // Report Count(3) 70 | 0x75, 0x08, // Report Size(8) 71 | 0x15, 0x00, // Logical Minimum (0) 72 | 0x25, 0xE7, // Logical maximum (231) 73 | 74 | // Key array 75 | // 0x05, 0x07, // Usage Page (key Codes) 76 | 0x19, 0x00, // Usage Minimum(0) 77 | 0x29, 0xE7, // Usage Maximum(231) 78 | 0x81, 0x00, // Input (Data, Array) 79 | 80 | 0xc0, // END_COLLECTION 81 | }; 82 | 83 | static const unsigned char gcKeyboardDevDesc[] PROGMEM = { /* USB device descriptor */ 84 | 18, /* sizeof(usbDescrDevice): length of descriptor in bytes */ 85 | USBDESCR_DEVICE, /* descriptor type */ 86 | 0x01, 0x01, /* USB version supported */ 87 | USB_CFG_DEVICE_CLASS, 88 | USB_CFG_DEVICE_SUBCLASS, 89 | 0, /* protocol */ 90 | 8, /* max packet size */ 91 | 0x9B, 0x28, // Vendor ID 92 | 0x0B, 0x00, // Product ID 93 | 0x00, 0x01, // Version: Minor, Major 94 | 1, // Manufacturer String 95 | 2, // Product string 96 | 3, // Serial number string 97 | 1, /* number of configurations */ 98 | }; 99 | 100 | // http://www2d.biglobe.ne.jp/~msyk/keyboard/layout/usbkeycode.html 101 | 102 | static const unsigned char gc_to_hid_table[] PROGMEM = { 103 | GC_KEY_RESERVED, HID_KB_NOEVENT, 104 | GC_KEY_HOME, HID_KB_HOME, 105 | GC_KEY_END, HID_KB_END, 106 | GC_KEY_PGUP, HID_KB_PGUP, 107 | GC_KEY_PGDN, HID_KB_PGDN, 108 | GC_KEY_SCROLL_LOCK, HID_KB_SCROLL_LOCK, 109 | GC_KEY_DASH_UNDERSCORE, HID_KB_DASH_UNDERSCORE, 110 | GC_KEY_PLUS_EQUAL, HID_KB_EQUAL_PLUS, 111 | GC_KEY_YEN, HID_KB_INTERNATIONAL3, 112 | GC_KEY_OPEN_BRKT_BRACE, HID_KB_OPEN_BRKT_BRACE, 113 | GC_KEY_SEMI_COLON_COLON,HID_KB_SEMI_COLON_COLON, 114 | GC_KEY_QUOTES, HID_KB_QUOTES, 115 | GC_KEY_CLOSE_BRKT_BRACE,HID_KB_CLOSE_BRKT_BRACE, 116 | GC_KEY_BRACKET_MU, HID_KB_NONUS_HASH_TILDE, 117 | GC_KEY_COMMA_ST, HID_KB_COMMA_SMALLER_THAN, 118 | GC_KEY_PERIOD_GT, HID_KB_PERIOD_GREATER_THAN, 119 | GC_KEY_SLASH_QUESTION, HID_KB_SLASH_QUESTION, 120 | GC_KEY_INTERNATIONAL1, HID_KB_INTERNATIONAL1, 121 | GC_KEY_ESC, HID_KB_ESCAPE, 122 | GC_KEY_INSERT, HID_KB_INSERT, 123 | GC_KEY_DELETE, HID_KB_DELETE_FORWARD, 124 | GC_KEY_HANKAKU, HID_KB_GRAVE_ACCENT_AND_TILDE, 125 | GC_KEY_BACKSPACE, HID_KB_BACKSPACE, 126 | GC_KEY_TAB, HID_KB_TAB, 127 | GC_KEY_CAPS_LOCK, HID_KB_CAPS_LOCK, 128 | GC_KEY_MUHENKAN, HID_KB_INTERNATIONAL5, 129 | GC_KEY_SPACE, HID_KB_SPACE, 130 | GC_KEY_HENKAN, HID_KB_INTERNATIONAL4, 131 | GC_KEY_KANA, HID_KB_INTERNATIONAL2, 132 | GC_KEY_LEFT, HID_KB_LEFT_ARROW, 133 | GC_KEY_DOWN, HID_KB_DOWN_ARROW, 134 | GC_KEY_UP, HID_KB_UP_ARROW, 135 | GC_KEY_RIGHT, HID_KB_RIGHT_ARROW, 136 | GC_KEY_ENTER, HID_KB_ENTER, 137 | 138 | /* "shift" keys */ 139 | GC_KEY_LEFT_SHIFT, HID_KB_LEFT_SHIFT, 140 | GC_KEY_RIGHT_SHIFT, HID_KB_RIGHT_SHIFT, 141 | GC_KEY_LEFT_CTRL, HID_KB_LEFT_CONTROL, 142 | 143 | /* This keyboard only has a left alt key. But as right alt is required to access some 144 | * functions on japanese keyboards, I map the key to right alt. 145 | * 146 | * eg: RO-MAJI on the hiragana/katakana key */ 147 | GC_KEY_LEFT_ALT, HID_KB_RIGHT_ALT, 148 | }; 149 | 150 | unsigned char gcKeycodeToHID(unsigned char gc_code) 151 | { 152 | int i; 153 | 154 | if (gc_code >= GC_KEY_A && gc_code <= GC_KEY_0) { 155 | // Note: This works since A-Z, 1-9, 0 have consecutive keycode values. 156 | return (gc_code - GC_KEY_A) + HID_KB_A; 157 | } 158 | if (gc_code >= GC_KEY_F1 && gc_code <= GC_KEY_F12) { 159 | return (gc_code - GC_KEY_F1) + HID_KB_F1; 160 | } 161 | 162 | for (i=0; i 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "gamepad.h" 22 | #include "leds.h" 23 | #include "n64.h" 24 | #include "reportdesc.h" 25 | #include "gcn64_protocol.h" 26 | #include "usbdrv.h" 27 | 28 | #undef BUTTON_A_RUMBLE_TEST 29 | 30 | /*********** prototypes *************/ 31 | static void n64Init(void); 32 | static char n64Update(void); 33 | static char n64Changed(int id); 34 | static int n64BuildReport(unsigned char *reportBuffer, int id); 35 | static void n64SetVibration(int value); 36 | 37 | static char must_rumble = 0; 38 | #ifdef BUTTON_A_RUMBLE_TEST 39 | static char force_rumble = 0; 40 | #endif 41 | 42 | /* What was most recently read from the controller */ 43 | static unsigned char last_built_report[GCN64_REPORT_SIZE]; 44 | 45 | /* What was most recently sent to the host */ 46 | static unsigned char last_sent_report[GCN64_REPORT_SIZE]; 47 | 48 | static void n64Init(void) 49 | { 50 | // rumble on debug 51 | DDRC |= 0x01; // PC0 52 | PORTC &= ~0x01; 53 | n64Update(); 54 | } 55 | 56 | #define RSTATE_INIT 0 57 | #define RSTATE_OFF 1 58 | #define RSTATE_TURNON 2 59 | #define RSTATE_ON 3 60 | #define RSTATE_TURNOFF 4 61 | #define RSTATE_UNAVAILABLE 5 62 | static unsigned char n64_rumble_state = RSTATE_UNAVAILABLE; 63 | unsigned char tmpdata[40]; 64 | 65 | static char initRumble(void) 66 | { 67 | int count; 68 | 69 | tmpdata[0] = N64_EXPANSION_WRITE; 70 | tmpdata[1] = 0x80; 71 | tmpdata[2] = 0x01; 72 | memset(tmpdata+3, 0x80, 32); 73 | 74 | /* Note: The old test (count > 0) was not reliable. */ 75 | count = gcn64_transaction(tmpdata, 35); 76 | if (count == 8) 77 | return 0; 78 | 79 | return -1; 80 | } 81 | 82 | static char controlRumble(char enable) 83 | { 84 | int count; 85 | 86 | tmpdata[0] = N64_EXPANSION_WRITE; 87 | tmpdata[1] = 0xc0; 88 | tmpdata[2] = 0x1b; 89 | memset(tmpdata+3, enable ? 0x01 : 0x00, 32); 90 | count = gcn64_transaction(tmpdata, 35); 91 | if (count == 8) 92 | return 0; 93 | 94 | return -1; 95 | } 96 | 97 | static char n64Update(void) 98 | { 99 | int i; 100 | unsigned char count; 101 | unsigned char x,y; 102 | unsigned char btns1, btns2; 103 | unsigned char rb1, rb2; 104 | unsigned char caps[3]; 105 | 106 | /* Pad answer to N64_GET_CAPABILITIES 107 | * 108 | * 0x050000 : 0000 0101 0000 0000 0000 0000 : No expansion pack 109 | * 0x050001 : 0000 0101 0000 0000 0000 0001 : With expansion pack 110 | * 0x050002 : 0000 0101 0000 0000 0000 0010 : Expansion pack removed 111 | * 112 | * Bit 0 tells us if there is something connected to the expansion port. 113 | * Bit 1 tells is if there was something connected that has been removed. 114 | */ 115 | tmpdata[0] = N64_GET_CAPABILITIES; 116 | count = gcn64_transaction(tmpdata, 1); 117 | if (count != N64_CAPS_REPLY_LENGTH) { 118 | // a failed read could mean the pack or controller was gone. Init 119 | // will be necessary next time we detect a pack is present. 120 | n64_rumble_state = RSTATE_INIT; 121 | return -1; 122 | } 123 | 124 | caps[0] = gcn64_protocol_getByte(0); 125 | caps[1] = gcn64_protocol_getByte(8); 126 | caps[2] = gcn64_protocol_getByte(16); 127 | 128 | /* Detect when a pack becomes present and schedule initialisation when it happens. */ 129 | if ((caps[2] & 0x01) && (n64_rumble_state == RSTATE_UNAVAILABLE)) { 130 | n64_rumble_state = RSTATE_INIT; 131 | } 132 | 133 | /* Detect when a pack is removed. */ 134 | if (!(caps[2] & 0x01) || (caps[2] & 0x02) ) { 135 | n64_rumble_state = RSTATE_UNAVAILABLE; 136 | } 137 | #ifdef BUTTON_A_RUMBLE_TEST 138 | must_rumble = force_rumble; 139 | #endif 140 | 141 | switch (n64_rumble_state) 142 | { 143 | case RSTATE_INIT: 144 | /* Retry until the controller answers with a full byte. */ 145 | if (initRumble() != 0) { 146 | if (initRumble() != 0) { 147 | n64_rumble_state = RSTATE_UNAVAILABLE; 148 | } 149 | break; 150 | } 151 | 152 | if (must_rumble) { 153 | controlRumble(1); 154 | n64_rumble_state = RSTATE_ON; 155 | } else { 156 | controlRumble(0); 157 | n64_rumble_state = RSTATE_OFF; 158 | } 159 | break; 160 | 161 | case RSTATE_TURNON: 162 | if (0 == controlRumble(1)) { 163 | n64_rumble_state = RSTATE_ON; 164 | } 165 | break; 166 | 167 | case RSTATE_TURNOFF: 168 | if (0 == controlRumble(0)) { 169 | n64_rumble_state = RSTATE_OFF; 170 | } 171 | break; 172 | 173 | case RSTATE_ON: 174 | if (!must_rumble) { 175 | controlRumble(0); 176 | n64_rumble_state = RSTATE_OFF; 177 | } 178 | break; 179 | 180 | case RSTATE_OFF: 181 | if (must_rumble) { 182 | controlRumble(1); 183 | n64_rumble_state = RSTATE_ON; 184 | } 185 | break; 186 | } 187 | 188 | tmpdata[0] = N64_GET_STATUS; 189 | count = gcn64_transaction(tmpdata, 1); 190 | if (count != N64_GET_STATUS_REPLY_LENGTH) { 191 | return -1; 192 | } 193 | 194 | /* 195 | Bit Function 196 | 0 A 197 | 1 B 198 | 2 Z 199 | 3 Start 200 | 4 Directional Up 201 | 5 Directional Down 202 | 6 Directional Left 203 | 7 Directional Right 204 | 8 unknown (always 0) 205 | 9 unknown (always 0) 206 | 10 L 207 | 11 R 208 | 12 C Up 209 | 13 C Down 210 | 14 C Left 211 | 15 C Right 212 | 16-23: analog X axis 213 | 24-31: analog Y axis 214 | */ 215 | 216 | btns1 = gcn64_protocol_getByte(0); 217 | btns2 = gcn64_protocol_getByte(8); 218 | x = gcn64_protocol_getByte(16); // X axis 219 | y = gcn64_protocol_getByte(24); // Y axis 220 | 221 | #ifdef BUTTON_A_RUMBLE_TEST 222 | if (btns1 & 0x80) { 223 | force_rumble = 1; 224 | } else { 225 | force_rumble = 0; 226 | } 227 | #endif 228 | 229 | // Remap buttons as they always were by this 230 | // adapter. Might change in v3 when a N64 231 | // specific report descriptor will be used. 232 | // 233 | rb1 = rb2 = 0; 234 | for (i=0; i<4; i++) // A B Z START 235 | rb1 |= (btns1 & (0x80 >> i)) ? (0x01<> i) ? (0x10<> i) ? (0x01<> i) ? (0x04< 10.6666666 cycles per bit, 85.333333333 cycles per byte 29 | ; Numbers in brackets are clocks counted from center of last sync bit 30 | ; when instruction starts 31 | 32 | USB_INTR_VECTOR: 33 | ;order of registers pushed: YL, SREG YH, [sofError], bitcnt, shift, x1, x2, x3, x4, cnt 34 | push YL ;[-25] push only what is necessary to sync with edge ASAP 35 | in YL, SREG ;[-23] 36 | push YL ;[-22] 37 | push YH ;[-20] 38 | ;---------------------------------------------------------------------------- 39 | ; Synchronize with sync pattern: 40 | ;---------------------------------------------------------------------------- 41 | ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] 42 | ;sync up with J to K edge during sync pattern -- use fastest possible loops 43 | ;The first part waits at most 1 bit long since we must be in sync pattern. 44 | ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to 45 | ;waitForJ, ensure that this prerequisite is met. 46 | waitForJ: 47 | inc YL 48 | sbis USBIN, USBMINUS 49 | brne waitForJ ; just make sure we have ANY timeout 50 | waitForK: 51 | ;The following code results in a sampling window of < 1/4 bit which meets the spec. 52 | sbis USBIN, USBMINUS ;[-15] 53 | rjmp foundK ;[-14] 54 | sbis USBIN, USBMINUS 55 | rjmp foundK 56 | sbis USBIN, USBMINUS 57 | rjmp foundK 58 | sbis USBIN, USBMINUS 59 | rjmp foundK 60 | sbis USBIN, USBMINUS 61 | rjmp foundK 62 | sbis USBIN, USBMINUS 63 | rjmp foundK 64 | #if USB_COUNT_SOF 65 | lds YL, usbSofCount 66 | inc YL 67 | sts usbSofCount, YL 68 | #endif /* USB_COUNT_SOF */ 69 | #ifdef USB_SOF_HOOK 70 | USB_SOF_HOOK 71 | #endif 72 | rjmp sofError 73 | foundK: ;[-12] 74 | ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for center sampling] 75 | ;we have 1 bit time for setup purposes, then sample again. Numbers in brackets 76 | ;are cycles from center of first sync (double K) bit after the instruction 77 | push bitcnt ;[-12] 78 | ; [---] ;[-11] 79 | lds YL, usbInputBufOffset;[-10] 80 | ; [---] ;[-9] 81 | clr YH ;[-8] 82 | subi YL, lo8(-(usbRxBuf));[-7] [rx loop init] 83 | sbci YH, hi8(-(usbRxBuf));[-6] [rx loop init] 84 | push shift ;[-5] 85 | ; [---] ;[-4] 86 | ldi bitcnt, 0x55 ;[-3] [rx loop init] 87 | sbis USBIN, USBMINUS ;[-2] we want two bits K (sample 2 cycles too early) 88 | rjmp haveTwoBitsK ;[-1] 89 | pop shift ;[0] undo the push from before 90 | pop bitcnt ;[2] undo the push from before 91 | rjmp waitForK ;[4] this was not the end of sync, retry 92 | ; The entire loop from waitForK until rjmp waitForK above must not exceed two 93 | ; bit times (= 21 cycles). 94 | 95 | ;---------------------------------------------------------------------------- 96 | ; push more registers and initialize values while we sample the first bits: 97 | ;---------------------------------------------------------------------------- 98 | haveTwoBitsK: 99 | push x1 ;[1] 100 | push x2 ;[3] 101 | push x3 ;[5] 102 | ldi shift, 0 ;[7] 103 | ldi x3, 1<<4 ;[8] [rx loop init] first sample is inverse bit, compensate that 104 | push x4 ;[9] == leap 105 | 106 | in x1, USBIN ;[11] <-- sample bit 0 107 | andi x1, USBMASK ;[12] 108 | bst x1, USBMINUS ;[13] 109 | bld shift, 7 ;[14] 110 | push cnt ;[15] 111 | ldi leap, 0 ;[17] [rx loop init] 112 | ldi cnt, USB_BUFSIZE;[18] [rx loop init] 113 | rjmp rxbit1 ;[19] arrives at [21] 114 | 115 | ;---------------------------------------------------------------------------- 116 | ; Receiver loop (numbers in brackets are cycles within byte after instr) 117 | ;---------------------------------------------------------------------------- 118 | 119 | ; duration of unstuffing code should be 10.66666667 cycles. We adjust "leap" 120 | ; accordingly to approximate this value in the long run. 121 | 122 | unstuff6: 123 | andi x2, USBMASK ;[03] 124 | ori x3, 1<<6 ;[04] will not be shifted any more 125 | andi shift, ~0x80;[05] 126 | mov x1, x2 ;[06] sampled bit 7 is actually re-sampled bit 6 127 | subi leap, -1 ;[07] total duration = 11 bits -> subtract 1/3 128 | rjmp didUnstuff6 ;[08] 129 | 130 | unstuff7: 131 | ori x3, 1<<7 ;[09] will not be shifted any more 132 | in x2, USBIN ;[00] [10] re-sample bit 7 133 | andi x2, USBMASK ;[01] 134 | andi shift, ~0x80;[02] 135 | subi leap, 2 ;[03] total duration = 10 bits -> add 1/3 136 | rjmp didUnstuff7 ;[04] 137 | 138 | unstuffEven: 139 | ori x3, 1<<6 ;[09] will be shifted right 6 times for bit 0 140 | in x1, USBIN ;[00] [10] 141 | andi shift, ~0x80;[01] 142 | andi x1, USBMASK ;[02] 143 | breq se0 ;[03] 144 | subi leap, -1 ;[04] total duration = 11 bits -> subtract 1/3 145 | nop2 ;[05] 146 | rjmp didUnstuffE ;[06] 147 | 148 | unstuffOdd: 149 | ori x3, 1<<5 ;[09] will be shifted right 4 times for bit 1 150 | in x2, USBIN ;[00] [10] 151 | andi shift, ~0x80;[01] 152 | andi x2, USBMASK ;[02] 153 | breq se0 ;[03] 154 | subi leap, -1 ;[04] total duration = 11 bits -> subtract 1/3 155 | nop2 ;[05] 156 | rjmp didUnstuffO ;[06] 157 | 158 | rxByteLoop: 159 | andi x1, USBMASK ;[03] 160 | eor x2, x1 ;[04] 161 | subi leap, 1 ;[05] 162 | brpl skipLeap ;[06] 163 | subi leap, -3 ;1 one leap cycle every 3rd byte -> 85 + 1/3 cycles per byte 164 | nop ;1 165 | skipLeap: 166 | subi x2, 1 ;[08] 167 | ror shift ;[09] 168 | didUnstuff6: 169 | cpi shift, 0xfc ;[10] 170 | in x2, USBIN ;[00] [11] <-- sample bit 7 171 | brcc unstuff6 ;[01] 172 | andi x2, USBMASK ;[02] 173 | eor x1, x2 ;[03] 174 | subi x1, 1 ;[04] 175 | ror shift ;[05] 176 | didUnstuff7: 177 | cpi shift, 0xfc ;[06] 178 | brcc unstuff7 ;[07] 179 | eor x3, shift ;[08] reconstruct: x3 is 1 at bit locations we changed, 0 at others 180 | st y+, x3 ;[09] store data 181 | rxBitLoop: 182 | in x1, USBIN ;[00] [11] <-- sample bit 0/2/4 183 | andi x1, USBMASK ;[01] 184 | eor x2, x1 ;[02] 185 | andi x3, 0x3f ;[03] topmost two bits reserved for 6 and 7 186 | subi x2, 1 ;[04] 187 | ror shift ;[05] 188 | cpi shift, 0xfc ;[06] 189 | brcc unstuffEven ;[07] 190 | didUnstuffE: 191 | lsr x3 ;[08] 192 | lsr x3 ;[09] 193 | rxbit1: 194 | in x2, USBIN ;[00] [10] <-- sample bit 1/3/5 195 | andi x2, USBMASK ;[01] 196 | breq se0 ;[02] 197 | eor x1, x2 ;[03] 198 | subi x1, 1 ;[04] 199 | ror shift ;[05] 200 | cpi shift, 0xfc ;[06] 201 | brcc unstuffOdd ;[07] 202 | didUnstuffO: 203 | subi bitcnt, 0xab;[08] == addi 0x55, 0x55 = 0x100/3 204 | brcs rxBitLoop ;[09] 205 | 206 | subi cnt, 1 ;[10] 207 | in x1, USBIN ;[00] [11] <-- sample bit 6 208 | brcc rxByteLoop ;[01] 209 | rjmp overflow 210 | 211 | macro POP_STANDARD ; 14 cycles 212 | pop cnt 213 | pop x4 214 | pop x3 215 | pop x2 216 | pop x1 217 | pop shift 218 | pop bitcnt 219 | endm 220 | macro POP_RETI ; 7 cycles 221 | pop YH 222 | pop YL 223 | out SREG, YL 224 | pop YL 225 | endm 226 | 227 | #include "asmcommon.inc" 228 | 229 | ; USB spec says: 230 | ; idle = J 231 | ; J = (D+ = 0), (D- = 1) 232 | ; K = (D+ = 1), (D- = 0) 233 | ; Spec allows 7.5 bit times from EOP to SOP for replies 234 | 235 | bitstuffN: 236 | eor x1, x4 ;[5] 237 | ldi x2, 0 ;[6] 238 | nop2 ;[7] 239 | nop ;[9] 240 | out USBOUT, x1 ;[10] <-- out 241 | rjmp didStuffN ;[0] 242 | 243 | bitstuff6: 244 | eor x1, x4 ;[5] 245 | ldi x2, 0 ;[6] Carry is zero due to brcc 246 | rol shift ;[7] compensate for ror shift at branch destination 247 | rjmp didStuff6 ;[8] 248 | 249 | bitstuff7: 250 | ldi x2, 0 ;[2] Carry is zero due to brcc 251 | rjmp didStuff7 ;[3] 252 | 253 | 254 | sendNakAndReti: 255 | ldi x3, USBPID_NAK ;[-18] 256 | rjmp sendX3AndReti ;[-17] 257 | sendAckAndReti: 258 | ldi cnt, USBPID_ACK ;[-17] 259 | sendCntAndReti: 260 | mov x3, cnt ;[-16] 261 | sendX3AndReti: 262 | ldi YL, 20 ;[-15] x3==r20 address is 20 263 | ldi YH, 0 ;[-14] 264 | ldi cnt, 2 ;[-13] 265 | ; rjmp usbSendAndReti fallthrough 266 | 267 | ;usbSend: 268 | ;pointer to data in 'Y' 269 | ;number of bytes in 'cnt' -- including sync byte [range 2 ... 12] 270 | ;uses: x1...x4, btcnt, shift, cnt, Y 271 | ;Numbers in brackets are time since first bit of sync pattern is sent 272 | ;We don't match the transfer rate exactly (don't insert leap cycles every third 273 | ;byte) because the spec demands only 1.5% precision anyway. 274 | usbSendAndReti: ; 12 cycles until SOP 275 | in x2, USBDDR ;[-12] 276 | ori x2, USBMASK ;[-11] 277 | sbi USBOUT, USBMINUS;[-10] prepare idle state; D+ and D- must have been 0 (no pullups) 278 | in x1, USBOUT ;[-8] port mirror for tx loop 279 | out USBDDR, x2 ;[-7] <- acquire bus 280 | ; need not init x2 (bitstuff history) because sync starts with 0 281 | ldi x4, USBMASK ;[-6] exor mask 282 | ldi shift, 0x80 ;[-5] sync byte is first byte sent 283 | txByteLoop: 284 | ldi bitcnt, 0x35 ;[-4] [6] binary 0011 0101 285 | txBitLoop: 286 | sbrs shift, 0 ;[-3] [7] 287 | eor x1, x4 ;[-2] [8] 288 | out USBOUT, x1 ;[-1] [9] <-- out N 289 | ror shift ;[0] [10] 290 | ror x2 ;[1] 291 | didStuffN: 292 | cpi x2, 0xfc ;[2] 293 | brcc bitstuffN ;[3] 294 | lsr bitcnt ;[4] 295 | brcc txBitLoop ;[5] 296 | brne txBitLoop ;[6] 297 | 298 | sbrs shift, 0 ;[7] 299 | eor x1, x4 ;[8] 300 | didStuff6: 301 | out USBOUT, x1 ;[-1] [9] <-- out 6 302 | ror shift ;[0] [10] 303 | ror x2 ;[1] 304 | cpi x2, 0xfc ;[2] 305 | brcc bitstuff6 ;[3] 306 | ror shift ;[4] 307 | didStuff7: 308 | ror x2 ;[5] 309 | sbrs x2, 7 ;[6] 310 | eor x1, x4 ;[7] 311 | nop ;[8] 312 | cpi x2, 0xfc ;[9] 313 | out USBOUT, x1 ;[-1][10] <-- out 7 314 | brcc bitstuff7 ;[0] [11] 315 | ld shift, y+ ;[1] 316 | dec cnt ;[3] 317 | brne txByteLoop ;[4] 318 | ;make SE0: 319 | cbr x1, USBMASK ;[5] prepare SE0 [spec says EOP may be 21 to 25 cycles] 320 | lds x2, usbNewDeviceAddr;[6] 321 | lsl x2 ;[8] we compare with left shifted address 322 | subi YL, 20 + 2 ;[9] Only assign address on data packets, not ACK/NAK in x3 323 | sbci YH, 0 ;[10] 324 | out USBOUT, x1 ;[11] <-- out SE0 -- from now 2 bits = 22 cycles until bus idle 325 | ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: 326 | ;set address only after data packet was sent, not after handshake 327 | breq skipAddrAssign ;[0] 328 | sts usbDeviceAddr, x2; if not skipped: SE0 is one cycle longer 329 | skipAddrAssign: 330 | ;end of usbDeviceAddress transfer 331 | ldi x2, 1< 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | #include 18 | #include 19 | 20 | #include "gcn64_protocol.h" 21 | 22 | #undef FORCE_KEYBOARD 23 | #undef FORCE_GAMECUBE 24 | 25 | // I have a MadCatz micro-con contorller which misbehaves when 26 | // N64 timing (3/1 ratio) is used. None of my N64 controllers 27 | // misbehave using gamecube timings, but as this adapter is not 28 | // easily updatable, I won't take the risk of changing a parameter 29 | // that has been constant for years. 30 | // 31 | // But the option is there for those of you who are going to compile 32 | // the project and are willing to change this. 33 | #undef GAMECUBE_TIMINGS // If not defined, use N64 timings 34 | 35 | #define GCN64_BUF_SIZE 300 36 | static volatile unsigned char gcn64_workbuf[GCN64_BUF_SIZE]; 37 | 38 | /******** IO port definitions **************/ 39 | #define GCN64_DATA_PORT PORTC 40 | #define GCN64_DATA_DDR DDRC 41 | #define GCN64_DATA_PIN PINC 42 | #define GCN64_DATA_BIT (1<<5) 43 | 44 | /* 45 | * \brief Explode bytes to bits 46 | * \param bytes The input byte array 47 | * \param num_bytes The number of input bytes 48 | * \param workbuf_bit_offset The offset to start writing at 49 | * \return number of bits (i.e. written output bytes) 50 | * 51 | * 1 input byte = 8 output bytes, where each output byte is zero or non-zero depending 52 | * on the input byte bits, starting with the most significant one. 53 | */ 54 | static int bitsToWorkbufBytes(unsigned char *bytes, int num_bytes, int workbuf_bit_offset) 55 | { 56 | int i, bit; 57 | unsigned char p; 58 | 59 | if (num_bytes * 8 > GCN64_BUF_SIZE) 60 | return 0; 61 | 62 | for (i=0,bit=0; i>=1) { 64 | gcn64_workbuf[bit+workbuf_bit_offset] = bytes[i] & p; 65 | bit++; 66 | } 67 | } 68 | 69 | return bit; 70 | } 71 | 72 | /* Read a byte from the buffer (where 1 byte is 1 bit). 73 | * MSb first. 74 | */ 75 | unsigned char gcn64_protocol_getByte(int offset) 76 | { 77 | unsigned char val, b; 78 | unsigned char volatile *addr = gcn64_workbuf + offset; 79 | 80 | for (b=0x80, val=0; b; b>>=1) 81 | { 82 | if (*addr) 83 | val |= b; 84 | addr++; 85 | } 86 | return val; 87 | } 88 | 89 | void gcn64_protocol_getBytes(int offset, int n_bytes, unsigned char *dstbuf) 90 | { 91 | int i; 92 | 93 | for (i=0; i 127 (approx 50uS timeout) 136 | " sbic %2, 5 \n" 137 | " rjmp waitlow_lp \n" 138 | 139 | " inc %0 \n" // count this timed low level 140 | " breq overflow \n" // > 255 141 | " st z+,r16 \n" 142 | 143 | "waithigh:\n" 144 | " ldi r16, %4 \n" 145 | "waithigh_lp:\n" 146 | " inc r16 \n" 147 | " brmi timeout \n" // > 127 148 | " sbis %2, 5 \n" 149 | " rjmp waithigh_lp \n" 150 | 151 | " inc %0 \n" // count this timed high level 152 | " breq overflow \n" // > 255 153 | " st z+,r16 \n" 154 | 155 | " rjmp waitlow \n" 156 | 157 | "overflow: \n" 158 | "timeout: \n" 159 | " pop r31 \n" // restore z 160 | " pop r30 \n" // restore z 161 | 162 | : "=&r" (count) // %0 163 | : "z" ((unsigned char volatile *)gcn64_workbuf), // %1 164 | "I" (_SFR_IO_ADDR(GCN64_DATA_PIN)), // %2 165 | "I" (_SFR_IO_ADDR(PORTB)), // %3 166 | "M" (TIMING_OFFSET) // %4 167 | : "r16" 168 | ); 169 | 170 | return count; 171 | } 172 | 173 | static void gcn64_sendBytes(unsigned char *data, unsigned char n_bytes) 174 | { 175 | unsigned int bits; 176 | 177 | if (n_bytes == 0) 178 | return; 179 | 180 | // Explode the data to one byte per bit for very easy transmission in assembly. 181 | // This trades memory for ease of implementation. 182 | bits = bitsToWorkbufBytes(data, n_bytes, 0); 183 | if (!bits) 184 | return; 185 | 186 | // the value of the gpio is pre-configured to low. We simulate 187 | // an open drain output by toggling the direction. 188 | #define PULL_DATA " sbi %0, 5 \n" 189 | #define RELEASE_DATA " cbi %0, 5 \n" 190 | 191 | // busy looping delays based on busy loop and nop tuning. 192 | // valid for 12Mhz clock. 193 | #ifdef GAMECUBE_TIMINGS // (3.6/1.5us) 194 | #define DLY_SHORT_1ST "ldi r17, 2\n rcall sb_dly%=\nnop\nnop\n " 195 | #define DLY_LARGE_1ST "ldi r17, 11\n rcall sb_dly%=\nnop\n" 196 | #define DLY_SHORT_2ND "nop\nnop\nnop\nnop\nnop\n" 197 | #define DLY_LARGE_2ND "ldi r17, 7\n rcall sb_dly%=\n nop\nnop\n" 198 | #warning USING GAMECUBE TIMINGS 199 | #else // N64 timings (3/1us) 200 | #define DLY_SHORT_1ST "ldi r17, 1\n rcall sb_dly%=\n " 201 | #define DLY_LARGE_1ST "ldi r17, 9\n rcall sb_dly%=\n" 202 | #define DLY_SHORT_2ND "\n" 203 | #define DLY_LARGE_2ND "ldi r17, 5\n rcall sb_dly%=\n nop\nnop\n" 204 | #endif 205 | asm volatile( 206 | // Save the modified input operands 207 | " push r28 \n" // y 208 | " push r29 \n" 209 | " push r30 \n" // z 210 | " push r31 \n" 211 | 212 | "sb_loop%=: \n" 213 | " ld r16, z+ \n" 214 | " tst r16 \n" 215 | " breq sb_send0%= \n" 216 | " brne sb_send1%= \n" 217 | 218 | " rjmp sb_end%= \n" // not reached 219 | 220 | 221 | "sb_send0%=: \n" 222 | " nop \n" 223 | PULL_DATA 224 | DLY_LARGE_1ST 225 | RELEASE_DATA 226 | DLY_SHORT_2ND 227 | " sbiw %1, 1 \n" 228 | " brne sb_loop%= \n" 229 | " rjmp sb_end%= \n" 230 | 231 | "sb_send1%=: \n" 232 | PULL_DATA 233 | DLY_SHORT_1ST 234 | RELEASE_DATA 235 | DLY_LARGE_2ND 236 | " sbiw %1, 1 \n" 237 | " brne sb_loop%= \n" 238 | " rjmp sb_end%= \n" 239 | 240 | // delay sub (arg r17) 241 | "sb_dly%=: \n" 242 | " dec r17 \n" 243 | " brne sb_dly%= \n" 244 | " ret \n" 245 | 246 | 247 | "sb_end%=:\n" 248 | // going here is fast so we need to extend the last 249 | // delay by 500nS 250 | " nop\n " 251 | " pop r31 \n" 252 | " pop r30 \n" 253 | " pop r29 \n" 254 | " pop r28 \n" 255 | PULL_DATA 256 | DLY_SHORT_1ST 257 | RELEASE_DATA 258 | 259 | // Now, we need to loop until the wire is high to 260 | // prevent the reception code from thinking this is 261 | // the beginning of the first reply bit. 262 | 263 | " ldi r16, 0xff \n" // setup a timeout 264 | "sb_waitHigh%=: \n" 265 | " dec r16 \n" // decrement timeout 266 | " breq sb_wait_high_done%= \n" // handle timeout condition 267 | " sbis %3, 5 \n" // Read the port 268 | " rjmp sb_waitHigh%= \n" 269 | "sb_wait_high_done%=:\n" 270 | : 271 | : "I" (_SFR_IO_ADDR(GCN64_DATA_DDR)), // %0 272 | "w" (bits), // %1 273 | "z" ((unsigned char volatile *)gcn64_workbuf), // %2 274 | "I" (_SFR_IO_ADDR(GCN64_DATA_PIN)) // %3 275 | : "r16", "r17"); 276 | } 277 | 278 | /* \brief Decode the received length of low/high states to byte-per-bit format 279 | * 280 | * The result is in workbuf. 281 | * 282 | **/ 283 | static void gcn64_decodeWorkbuf(unsigned char count) 284 | { 285 | unsigned char i; 286 | volatile unsigned char *output = gcn64_workbuf; 287 | volatile unsigned char *input = gcn64_workbuf; 288 | unsigned char t; 289 | 290 | // 291 | // ________ 292 | // ________/ 293 | // 294 | // [i*2] [i*2+1] 295 | // 296 | // ________________ 297 | // 0 : ____/ 298 | // ____ 299 | // 1 : ________________/ 300 | // 301 | // The timings on a real N64 are 302 | // 303 | // 0 : 1 us low, 3 us high 304 | // 1 : 3 us low, 1 us high 305 | // 306 | // However, HORI pads use something similar to 307 | // 308 | // 0 : 1.5 us low, 4.5 us high 309 | // 1 : 4.5 us low, 1.5 us high 310 | // 311 | // 312 | // No64 us = microseconds 313 | 314 | // This operation takes approximately 100uS on 64bit gamecube messages 315 | for (i=0; i> 8)&0x0f) { 461 | case 0x05: 462 | return CONTROLLER_IS_N64; 463 | 464 | case 0x09: // normal controllers 465 | case 0x0b: // Never saw this one, but it is mentionned above. 466 | return CONTROLLER_IS_GC; 467 | 468 | case 0x08: 469 | if (id == 0x0820) { 470 | // Ascii keyboard 471 | return CONTROLLER_IS_GC_KEYBOARD; 472 | } 473 | // wavebird, controller off. 474 | return CONTROLLER_IS_GC; 475 | 476 | default: 477 | return CONTROLLER_IS_UNKNOWN; 478 | } 479 | 480 | return 0; 481 | } 482 | 483 | 484 | -------------------------------------------------------------------------------- /usbdrv/Changelog.txt: -------------------------------------------------------------------------------- 1 | This file documents changes in the firmware-only USB driver for atmel's AVR 2 | microcontrollers. New entries are always appended to the end of the file. 3 | Scroll down to the bottom to see the most recent changes. 4 | 5 | 2005-04-01: 6 | - Implemented endpoint 1 as interrupt-in endpoint. 7 | - Moved all configuration options to usbconfig.h which is not part of the 8 | driver. 9 | - Changed interface for usbVendorSetup(). 10 | - Fixed compatibility with ATMega8 device. 11 | - Various minor optimizations. 12 | 13 | 2005-04-11: 14 | - Changed interface to application: Use usbFunctionSetup(), usbFunctionRead() 15 | and usbFunctionWrite() now. Added configuration options to choose which 16 | of these functions to compile in. 17 | - Assembler module delivers receive data non-inverted now. 18 | - Made register and bit names compatible with more AVR devices. 19 | 20 | 2005-05-03: 21 | - Allow address of usbRxBuf on any memory page as long as the buffer does 22 | not cross 256 byte page boundaries. 23 | - Better device compatibility: works with Mega88 now. 24 | - Code optimization in debugging module. 25 | - Documentation updates. 26 | 27 | 2006-01-02: 28 | - Added (free) default Vendor- and Product-IDs bought from voti.nl. 29 | - Added USBID-License.txt file which defines the rules for using the free 30 | shared VID/PID pair. 31 | - Added Readme.txt to the usbdrv directory which clarifies administrative 32 | issues. 33 | 34 | 2006-01-25: 35 | - Added "configured state" to become more standards compliant. 36 | - Added "HALT" state for interrupt endpoint. 37 | - Driver passes the "USB Command Verifier" test from usb.org now. 38 | - Made "serial number" a configuration option. 39 | - Minor optimizations, we now recommend compiler option "-Os" for best 40 | results. 41 | - Added a version number to usbdrv.h 42 | 43 | 2006-02-03: 44 | - New configuration variable USB_BUFFER_SECTION for the memory section where 45 | the USB rx buffer will go. This defaults to ".bss" if not defined. Since 46 | this buffer MUST NOT cross 256 byte pages (not even touch a page at the 47 | end), the user may want to pass a linker option similar to 48 | "-Wl,--section-start=.mybuffer=0x800060". 49 | - Provide structure for usbRequest_t. 50 | - New defines for USB constants. 51 | - Prepared for HID implementations. 52 | - Increased data size limit for interrupt transfers to 8 bytes. 53 | - New macro usbInterruptIsReady() to query interrupt buffer state. 54 | 55 | 2006-02-18: 56 | - Ensure that the data token which is sent as an ack to an OUT transfer is 57 | always zero sized. This fixes a bug where the host reports an error after 58 | sending an out transfer to the device, although all data arrived at the 59 | device. 60 | - Updated docs in usbdrv.h to reflect changed API in usbFunctionWrite(). 61 | 62 | * Release 2006-02-20 63 | 64 | - Give a compiler warning when compiling with debugging turned on. 65 | - Added Oleg Semyonov's changes for IAR-cc compatibility. 66 | - Added new (optional) functions usbDeviceConnect() and usbDeviceDisconnect() 67 | (also thanks to Oleg!). 68 | - Rearranged tests in usbPoll() to save a couple of instructions in the most 69 | likely case that no actions are pending. 70 | - We need a delay between the SET ADDRESS request until the new address 71 | becomes active. This delay was handled in usbPoll() until now. Since the 72 | spec says that the delay must not exceed 2ms, previous versions required 73 | aggressive polling during the enumeration phase. We have now moved the 74 | handling of the delay into the interrupt routine. 75 | - We must not reply with NAK to a SETUP transaction. We can only achieve this 76 | by making sure that the rx buffer is empty when SETUP tokens are expected. 77 | We therefore don't pass zero sized data packets from the status phase of 78 | a transfer to usbPoll(). This change MAY cause troubles if you rely on 79 | receiving a less than 8 bytes long packet in usbFunctionWrite() to 80 | identify the end of a transfer. usbFunctionWrite() will NEVER be called 81 | with a zero length. 82 | 83 | * Release 2006-03-14 84 | 85 | - Improved IAR C support: tiny memory model, more devices 86 | - Added template usbconfig.h file under the name usbconfig-prototype.h 87 | 88 | * Release 2006-03-26 89 | 90 | - Added provision for one more interrupt-in endpoint (endpoint 3). 91 | - Added provision for one interrupt-out endpoint (endpoint 1). 92 | - Added flowcontrol macros for USB. 93 | - Added provision for custom configuration descriptor. 94 | - Allow ANY two port bits for D+ and D-. 95 | - Merged (optional) receive endpoint number into global usbRxToken variable. 96 | - Use USB_CFG_IOPORTNAME instead of USB_CFG_IOPORT. We now construct the 97 | variable name from the single port letter instead of computing the address 98 | of related ports from the output-port address. 99 | 100 | * Release 2006-06-26 101 | 102 | - Updated documentation in usbdrv.h and usbconfig-prototype.h to reflect the 103 | new features. 104 | - Removed "#warning" directives because IAR does not understand them. Use 105 | unused static variables instead to generate a warning. 106 | - Do not include when compiling with IAR. 107 | - Introduced USB_CFG_DESCR_PROPS_* in usbconfig.h to configure how each 108 | USB descriptor should be handled. It is now possible to provide descriptor 109 | data in Flash, RAM or dynamically at runtime. 110 | - STALL is now a status in usbTxLen* instead of a message. We can now conform 111 | to the spec and leave the stall status pending until it is cleared. 112 | - Made usbTxPacketCnt1 and usbTxPacketCnt3 public. This allows the 113 | application code to reset data toggling on interrupt pipes. 114 | 115 | * Release 2006-07-18 116 | 117 | - Added an #if !defined __ASSEMBLER__ to the warning in usbdrv.h. This fixes 118 | an assembler error. 119 | - usbDeviceDisconnect() takes pull-up resistor to high impedance now. 120 | 121 | * Release 2007-02-01 122 | 123 | - Merged in some code size improvements from usbtiny (thanks to Dick 124 | Streefland for these optimizations!) 125 | - Special alignment requirement for usbRxBuf not required any more. Thanks 126 | again to Dick Streefland for this hint! 127 | - Reverted to "#warning" instead of unused static variables -- new versions 128 | of IAR CC should handle this directive. 129 | - Changed Open Source license to GNU GPL v2 in order to make linking against 130 | other free libraries easier. We no longer require publication of the 131 | circuit diagrams, but we STRONGLY encourage it. If you improve the driver 132 | itself, PLEASE grant us a royalty free license to your changes for our 133 | commercial license. 134 | 135 | * Release 2007-03-29 136 | 137 | - New configuration option "USB_PUBLIC" in usbconfig.h. 138 | - Set USB version number to 1.10 instead of 1.01. 139 | - Code used USB_CFG_DESCR_PROPS_STRING_DEVICE and 140 | USB_CFG_DESCR_PROPS_STRING_PRODUCT inconsistently. Changed all occurrences 141 | to USB_CFG_DESCR_PROPS_STRING_PRODUCT. 142 | - New assembler module for 16.5 MHz RC oscillator clock with PLL in receiver 143 | code. 144 | - New assembler module for 16 MHz crystal. 145 | - usbdrvasm.S contains common code only, clock-specific parts have been moved 146 | to usbdrvasm12.S, usbdrvasm16.S and usbdrvasm165.S respectively. 147 | 148 | * Release 2007-06-25 149 | 150 | - 16 MHz module: Do SE0 check in stuffed bits as well. 151 | 152 | * Release 2007-07-07 153 | 154 | - Define hi8(x) for IAR compiler to limit result to 8 bits. This is necessary 155 | for negative values. 156 | - Added 15 MHz module contributed by V. Bosch. 157 | - Interrupt vector name can now be configured. This is useful if somebody 158 | wants to use a different hardware interrupt than INT0. 159 | 160 | * Release 2007-08-07 161 | 162 | - Moved handleIn3 routine in usbdrvasm16.S so that relative jump range is 163 | not exceeded. 164 | - More config options: USB_RX_USER_HOOK(), USB_INITIAL_DATATOKEN, 165 | USB_COUNT_SOF 166 | - USB_INTR_PENDING can now be a memory address, not just I/O 167 | 168 | * Release 2007-09-19 169 | 170 | - Split out common parts of assembler modules into separate include file 171 | - Made endpoint numbers configurable so that given interface definitions 172 | can be matched. See USB_CFG_EP3_NUMBER in usbconfig-prototype.h. 173 | - Store endpoint number for interrupt/bulk-out so that usbFunctionWriteOut() 174 | can handle any number of endpoints. 175 | - Define usbDeviceConnect() and usbDeviceDisconnect() even if no 176 | USB_CFG_PULLUP_IOPORTNAME is defined. Directly set D+ and D- to 0 in this 177 | case. 178 | 179 | * Release 2007-12-01 180 | 181 | - Optimize usbDeviceConnect() and usbDeviceDisconnect() for less code size 182 | when USB_CFG_PULLUP_IOPORTNAME is not defined. 183 | 184 | * Release 2007-12-13 185 | 186 | - Renamed all include-only assembler modules from *.S to *.inc so that 187 | people don't add them to their project sources. 188 | - Distribute leap bits in tx loop more evenly for 16 MHz module. 189 | - Use "macro" and "endm" instead of ".macro" and ".endm" for IAR 190 | - Avoid compiler warnings for constant expr range by casting some values in 191 | USB descriptors. 192 | 193 | * Release 2008-01-21 194 | 195 | - Fixed bug in 15 and 16 MHz module where the new address set with 196 | SET_ADDRESS was already accepted at the next NAK or ACK we send, not at 197 | the next data packet we send. This caused problems when the host polled 198 | too fast. Thanks to Alexander Neumann for his help and patience debugging 199 | this issue! 200 | 201 | * Release 2008-02-05 202 | 203 | - Fixed bug in 16.5 MHz module where a register was used in the interrupt 204 | handler before it was pushed. This bug was introduced with version 205 | 2007-09-19 when common parts were moved to a separate file. 206 | - Optimized CRC routine (thanks to Reimar Doeffinger). 207 | 208 | * Release 2008-02-16 209 | 210 | - Removed outdated IAR compatibility stuff (code sections). 211 | - Added hook macros for USB_RESET_HOOK() and USB_SET_ADDRESS_HOOK(). 212 | - Added optional routine usbMeasureFrameLength() for calibration of the 213 | internal RC oscillator. 214 | 215 | * Release 2008-02-28 216 | 217 | - USB_INITIAL_DATATOKEN defaults to USBPID_DATA1 now, which means that we 218 | start with sending USBPID_DATA0. 219 | - Changed defaults in usbconfig-prototype.h 220 | - Added free USB VID/PID pair for MIDI class devices 221 | - Restructured AVR-USB as separate package, not part of PowerSwitch any more. 222 | 223 | * Release 2008-04-18 224 | 225 | - Restructured usbdrv.c so that it is easier to read and understand. 226 | - Better code optimization with gcc 4. 227 | - If a second interrupt in endpoint is enabled, also add it to config 228 | descriptor. 229 | - Added config option for long transfers (above 254 bytes), see 230 | USB_CFG_LONG_TRANSFERS in usbconfig.h. 231 | - Added 20 MHz module contributed by Jeroen Benschop. 232 | 233 | * Release 2008-05-13 234 | 235 | - Fixed bug in libs-host/hiddata.c function usbhidGetReport(): length 236 | was not incremented, pointer to length was incremented instead. 237 | - Added code to command line tool(s) which claims an interface. This code 238 | is disabled by default, but may be necessary on newer Linux kernels. 239 | - Added usbconfig.h option "USB_CFG_CHECK_DATA_TOGGLING". 240 | - New header "usbportability.h" prepares ports to other development 241 | environments. 242 | - Long transfers (above 254 bytes) did not work when usbFunctionRead() was 243 | used to supply the data. Fixed this bug. [Thanks to Alexander Neumann!] 244 | - In hiddata.c (example code for sending/receiving data over HID), use 245 | USB_RECIP_DEVICE instead of USB_RECIP_INTERFACE for control transfers so 246 | that we need not claim the interface. 247 | - in usbPoll() loop 20 times polling for RESET state instead of 10 times. 248 | This accounts for the higher clock rates we now support. 249 | - Added a module for 12.8 MHz RC oscillator with PLL in receiver loop. 250 | - Added hook to SOF code so that oscillator can be tuned to USB frame clock. 251 | - Added timeout to waitForJ loop. Helps preventing unexpected hangs. 252 | - Added example code for oscillator tuning to libs-device (thanks to 253 | Henrik Haftmann for the idea to this routine). 254 | - Implemented option USB_CFG_SUPPRESS_INTR_CODE. 255 | 256 | * Release 2008-10-22 257 | 258 | - Fixed libs-device/osctune.h: OSCCAL is memory address on ATMega88 and 259 | similar, not offset of 0x20 needs to be added. 260 | - Allow distribution under GPLv3 for those who have to link against other 261 | code distributed under GPLv3. 262 | 263 | * Release 2008-11-26 264 | 265 | - Removed libusb-win32 dependency for hid-data example in Makefile.windows. 266 | It was never required and confused many people. 267 | - Added extern uchar usbRxToken to usbdrv.h. 268 | - Integrated a module with CRC checks at 18 MHz by Lukas Schrittwieser. 269 | 270 | * Release 2009-03-23 271 | 272 | - Hid-mouse example used settings from hid-data example, fixed that. 273 | - Renamed project to V-USB due to a trademark issue with Atmel(r). 274 | - Changed CommercialLicense.txt and USBID-License.txt to make the 275 | background of USB ID registration clearer. 276 | 277 | * Release 2009-04-15 278 | 279 | - Changed CommercialLicense.txt to reflect the new range of PIDs from 280 | Jason Kotzin. 281 | - Removed USBID-License.txt in favor of USB-IDs-for-free.txt and 282 | USB-ID-FAQ.txt 283 | - Fixed a bug in the 12.8 MHz module: End Of Packet decection was made in 284 | the center between bit 0 and 1 of each byte. This is where the data lines 285 | are expected to change and the sampled data may therefore be nonsense. 286 | We therefore check EOP ONLY if bits 0 AND 1 have both been read as 0 on D-. 287 | - Fixed a bitstuffing problem in the 16 MHz module: If bit 6 was stuffed, 288 | the unstuffing code in the receiver routine was 1 cycle too long. If 289 | multiple bytes had the unstuffing in bit 6, the error summed up until the 290 | receiver was out of sync. 291 | - Included option for faster CRC routine. 292 | Thanks to Slawomir Fras (BoskiDialer) for this code! 293 | - Updated bits in Configuration Descriptor's bmAttributes according to 294 | USB 1.1 (in particular bit 7, it is a must-be-set bit now). 295 | 296 | * Release 2009-08-22 297 | 298 | - Moved first DBG1() after odDebugInit() in all examples. 299 | - Use vector INT0_vect instead of SIG_INTERRUPT0 if defined. This makes 300 | V-USB compatible with the new "p" suffix devices (e.g. ATMega328p). 301 | - USB_CFG_CLOCK_KHZ setting is now required in usbconfig.h (no default any 302 | more). 303 | - New option USB_CFG_DRIVER_FLASH_PAGE allows boot loaders on devices with 304 | more than 64 kB flash. 305 | - Built-in configuration descriptor allows custom definition for second 306 | endpoint now. 307 | 308 | * Release 2010-07-15 309 | 310 | - Fixed bug in usbDriverSetup() which prevented descriptor sizes above 255 311 | bytes. 312 | - Avoid a compiler warning for unused parameter in usbHandleResetHook() when 313 | compiler option -Wextra is enabled. 314 | - Fixed wrong hex value for some IDs in USB-IDs-for-free.txt. 315 | - Keep a define for USBATTR_BUSPOWER, although the flag does not exist 316 | in USB 1.1 any more. Set it to 0. This is for backward compatibility. 317 | 318 | * Release 2012-01-09 319 | 320 | - Define a separate (defined) type for usbMsgPtr so that projects using a 321 | tiny memory model can define it to an 8 bit type in usbconfig.h. This 322 | change also saves a couple of bytes when using a scalar 16 bit type. 323 | - Inserted "const" keyword for all PROGMEM declarations because new GCC 324 | requires it. 325 | - Fixed problem with dependence of usbportability.h on usbconfig.h. This 326 | problem occurred with IAR CC only. 327 | - Prepared repository for github.com. 328 | 329 | * Release 2012-12-06 -------------------------------------------------------------------------------- /usbdrv/usbdrvasm20.inc: -------------------------------------------------------------------------------- 1 | /* Name: usbdrvasm20.inc 2 | * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers 3 | * Author: Jeroen Benschop 4 | * Based on usbdrvasm16.inc from Christian Starkjohann 5 | * Creation Date: 2008-03-05 6 | * Tabsize: 4 7 | * Copyright: (c) 2008 by Jeroen Benschop and OBJECTIVE DEVELOPMENT Software GmbH 8 | * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) 9 | */ 10 | 11 | /* Do not link this file! Link usbdrvasm.S instead, which includes the 12 | * appropriate implementation! 13 | */ 14 | 15 | /* 16 | General Description: 17 | This file is the 20 MHz version of the asssembler part of the USB driver. It 18 | requires a 20 MHz crystal (not a ceramic resonator and not a calibrated RC 19 | oscillator). 20 | 21 | See usbdrv.h for a description of the entire driver. 22 | 23 | Since almost all of this code is timing critical, don't change unless you 24 | really know what you are doing! Many parts require not only a maximum number 25 | of CPU cycles, but even an exact number of cycles! 26 | */ 27 | 28 | #define leap2 x3 29 | #ifdef __IAR_SYSTEMS_ASM__ 30 | #define nextInst $+2 31 | #else 32 | #define nextInst .+0 33 | #endif 34 | 35 | ;max stack usage: [ret(2), YL, SREG, YH, bitcnt, shift, x1, x2, x3, x4, cnt] = 12 bytes 36 | ;nominal frequency: 20 MHz -> 13.333333 cycles per bit, 106.666667 cycles per byte 37 | ; Numbers in brackets are clocks counted from center of last sync bit 38 | ; when instruction starts 39 | ;register use in receive loop: 40 | ; shift assembles the byte currently being received 41 | ; x1 holds the D+ and D- line state 42 | ; x2 holds the previous line state 43 | ; x4 (leap) is used to add a leap cycle once every three bytes received 44 | ; X3 (leap2) is used to add a leap cycle once every three stuff bits received 45 | ; bitcnt is used to determine when a stuff bit is due 46 | ; cnt holds the number of bytes left in the receive buffer 47 | 48 | USB_INTR_VECTOR: 49 | ;order of registers pushed: YL, SREG YH, [sofError], bitcnt, shift, x1, x2, x3, x4, cnt 50 | push YL ;[-28] push only what is necessary to sync with edge ASAP 51 | in YL, SREG ;[-26] 52 | push YL ;[-25] 53 | push YH ;[-23] 54 | ;---------------------------------------------------------------------------- 55 | ; Synchronize with sync pattern: 56 | ;---------------------------------------------------------------------------- 57 | ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] 58 | ;sync up with J to K edge during sync pattern -- use fastest possible loops 59 | ;The first part waits at most 1 bit long since we must be in sync pattern. 60 | ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to 61 | ;waitForJ, ensure that this prerequisite is met. 62 | waitForJ: 63 | inc YL 64 | sbis USBIN, USBMINUS 65 | brne waitForJ ; just make sure we have ANY timeout 66 | waitForK: 67 | ;The following code results in a sampling window of < 1/4 bit which meets the spec. 68 | sbis USBIN, USBMINUS ;[-19] 69 | rjmp foundK ;[-18] 70 | sbis USBIN, USBMINUS 71 | rjmp foundK 72 | sbis USBIN, USBMINUS 73 | rjmp foundK 74 | sbis USBIN, USBMINUS 75 | rjmp foundK 76 | sbis USBIN, USBMINUS 77 | rjmp foundK 78 | sbis USBIN, USBMINUS 79 | rjmp foundK 80 | sbis USBIN, USBMINUS 81 | rjmp foundK 82 | sbis USBIN, USBMINUS 83 | rjmp foundK 84 | sbis USBIN, USBMINUS 85 | rjmp foundK 86 | #if USB_COUNT_SOF 87 | lds YL, usbSofCount 88 | inc YL 89 | sts usbSofCount, YL 90 | #endif /* USB_COUNT_SOF */ 91 | #ifdef USB_SOF_HOOK 92 | USB_SOF_HOOK 93 | #endif 94 | rjmp sofError 95 | foundK: ;[-16] 96 | ;{3, 5} after falling D- edge, average delay: 4 cycles 97 | ;bit0 should be at 34 for center sampling. Currently at 4 so 30 cylces till bit 0 sample 98 | ;use 1 bit time for setup purposes, then sample again. Numbers in brackets 99 | ;are cycles from center of first sync (double K) bit after the instruction 100 | push bitcnt ;[-16] 101 | ; [---] ;[-15] 102 | lds YL, usbInputBufOffset;[-14] 103 | ; [---] ;[-13] 104 | clr YH ;[-12] 105 | subi YL, lo8(-(usbRxBuf));[-11] [rx loop init] 106 | sbci YH, hi8(-(usbRxBuf));[-10] [rx loop init] 107 | push shift ;[-9] 108 | ; [---] ;[-8] 109 | ldi shift,0x40 ;[-7] set msb to "1" so processing bit7 can be detected 110 | nop2 ;[-6] 111 | ; [---] ;[-5] 112 | ldi bitcnt, 5 ;[-4] [rx loop init] 113 | sbis USBIN, USBMINUS ;[-3] we want two bits K (sample 3 cycles too early) 114 | rjmp haveTwoBitsK ;[-2] 115 | pop shift ;[-1] undo the push from before 116 | pop bitcnt ;[1] 117 | rjmp waitForK ;[3] this was not the end of sync, retry 118 | ; The entire loop from waitForK until rjmp waitForK above must not exceed two 119 | ; bit times (= 27 cycles). 120 | 121 | ;---------------------------------------------------------------------------- 122 | ; push more registers and initialize values while we sample the first bits: 123 | ;---------------------------------------------------------------------------- 124 | haveTwoBitsK: 125 | push x1 ;[0] 126 | push x2 ;[2] 127 | push x3 ;[4] (leap2) 128 | ldi leap2, 0x55 ;[6] add leap cycle on 2nd,5th,8th,... stuff bit 129 | push x4 ;[7] == leap 130 | ldi leap, 0x55 ;[9] skip leap cycle on 2nd,5th,8th,... byte received 131 | push cnt ;[10] 132 | ldi cnt, USB_BUFSIZE ;[12] [rx loop init] 133 | ldi x2, 1< max 25 cycles interrupt disable 38 | ;max stack usage: [ret(2), YL, SREG, YH, shift, x1, x2, x3, cnt, x4] = 11 bytes 39 | ;Numbers in brackets are maximum cycles since SOF. 40 | USB_INTR_VECTOR: 41 | ;order of registers pushed: YL, SREG [sofError], YH, shift, x1, x2, x3, cnt 42 | push YL ;2 [35] push only what is necessary to sync with edge ASAP 43 | in YL, SREG ;1 [37] 44 | push YL ;2 [39] 45 | ;---------------------------------------------------------------------------- 46 | ; Synchronize with sync pattern: 47 | ;---------------------------------------------------------------------------- 48 | ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] 49 | ;sync up with J to K edge during sync pattern -- use fastest possible loops 50 | ;The first part waits at most 1 bit long since we must be in sync pattern. 51 | ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to 52 | ;waitForJ, ensure that this prerequisite is met. 53 | waitForJ: 54 | inc YL 55 | sbis USBIN, USBMINUS 56 | brne waitForJ ; just make sure we have ANY timeout 57 | waitForK: 58 | ;The following code results in a sampling window of 1/4 bit which meets the spec. 59 | sbis USBIN, USBMINUS 60 | rjmp foundK 61 | sbis USBIN, USBMINUS 62 | rjmp foundK 63 | sbis USBIN, USBMINUS 64 | rjmp foundK 65 | sbis USBIN, USBMINUS 66 | rjmp foundK 67 | sbis USBIN, USBMINUS 68 | rjmp foundK 69 | #if USB_COUNT_SOF 70 | lds YL, usbSofCount 71 | inc YL 72 | sts usbSofCount, YL 73 | #endif /* USB_COUNT_SOF */ 74 | #ifdef USB_SOF_HOOK 75 | USB_SOF_HOOK 76 | #endif 77 | rjmp sofError 78 | foundK: 79 | ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 4 for center sampling] 80 | ;we have 1 bit time for setup purposes, then sample again. Numbers in brackets 81 | ;are cycles from center of first sync (double K) bit after the instruction 82 | push YH ;2 [2] 83 | lds YL, usbInputBufOffset;2 [4] 84 | clr YH ;1 [5] 85 | subi YL, lo8(-(usbRxBuf));1 [6] 86 | sbci YH, hi8(-(usbRxBuf));1 [7] 87 | 88 | sbis USBIN, USBMINUS ;1 [8] we want two bits K [sample 1 cycle too early] 89 | rjmp haveTwoBitsK ;2 [10] 90 | pop YH ;2 [11] undo the push from before 91 | rjmp waitForK ;2 [13] this was not the end of sync, retry 92 | haveTwoBitsK: 93 | ;---------------------------------------------------------------------------- 94 | ; push more registers and initialize values while we sample the first bits: 95 | ;---------------------------------------------------------------------------- 96 | push shift ;2 [16] 97 | push x1 ;2 [12] 98 | push x2 ;2 [14] 99 | 100 | in x1, USBIN ;1 [17] <-- sample bit 0 101 | ldi shift, 0xff ;1 [18] 102 | bst x1, USBMINUS ;1 [19] 103 | bld shift, 0 ;1 [20] 104 | push x3 ;2 [22] 105 | push cnt ;2 [24] 106 | 107 | in x2, USBIN ;1 [25] <-- sample bit 1 108 | ser x3 ;1 [26] [inserted init instruction] 109 | eor x1, x2 ;1 [27] 110 | bst x1, USBMINUS ;1 [28] 111 | bld shift, 1 ;1 [29] 112 | ldi cnt, USB_BUFSIZE;1 [30] [inserted init instruction] 113 | rjmp rxbit2 ;2 [32] 114 | 115 | ;---------------------------------------------------------------------------- 116 | ; Receiver loop (numbers in brackets are cycles within byte after instr) 117 | ;---------------------------------------------------------------------------- 118 | 119 | unstuff0: ;1 (branch taken) 120 | andi x3, ~0x01 ;1 [15] 121 | mov x1, x2 ;1 [16] x2 contains last sampled (stuffed) bit 122 | in x2, USBIN ;1 [17] <-- sample bit 1 again 123 | ori shift, 0x01 ;1 [18] 124 | rjmp didUnstuff0 ;2 [20] 125 | 126 | unstuff1: ;1 (branch taken) 127 | mov x2, x1 ;1 [21] x1 contains last sampled (stuffed) bit 128 | andi x3, ~0x02 ;1 [22] 129 | ori shift, 0x02 ;1 [23] 130 | nop ;1 [24] 131 | in x1, USBIN ;1 [25] <-- sample bit 2 again 132 | rjmp didUnstuff1 ;2 [27] 133 | 134 | unstuff2: ;1 (branch taken) 135 | andi x3, ~0x04 ;1 [29] 136 | ori shift, 0x04 ;1 [30] 137 | mov x1, x2 ;1 [31] x2 contains last sampled (stuffed) bit 138 | nop ;1 [32] 139 | in x2, USBIN ;1 [33] <-- sample bit 3 140 | rjmp didUnstuff2 ;2 [35] 141 | 142 | unstuff3: ;1 (branch taken) 143 | in x2, USBIN ;1 [34] <-- sample stuffed bit 3 [one cycle too late] 144 | andi x3, ~0x08 ;1 [35] 145 | ori shift, 0x08 ;1 [36] 146 | rjmp didUnstuff3 ;2 [38] 147 | 148 | unstuff4: ;1 (branch taken) 149 | andi x3, ~0x10 ;1 [40] 150 | in x1, USBIN ;1 [41] <-- sample stuffed bit 4 151 | ori shift, 0x10 ;1 [42] 152 | rjmp didUnstuff4 ;2 [44] 153 | 154 | unstuff5: ;1 (branch taken) 155 | andi x3, ~0x20 ;1 [48] 156 | in x2, USBIN ;1 [49] <-- sample stuffed bit 5 157 | ori shift, 0x20 ;1 [50] 158 | rjmp didUnstuff5 ;2 [52] 159 | 160 | unstuff6: ;1 (branch taken) 161 | andi x3, ~0x40 ;1 [56] 162 | in x1, USBIN ;1 [57] <-- sample stuffed bit 6 163 | ori shift, 0x40 ;1 [58] 164 | rjmp didUnstuff6 ;2 [60] 165 | 166 | ; extra jobs done during bit interval: 167 | ; bit 0: store, clear [SE0 is unreliable here due to bit dribbling in hubs] 168 | ; bit 1: se0 check 169 | ; bit 2: overflow check 170 | ; bit 3: recovery from delay [bit 0 tasks took too long] 171 | ; bit 4: none 172 | ; bit 5: none 173 | ; bit 6: none 174 | ; bit 7: jump, eor 175 | rxLoop: 176 | eor x3, shift ;1 [0] reconstruct: x3 is 0 at bit locations we changed, 1 at others 177 | in x1, USBIN ;1 [1] <-- sample bit 0 178 | st y+, x3 ;2 [3] store data 179 | ser x3 ;1 [4] 180 | nop ;1 [5] 181 | eor x2, x1 ;1 [6] 182 | bst x2, USBMINUS;1 [7] 183 | bld shift, 0 ;1 [8] 184 | in x2, USBIN ;1 [9] <-- sample bit 1 (or possibly bit 0 stuffed) 185 | andi x2, USBMASK ;1 [10] 186 | breq se0 ;1 [11] SE0 check for bit 1 187 | andi shift, 0xf9 ;1 [12] 188 | didUnstuff0: 189 | breq unstuff0 ;1 [13] 190 | eor x1, x2 ;1 [14] 191 | bst x1, USBMINUS;1 [15] 192 | bld shift, 1 ;1 [16] 193 | rxbit2: 194 | in x1, USBIN ;1 [17] <-- sample bit 2 (or possibly bit 1 stuffed) 195 | andi shift, 0xf3 ;1 [18] 196 | breq unstuff1 ;1 [19] do remaining work for bit 1 197 | didUnstuff1: 198 | subi cnt, 1 ;1 [20] 199 | brcs overflow ;1 [21] loop control 200 | eor x2, x1 ;1 [22] 201 | bst x2, USBMINUS;1 [23] 202 | bld shift, 2 ;1 [24] 203 | in x2, USBIN ;1 [25] <-- sample bit 3 (or possibly bit 2 stuffed) 204 | andi shift, 0xe7 ;1 [26] 205 | breq unstuff2 ;1 [27] 206 | didUnstuff2: 207 | eor x1, x2 ;1 [28] 208 | bst x1, USBMINUS;1 [29] 209 | bld shift, 3 ;1 [30] 210 | didUnstuff3: 211 | andi shift, 0xcf ;1 [31] 212 | breq unstuff3 ;1 [32] 213 | in x1, USBIN ;1 [33] <-- sample bit 4 214 | eor x2, x1 ;1 [34] 215 | bst x2, USBMINUS;1 [35] 216 | bld shift, 4 ;1 [36] 217 | didUnstuff4: 218 | andi shift, 0x9f ;1 [37] 219 | breq unstuff4 ;1 [38] 220 | nop2 ;2 [40] 221 | in x2, USBIN ;1 [41] <-- sample bit 5 222 | eor x1, x2 ;1 [42] 223 | bst x1, USBMINUS;1 [43] 224 | bld shift, 5 ;1 [44] 225 | didUnstuff5: 226 | andi shift, 0x3f ;1 [45] 227 | breq unstuff5 ;1 [46] 228 | nop2 ;2 [48] 229 | in x1, USBIN ;1 [49] <-- sample bit 6 230 | eor x2, x1 ;1 [50] 231 | bst x2, USBMINUS;1 [51] 232 | bld shift, 6 ;1 [52] 233 | didUnstuff6: 234 | cpi shift, 0x02 ;1 [53] 235 | brlo unstuff6 ;1 [54] 236 | nop2 ;2 [56] 237 | in x2, USBIN ;1 [57] <-- sample bit 7 238 | eor x1, x2 ;1 [58] 239 | bst x1, USBMINUS;1 [59] 240 | bld shift, 7 ;1 [60] 241 | didUnstuff7: 242 | cpi shift, 0x04 ;1 [61] 243 | brsh rxLoop ;2 [63] loop control 244 | unstuff7: 245 | andi x3, ~0x80 ;1 [63] 246 | ori shift, 0x80 ;1 [64] 247 | in x2, USBIN ;1 [65] <-- sample stuffed bit 7 248 | nop ;1 [66] 249 | rjmp didUnstuff7 ;2 [68] 250 | 251 | macro POP_STANDARD ; 12 cycles 252 | pop cnt 253 | pop x3 254 | pop x2 255 | pop x1 256 | pop shift 257 | pop YH 258 | endm 259 | macro POP_RETI ; 5 cycles 260 | pop YL 261 | out SREG, YL 262 | pop YL 263 | endm 264 | 265 | #include "asmcommon.inc" 266 | 267 | ;---------------------------------------------------------------------------- 268 | ; Transmitting data 269 | ;---------------------------------------------------------------------------- 270 | 271 | txByteLoop: 272 | txBitloop: 273 | stuffN1Delay: ; [03] 274 | ror shift ;[-5] [11] [59] 275 | brcc doExorN1 ;[-4] [60] 276 | subi x4, 1 ;[-3] 277 | brne commonN1 ;[-2] 278 | lsl shift ;[-1] compensate ror after rjmp stuffDelay 279 | nop ;[00] stuffing consists of just waiting 8 cycles 280 | rjmp stuffN1Delay ;[01] after ror, C bit is reliably clear 281 | 282 | sendNakAndReti: ;0 [-19] 19 cycles until SOP 283 | ldi x3, USBPID_NAK ;1 [-18] 284 | rjmp usbSendX3 ;2 [-16] 285 | sendAckAndReti: ;0 [-19] 19 cycles until SOP 286 | ldi x3, USBPID_ACK ;1 [-18] 287 | rjmp usbSendX3 ;2 [-16] 288 | sendCntAndReti: ;0 [-17] 17 cycles until SOP 289 | mov x3, cnt ;1 [-16] 290 | usbSendX3: ;0 [-16] 291 | ldi YL, 20 ;1 [-15] 'x3' is R20 292 | ldi YH, 0 ;1 [-14] 293 | ldi cnt, 2 ;1 [-13] 294 | ; rjmp usbSendAndReti fallthrough 295 | 296 | ; USB spec says: 297 | ; idle = J 298 | ; J = (D+ = 0), (D- = 1) or USBOUT = 0x01 299 | ; K = (D+ = 1), (D- = 0) or USBOUT = 0x02 300 | ; Spec allows 7.5 bit times from EOP to SOP for replies (= 60 cycles) 301 | 302 | ;usbSend: 303 | ;pointer to data in 'Y' 304 | ;number of bytes in 'cnt' -- including sync byte 305 | ;uses: x1...x2, x4, shift, cnt, Y [x1 = mirror USBOUT, x2 = USBMASK, x4 = bitstuff cnt] 306 | ;Numbers in brackets are time since first bit of sync pattern is sent (start of instruction) 307 | usbSendAndReti: 308 | in x2, USBDDR ;[-12] 12 cycles until SOP 309 | ori x2, USBMASK ;[-11] 310 | sbi USBOUT, USBMINUS ;[-10] prepare idle state; D+ and D- must have been 0 (no pullups) 311 | out USBDDR, x2 ;[-8] <--- acquire bus 312 | in x1, USBOUT ;[-7] port mirror for tx loop 313 | ldi shift, 0x40 ;[-6] sync byte is first byte sent (we enter loop after ror) 314 | ldi x2, USBMASK ;[-5] 315 | push x4 ;[-4] 316 | doExorN1: 317 | eor x1, x2 ;[-2] [06] [62] 318 | ldi x4, 6 ;[-1] [07] [63] 319 | commonN1: 320 | stuffN2Delay: 321 | out USBOUT, x1 ;[00] [08] [64] <--- set bit 322 | ror shift ;[01] 323 | brcc doExorN2 ;[02] 324 | subi x4, 1 ;[03] 325 | brne commonN2 ;[04] 326 | lsl shift ;[05] compensate ror after rjmp stuffDelay 327 | rjmp stuffN2Delay ;[06] after ror, C bit is reliably clear 328 | doExorN2: 329 | eor x1, x2 ;[04] [12] 330 | ldi x4, 6 ;[05] [13] 331 | commonN2: 332 | nop ;[06] [14] 333 | subi cnt, 171 ;[07] [15] trick: (3 * 171) & 0xff = 1 334 | out USBOUT, x1 ;[08] [16] <--- set bit 335 | brcs txBitloop ;[09] [25] [41] 336 | 337 | stuff6Delay: 338 | ror shift ;[42] [50] 339 | brcc doExor6 ;[43] 340 | subi x4, 1 ;[44] 341 | brne common6 ;[45] 342 | lsl shift ;[46] compensate ror after rjmp stuffDelay 343 | nop ;[47] stuffing consists of just waiting 8 cycles 344 | rjmp stuff6Delay ;[48] after ror, C bit is reliably clear 345 | doExor6: 346 | eor x1, x2 ;[45] [53] 347 | ldi x4, 6 ;[46] 348 | common6: 349 | stuff7Delay: 350 | ror shift ;[47] [55] 351 | out USBOUT, x1 ;[48] <--- set bit 352 | brcc doExor7 ;[49] 353 | subi x4, 1 ;[50] 354 | brne common7 ;[51] 355 | lsl shift ;[52] compensate ror after rjmp stuffDelay 356 | rjmp stuff7Delay ;[53] after ror, C bit is reliably clear 357 | doExor7: 358 | eor x1, x2 ;[51] [59] 359 | ldi x4, 6 ;[52] 360 | common7: 361 | ld shift, y+ ;[53] 362 | tst cnt ;[55] 363 | out USBOUT, x1 ;[56] <--- set bit 364 | brne txByteLoop ;[57] 365 | 366 | ;make SE0: 367 | cbr x1, USBMASK ;[58] prepare SE0 [spec says EOP may be 15 to 18 cycles] 368 | lds x2, usbNewDeviceAddr;[59] 369 | lsl x2 ;[61] we compare with left shifted address 370 | subi YL, 2 + 20 ;[62] Only assign address on data packets, not ACK/NAK in x3 371 | sbci YH, 0 ;[63] 372 | out USBOUT, x1 ;[00] <-- out SE0 -- from now 2 bits = 16 cycles until bus idle 373 | ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: 374 | ;set address only after data packet was sent, not after handshake 375 | breq skipAddrAssign ;[01] 376 | sts usbDeviceAddr, x2 ; if not skipped: SE0 is one cycle longer 377 | skipAddrAssign: 378 | ;end of usbDeviceAddress transfer 379 | ldi x2, 1< max 52 cycles interrupt disable 31 | ;max stack usage: [ret(2), r0, SREG, YL, YH, shift, x1, x2, x3, x4, cnt] = 12 bytes 32 | ;nominal frequency: 16.5 MHz -> 11 cycles per bit 33 | ; 16.3125 MHz < F_CPU < 16.6875 MHz (+/- 1.1%) 34 | ; Numbers in brackets are clocks counted from center of last sync bit 35 | ; when instruction starts 36 | 37 | 38 | USB_INTR_VECTOR: 39 | ;order of registers pushed: YL, SREG [sofError], r0, YH, shift, x1, x2, x3, x4, cnt 40 | push YL ;[-23] push only what is necessary to sync with edge ASAP 41 | in YL, SREG ;[-21] 42 | push YL ;[-20] 43 | ;---------------------------------------------------------------------------- 44 | ; Synchronize with sync pattern: 45 | ;---------------------------------------------------------------------------- 46 | ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K] 47 | ;sync up with J to K edge during sync pattern -- use fastest possible loops 48 | ;The first part waits at most 1 bit long since we must be in sync pattern. 49 | ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to 50 | ;waitForJ, ensure that this prerequisite is met. 51 | waitForJ: 52 | inc YL 53 | sbis USBIN, USBMINUS 54 | brne waitForJ ; just make sure we have ANY timeout 55 | waitForK: 56 | ;The following code results in a sampling window of < 1/4 bit which meets the spec. 57 | sbis USBIN, USBMINUS ;[-15] 58 | rjmp foundK ;[-14] 59 | sbis USBIN, USBMINUS 60 | rjmp foundK 61 | sbis USBIN, USBMINUS 62 | rjmp foundK 63 | sbis USBIN, USBMINUS 64 | rjmp foundK 65 | sbis USBIN, USBMINUS 66 | rjmp foundK 67 | sbis USBIN, USBMINUS 68 | rjmp foundK 69 | #if USB_COUNT_SOF 70 | lds YL, usbSofCount 71 | inc YL 72 | sts usbSofCount, YL 73 | #endif /* USB_COUNT_SOF */ 74 | #ifdef USB_SOF_HOOK 75 | USB_SOF_HOOK 76 | #endif 77 | rjmp sofError 78 | foundK: ;[-12] 79 | ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for center sampling] 80 | ;we have 1 bit time for setup purposes, then sample again. Numbers in brackets 81 | ;are cycles from center of first sync (double K) bit after the instruction 82 | push r0 ;[-12] 83 | ; [---] ;[-11] 84 | push YH ;[-10] 85 | ; [---] ;[-9] 86 | lds YL, usbInputBufOffset;[-8] 87 | ; [---] ;[-7] 88 | clr YH ;[-6] 89 | subi YL, lo8(-(usbRxBuf));[-5] [rx loop init] 90 | sbci YH, hi8(-(usbRxBuf));[-4] [rx loop init] 91 | mov r0, x2 ;[-3] [rx loop init] 92 | sbis USBIN, USBMINUS ;[-2] we want two bits K (sample 2 cycles too early) 93 | rjmp haveTwoBitsK ;[-1] 94 | pop YH ;[0] undo the pushes from before 95 | pop r0 ;[2] 96 | rjmp waitForK ;[4] this was not the end of sync, retry 97 | ; The entire loop from waitForK until rjmp waitForK above must not exceed two 98 | ; bit times (= 22 cycles). 99 | 100 | ;---------------------------------------------------------------------------- 101 | ; push more registers and initialize values while we sample the first bits: 102 | ;---------------------------------------------------------------------------- 103 | haveTwoBitsK: ;[1] 104 | push shift ;[1] 105 | push x1 ;[3] 106 | push x2 ;[5] 107 | push x3 ;[7] 108 | ldi shift, 0xff ;[9] [rx loop init] 109 | ori x3, 0xff ;[10] [rx loop init] == ser x3, clear zero flag 110 | 111 | in x1, USBIN ;[11] <-- sample bit 0 112 | bst x1, USBMINUS ;[12] 113 | bld shift, 0 ;[13] 114 | push x4 ;[14] == phase 115 | ; [---] ;[15] 116 | push cnt ;[16] 117 | ; [---] ;[17] 118 | ldi phase, 0 ;[18] [rx loop init] 119 | ldi cnt, USB_BUFSIZE;[19] [rx loop init] 120 | rjmp rxbit1 ;[20] 121 | ; [---] ;[21] 122 | 123 | ;---------------------------------------------------------------------------- 124 | ; Receiver loop (numbers in brackets are cycles within byte after instr) 125 | ;---------------------------------------------------------------------------- 126 | /* 127 | byte oriented operations done during loop: 128 | bit 0: store data 129 | bit 1: SE0 check 130 | bit 2: overflow check 131 | bit 3: catch up 132 | bit 4: rjmp to achieve conditional jump range 133 | bit 5: PLL 134 | bit 6: catch up 135 | bit 7: jump, fixup bitstuff 136 | ; 87 [+ 2] cycles 137 | ------------------------------------------------------------------ 138 | */ 139 | continueWithBit5: 140 | in x2, USBIN ;[055] <-- bit 5 141 | eor r0, x2 ;[056] 142 | or phase, r0 ;[057] 143 | sbrc phase, USBMINUS ;[058] 144 | lpm ;[059] optional nop3; modifies r0 145 | in phase, USBIN ;[060] <-- phase 146 | eor x1, x2 ;[061] 147 | bst x1, USBMINUS ;[062] 148 | bld shift, 5 ;[063] 149 | andi shift, 0x3f ;[064] 150 | in x1, USBIN ;[065] <-- bit 6 151 | breq unstuff5 ;[066] *** unstuff escape 152 | eor phase, x1 ;[067] 153 | eor x2, x1 ;[068] 154 | bst x2, USBMINUS ;[069] 155 | bld shift, 6 ;[070] 156 | didUnstuff6: ;[ ] 157 | in r0, USBIN ;[071] <-- phase 158 | cpi shift, 0x02 ;[072] 159 | brlo unstuff6 ;[073] *** unstuff escape 160 | didUnstuff5: ;[ ] 161 | nop2 ;[074] 162 | ; [---] ;[075] 163 | in x2, USBIN ;[076] <-- bit 7 164 | eor x1, x2 ;[077] 165 | bst x1, USBMINUS ;[078] 166 | bld shift, 7 ;[079] 167 | didUnstuff7: ;[ ] 168 | eor r0, x2 ;[080] 169 | or phase, r0 ;[081] 170 | in r0, USBIN ;[082] <-- phase 171 | cpi shift, 0x04 ;[083] 172 | brsh rxLoop ;[084] 173 | ; [---] ;[085] 174 | unstuff7: ;[ ] 175 | andi x3, ~0x80 ;[085] 176 | ori shift, 0x80 ;[086] 177 | in x2, USBIN ;[087] <-- sample stuffed bit 7 178 | nop ;[088] 179 | rjmp didUnstuff7 ;[089] 180 | ; [---] ;[090] 181 | ;[080] 182 | 183 | unstuff5: ;[067] 184 | eor phase, x1 ;[068] 185 | andi x3, ~0x20 ;[069] 186 | ori shift, 0x20 ;[070] 187 | in r0, USBIN ;[071] <-- phase 188 | mov x2, x1 ;[072] 189 | nop ;[073] 190 | nop2 ;[074] 191 | ; [---] ;[075] 192 | in x1, USBIN ;[076] <-- bit 6 193 | eor r0, x1 ;[077] 194 | or phase, r0 ;[078] 195 | eor x2, x1 ;[079] 196 | bst x2, USBMINUS ;[080] 197 | bld shift, 6 ;[081] no need to check bitstuffing, we just had one 198 | in r0, USBIN ;[082] <-- phase 199 | rjmp didUnstuff5 ;[083] 200 | ; [---] ;[084] 201 | ;[074] 202 | 203 | unstuff6: ;[074] 204 | andi x3, ~0x40 ;[075] 205 | in x1, USBIN ;[076] <-- bit 6 again 206 | ori shift, 0x40 ;[077] 207 | nop2 ;[078] 208 | ; [---] ;[079] 209 | rjmp didUnstuff6 ;[080] 210 | ; [---] ;[081] 211 | ;[071] 212 | 213 | unstuff0: ;[013] 214 | eor r0, x2 ;[014] 215 | or phase, r0 ;[015] 216 | andi x2, USBMASK ;[016] check for SE0 217 | in r0, USBIN ;[017] <-- phase 218 | breq didUnstuff0 ;[018] direct jump to se0 would be too long 219 | andi x3, ~0x01 ;[019] 220 | ori shift, 0x01 ;[020] 221 | mov x1, x2 ;[021] mov existing sample 222 | in x2, USBIN ;[022] <-- bit 1 again 223 | rjmp didUnstuff0 ;[023] 224 | ; [---] ;[024] 225 | ;[014] 226 | 227 | unstuff1: ;[024] 228 | eor r0, x1 ;[025] 229 | or phase, r0 ;[026] 230 | andi x3, ~0x02 ;[027] 231 | in r0, USBIN ;[028] <-- phase 232 | ori shift, 0x02 ;[029] 233 | mov x2, x1 ;[030] 234 | rjmp didUnstuff1 ;[031] 235 | ; [---] ;[032] 236 | ;[022] 237 | 238 | unstuff2: ;[035] 239 | eor r0, x2 ;[036] 240 | or phase, r0 ;[037] 241 | andi x3, ~0x04 ;[038] 242 | in r0, USBIN ;[039] <-- phase 243 | ori shift, 0x04 ;[040] 244 | mov x1, x2 ;[041] 245 | rjmp didUnstuff2 ;[042] 246 | ; [---] ;[043] 247 | ;[033] 248 | 249 | unstuff3: ;[043] 250 | in x2, USBIN ;[044] <-- bit 3 again 251 | eor r0, x2 ;[045] 252 | or phase, r0 ;[046] 253 | andi x3, ~0x08 ;[047] 254 | ori shift, 0x08 ;[048] 255 | nop ;[049] 256 | in r0, USBIN ;[050] <-- phase 257 | rjmp didUnstuff3 ;[051] 258 | ; [---] ;[052] 259 | ;[042] 260 | 261 | unstuff4: ;[053] 262 | andi x3, ~0x10 ;[054] 263 | in x1, USBIN ;[055] <-- bit 4 again 264 | ori shift, 0x10 ;[056] 265 | rjmp didUnstuff4 ;[057] 266 | ; [---] ;[058] 267 | ;[048] 268 | 269 | rxLoop: ;[085] 270 | eor x3, shift ;[086] reconstruct: x3 is 0 at bit locations we changed, 1 at others 271 | in x1, USBIN ;[000] <-- bit 0 272 | st y+, x3 ;[001] 273 | ; [---] ;[002] 274 | eor r0, x1 ;[003] 275 | or phase, r0 ;[004] 276 | eor x2, x1 ;[005] 277 | in r0, USBIN ;[006] <-- phase 278 | ser x3 ;[007] 279 | bst x2, USBMINUS ;[008] 280 | bld shift, 0 ;[009] 281 | andi shift, 0xf9 ;[010] 282 | rxbit1: ;[ ] 283 | in x2, USBIN ;[011] <-- bit 1 284 | breq unstuff0 ;[012] *** unstuff escape 285 | andi x2, USBMASK ;[013] SE0 check for bit 1 286 | didUnstuff0: ;[ ] Z only set if we detected SE0 in bitstuff 287 | breq se0 ;[014] 288 | eor r0, x2 ;[015] 289 | or phase, r0 ;[016] 290 | in r0, USBIN ;[017] <-- phase 291 | eor x1, x2 ;[018] 292 | bst x1, USBMINUS ;[019] 293 | bld shift, 1 ;[020] 294 | andi shift, 0xf3 ;[021] 295 | didUnstuff1: ;[ ] 296 | in x1, USBIN ;[022] <-- bit 2 297 | breq unstuff1 ;[023] *** unstuff escape 298 | eor r0, x1 ;[024] 299 | or phase, r0 ;[025] 300 | subi cnt, 1 ;[026] overflow check 301 | brcs overflow ;[027] 302 | in r0, USBIN ;[028] <-- phase 303 | eor x2, x1 ;[029] 304 | bst x2, USBMINUS ;[030] 305 | bld shift, 2 ;[031] 306 | andi shift, 0xe7 ;[032] 307 | didUnstuff2: ;[ ] 308 | in x2, USBIN ;[033] <-- bit 3 309 | breq unstuff2 ;[034] *** unstuff escape 310 | eor r0, x2 ;[035] 311 | or phase, r0 ;[036] 312 | eor x1, x2 ;[037] 313 | bst x1, USBMINUS ;[038] 314 | in r0, USBIN ;[039] <-- phase 315 | bld shift, 3 ;[040] 316 | andi shift, 0xcf ;[041] 317 | didUnstuff3: ;[ ] 318 | breq unstuff3 ;[042] *** unstuff escape 319 | nop ;[043] 320 | in x1, USBIN ;[044] <-- bit 4 321 | eor x2, x1 ;[045] 322 | bst x2, USBMINUS ;[046] 323 | bld shift, 4 ;[047] 324 | didUnstuff4: ;[ ] 325 | eor r0, x1 ;[048] 326 | or phase, r0 ;[049] 327 | in r0, USBIN ;[050] <-- phase 328 | andi shift, 0x9f ;[051] 329 | breq unstuff4 ;[052] *** unstuff escape 330 | rjmp continueWithBit5;[053] 331 | ; [---] ;[054] 332 | 333 | macro POP_STANDARD ; 16 cycles 334 | pop cnt 335 | pop x4 336 | pop x3 337 | pop x2 338 | pop x1 339 | pop shift 340 | pop YH 341 | pop r0 342 | endm 343 | macro POP_RETI ; 5 cycles 344 | pop YL 345 | out SREG, YL 346 | pop YL 347 | endm 348 | 349 | #include "asmcommon.inc" 350 | 351 | 352 | ; USB spec says: 353 | ; idle = J 354 | ; J = (D+ = 0), (D- = 1) 355 | ; K = (D+ = 1), (D- = 0) 356 | ; Spec allows 7.5 bit times from EOP to SOP for replies 357 | 358 | bitstuff7: 359 | eor x1, x4 ;[4] 360 | ldi x2, 0 ;[5] 361 | nop2 ;[6] C is zero (brcc) 362 | rjmp didStuff7 ;[8] 363 | 364 | bitstuffN: 365 | eor x1, x4 ;[5] 366 | ldi x2, 0 ;[6] 367 | lpm ;[7] 3 cycle NOP, modifies r0 368 | out USBOUT, x1 ;[10] <-- out 369 | rjmp didStuffN ;[0] 370 | 371 | #define bitStatus x3 372 | 373 | sendNakAndReti: 374 | ldi cnt, USBPID_NAK ;[-19] 375 | rjmp sendCntAndReti ;[-18] 376 | sendAckAndReti: 377 | ldi cnt, USBPID_ACK ;[-17] 378 | sendCntAndReti: 379 | mov r0, cnt ;[-16] 380 | ldi YL, 0 ;[-15] R0 address is 0 381 | ldi YH, 0 ;[-14] 382 | ldi cnt, 2 ;[-13] 383 | ; rjmp usbSendAndReti fallthrough 384 | 385 | ;usbSend: 386 | ;pointer to data in 'Y' 387 | ;number of bytes in 'cnt' -- including sync byte [range 2 ... 12] 388 | ;uses: x1...x4, shift, cnt, Y 389 | ;Numbers in brackets are time since first bit of sync pattern is sent 390 | usbSendAndReti: ; 12 cycles until SOP 391 | in x2, USBDDR ;[-12] 392 | ori x2, USBMASK ;[-11] 393 | sbi USBOUT, USBMINUS;[-10] prepare idle state; D+ and D- must have been 0 (no pullups) 394 | in x1, USBOUT ;[-8] port mirror for tx loop 395 | out USBDDR, x2 ;[-7] <- acquire bus 396 | ; need not init x2 (bitstuff history) because sync starts with 0 397 | ldi x4, USBMASK ;[-6] exor mask 398 | ldi shift, 0x80 ;[-5] sync byte is first byte sent 399 | ldi bitStatus, 0xff ;[-4] init bit loop counter, works for up to 12 bytes 400 | byteloop: 401 | bitloop: 402 | sbrs shift, 0 ;[8] [-3] 403 | eor x1, x4 ;[9] [-2] 404 | out USBOUT, x1 ;[10] [-1] <-- out 405 | ror shift ;[0] 406 | ror x2 ;[1] 407 | didStuffN: 408 | cpi x2, 0xfc ;[2] 409 | brcc bitstuffN ;[3] 410 | nop ;[4] 411 | subi bitStatus, 37 ;[5] 256 / 7 ~=~ 37 412 | brcc bitloop ;[6] when we leave the loop, bitStatus has almost the initial value 413 | sbrs shift, 0 ;[7] 414 | eor x1, x4 ;[8] 415 | ror shift ;[9] 416 | didStuff7: 417 | out USBOUT, x1 ;[10] <-- out 418 | ror x2 ;[0] 419 | cpi x2, 0xfc ;[1] 420 | brcc bitstuff7 ;[2] 421 | ld shift, y+ ;[3] 422 | dec cnt ;[5] 423 | brne byteloop ;[6] 424 | ;make SE0: 425 | cbr x1, USBMASK ;[7] prepare SE0 [spec says EOP may be 21 to 25 cycles] 426 | lds x2, usbNewDeviceAddr;[8] 427 | lsl x2 ;[10] we compare with left shifted address 428 | out USBOUT, x1 ;[11] <-- out SE0 -- from now 2 bits = 22 cycles until bus idle 429 | ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: 430 | ;set address only after data packet was sent, not after handshake 431 | subi YL, 2 ;[0] Only assign address on data packets, not ACK/NAK in r0 432 | sbci YH, 0 ;[1] 433 | breq skipAddrAssign ;[2] 434 | sts usbDeviceAddr, x2; if not skipped: SE0 is one cycle longer 435 | skipAddrAssign: 436 | ;end of usbDeviceAddress transfer 437 | ldi x2, 1<