Compare commits
4 Commits
1414d915a4
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
722a9b489b
|
|||
|
e3620971b1
|
|||
|
8082191d4e
|
|||
|
cc57b02d8c
|
+2
-2
@@ -1,2 +1,2 @@
|
||||
/build/**/*
|
||||
/external/**/*
|
||||
/*/**/*
|
||||
!/html/**/*
|
||||
|
||||
+5
-1
@@ -2,7 +2,9 @@ set(PROJECT aw410k_rgb)
|
||||
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(PICO_BOARD pico2)
|
||||
if (NOT DEFINED PICO_BOARD)
|
||||
set(PICO_BOARD pico)
|
||||
endif()
|
||||
set(TUSB_NETWORKING_PATH ${PICO_SDK_PATH}/lib/tinyusb/lib/networking)
|
||||
include (${PICO_SDK_PATH}/external/pico_sdk_import.cmake)
|
||||
project(${PROJECT} C CXX ASM)
|
||||
@@ -68,5 +70,7 @@ target_link_libraries(${PROJECT} PRIVATE
|
||||
hardware_adc
|
||||
)
|
||||
|
||||
set_target_properties(${PROJECT} PROPERTIES OUTPUT_NAME "${PROJECT}-${PICO_BOARD}")
|
||||
|
||||
pico_add_extra_outputs(${PROJECT})
|
||||
|
||||
|
||||
@@ -2,34 +2,38 @@
|
||||
|
||||
This project provides control to the RGB lighting on an Alienware AW410K
|
||||
keyboard based on ADC readings from an attached light dependent resistor using
|
||||
a webpage served by a Raspberry Pi Pico 2. Each key on the keyboard is
|
||||
a webpage served by a Raspberry Pi Pico (2). Each key on the keyboard is
|
||||
individually configurable from the webpage and can be set to automatically
|
||||
adjust brightness based off the ambient lighting.
|
||||
|
||||

|
||||
|
||||
[YouTube Video](https://youtu.be/uY1V1W5CdWM)
|
||||
|
||||
## Setup
|
||||
|
||||
### Hardware
|
||||
|
||||
You will need the following hardware to make the device:
|
||||
- Raspberry Pi Pico 2
|
||||
- Raspberry Pi Pico or Raspbery 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 2. The default configuration is to attach
|
||||
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 2. 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.
|
||||
|
||||

|
||||
@@ -43,8 +47,8 @@ the following.
|
||||
|
||||
The individual wires on the USB can be fragile, so hot glue or other strain
|
||||
relief is a good idea. There is also a [model for a 3D printed
|
||||
enclosure](pico-usb-ldr.stl) that you can use to place the Pico inside with a
|
||||
hole for the LDR to detect ambient light.
|
||||
enclosure](pico-usb-ldr.stl) that you can use to place the Pico (2) inside with
|
||||
a hole for the LDR to detect ambient light.
|
||||
|
||||

