-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathArduino-HID-Lighting.ino
More file actions
150 lines (125 loc) · 4.57 KB
/
Arduino-HID-Lighting.ino
File metadata and controls
150 lines (125 loc) · 4.57 KB
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include "PluggableUSB.h"
#include "HID.h"
typedef struct {
uint8_t brightness;
} SingleLED;
typedef struct {
uint8_t r;
uint8_t g;
uint8_t b;
} RGBLed;
// ******************************
// EDIT THESE LINES
// The single LEDs will be first in BTools
// The RGB LEDs will come afterwards, with R/G/B individually
#define NUMBER_OF_SINGLE 0
#define NUMBER_OF_RGB 1
/* Important note!
* light_update works inside an interrupt handler. If the code inside here
* takes more than about 1ms, the USB stack will start breaking. Delay functions
* will also not work. Do not write out to Serial, neopixels, SPI etc. Just
* copy the data to a good place and then send it out in loop()
*
* Check the "examples" folder for how to do Neopixels without breaking.
*/
void light_update(SingleLED* single_leds, RGBLed* rgb_leds) {
for(int i = 0; i < NUMBER_OF_SINGLE; i++) {
// YOUR CODE HERE
// led_stuff(single_leds[i].brightness);
}
for(int i = 0; i < NUMBER_OF_RGB; i++) {
// YOUR CODE HERE
// rgb_stuff(rgb_leds[i].r, rgb_leds[i].g, rgb_leds[i].b);
}
}
void setup() {
// setup your LEDs here
}
void loop() {
// USB module does the hard work
}
// ******************************
// don't need to edit below here
#define NUMBER_OF_LIGHTS (NUMBER_OF_SINGLE + NUMBER_OF_RGB*3)
#if NUMBER_OF_LIGHTS > 63
#error You must have less than 64 lights
#endif
union {
struct {
SingleLED singles[NUMBER_OF_SINGLE];
RGBLed rgb[NUMBER_OF_RGB];
} leds;
uint8_t raw[NUMBER_OF_LIGHTS];
} led_data;
static const uint8_t PROGMEM _hidReportLEDs[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x00, // USAGE (Undefined)
0xa1, 0x01, // COLLECTION (Application)
// Globals
0x95, NUMBER_OF_LIGHTS, // REPORT_COUNT
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x05, 0x0a, // USAGE_PAGE (Ordinals)
// Locals
0x19, 0x01, // USAGE_MINIMUM (Instance 1)
0x29, NUMBER_OF_LIGHTS, // USAGE_MAXIMUM (Instance n)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
// BTools needs at least 1 input to work properly
0x19, 0x01, // USAGE_MINIMUM (Instance 1)
0x29, 0x01, // USAGE_MAXIMUM (Instance 1)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0xc0 // END_COLLECTION
};
// This is almost entirely copied from NicoHood's wonderful RawHID example
// Trimmed to the bare minimum
// https://github.com/NicoHood/HID/blob/master/src/SingleReport/RawHID.cpp
class HIDLED_ : public PluggableUSBModule {
uint8_t epType[1];
public:
HIDLED_(void) : PluggableUSBModule(1, 1, epType) {
epType[0] = EP_TYPE_INTERRUPT_IN;
PluggableUSB().plug(this);
}
int getInterface(uint8_t* interfaceCount) {
*interfaceCount += 1; // uses 1
HIDDescriptor hidInterface = {
D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE),
D_HIDREPORT(sizeof(_hidReportLEDs)),
D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 16)
};
return USB_SendControl(0, &hidInterface, sizeof(hidInterface));
}
int getDescriptor(USBSetup& setup)
{
// Check if this is a HID Class Descriptor request
if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; }
if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; }
// In a HID Class Descriptor wIndex contains the interface number
if (setup.wIndex != pluggedInterface) { return 0; }
return USB_SendControl(TRANSFER_PGM, _hidReportLEDs, sizeof(_hidReportLEDs));
}
bool setup(USBSetup& setup)
{
if (pluggedInterface != setup.wIndex) {
return false;
}
uint8_t request = setup.bRequest;
uint8_t requestType = setup.bmRequestType;
if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE)
{
return true;
}
if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) {
if (request == HID_SET_REPORT) {
if(setup.wValueH == HID_REPORT_TYPE_OUTPUT && setup.wLength == NUMBER_OF_LIGHTS){
USB_RecvControl(led_data.raw, NUMBER_OF_LIGHTS);
light_update(led_data.leds.singles, led_data.leds.rgb);
return true;
}
}
}
return false;
}
};
HIDLED_ HIDLeds;