Created
May 22, 2021 03:41
-
-
Save skogaby/adad2671313f5dbbdcbe42ee7224980f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "PluggableUSB.h" | |
#include "HID.h" | |
#include <FastLED.h> | |
typedef struct { | |
uint8_t brightness; | |
} SingleLED; | |
typedef struct { | |
uint8_t r; | |
uint8_t g; | |
uint8_t b; | |
} RGBLed; | |
// The single LEDs will be first in BTools | |
// The RGB LEDs will come afterwards, with R/G/B individually | |
#define NUMBER_OF_SINGLE 3 | |
#define NUMBER_OF_RGB 0 | |
#define NUM_LEDS 16 | |
#define DATA_PIN A3 | |
#define ON_COL CRGB::White | |
#define OFF_COL CRGB::Black | |
bool lightsUpdate = false; | |
CRGB leds[NUM_LEDS]; | |
void light_update(SingleLED* single_leds, RGBLed* rgb_leds) { | |
CRGB popColor = (single_leds[0].brightness > 128) ? ON_COL : OFF_COL; | |
CRGB titleLeftColor = (single_leds[1].brightness > 128) ? ON_COL : OFF_COL; | |
CRGB titleRightColor = (single_leds[2].brightness > 128) ? ON_COL : OFF_COL; | |
// Pop | |
if (single_leds[0].brightness > 128) { | |
for (int i = 1; i < 7; i++) { | |
leds[i] = popColor; | |
} | |
} | |
// Title Left | |
if (single_leds[1].brightness > 128) { | |
leds[0] = titleLeftColor; | |
for (int i = 12; i < 16; i++) { | |
leds[i] = titleLeftColor; | |
} | |
} | |
// Title Right | |
if (single_leds[2].brightness > 128) { | |
leds[7] = titleRightColor; | |
for (int i = 8; i < 12; i++) { | |
leds[i] = titleRightColor; | |
} | |
} | |
lightsUpdate = true; | |
} | |
void setup() { | |
FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS); | |
// Flash them a few times | |
for (int i = 0; i < 3; i++) { | |
for (int j = 0; j < NUM_LEDS; j++) { | |
leds[j] = ON_COL; | |
} | |
FastLED.show(); | |
delay(500); | |
for (int j = 0; j < NUM_LEDS; j++) { | |
leds[j] = OFF_COL; | |
} | |
FastLED.show(); | |
delay(500); | |
} | |
} | |
void loop() { | |
if (lightsUpdate) { | |
FastLED.show(); | |
lightsUpdate = false; | |
} | |
} | |
// ****************************** | |
// 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; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment