/
main.c
127 lines (104 loc) · 2.93 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/* Minimal V-USB joystick example. Runs on USBasp hardware.
Copyright (C) 2014 Shay Green
Licensed under GPL v2 or later. See License.txt. */
#include <stdint.h>
#include <string.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "usbdrv/usbdrv.h"
// Report format: Y, X, buttons (up to 8)
static uint8_t report [3]; // current
static uint8_t report_out [3]; // last sent over USB
static void init_joy( void )
{
// Configure as inputs with pull-ups
DDRB &= ~0x3c;
PORTB |= 0x3c;
DDRD &= ~0x03;
PORTD |= 0x03;
}
static void read_joy( void )
{
report [0] = 0;
report [1] = 0;
report [2] = 0;
// Y
if ( ! (PINB & 0x04) ) report [0] = -127;
if ( ! (PINB & 0x08) ) report [0] = +127;
// X
if ( ! (PINB & 0x10) ) report [1] = -127;
if ( ! (PINB & 0x20) ) report [1] = +127;
// Buttons
if ( ! (PIND & 0x01) ) report [2] |= 0x01;
if ( ! (PIND & 0x02) ) report [2] |= 0x02;
// ...
}
// X/Y joystick w/ 8-bit readings (-127 to +127), 8 digital buttons
PROGMEM const char usbHidReportDescriptor [USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x05, // USAGE (Game Pad)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x08, // USAGE_MAXIMUM (Button 8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0 // END_COLLECTION
};
uint8_t usbFunctionSetup( uint8_t data [8] )
{
usbRequest_t const* rq = (usbRequest_t const*) data;
if ( (rq->bmRequestType & USBRQ_TYPE_MASK) != USBRQ_TYPE_CLASS )
return 0;
switch ( rq->bRequest )
{
case USBRQ_HID_GET_REPORT: // HID joystick only has to handle this
usbMsgPtr = (usbMsgPtr_t) report_out;
return sizeof report_out;
//case USBRQ_HID_SET_REPORT: // LEDs on joystick?
default:
return 0;
}
}
static void toggle_led( void )
{
DDRC |= 1;
PORTC ^= 1;
}
int main( void )
{
usbInit();
sei();
init_joy();
for ( ;; )
{
usbPoll();
// Don't bother reading joy if previous changes haven't gone out yet.
// Forces delay after changes which serves to debounce controller as well.
if ( usbInterruptIsReady() )
{
read_joy();
// Don't send update unless joystick changed
if ( memcmp( report_out, report, sizeof report ) )
{
memcpy( report_out, report, sizeof report );
usbSetInterrupt( report_out, sizeof report_out );
toggle_led();
}
}
}
return 0;
}