|
||||
|
||||
@@ -52,8 +56,8 @@ hole for the LDR to detect ambient light.
|
||||
|
||||
Flash the aw410k_rgb.uf2 file found from the latest
|
||||
[release](https://git.kkozai.com/kenji/aw410k_rgb/releases) to the 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.
|
||||
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://aw410k.usb, or if that doesn't load, to http://192.168.40.1. From the
|
||||
@@ -64,10 +68,10 @@ 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
|
||||
|
||||
@@ -30,6 +30,8 @@ static void send_color(uint8_t dev_addr);
|
||||
static void send_initial(uint8_t dev_addr);
|
||||
static struct key * find_key(char * name);
|
||||
static void set_color(char * name, uint8_t red, uint8_t green, uint8_t blue, uint8_t mode);
|
||||
static uint8_t hexint (const char c);
|
||||
static uint8_t hexbyte (const char * s);
|
||||
|
||||
static struct key key_list[NUM_KEYS] =
|
||||
{
|
||||
@@ -326,7 +328,9 @@ void parse_colors(char * data, uint16_t len) {
|
||||
if (token != NULL) {
|
||||
// first string is the RGB color code
|
||||
uint8_t red, green, blue;
|
||||
sscanf(token, "%2x%2x%2x", &red, &green, &blue);
|
||||
red = hexbyte(token);
|
||||
green = hexbyte(token+2);
|
||||
blue = hexbyte(token+4);
|
||||
|
||||
token = strtok(NULL, ",");
|
||||
if (token != NULL) {
|
||||
@@ -372,12 +376,17 @@ void startADC() {
|
||||
|
||||
// forward HID report after processing
|
||||
bool forward_report(uint8_t instance, uint8_t const* report, uint16_t len) {
|
||||
// toggle mute button color if mute button is pressed
|
||||
if ( instance == 0x02 && report[0] == 0x02 && (report[2] & 0x01) ) {
|
||||
mute = !mute;
|
||||
// forward only if device is connected
|
||||
if (device_state == DEVICE_ACTIVE) {
|
||||
// toggle mute button color if mute button is pressed
|
||||
if ( instance == 0x02 && report[0] == 0x02 && (report[2] & 0x01) ) {
|
||||
mute = !mute;
|
||||
}
|
||||
|
||||
return tud_hid_n_report(instance, 0, report, len);
|
||||
}
|
||||
|
||||
return tud_hid_n_report(instance, 0, report, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
// save RGB configuration to flash
|
||||
@@ -432,3 +441,21 @@ bool load_rgb_config(void) {
|
||||
tud_cdc_write_str("Configuration failed to load\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// simple helper to convert hex char to uint8_t value
|
||||
static uint8_t hexint (const char c) {
|
||||
if (c >= '0' && c <= '9') {
|
||||
return c - '0';
|
||||
} else if ( c >= 'a' && c <= 'f') {
|
||||
return c - 'a' + 10;
|
||||
} else if (c >= 'A' && c <= 'F') {
|
||||
return c- 'A' + 10;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// simple helper to convert 2 hex characters into a byte (uint8_t)
|
||||
static uint8_t hexbyte (const char * s) {
|
||||
return (hexint(s[0]) << 4) | (hexint(s[1]));
|
||||
}
|
||||
|
||||
@@ -151,6 +151,12 @@ bool load_rgb_config(void);
|
||||
|
||||
#define CFG_SIGNATURE 0xa22e
|
||||
|
||||
#define FLASH_TARGET_OFFSET (PICO_FLASH_SIZE_BYTES - FLASH_BLOCK_SIZE - 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
|
||||
|
||||
+14802
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 268 KiB |
+10
-7
@@ -79,19 +79,17 @@ void usb_device_main(void) {
|
||||
while (true) {
|
||||
switch ( device_state ) {
|
||||
case DEVICE_ACTIVE:
|
||||
if (!tud_mounted()) {
|
||||
device_state = DEVICE_INACTIVE;
|
||||
}
|
||||
break;
|
||||
case DEVICE_INACTIVE:
|
||||
break;
|
||||
case DEVICE_RESTART:
|
||||
if (tud_disconnect()) {
|
||||
device_state = DEVICE_INACTIVE;
|
||||
sleep_ms(10);
|
||||
if (tud_connect()) {
|
||||
if ( host_state == HOST_INACTIVE ) {
|
||||
device_state = DEVICE_INACTIVE;
|
||||
} else {
|
||||
device_state = DEVICE_ACTIVE;
|
||||
}
|
||||
}
|
||||
tud_connect();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -243,6 +241,11 @@ uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_t
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Invoked when device is mounted
|
||||
void tud_mount_cb(void) {
|
||||
device_state = DEVICE_ACTIVE;
|
||||
}
|
||||
|
||||
// print message to CDC in raw hex
|
||||
void cdc_print_hex(uint8_t const* msg, uint16_t msg_len) {
|
||||
(void) msg;
|
||||
|
||||
+5
-4
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user