From: Drew Fisher <drew.m.fisher@gmail.com>
Date: Fri, 11 Jun 2010 06:32:37 +0000 (-0700)
Subject: Recognized as a joystick, timer verified working.
X-Git-Url: http://git.zarvox.org/shortlog/static/%7Bgravatar%7D?a=commitdiff_plain;h=c18d4bb915d84ff09ee45e8f1101e62c34bc813e;p=usbsnes.git

Recognized as a joystick, timer verified working.

Actually gets recognized and polled correctly.  Increments a bitmask revealed in the button state every second.
---

diff --git a/Makefile b/Makefile
index fa79efa..6941d0c 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,8 @@ F_CPU   = 18000000	# in Hz
 FUSE_L  = 0xd7# see below for fuse values for particular devices
 FUSE_H  = 0xd9
 
-AVRDUDE = avrdude -c stk500 -B 2 -p $(DEVICE) -P /dev/ttyACM0 # edit this line for your programmer
+#AVRDUDE = avrdude -c stk500 -B 2 -p $(DEVICE) -P /dev/ttyACM0 # edit this line for your programmer
+AVRDUDE = avrdude -c avrispmkII -B 10 -p $(DEVICE) -P usb # edit this line for your programmer
 
 CFLAGS  = -Iusbdrv -I. -DDEBUG_LEVEL=0
 OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o snes.o
diff --git a/main.c b/main.c
index e34a7cf..9e8ccb8 100644
--- a/main.c
+++ b/main.c
@@ -10,37 +10,48 @@
 
 uint16_t pollSnes();
 
