184 lines
5.2 KiB
C
184 lines
5.2 KiB
C
#include <stdlib.h>
|
|
|
|
#include "pico/stdlib.h"
|
|
#include "tusb.h"
|
|
#include "hardware/adc.h"
|
|
|
|
#include "hyperx_elite2.h"
|
|
|
|
static absolute_time_t lastSend;
|
|
static absolute_time_t lastRead;
|
|
static bool backlight = false;
|
|
static uint16_t adc_value = 0;
|
|
static bool mute = false;
|
|
|
|
static const unsigned int SKIP_INDICES[] = { 23, 29, 41, 47, 70, 71, 76, 87, 88, 93, 99, 100, 102, 108, 113 };
|
|
|
|
static unsigned char buf[BUF_SIZE];
|
|
static uint8_t buf_idx=0;
|
|
static uint8_t packets_sent=0;
|
|
static uint8_t color_idx = 0;
|
|
static uint8_t skipped = 0;
|
|
const unsigned int* skip_idx = &SKIP_INDICES[0];
|
|
|
|
static void send_color(uint8_t dev_addr, uint8_t red, uint8_t green, uint8_t blue);
|
|
static void send_initial(uint8_t dev_addr);
|
|
|
|
void get_light() {
|
|
// get ADC reading from LDR every 500ms
|
|
// if above threshold, set backlight to off
|
|
if ( absolute_time_diff_us(lastRead, get_absolute_time()) >= 500000) {
|
|
adc_value = adc_read();
|
|
if (backlight && adc_value >= LDR_OFF_THRESHOLD) {
|
|
backlight = false;
|
|
} else if (!backlight && adc_value <= LDR_ON_THRESHOLD) {
|
|
backlight = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
void rgb_task(uint8_t dev_addr) {
|
|
// the RGB protocol used by HyperX sends individual key RGB data in
|
|
// multiple packets
|
|
// the code here will determine if we are in the middle of sending
|
|
// updated color info (packets_sent>0) and continue to send the next
|
|
// packet if so at a rate of one packet every 20ms
|
|
// otherwise, wait 0.5s before sending the next set of color packets
|
|
if (packets_sent>0) {
|
|
if ( absolute_time_diff_us(lastSend, get_absolute_time()) >= 20000) {
|
|
if (backlight) {
|
|
send_color(dev_addr, 0x20, 0x20, 0x20);
|
|
// send a dim white color (#202020) for all keys
|
|
} else {
|
|
send_color(dev_addr, 0x00, 0x00, 0x00);
|
|
// turn off all lighting by sending (#000000) for all keys
|
|
}
|
|
lastSend = get_absolute_time();
|
|
}
|
|
} else {
|
|
if ( absolute_time_diff_us(lastSend, get_absolute_time()) >= 500000) {
|
|
send_initial(dev_addr);
|
|
lastSend = get_absolute_time();
|
|
}
|
|
}
|
|
}
|
|
|
|
// send an individual color packett with the desired RGB color
|
|
static void send_color(uint8_t dev_addr, uint8_t red, uint8_t green, uint8_t blue) {
|
|
memset(buf, 0x00, BUF_SIZE);
|
|
|
|
buf_idx = 0;
|
|
|
|
// check if there are still keys left to send and send updated colors
|
|
// for those keys
|
|
// each key gets 4 bytes - an init byte (0x81) plus 3 bytes for RGB
|
|
if(color_idx < NUM_KEYS)
|
|
{
|
|
while (color_idx < NUM_KEYS && buf_idx < BUF_SIZE) {
|
|
if (*skip_idx == color_idx + skipped) {
|
|
// keys in skip_idx are not assigned to a key, so send all 0x00
|
|
buf[buf_idx] = 0x00;
|
|
buf[buf_idx + 1] = 0x00;
|
|
buf[buf_idx + 2] = 0x00;
|
|
buf[buf_idx + 3] = 0x00;
|
|
|
|
skip_idx++;
|
|
|
|
if(skip_idx >= SKIP_INDICES + sizeof(SKIP_INDICES) / sizeof(unsigned int))
|
|
{
|
|
skip_idx = SKIP_INDICES;
|
|
}
|
|
skipped++;
|
|
} else {
|
|
// start by sending color init byte for the current key
|
|
buf[buf_idx] = 0x81;
|
|
// turn rewind, play, and fast forward keys to white
|
|
if(color_idx==105 || color_idx==108 || color_idx==109) {
|
|
buf[buf_idx + 1] = 0x20;
|
|
buf[buf_idx + 2] = 0x20;
|
|
buf[buf_idx + 3] = 0x20;
|
|
} else if(color_idx==99) {
|
|
// set color of mute button to green or red based on mute
|
|
// toggle - note that this toggle is not synced to the PC's
|
|
// audio state and is presumed to be unmuted when the keyboard
|
|
// first receives power
|
|
if(mute) {
|
|
buf[buf_idx + 1] = 0x40;
|
|
buf[buf_idx + 2] = 0x00;
|
|
buf[buf_idx + 3] = 0x00;
|
|
} else {
|
|
buf[buf_idx + 1] = 0x00;
|
|
buf[buf_idx + 2] = 0x40;
|
|
buf[buf_idx + 3] = 0x00;
|
|
}
|
|
} else {
|
|
// for a normal key, send the desired RGB colors
|
|
buf[buf_idx + 1] = red;
|
|
buf[buf_idx + 2] = green;
|
|
buf[buf_idx + 3] = blue;
|
|
}
|
|
color_idx++;
|
|
}
|
|
buf_idx += 4;
|
|
}
|
|
|
|
if(tuh_hid_set_report(dev_addr, 0, 0, HID_REPORT_TYPE_FEATURE, buf, BUF_SIZE))
|
|
{
|
|
// packet sent successfully, increment
|
|
packets_sent++;
|
|
}
|
|
} else {
|
|
if(packets_sent < NUM_PACKETS)
|
|
{
|
|
// all keys have been sent, but the protocol expects NUM_PACKETS
|
|
// packets to be sent in total; if we have not sent enough packets,
|
|
// send extra packets of all 0x00 until done
|
|
if(tuh_hid_set_report(dev_addr, 0, 0, HID_REPORT_TYPE_FEATURE, buf, BUF_SIZE))
|
|
{
|
|
packets_sent++;
|
|
}
|
|
} else {
|
|
// a full round of color packets completed, reset packets to 0
|
|
packets_sent=0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// send the special initialization packet that tells the keyboard to expect
|
|
// color packets to follow
|
|
static void send_initial(uint8_t dev_addr) {
|
|
memset(buf, 0x00, BUF_SIZE);
|
|
|
|
color_idx = 0;
|
|
skipped = 0;
|
|
skip_idx = &SKIP_INDICES[0];
|
|
|
|
// send initialization packet
|
|
buf[0x00] = 0x04;
|
|
buf[0x01] = 0xf2;
|
|
|
|
if (tuh_hid_set_report(dev_addr, 0, 0, HID_REPORT_TYPE_FEATURE, buf, BUF_SIZE))
|
|
{
|
|
// we have begun sending packets, so indicate first packet was sent
|
|
// remaining packets will be sent at regular intervals
|
|
packets_sent=1;
|
|
}
|
|
}
|
|
|
|
// initialize the ADC for reading the LDR
|
|
void startADC() {
|
|
stdio_init_all();
|
|
adc_init();
|
|
adc_gpio_init(LDR_PIN);
|
|
adc_select_input(LDR_ADC);
|
|
}
|
|
|
|
// forward HID report after processing
|
|
bool forward_report(uint8_t instance, uint8_t const* report, uint16_t len) {
|
|
if (instance == 0x01 && report[0] == 0x03 && report[1] == 0xE2) {
|
|
mute = !mute;
|
|
}
|
|
|
|
return tud_hid_n_report(instance, 0, report, len);
|
|
}
|