Add Pico 2 support

This commit is contained in:
2025-09-06 12:01:00 -04:00
parent 2fac602e44
commit a1cb13a2f9
9 changed files with 73 additions and 52 deletions
+5 -1
View File
@@ -3,6 +3,9 @@ cmake_minimum_required(VERSION 3.13)
set(PICO_SDK_PATH /home/kenji/programming/pico/c/pico-sdk)
set(PICO_PIO_USB_PATH /home/kenji/programming/pico/c/Pico-PIO-USB)
set(TUSB_NETWORKING_PATH ${PICO_SDK_PATH}/lib/tinyusb/lib/networking)
if (NOT DEFINED PICO_BOARD)
set(PICO_BOARD pico)
endif()
include (${PICO_SDK_PATH}/external/pico_sdk_import.cmake)
project(${PROJECT} C CXX ASM)
@@ -67,5 +70,6 @@ target_link_libraries(${PROJECT} PRIVATE
hardware_adc
)
pico_add_extra_outputs(${PROJECT})
set_target_properties(${PROJECT} PROPERTIES OUTPUT_NAME "${PROJECT}-${PICO_BOARD}")
pico_add_extra_outputs(${PROJECT})
+17 -17
View File
@@ -1,9 +1,9 @@
# HyperX Alloy Elite 2 RGB Controller
This project provides individual controls of the RGB LEDs of a HyperX Alloy
Elite 2 keyboard using a webpage served over a USB connection. ADC readings
from an attached light dependent resistor can also be used to make the
lighting adaptive to the environment.
Elite 2 keyboard using a webpage served over a USB connection from a Raspberry
Pi Pico (2). ADC readings from an attached light dependent resistor can also be
used to make the lighting adaptive to the environment.
![Web interface for setting individual LED RGB values](ui.png)
@@ -12,23 +12,23 @@ lighting adaptive to the environment.
### Hardware
You will need the following hardware to make the device:
- Raspberry Pi Pico
- Raspberry Pi Pico or Raspberry Pi Pico 2
- USB extension cable
- light dependent resistor such as GL5528 (specific part number may vary)
- 10k ohm resistor (resistance value may vary)
You will need to cut the USB extension in half and connect the wires from the
female end to the Raspberry Pi Pico. The default configuration is to attach the
USB's green wire to pin 1/GP0 and USB's white wire to pin 2/GP1. You will also
need to connect the red to 5V VBUS/VSYS (since you'll be powering from the
female end to the Raspberry Pi Pico (2). The default configuration is to attach
the USB's green wire to pin 1/GP0 and USB's white wire to pin 2/GP1. You will
also need to connect the red to 5V VBUS/VSYS (since you'll be powering from the
USB host device, VBUS should be fine) and the black to any ground pin. Pin 38
is the closest and most convenient. While you can connect the Raspberry Pi Pico
to the host device using the micro USB port and a micro USB cable, since
(2) to the host device using the micro USB port and a micro USB cable, since
you have already sacrificed half of the USB extension cable, you might as well
use the male half to create a standard USB-A connection. If you wish to do so,
then simply connect the red and black wires of the male connector end to
VBUS (5V) and GND, respectively. For the data wires, you can solder them to the
two test points TP2 and TP3 on the back of the Raspberry Pi Pico. The white
two test points TP2 and TP3 on the back of the Raspberry Pi Pico (2). The white
cable goes to TP2 and the green cable to TP3.
![Back of Raspberry Pi Pico with USB connections to TP2 and TP3](back.jpg)
@@ -49,23 +49,23 @@ hole for the LDR to detect ambient light.
## Software
Flash the elite2_rgb.uf2 file from the latest
Flash the elite2_rgb-pico.uf2 or elite2_rgb-pico2.uf2 file from the latest
[release](https://git.kkozai.com/kenji/alloy_elite2_rgb/releases) to the
Raspberry Pi Pico, and connect the keyboard to the female USB port and insert
the male USB connector of the device into your host device such as PC.
Raspberry Pi Pico (2), and connect the keyboard to the female USB port and
insert the male USB connector of the device into your host device such as PC.
To load the UI for configuring the RGB lighting, open a browser to the page at
http://alloyelite2.usb, or if that doesn't load, to http://192.168.226.1
(226 is E2 for "Elite 2" in hexademical). From the webpage, you can click on
(226 is E2 for "Elite 2" in hexadecimal). From the webpage, you can click on
any individual key that you want to configure and change the color using the
color selector or by manually inputting the RGB color value into the text
boxes. To finalize setting the color for the selected key(s), click on the
"Set Color" button.
To save the lighting configuration to the Pico 2 so that it loads the next time
it is powered on, click on the "Save" button under the "Flash Memory" section.
If you make unsaved changes and want to reload the configuration from memory,
you can also click the "Load" button to reset to the last saved setting.
To save the lighting configuration to the Pico (2) so that it loads the next
time it is powered on, click on the "Save" button under the "Flash Memory"
section. If you make unsaved changes and want to reload the configuration from
memory, you can also click the "Load" button to reset to the last saved setting.
If the checkbox next to "Adaptive" is selected when setting the color, the key's
brightness will automatically adjust with the ambient lighting, as determined by
+7 -23
View File
@@ -1,4 +1,5 @@
#include <stdlib.h>
#include <math.h>
#include "pico/stdlib.h"
#include "pico/multicore.h"
@@ -13,7 +14,8 @@
static absolute_time_t lastSend;
static absolute_time_t lastRead;
static uint16_t adc_value = 0;
//static uint16_t adc_value = 0;
static uint8_t adc_value = 0;
static bool mute = false;
static unsigned char buf[BUF_SIZE];
@@ -165,7 +167,7 @@ static struct key key_list[NUM_KEYS] =
void get_light() {
// get ADC reading from LDR every 500ms
if ( absolute_time_diff_us(lastRead, get_absolute_time()) >= 500000) {
adc_value = adc_read();
adc_value = log2(adc_read());
}
}
@@ -176,24 +178,6 @@ void rgb_task(uint8_t dev_addr) {
// 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();
}
}*/
if ( absolute_time_diff_us(lastSend, get_absolute_time()) >= delay) {
if ( packets_sent == 0) {
// first packet is initialization packet
@@ -227,9 +211,9 @@ static void send_color(uint8_t dev_addr) {
buf[buf_idx] = 0x81;
switch (key_list[key_idx].mode) {
case RGB_MODE_ADAPTIVE: // adjust brightness based on LDR ADC reading
buf[buf_idx+1] = (ADC_MAX-adc_value)*key_list[key_idx].red/ADC_MAX;
buf[buf_idx+2] = (ADC_MAX-adc_value)*key_list[key_idx].green/ADC_MAX;
buf[buf_idx+3] = (ADC_MAX-adc_value)*key_list[key_idx].blue/ADC_MAX;
buf[buf_idx+1] = (ADC_MAX_LOG2-adc_value)*key_list[key_idx].red/ADC_MAX_LOG2;
buf[buf_idx+2] = (ADC_MAX_LOG2-adc_value)*key_list[key_idx].green/ADC_MAX_LOG2;
buf[buf_idx+3] = (ADC_MAX_LOG2-adc_value)*key_list[key_idx].blue/ADC_MAX_LOG2;
break;
case RGB_MODE_MUTE:
if (mute) {
+9 -1
View File
@@ -11,6 +11,7 @@
#define NUM_KEYS 126
#define BUF_SIZE 64
#define ADC_MAX 4096
#define ADC_MAX_LOG2 log2(ADC_MAX)
enum {
RGG_MODE_INVALID=0,
@@ -187,6 +188,13 @@ bool load_rgb_config(void);
#define CFG_SIGNATURE 0x9e4c
#define FLASH_TARGET_OFFSET (PICO_FLASH_SIZE_BYTES - FLASH_SECTOR_SIZE)
#if PICO_RP2040
#define FLASH_TARGET_OFFSET (PICO_FLASH_SIZE_BYTES - FLASH_SECTOR_SIZE)
#elif PICO_RP2350
#define FLASH_TARGET_OFFSET (PICO_FLASH_SIZE_BYTES - FLASH_BLOCK_SIZE - FLASH_SECTOR_SIZE)
#else
#error "Unsupported device. Expected RP2040 or RP2350."
#endif
#endif
+25 -1
View File
@@ -1034,7 +1034,31 @@ static const unsigned char data_index_html[] = {
0x61, 0x6c, 0x75, 0x65, 0x29, 0x20, 0x3c, 0x20, 0x30, 0x29,
0x20, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x63, 0x68, 0x61, 0x6e,
0x6e, 0x65, 0x6c, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20,
0x3d, 0x20, 0x30, 0x3b, 0xa, 0x9, 0x9, 0x7d, 0xa, 0x9,
0x3d, 0x20, 0x30, 0x3b, 0xa, 0x9, 0x9, 0x7d, 0x20, 0x65,
0x6c, 0x73, 0x65, 0x20, 0x69, 0x66, 0x20, 0x28, 0x20, 0x69,
0x73, 0x4e, 0x61, 0x4e, 0x28, 0x70, 0x61, 0x72, 0x73, 0x65,
0x49, 0x6e, 0x74, 0x28, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65,
0x6c, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x29, 0x29, 0x20,
0x29, 0x20, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x2f, 0x2f, 0x20,
0x6e, 0x6f, 0x6e, 0x2d, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69,
0x63, 0x61, 0x6c, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20,
0x65, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x64, 0x2c, 0x20, 0x73,
0x65, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x65, 0x66, 0x61,
0x75, 0x6c, 0x74, 0xa, 0x9, 0x9, 0x9, 0x63, 0x68, 0x61,
0x6e, 0x6e, 0x65, 0x6c, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65,
0x20, 0x3d, 0x20, 0x31, 0x32, 0x38, 0x3b, 0xa, 0x9, 0x9,
0x7d, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x7b, 0xa, 0x9,
0x9, 0x9, 0x2f, 0x2f, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20,
0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x62,
0x6f, 0x78, 0x20, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74,
0x73, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x70, 0x61, 0x72,
0x73, 0x65, 0x72, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x6b, 0x73,
0xa, 0x9, 0x9, 0x9, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65,
0x6c, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x3d, 0x20,
0x70, 0x61, 0x72, 0x73, 0x65, 0x49, 0x6e, 0x74, 0x28, 0x63,
0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x2e, 0x76, 0x61, 0x6c,
0x75, 0x65, 0x29, 0x3b, 0xa, 0x9, 0x9, 0x7d, 0xa, 0x9,
0x7d, 0xa, 0xa, 0x9, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65,
0x6e, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d,
0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x72,
+2 -2
View File
@@ -13,9 +13,9 @@
#include "usb_device.h"
char cdc_buf[64];
char cdc_buf[128];
uint16_t cdc_len;
size_t cdc_count;
uint32_t cdc_count;
device_state_t device_state;
static uint8_t desc_configuration[DESC_CFG_MAX];
+2 -2
View File
@@ -30,9 +30,9 @@ typedef enum {
DEVICE_RESTART,
} device_state_t;
extern char cdc_buf[64];
extern char cdc_buf[128];
extern uint16_t cdc_len;
extern size_t cdc_count;
extern uint32_t cdc_count;
extern device_state_t device_state;
void usb_device_main(void);
+5 -4
View File
@@ -354,12 +354,14 @@ static err_t ws_read(struct altcp_pcb *pcb, struct ws_state *wss, struct pbuf *p
uint8_t masked = data[1] & 0x80;
uint16_t msg_len = data[1] & 0x7F;
uint8_t *msg;
uint8_t *mask;
switch (msg_len) {
case 126: // next two bytes are length
memcpy(&msg_len, &data[2], 2);
msg_len = ( (uint16_t)data[2] << 8) | data[3];
if (len >= 8) {
msg = &data[8];
mask = &data[4];
}
break;
case 127: // next four bytes are length
@@ -369,6 +371,7 @@ static err_t ws_read(struct altcp_pcb *pcb, struct ws_state *wss, struct pbuf *p
default:
if (len >= 6) {
msg = &data[6];
mask = &data[2];
}
break;
}
@@ -382,8 +385,6 @@ static err_t ws_read(struct altcp_pcb *pcb, struct ws_state *wss, struct pbuf *p
if (msg && ws_receive_cb != NULL) {
// unmask the data if mask bit is received
if (masked) {
uint8_t *mask = &data[2];
for (int i=0; i<msg_len; i++) {
msg[i] ^= mask[i % 4];
}
+1 -1
View File
@@ -7,7 +7,7 @@
#define WS_MAX_RETRIES 10
#define WS_POLL_INTERVAL 60 // WS_POLL_INTERVAL/2 seconds
#define WS_MAX_CONN 4
#define WS_BUFFER_SIZE 512
#define WS_BUFFER_SIZE 1024
#define OP_CONT 0x00
#define OP_TEXT 0x01