-PROGMEM char usbHidReportDescriptor[28] = {
-	0x05, 0x01,  // USAGE_PAGE (Generic Desktop)
-	0x09, 0x05,  // USAGE (Game Pad)
-	0xa1, 0x01,  // COLLECTION (Application)
-	0x09, 0x05,  //   USAGE (Game Pad)
-	0xa1, 0x00,  //   COLLECTION (Physical)
-	0x05, 0x09,  //     USAGE_PAGE (Button)
-	0x19, 0x01,  //     USAGE_MINIMUM (Button 1)
-	0x29, 0x10,  //     USAGE_MAXIMUM (Button 16)
-	0x15, 0x00,  //     LOGICAL MINIMUM (0)
-	0x25, 0x01,  //     LOGICAL MAXIMUM (1)
-	0x95, 0x10,  //     REPORT_COUNT (16)
-	0x75, 0x01,  //     REPORT_SIZE (1)
-	0x81, 0x02,  //     INPUT (Data, Var, Abs)
-	0xc0,        //   END_COLLECTION
-	0xc0         // END_COLLECTION
+PROGMEM char usbHidReportDescriptor[] = {
+	0x05, 0x01,			// USAGE_PAGE (Generic Desktop)
+	0x09, 0x04,			// USAGE (Joystick)
+	0xa1, 0x01,			// COLLECTION (Application)
+	0x09, 0x01,			//	USAGE (Pointer)
+	0xa1, 0x00,			//	COLLECTION (Physical)
+//	0x85, 0x01,			//		REPORT_ID (1)
+	0x09, 0x30,			//		USAGE (X)
+	0x09, 0x31,			//		USAGE (Y)
+	0x15, 0x00,			//		LOGICAL_MINIMUM (0)
+	0x26, 0xff, 0x00,	//			LOGICAL_MAXIMUM (255)
+	0x75, 0x08,			//		REPORT_SIZE (8)
+	0x95, 0x02,			//		REPORT_COUNT (2)
+	0x81, 0x02,			//		INPUT (Data,Var,Abs)
+
+	0x05, 0x09,			//		USAGE_PAGE (Button)
+	0x19, 1,			//		USAGE_MINIMUM (Button 1)
+	0x29, 8,			//		USAGE_MAXIMUM (Button 8)
+	0x15, 0x00,			//		LOGICAL_MINIMUM (0)
+	0x25, 0x01,			//		LOGICAL_MAXIMUM (1)
+	0x75, 1,			//		REPORT_SIZE (1)
+	0x95, 8,			//		REPORT_COUNT (8)
+	0x81, 0x02,			//		INPUT (Data,Var,Abs)
+	0xc0,				//	END_COLLECTION
+	0xc0,				// END_COLLECTION
 };
-/*
-typedef struct {
-	uchar buttons[2];
-} report_t;
-*/
+
 typedef struct {
-	uint16_t buttons;
+	//uchar id;
+	char x;
+	char y;
+	uchar buttons;
 } report_t;
 
 static report_t buttonState;
 static report_t reportBuffer;
 static uint8_t pollInProgress = 0;
+static unsigned char idleRate;
+static uint8_t interrupt_count = 0;
 
 usbMsgLen_t usbFunctionSetup(uchar data[8]) {
+
 	usbRequest_t    *rq = (void *)data;
 
 	/* The following requests are never used. But since they are required by
@@ -52,6 +63,11 @@ usbMsgLen_t usbFunctionSetup(uchar data[8]) {
 			/* we only have one report type, so don't look at wValue */
 			usbMsgPtr = (void *)&reportBuffer;
 			return sizeof(reportBuffer);
+		} else if (rq->bRequest == USBRQ_HID_GET_IDLE){
+			usbMsgPtr = &idleRate;
+			return 1;
+		} else if (rq->bRequest == USBRQ_HID_SET_IDLE){
+			idleRate = rq->wValue.bytes[1];
 		}
 	}else{
 		/* no vendor specific requests implemented */
@@ -59,19 +75,26 @@ usbMsgLen_t usbFunctionSetup(uchar data[8]) {
 	return 0;   /* default for not implemented requests: return no data back to host */
 }
 
+
 ISR(TIMER1_COMPA_vect) {
+/*
 	if(pollInProgress) // Mutex, to prevent infinite recursion if terribly many USB interrupts (shouldn't happen, but safety net)
 		return; // We've already started polling the SNES controller, return up the stack so that the original ISR can finish
 	pollInProgress = 1; // Acquire lock
 	sei(); // Allow for nested interrupts - namely, USB interrupts.
 	buttonState.buttons = pollSnes();
 	pollInProgress = 0; // Release lock
+*/
+	if (interrupt_count++ == 60) {
+		reportBuffer.buttons++;
+		interrupt_count = 0;
+	}
 }
 
 static void initPins() {
 	// Enable PD3 as output high (pull-up to D-)
-	DDRD |= _BV(PIND3);
-	PORTD |= _BV(PIND3);
+	//DDRD |= _BV(PIND3);
+	//PORTD |= _BV(PIND3);
 
 	// Enable PC1:0 as output, and set data clock high
 	// Serial data is PC2 (input, hi-z)
@@ -101,14 +124,14 @@ static void initTimer() {
 
 int main(void)
 {
-	uchar i;
+	uchar counter = 0;
 	wdt_enable(WDTO_1S); // Enable watchdog with 1s reset time
 
 	/* Even if you don't use the watchdog, turn it off here. On newer devices,
 	 * the status of the watchdog (on/off, period) is PRESERVED OVER RESET!
 	 */
 
-	cli(); // Disable interrupts
+	cli(); // Disable interrupts (technically, they're disabled on reset, but...)
 	
 	//DBG1(0x00, 0, 0);       /* debug output: main starts */
 	
@@ -132,17 +155,20 @@ int main(void)
 	//odDebugInit();
 	
 	usbInit();
+	
 	usbDeviceDisconnect();  /* enforce re-enumeration, do this while interrupts are disabled! */
-	i = 0;
-	while(--i){             /* fake USB disconnect for > 250 ms */
+	counter = 0;
+	while(--counter){             /* fake USB disconnect for > 250 ms */
 		wdt_reset();
 		_delay_ms(1);
 	}
 	usbDeviceConnect();
+
 	sei(); // Enable interrupts (after device reconnect)
 	//DBG1(0x01, 0, 0);       /* debug output: main loop starts */
-
-	uchar counter = 0;
+	reportBuffer.x = 0;
+	reportBuffer.y = 0;
+	reportBuffer.buttons = 0;
 
 	for(;;){                /* main event loop */
 		//DBG1(0x02, 0, 0);   /* debug output: main loop iterates */
@@ -154,10 +180,12 @@ int main(void)
 			//reportBuffer.buttons = buttonState.buttons;
 
 			// Testing USB reports - change button state every second, incrementing the report buffer by 1.
-			if(counter++ == 60) {
-				reportBuffer.buttons++;
-				counter = 0;
-			}
+			//if(counter++ == 10) {
+			//	reportBuffer.buttons = 'a';
+			//	reportBuffer.buttons2 = 'a';
+			//	reportBuffer.buttons3 = 'a';
+			//	counter = 0;
+			//}
 			//DBG1(0x03, 0, 0);   /* debug output: interrupt report prepared */
 			usbSetInterrupt((void *)&reportBuffer, sizeof(reportBuffer));
 		}
diff --git a/usbconfig.h b/usbconfig.h
index 3363dc9..9dfeae0 100644
--- a/usbconfig.h
+++ b/usbconfig.h
@@ -202,7 +202,7 @@ section at the end of this file).
 /* define this macro to 1 if you want the function usbMeasureFrameLength()
  * compiled in. This function can be used to calibrate the AVR's RC oscillator.
  */
-#define USB_USE_FAST_CRC                1
+#define USB_USE_FAST_CRC                0
 /* The assembler module has two implementations for the CRC algorithm. One is
  * faster, the other is smaller. This CRC routine is only used for transmitted
  * messages where timing is not critical. The faster routine needs 31 cycles
@@ -278,7 +278,7 @@ section at the end of this file).
  * HID class is 3, no subclass and protocol required (but may be useful!)
  * CDC class is 2, use subclass 2 and protocol 1 for ACM
  */
-#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH    28
+#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH    43
 /* Define this to the length of the HID report descriptor, if you implement
  * an HID device. Otherwise don't define it or define it to 0.
  * If you use this define, you must add a PROGMEM character array named