mirror of
https://github.com/mon/PocketVoltex.git
synced 2026-09-22 22:57:58 +03:00
Working LEDs
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
#include <avr/eeprom.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#define MAGIC_NUMBER 43
|
||||
#define MAGIC_NUMBER 42
|
||||
|
||||
static sdvx_config_t defaults PROGMEM = {
|
||||
.switches = {
|
||||
|
||||
@@ -18,77 +18,48 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM GenericReport[] =
|
||||
HID_RI_USAGE_PAGE(16, 0xFFDC), /* Vendor Page 0xDC */
|
||||
HID_RI_USAGE(8, 0xFB), /* Vendor Usage 0xFB */
|
||||
HID_RI_COLLECTION(8, 0x01), /* Vendor Usage 1 */
|
||||
HID_RI_USAGE(8, 0x02), /* Vendor Usage 2 */
|
||||
// Global Items
|
||||
HID_RI_LOGICAL_MINIMUM(8, 0x00),
|
||||
HID_RI_LOGICAL_MAXIMUM(8, 0xFF),
|
||||
HID_RI_REPORT_SIZE(8, 8),
|
||||
HID_RI_REPORT_COUNT(8, CONFIG_BYTES),
|
||||
|
||||
// Write config
|
||||
HID_RI_USAGE(8, 0x02), /* Vendor Usage 2 */
|
||||
HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
|
||||
|
||||
// Read config
|
||||
HID_RI_USAGE(8, 0x02), /* Vendor Usage 2 */
|
||||
HID_RI_LOGICAL_MINIMUM(8, 0x00),
|
||||
HID_RI_LOGICAL_MAXIMUM(8, 0xFF),
|
||||
HID_RI_REPORT_SIZE(8, 8),
|
||||
HID_RI_REPORT_COUNT(8, CONFIG_BYTES),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
|
||||
HID_RI_END_COLLECTION(0),
|
||||
};
|
||||
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM LEDReport[] =
|
||||
{
|
||||
HID_RI_USAGE_PAGE(16, 0xFFDE), /* Vendor Page 0xDC */
|
||||
HID_RI_USAGE(8, 0xFE), /* Vendor Usage 0xFB */
|
||||
HID_RI_COLLECTION(8, 0x03), /* Vendor Usage 1 */
|
||||
HID_RI_USAGE(8, 0x04), /* Vendor Usage 2 */
|
||||
HID_RI_LOGICAL_MINIMUM(8, 0x00),
|
||||
HID_RI_LOGICAL_MAXIMUM(8, 0xFF),
|
||||
HID_RI_REPORT_SIZE(8, 8),
|
||||
HID_RI_REPORT_COUNT(8, CONFIG_BYTES),
|
||||
HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
|
||||
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
|
||||
HID_RI_USAGE(8, 0x00), /* Undefined */
|
||||
HID_RI_COLLECTION(8, 0x01), /* Application */
|
||||
// Global Items
|
||||
HID_RI_REPORT_COUNT(8, LED_TOTAL_COUNT),
|
||||
HID_RI_REPORT_SIZE(8, 8),
|
||||
HID_RI_LOGICAL_MINIMUM(8, 0),
|
||||
HID_RI_LOGICAL_MAXIMUM(8, BRIGHTNESS_LEVELS-1),
|
||||
HID_RI_USAGE_PAGE(8, 0x0A), // Ordinals
|
||||
|
||||
HID_RI_USAGE(8, 0x04), /* Vendor Usage 2 */
|
||||
HID_RI_LOGICAL_MINIMUM(8, 0x00),
|
||||
HID_RI_LOGICAL_MAXIMUM(8, 0xFF),
|
||||
HID_RI_REPORT_SIZE(8, 8),
|
||||
HID_RI_REPORT_COUNT(8, CONFIG_BYTES),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
|
||||
HID_RI_END_COLLECTION(0),
|
||||
//HID_RI_USAGE_PAGE(16, 0xFF00),
|
||||
// HID_RI_USAGE(8, 0x01),
|
||||
// HID_RI_COLLECTION(8, 0x01),
|
||||
// HID_RI_USAGE(8, 0x02),
|
||||
// HID_RI_LOGICAL_MINIMUM(8, 0),
|
||||
// HID_RI_LOGICAL_MAXIMUM(8, 64),
|
||||
// HID_RI_REPORT_SIZE(8, 8),
|
||||
// HID_RI_REPORT_COUNT(8, 1),
|
||||
// HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
|
||||
//
|
||||
// HID_RI_USAGE(8, 0x02),
|
||||
// HID_RI_LOGICAL_MINIMUM(8, 0),
|
||||
// HID_RI_LOGICAL_MAXIMUM(8, 64),
|
||||
// HID_RI_REPORT_SIZE(8, 8),
|
||||
// HID_RI_REPORT_COUNT(8, 1),
|
||||
// HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
|
||||
// HID_RI_END_COLLECTION(0)
|
||||
//HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */
|
||||
//HID_RI_USAGE(8, 0x4b), /* Generic indicator */
|
||||
//HID_RI_COLLECTION(8, 0x01), /* Application */
|
||||
// // Lights aren't the full 256 shades
|
||||
// HID_RI_USAGE(8, 0x4B), /* Generic indicator 1 */
|
||||
// HID_RI_LOGICAL_MINIMUM(8, 0),
|
||||
// HID_RI_LOGICAL_MAXIMUM(8, 64),
|
||||
// HID_RI_USAGE_PAGE(8, 0x0A), /* Ordinals */
|
||||
//
|
||||
// HID_RI_USAGE(8, 1), /* Instance 1 */
|
||||
// HID_RI_COLLECTION(8, 0x02), /* Logical */
|
||||
// HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */
|
||||
//
|
||||
// HID_RI_REPORT_SIZE(8, 8),
|
||||
// HID_RI_REPORT_COUNT(8, 8),
|
||||
// HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
|
||||
// HID_RI_END_COLLECTION(0),
|
||||
//
|
||||
//HID_RI_END_COLLECTION(0),
|
||||
// Locals repeated for INPUT/OUTPUT
|
||||
0x79, STRING_ID_LED_INDIV, //HID_RI_STRING_MINIMUM(8, STRING_ID_LED_INDIV),
|
||||
0x89, STRING_ID_LED_INDIV + LED_TOTAL_COUNT, //HID_RI_STRING_MAXIMUM(8, STRING_ID_LED_INDIV + LED_COUNT),
|
||||
HID_RI_USAGE_MINIMUM(8, 1), // LED 1
|
||||
HID_RI_USAGE_MAXIMUM(8, LED_TOTAL_COUNT), // LED 8
|
||||
HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
|
||||
|
||||
// INPUT is also needed to be recognised by Bemanitools
|
||||
0x79, STRING_ID_LED_INDIV, //HID_RI_STRING_MINIMUM(8, STRING_ID_LED_INDIV),
|
||||
0x89, STRING_ID_LED_INDIV + LED_TOTAL_COUNT, //HID_RI_STRING_MAXIMUM(8, STRING_ID_LED_INDIV + LED_COUNT),
|
||||
HID_RI_USAGE_MINIMUM(8, 1), // LED 1
|
||||
HID_RI_USAGE_MAXIMUM(8, LED_TOTAL_COUNT), // LED 8
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
|
||||
HID_RI_END_COLLECTION(0),
|
||||
};
|
||||
|
||||
/** HID class report descriptor. This is a special descriptor constructed with values from the
|
||||
@@ -224,7 +195,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
||||
.SubClass = HID_CSCP_BootSubclass,
|
||||
.Protocol = HID_CSCP_MouseBootProtocol,
|
||||
|
||||
.InterfaceStrIndex = NO_DESCRIPTOR
|
||||
.InterfaceStrIndex = STRING_ID_KNOB
|
||||
},
|
||||
|
||||
.HID2_MouseHID =
|
||||
@@ -312,7 +283,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
||||
.HIDReportLength = sizeof(LEDReport)
|
||||
},
|
||||
|
||||
.HID4_ReportOUTEndpoint =
|
||||
.HID4_ReportINEndpoint =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
|
||||
|
||||
@@ -342,6 +313,39 @@ const USB_Descriptor_String_t PROGMEM ManufacturerString = USB_STRING_DESCRIPTOR
|
||||
const USB_Descriptor_String_t PROGMEM ProductString = USB_STRING_DESCRIPTOR(L"Pocket Voltex");
|
||||
const USB_Descriptor_String_t PROGMEM ConfigString = USB_STRING_DESCRIPTOR(L"Pocket Voltex Config");
|
||||
const USB_Descriptor_String_t PROGMEM LEDString = USB_STRING_DESCRIPTOR(L"Pocket Voltex LEDs");
|
||||
const USB_Descriptor_String_t PROGMEM KnobString = USB_STRING_DESCRIPTOR(L"Pocket Voltex Knobs");
|
||||
const USB_Descriptor_String_t PROGMEM LEDString_indiv[] = {
|
||||
USB_STRING_DESCRIPTOR(L"L1-B"),
|
||||
USB_STRING_DESCRIPTOR(L"L1-G"),
|
||||
USB_STRING_DESCRIPTOR(L"L1-R"),
|
||||
USB_STRING_DESCRIPTOR(L"L2-B"),
|
||||
USB_STRING_DESCRIPTOR(L"L2-G"),
|
||||
USB_STRING_DESCRIPTOR(L"L2-R"),
|
||||
USB_STRING_DESCRIPTOR(L"L3-B"),
|
||||
USB_STRING_DESCRIPTOR(L"L3-G"),
|
||||
USB_STRING_DESCRIPTOR(L"L3-R"),
|
||||
USB_STRING_DESCRIPTOR(L"L4-B"),
|
||||
USB_STRING_DESCRIPTOR(L"L4-G"),
|
||||
USB_STRING_DESCRIPTOR(L"L4-R"),
|
||||
USB_STRING_DESCRIPTOR(L"L5-B"),
|
||||
USB_STRING_DESCRIPTOR(L"L5-G"),
|
||||
USB_STRING_DESCRIPTOR(L"L5-R"),
|
||||
USB_STRING_DESCRIPTOR(L"L6-B"),
|
||||
USB_STRING_DESCRIPTOR(L"L6-G"),
|
||||
USB_STRING_DESCRIPTOR(L"L6-R"),
|
||||
USB_STRING_DESCRIPTOR(L"L7-B"),
|
||||
USB_STRING_DESCRIPTOR(L"L7-G"),
|
||||
USB_STRING_DESCRIPTOR(L"L7-R"),
|
||||
USB_STRING_DESCRIPTOR(L"L8-B"),
|
||||
USB_STRING_DESCRIPTOR(L"L8-G"),
|
||||
USB_STRING_DESCRIPTOR(L"L8-R"),
|
||||
USB_STRING_DESCRIPTOR(L"BT-A"),
|
||||
USB_STRING_DESCRIPTOR(L"BT-B"),
|
||||
USB_STRING_DESCRIPTOR(L"BT-C"),
|
||||
USB_STRING_DESCRIPTOR(L"BT-D"),
|
||||
USB_STRING_DESCRIPTOR(L"FX-L"),
|
||||
USB_STRING_DESCRIPTOR(L"FX-R"),
|
||||
};
|
||||
|
||||
/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
|
||||
* documentation) by the application code so that the address and size of a requested descriptor can be given
|
||||
@@ -392,6 +396,15 @@ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
|
||||
Address = &LEDString;
|
||||
Size = pgm_read_byte(&LEDString.Header.Size);
|
||||
break;
|
||||
case STRING_ID_KNOB:
|
||||
Address = &KnobString;
|
||||
Size = pgm_read_byte(&KnobString.Header.Size);
|
||||
break;
|
||||
default:
|
||||
if(DescriptorNumber >= STRING_ID_LED_INDIV) {
|
||||
Address = &(LEDString_indiv[STRING_ID_LED_INDIV - DescriptorNumber]);
|
||||
Size = pgm_read_byte(&LEDString_indiv[STRING_ID_LED_INDIV - DescriptorNumber].Header.Size);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
// LED HID Interface for pretty lights
|
||||
USB_Descriptor_Interface_t HID4_Interface;
|
||||
USB_HID_Descriptor_HID_t HID4_LEDHID;
|
||||
USB_Descriptor_Endpoint_t HID4_ReportOUTEndpoint;
|
||||
USB_Descriptor_Endpoint_t HID4_ReportINEndpoint;
|
||||
} USB_Descriptor_Configuration_t;
|
||||
|
||||
/** Enum for the device interface descriptor IDs within the device. Each interface descriptor
|
||||
@@ -96,7 +96,9 @@
|
||||
STRING_ID_Manufacturer = 1, /**< Manufacturer string ID */
|
||||
STRING_ID_Product = 2, /**< Product string ID */
|
||||
STRING_ID_Config = 3, /**< Config string ID */
|
||||
STRING_ID_LED = 4 /**< LED string ID */
|
||||
STRING_ID_KNOB = 4,
|
||||
STRING_ID_LED = 5, /**< LED string ID */
|
||||
STRING_ID_LED_INDIV = 6,
|
||||
};
|
||||
|
||||
/* Macros: */
|
||||
@@ -106,12 +108,12 @@
|
||||
|
||||
#define GENERIC_EPADDR (ENDPOINT_DIR_IN | 3)
|
||||
|
||||
#define LED_EPADDR (ENDPOINT_DIR_OUT | 4)
|
||||
#define LED_EPADDR (ENDPOINT_DIR_IN | 4)
|
||||
|
||||
#define KEYBOARD_EPSIZE 8
|
||||
#define MOUSE_EPSIZE 8
|
||||
#define GENERIC_EPSIZE CONFIG_BYTES
|
||||
#define LED_EPSIZE LED_COUNT
|
||||
#define LED_EPSIZE LED_TOTAL_COUNT
|
||||
|
||||
/* Function Prototypes: */
|
||||
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
|
||||
|
||||
@@ -12,11 +12,17 @@ typedef struct
|
||||
uint8_t KeyCode[SWITCH_COUNT]; // Length determined by the number of keys that can be reported
|
||||
} Keyboard_Report_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t mainLights[LED_RAW_COUNT];
|
||||
uint8_t btFx[6];
|
||||
} LED_Report_t;
|
||||
|
||||
/** Buffer to hold the previously generated Keyboard HID report, for comparison purposes inside the HID class driver. */
|
||||
static uint8_t PrevKeyboardHIDReportBuffer[sizeof(Keyboard_Report_t)];
|
||||
static uint8_t PrevMouseHIDReportBuffer[sizeof(USB_MouseReport_Data_t)];
|
||||
static uint8_t PrevGenericHIDReportBuffer[CONFIG_BYTES];
|
||||
static uint8_t PrevLEDHIDReportBuffer[LED_COUNT];
|
||||
static uint8_t PrevGenericHIDReportBuffer[sizeof(sdvx_config_t)];
|
||||
static uint8_t PrevLEDHIDReportBuffer[sizeof(LED_Report_t)];
|
||||
|
||||
/** LUFA HID Class driver interface configuration and state information. This structure is
|
||||
* passed to all HID Class driver functions, so that multiple instances of the same class
|
||||
@@ -172,11 +178,22 @@ int main(void)
|
||||
GlobalInterruptEnable();
|
||||
|
||||
// Blink to show we're not in bootloader
|
||||
for(uint8_t i = 0; i < LED_COUNT; i++) {
|
||||
led_set(i, 32, 0, 0);
|
||||
_delay_ms(100);
|
||||
led_set(i, 0, 0, 0);
|
||||
for(uint8_t flash = 0; flash < BRIGHTNESS_LEVELS; flash++) {
|
||||
for(uint8_t i = 0; i < LED_COUNT; i++) {
|
||||
uint8_t bright = ledLogCurve[flash];
|
||||
led_set(i, bright, bright/2, 0);
|
||||
_delay_us(500);
|
||||
}
|
||||
}
|
||||
// NOTE: signed
|
||||
for(int8_t flash = BRIGHTNESS_LEVELS; flash >= 0; flash--) {
|
||||
for(uint8_t i = 0; i < LED_COUNT; i++) {
|
||||
uint8_t bright = ledLogCurve[flash];
|
||||
led_set(i, bright, bright/2, 0);
|
||||
_delay_us(500);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Not in SetupHardware so we don't time out
|
||||
USB_Init();
|
||||
@@ -280,6 +297,11 @@ bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDIn
|
||||
memcpy(ConfigReport, &sdvxConfig, sizeof(sdvx_config_t));
|
||||
*ReportSize = CONFIG_BYTES;
|
||||
return true;
|
||||
} else if(HIDInterfaceInfo == &LED_HID_Interface) {
|
||||
uint8_t* LEDReport = (uint8_t*)ReportData;
|
||||
memcpy(LEDReport, (uint8_t*)leds, LED_TOTAL_COUNT);
|
||||
*ReportSize = LED_TOTAL_COUNT;
|
||||
return true;
|
||||
}
|
||||
*ReportSize = 0;
|
||||
return false;
|
||||
@@ -298,8 +320,7 @@ void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDI
|
||||
const uint8_t ReportID,
|
||||
const uint8_t ReportType,
|
||||
const void* ReportData,
|
||||
const uint16_t ReportSize)
|
||||
{
|
||||
const uint16_t ReportSize) {
|
||||
if(HIDInterfaceInfo == &Generic_HID_Interface && ReportType == HID_REPORT_ITEM_Out) {
|
||||
uint8_t* ConfigReport = (uint8_t*)ReportData;
|
||||
// So we can upgrade firmware without having to hit the button
|
||||
@@ -308,8 +329,22 @@ void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDI
|
||||
}
|
||||
SetConfig(ConfigReport);
|
||||
} else if(HIDInterfaceInfo == &LED_HID_Interface && ReportType == HID_REPORT_ITEM_Out) {
|
||||
uint8_t* LEDReport = (uint8_t*)ReportData;
|
||||
led_set_indiv(0, LEDReport[0]);
|
||||
LED_Report_t* LEDReport = (LED_Report_t*)ReportData;
|
||||
memcpy((uint8_t*)leds, LEDReport->mainLights, LED_RAW_COUNT);
|
||||
|
||||
// Keep normal lights but override when we get flashes on BT or FX
|
||||
// BT LEDs flash pure white
|
||||
for(uint8_t i = 0; i < 4; i++) {
|
||||
if(LEDReport->btFx[i]) {
|
||||
led_set(ledMap[i], BRIGHTNESS_LEVELS, BRIGHTNESS_LEVELS, BRIGHTNESS_LEVELS);
|
||||
}
|
||||
}
|
||||
// FX LEDs flash orange
|
||||
for(uint8_t i = 4; i < 6; i++) {
|
||||
if(LEDReport->btFx[i]) {
|
||||
led_set(ledMap[i], BRIGHTNESS_LEVELS, BRIGHTNESS_LEVELS/4, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "LED.h"
|
||||
|
||||
#define BRIGHTNESS_LEVELS 64
|
||||
#define GND_COUNT 4
|
||||
// RGB * 2
|
||||
#define LED_PINS 6
|
||||
@@ -20,10 +19,6 @@
|
||||
#define G 1
|
||||
#define B 0
|
||||
|
||||
// Arranged left to right, top to bottom
|
||||
// LED order is BGR...BGR
|
||||
static volatile uint8_t leds[LED_COUNT * 3];
|
||||
|
||||
void led_init() {
|
||||
// all GNDs low level for high impedence or gnd
|
||||
GND_PORT &= ~GND_MASK;
|
||||
@@ -35,9 +30,7 @@ void led_init() {
|
||||
// all LEDs output
|
||||
LED_DDR |= LED_MASK;
|
||||
|
||||
for(uint8_t i = 0; i < LED_COUNT * 3; i++) {
|
||||
leds[i] = 0;
|
||||
}
|
||||
memset((uint8_t*)leds, 0, LED_RAW_COUNT);
|
||||
|
||||
// 64 light levels * 60Hz update * 4 different GND pins = 15360Hz
|
||||
// 520 clock cycles for our interrupt handler
|
||||
@@ -46,7 +39,9 @@ void led_init() {
|
||||
// clk/8 prescaler
|
||||
TCCR0B = _BV(CS01);
|
||||
// 0.16% error on above calculation
|
||||
OCR0A = 64;
|
||||
//OCR0A = 64; // 60Hz
|
||||
OCR0A = 77; // 50Hz
|
||||
//OCR0A = 48; // 80Hz
|
||||
// Enable interrupt on OCR0A
|
||||
TIMSK0 = _BV(OCIE0A);
|
||||
// Clear interrupt
|
||||
|
||||
@@ -4,8 +4,24 @@
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LED_COUNT 8
|
||||
#define LED_RAW_COUNT (LED_COUNT*3)
|
||||
// BT + FX
|
||||
#define LED_VIRTUAL_COUNT 6
|
||||
#define LED_TOTAL_COUNT (LED_RAW_COUNT + LED_VIRTUAL_COUNT)
|
||||
#define BRIGHTNESS_LEVELS 64
|
||||
|
||||
const static uint8_t ledLogCurve[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 17, 20, 23, 25, 28, 31, 34, 37, 40, 43, 45, 48, 50, 52, 53, 55, 56, 57, 58, 59, 60, 60, 61, 61, 61, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63};
|
||||
|
||||
// Arranged left to right, top to bottom
|
||||
// LED order is BGR...BGR
|
||||
volatile uint8_t leds[LED_RAW_COUNT];
|
||||
|
||||
// Maps BT/FX keys to their associated LED
|
||||
// Order is BT-1-4, FX-L, FX-R
|
||||
static const uint8_t ledMap[] = {2, 0, 1, 3, 6, 7};
|
||||
|
||||
void led_init(void);
|
||||
void led_set(uint8_t num, uint8_t r, uint8_t g, uint8_t b);
|
||||
|
||||
Reference in New Issue
Block a user