1 | #include <avr/io.h>
|
---|
2 | #include <avr/interrupt.h>
|
---|
3 | #include <avr/wdt.h>
|
---|
4 | #include <avr/pgmspace.h>
|
---|
5 | #include <util/delay.h>
|
---|
6 |
|
---|
7 | #include <string.h>
|
---|
8 | #include <stdbool.h>
|
---|
9 |
|
---|
10 | #include "usbdrv/usbdrv.h"
|
---|
11 |
|
---|
12 | static uint8_t reportBuffer[5];
|
---|
13 | static uint8_t idleRate;
|
---|
14 |
|
---|
15 | void main() {
|
---|
16 | uint8_t idleCounter = 0;
|
---|
17 |
|
---|
18 | wdt_enable(WDTO_2S);
|
---|
19 |
|
---|
20 | // USB
|
---|
21 | usbInit();
|
---|
22 | sei();
|
---|
23 | bool doReport;
|
---|
24 |
|
---|
25 | DDRB = 0; // Keyboard matrix out
|
---|
26 | PORTB = 255; // Enable pull up
|
---|
27 | // We put all pins as input then output a 0 in only one at a time.
|
---|
28 | // All the other pins are high-Z to avoid short circuits when many buttons are pressed.
|
---|
29 | DDRC = 0; // Keyboard matrix in
|
---|
30 | PORTC = 255; // Enable pull up
|
---|
31 |
|
---|
32 | // configure timer 0 for a rate of 16M/(256 * 256) = ~244Hz
|
---|
33 | TCCR0 = 4; // timer 0 prescaler: 256
|
---|
34 |
|
---|
35 | while(1) {
|
---|
36 | wdt_reset();
|
---|
37 | usbPoll();
|
---|
38 |
|
---|
39 | doReport = false;
|
---|
40 | for(int i=0; i < 5; i++) {
|
---|
41 | DDRB = ~(1<<i);
|
---|
42 | PORTB = ~(1<<i);
|
---|
43 | reportBuffer[i] = (~PINC)&0x3F;
|
---|
44 | }
|
---|
45 |
|
---|
46 | DDRB = ~(1<<5);
|
---|
47 | PORTB = ~(1<<5);
|
---|
48 | reportBuffer[0] |= (~PINC)<<6 & 0xC0;
|
---|
49 | reportBuffer[1] |= (~PINC)<<4 & 0xC0;
|
---|
50 | reportBuffer[2] |= (~PINC)<<2 & 0xC0;
|
---|
51 | // reportBuffer[3] |= (~PINC)<<0 & 0xC0; // These are not existing pins...
|
---|
52 |
|
---|
53 | DDRB = 255;
|
---|
54 | PORTB = 255;
|
---|
55 |
|
---|
56 | if (usbInterruptIsReady()) {
|
---|
57 | usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
|
---|
58 | // LEDOFF;
|
---|
59 | doReport = false;
|
---|
60 | }
|
---|
61 |
|
---|
62 | if (TIFR & (1 << TOV0)) {
|
---|
63 | TIFR = (1 << TOV0); // reset flag
|
---|
64 |
|
---|
65 | if(++idleCounter > 4){ // yes, but not yet
|
---|
66 | idleCounter -= 5; // 22ms in units of 4ms
|
---|
67 | } else { // yes, it is time now
|
---|
68 | idleCounter = idleRate;
|
---|
69 | if (usbInterruptIsReady()) {
|
---|
70 | usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
|
---|
71 | }
|
---|
72 | }
|
---|
73 | }
|
---|
74 | }
|
---|
75 | }
|
---|
76 |
|
---|
77 |
|
---|
78 | static uint8_t protocolVer = 1;
|
---|
79 | uint8_t expectReport = 0;
|
---|
80 |
|
---|
81 |
|
---|
82 | char PROGMEM usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = {
|
---|
83 | 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
---|
84 | 0x09, 0x05, // USAGE (Game Pad)
|
---|
85 | 0xa1, 0x01, // COLLECTION (Application)
|
---|
86 | 0x09, 0x01, // USAGE (Pointer)
|
---|
87 | 0xa1, 0x00, // COLLECTION (Physical)
|
---|
88 | 0x09, 0x30, // USAGE (X)
|
---|
89 | 0x09, 0x31, // USAGE (Y)
|
---|
90 | 0x15, 0xff, // LOGICAL_MINIMUM (-1)
|
---|
91 | 0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
---|
92 | 0x75, 0x02, // REPORT_SIZE (2)
|
---|
93 | 0x95, 0x02, // REPORT_COUNT (2)
|
---|
94 | 0x81, 0x02, // INPUT (Data,Var,Abs)
|
---|
95 | 0xc0, // END_COLLECTION
|
---|
96 | 0x05, 0x09, // USAGE_PAGE (Button)
|
---|
97 | 0x19, 0x01, // USAGE_MINIMUM (Button 1)
|
---|
98 | 0x29, 0x24, // USAGE_MAXIMUM (Button 36)
|
---|
99 | 0x15, 0x00, // LOGICAL_MINIMUM (0)
|
---|
100 | 0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
---|
101 | 0x75, 0x01, // REPORT_SIZE (1)
|
---|
102 | 0x95, 0x24, // REPORT_COUNT (36)
|
---|
103 | 0x81, 0x02, // INPUT (Data,Var,Abs)
|
---|
104 | 0xc0 // END_COLLECTION
|
---|
105 | };
|
---|
106 |
|
---|
107 |
|
---|
108 | uint8_t usbFunctionSetup(uint8_t data[8]) {
|
---|
109 | usbRequest_t *rq = (void *)data;
|
---|
110 | usbMsgPtr = reportBuffer;
|
---|
111 | if ((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) {
|
---|
112 | // class request type
|
---|
113 | if (rq->bRequest == USBRQ_HID_GET_REPORT) {
|
---|
114 | // wValue: ReportType (highbyte), ReportID (lowbyte)
|
---|
115 | // we only have one report type, so don't look at wValue
|
---|
116 | return sizeof(reportBuffer);
|
---|
117 | } else if (rq->bRequest == USBRQ_HID_SET_REPORT) {
|
---|
118 | if (rq->wLength.word == 1) {
|
---|
119 | // We expect one byte reports
|
---|
120 | expectReport = 1;
|
---|
121 | return 0xff; // Call usbFunctionWrite with data
|
---|
122 | }
|
---|
123 | } else if (rq->bRequest == USBRQ_HID_GET_IDLE) {
|
---|
124 | usbMsgPtr = &idleRate;
|
---|
125 | return 1;
|
---|
126 | } else if (rq->bRequest == USBRQ_HID_SET_IDLE) {
|
---|
127 | idleRate = rq->wValue.bytes[1];
|
---|
128 | } else if (rq->bRequest == USBRQ_HID_GET_PROTOCOL) {
|
---|
129 | if (rq->wValue.bytes[1] < 1) {
|
---|
130 | protocolVer = rq->wValue.bytes[1];
|
---|
131 | }
|
---|
132 | } else if(rq->bRequest == USBRQ_HID_SET_PROTOCOL) {
|
---|
133 | usbMsgPtr = &protocolVer;
|
---|
134 | return 1;
|
---|
135 | }
|
---|
136 | } else {
|
---|
137 | // no vendor specific requests implemented
|
---|
138 | }
|
---|
139 | return 0;
|
---|
140 | }
|
---|
141 |
|
---|
142 | uint8_t usbFunctionWrite(uchar *data, uchar len) {
|
---|
143 | expectReport = 0;
|
---|
144 | return 0x01;
|
---|
145 | }
|
---|
146 |
|
---|