#include #include /* for sei() */ #include #include #include /* for _delay_ms() */ #include /* required by usbdrv.h */ #include "usbdrv.h" #include "oddebug.h" /* This is also an example for using debug macros */ #include "Wheel.h" /* ------------------------------------------------------------------------- */ /* ----------------------------- USB interface ----------------------------- */ /* ------------------------------------------------------------------------- */ PROGMEM const char usbHidReportDescriptor[] = { /* USB report descriptor, size must match usbconfig.h */ 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x02, // USAGE (Mouse) 0xa1, 0x01, // COLLECTION (Application) 0x09, 0x01, // USAGE (Pointer) 0xA1, 0x00, // COLLECTION (Physical) 0x05, 0x09, // USAGE_PAGE (Button) 0x19, 0x01, // USAGE_MINIMUM 0x29, 0x03, // USAGE_MAXIMUM 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x95, 0x03, // REPORT_COUNT (3) 0x75, 0x01, // REPORT_SIZE (1) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x95, 0x01, // REPORT_COUNT (1) 0x75, 0x05, // REPORT_SIZE (5) 0x81, 0x03, // INPUT (Const,Var,Abs) 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x30, // USAGE (X) 0x09, 0x31, // USAGE (Y) 0x09, 0x38, // USAGE (Wheel) 0x15, 0x81, // LOGICAL_MINIMUM (-127) 0x25, 0x7F, // LOGICAL_MAXIMUM (127) 0x75, 0x08, // REPORT_SIZE (8) 0x95, 0x03, // REPORT_COUNT (3) 0x81, 0x06, // INPUT (Data,Var,Rel) 0xC0, // END_COLLECTION 0xC0, // END COLLECTION }; // PROGMEM const char usbHidReportDescriptor[] = { /* USB report descriptor, size must match usbconfig.h */ // 0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 0x09, 0x02, // USAGE (Mouse) // 0xa1, 0x01, // COLLECTION (Application) // 0x09, 0x01, // USAGE (Pointer) // 0xA1, 0x00, // COLLECTION (Physical) // 0x05, 0x09, // USAGE_PAGE (Button) // 0x19, 0x01, // USAGE_MINIMUM // 0x29, 0x03, // USAGE_MAXIMUM // 0x15, 0x00, // LOGICAL_MINIMUM (0) // 0x25, 0x01, // LOGICAL_MAXIMUM (1) // 0x95, 0x03, // REPORT_COUNT (3) // 0x75, 0x01, // REPORT_SIZE (1) // 0x81, 0x02, // INPUT (Data,Var,Abs) // 0x95, 0x01, // REPORT_COUNT (1) // 0x75, 0x05, // REPORT_SIZE (5) // 0x81, 0x03, // INPUT (Const,Var,Abs) // 0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 0x09, 0x30, // USAGE (X) // 0x09, 0x31, // USAGE (Y) // 0x15, 0x81, // LOGICAL_MINIMUM (-127) // 0x25, 0x7F, // LOGICAL_MAXIMUM (127) // 0x75, 0x08, // REPORT_SIZE (8) // 0x95, 0x03, // REPORT_COUNT (2) // 0x81, 0x06, // INPUT (Data,Var,Rel) // 0x09, 0x38, // USAGE (Wheel) // 0x95, 0x01, // REPORT_COUNT (1) // 0x81, 0x06, // INPUT (Data, Variable, Relative) // 0xC0, // END_COLLECTION // 0xC0, // END COLLECTION // }; /* This is the same report descriptor as seen in a Logitech mouse. The data * described by this descriptor consists of 4 bytes: * . . . . . B2 B1 B0 .... one byte with mouse button states * X7 X6 X5 X4 X3 X2 X1 X0 .... 8 bit signed relative coordinate x * Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 .... 8 bit signed relative coordinate y * W7 W6 W5 W4 W3 W2 W1 W0 .... 8 bit signed relative coordinate wheel */ typedef struct{ uchar buttonMask; char dx; char dy; char dWheel; }report_t; static report_t reportBuffer; static uchar idleRate; /* repeat rate for keyboards, never used for mice */ static void read_Wheel(void) { reportBuffer.dx = 0; reportBuffer.dy = 0; reportBuffer.dWheel = 0; int Direction = (AnalogIn < 512) ? -1 : 1; timing = get_timing(AnalogIn); if (AnalogIn < LowerDead[Debounce] || AnalogIn > UpperDead[Debounce]) { if (Debounce == 1 || ticktock >= timing) { PINB |= _BV(PB1); reportBuffer.dWheel = Direction; Debounce = 0; ticktock = 0; } } else { if (Debounce == 0) { PINB &= ~(1< timingtable_in[index]) { index++; } return timingtable_out[index] * 2; } /* ------------------------------------------------------------------------- */ ISR(ADC_vect) { AnalogIn = ADC; } ISR(TIM0_COMPA_vect) { read_Wheel(); if(usbInterruptIsReady()) { usbSetInterrupt((void *)&reportBuffer, sizeof(reportBuffer)); } ticktock++; } /** Configures the board hardware and chip peripherals for the demo's functionality. */ void SetupHardware(void) { cli(); /* Disable watchdog if enabled by bootloader/fuses */ MCUSR &= ~(1 << WDRF); wdt_disable(); DDRB |= (1< 250 ms */ _delay_ms(2); } usbDeviceConnect(); /* ADC Settings */ // prescaler = 128 ADCSRA = (1<bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ /* class request type */ DBG1(0x50, &rq->bRequest, 1); /* debug output: print our request */ if(rq->bRequest == USBRQ_HID_GET_REPORT){ /* wValue: ReportType (highbyte), ReportID (lowbyte) */ /* 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 */ } return 0; /* default for not implemented requests: return no data back to host */ } // Called by V-USB after device reset void hadUsbReset() { cli(); int frameLength, targetLength = (unsigned)(1499 * (double)F_CPU / 10.5e6 + 0.5); int bestDeviation = 9999; uchar trialCal, bestCal, step, region; bestCal = OSCCAL; // do a binary search in regions 0-127 and 128-255 to get optimum OSCCAL for(region = 0; region <= 1; region++) { frameLength = 0; trialCal = (region == 0) ? 0 : 128; for(step = 64; step > 0; step >>= 1) { if(frameLength < targetLength) // true for initial iteration trialCal += step; // frequency too low else trialCal -= step; // frequency too high OSCCAL = trialCal; frameLength = usbMeasureFrameLength(); if(abs(frameLength-targetLength) < bestDeviation) { bestCal = trialCal; // new optimum found bestDeviation = abs(frameLength -targetLength); } } } OSCCAL = bestCal; sei(); } /* ------------------------------------------------------------------------- */ int main(void) { SetupHardware(); clearReport(); // int count = 0; for(;;) { if (USBIN&USBMASK) { sleep_cpu(); // sleep, except at SE0, until SOF } //wdt_reset(); usbPoll(); // if(usbInterruptIsReady()) // { // // if (count > 10) // // { // // PINB |= _BV(PB1); // // count = 0; // // } // // count++; // usbSetInterrupt((void *)&reportBuffer, sizeof(reportBuffer)); // clearReport(); // } } return 0; } /* ------------------------------------------------------------------------- */