diff --git a/build_uf2/Pico_Game_Controller.uf2 b/build_uf2/Pico_Game_Controller.uf2 index 7c95f78..2283fc5 100644 Binary files a/build_uf2/Pico_Game_Controller.uf2 and b/build_uf2/Pico_Game_Controller.uf2 differ diff --git a/src/controller_config.h b/src/controller_config.h index 47dfbc6..5ba03ca 100644 --- a/src/controller_config.h +++ b/src/controller_config.h @@ -10,8 +10,8 @@ #define SW_DEBOUNCE_TIME_US 4000 // Switch debounce delay in us #define ENC_PULSE (ENC_PPR * 4) // 4 pulses per PPR #define REACTIVE_TIMEOUT_MAX 1000000 // HID to reactive timeout in us -#define WS2812B_LED_SIZE 10 // Number of WS2812B LEDs -#define WS2812B_LED_ZONES 2 // Number of WS2812B LED Zones +#define WS2812B_LED_SIZE 32 // Number of WS2812B LEDs +#define WS2812B_LED_ZONES 1 // Number of WS2812B LED Zones #define WS2812B_LEDS_PER_ZONE \ WS2812B_LED_SIZE / WS2812B_LED_ZONES // Number of LEDs per zone @@ -23,14 +23,12 @@ const uint8_t SW_KEYCODE[] = { HID_KEY_M, HID_KEY_A, HID_KEY_B, HID_KEY_1, }; const uint8_t SW_GPIO[] = { - 4, 6, 8, 10, 12, 14, 27, 18, 20, + 29, 3, 4, 5, 17, 12, 0, 8, 1, }; -const uint8_t LED_GPIO[] = { - 5, 7, 9, 11, 13, 15, 21, -}; -const uint8_t ENC_GPIO[] = {0, 2}; // L_ENC(0, 1); R_ENC(2, 3) +const uint8_t LED_GPIO[] = {21}; +const uint8_t ENC_GPIO[] = {27, 6}; // L_ENC(0, 1); R_ENC(2, 3) const bool ENC_REV[] = {false, false}; // Reverse Encoders -const uint8_t WS2812B_GPIO = 28; +const uint8_t WS2812B_GPIO = 2; #endif diff --git a/src/pico_game_controller.c b/src/pico_game_controller.c index 5d53015..f814ece 100644 --- a/src/pico_game_controller.c +++ b/src/pico_game_controller.c @@ -8,8 +8,10 @@ #include #include +// clang-format off #include "bsp/board.h" #include "controller_config.h" +#include "types.h" #include "encoders.pio.h" #include "hardware/clocks.h" #include "hardware/dma.h" @@ -19,7 +21,6 @@ #include "pico/stdlib.h" #include "tusb.h" #include "usb_descriptors.h" -// clang-format off #include "debounce/debounce_include.h" #include "rgb/rgb_include.h" // clang-format on @@ -41,72 +42,8 @@ void (*loop_mode)(); uint16_t (*debounce_mode)(); bool joy_mode_check = true; -union { - struct { - uint8_t buttons[LED_GPIO_SIZE]; - RGB_t rgb[WS2812B_LED_ZONES]; - } lights; - uint8_t raw[LED_GPIO_SIZE + WS2812B_LED_ZONES * 3]; -} lights_report; - -/** - * WS2812B Lighting - * @param counter Current number of WS2812B cycles - **/ -void ws2812b_update(uint32_t counter) { - if (time_us_64() - reactive_timeout_timestamp >= REACTIVE_TIMEOUT_MAX) { - ws2812b_mode(counter); - } else { - for (int i = 0; i < WS2812B_LED_ZONES; i++) { - for (int j = 0; j < WS2812B_LEDS_PER_ZONE; j++) { - put_pixel(urgb_u32(lights_report.lights.rgb[i].r, - lights_report.lights.rgb[i].g, - lights_report.lights.rgb[i].b)); - } - } - } -} - -/** - * HID/Reactive Lights - **/ -void update_lights() { - for (int i = 0; i < LED_GPIO_SIZE - 1; i++) { - if (time_us_64() - reactive_timeout_timestamp >= REACTIVE_TIMEOUT_MAX) { - if (!gpio_get(SW_GPIO[i])) { - gpio_put(LED_GPIO[i], 1); - } else { - gpio_put(LED_GPIO[i], 0); - } - } else { - if (lights_report.lights.buttons[i] == 0) { - gpio_put(LED_GPIO[i], 0); - } else { - gpio_put(LED_GPIO[i], 1); - } - } - /* start button sw_val index is offset by two with respect to LED_GPIO */ - if (time_us_64() - reactive_timeout_timestamp >= REACTIVE_TIMEOUT_MAX) { - if (!gpio_get(SW_GPIO[LED_GPIO_SIZE + 1])) { - gpio_put(LED_GPIO[LED_GPIO_SIZE - 1], 1); - } else { - gpio_put(LED_GPIO[LED_GPIO_SIZE - 1], 0); - } - } else { - if (lights_report.lights.buttons[LED_GPIO_SIZE - 1] == 0) { - gpio_put(LED_GPIO[LED_GPIO_SIZE - 1], 0); - } else { - gpio_put(LED_GPIO[LED_GPIO_SIZE - 1], 1); - } - } - } -} - -struct report { - uint16_t buttons; - uint8_t joy0; - uint8_t joy1; -} report; +lights_report_t lights_report; +report_t report; /** * Gamepad Mode @@ -205,9 +142,11 @@ void dma_handler() { **/ void core1_entry() { uint32_t counter = 0; + uint32_t rgb_idx = 0; while (1) { - ws2812b_update(++counter); - sleep_ms(5); + counter++; + if (counter % 32 == 0) ws2812b_mode(++rgb_idx); + sleep_ms(1); } } @@ -263,12 +202,6 @@ void init() { gpio_pull_up(SW_GPIO[i]); } - // Setup LED GPIO - for (int i = 0; i < LED_GPIO_SIZE; i++) { - gpio_init(LED_GPIO[i]); - gpio_set_dir(LED_GPIO[i], GPIO_OUT); - } - // Set listener bools kbm_report = false; @@ -282,11 +215,7 @@ void init() { } // RGB Mode Switching - if (!gpio_get(SW_GPIO[1])) { - ws2812b_mode = &turbocharger_color_cycle; - } else { - ws2812b_mode = &ws2812b_color_cycle; - } + ws2812b_mode = &ws2812b_color_cycle_v5; // Debouncing Mode debounce_mode = &debounce_eager; @@ -310,7 +239,6 @@ int main(void) { update_inputs(); report.buttons = debounce_mode(); loop_mode(); - update_lights(); } return 0; diff --git a/src/rgb/color_cycle_v5.c b/src/rgb/color_cycle_v5.c new file mode 100644 index 0000000..055e113 --- /dev/null +++ b/src/rgb/color_cycle_v5.c @@ -0,0 +1,79 @@ +/** + * Color cycle effect & reactive buttons for Pocket SDVX Pico v5 + * @author SpeedyPotato + **/ +const double WS2812B_BRIGHTNESS = 0.5; +const RGB_t COLOR_BLACK = {0, 0, 0}; +const RGB_t SW_LABEL_COLORS[] = { + {255, 255, 255}, // START + {255, 255, 255}, // BT-A + {255, 255, 255}, // BT-B + {255, 255, 255}, // BT-C + {255, 255, 255}, // BT-D + {255, 255, 255}, // FX-L + {255, 255, 255}, // FX-R +}; +const RGB_t SW_COLORS[] = { + {0, 0, 255}, // START + {255, 255, 255}, // BT-A + {255, 255, 255}, // BT-B + {255, 255, 255}, // BT-C + {255, 255, 255}, // BT-D + {255, 0, 0}, // FX-L + {255, 0, 0}, // FX-R +}; + +RGB_t ws2812b_data[WS2812B_LED_SIZE] = {0}; + +void ws2812b_color_cycle_v5(uint32_t counter) { + RGB_t base_color = color_wheel_rgbt(counter); + /* Peripheral RGB */ + for (int i = (SW_GPIO_SIZE - 2) * 2; i < WS2812B_LED_SIZE; i++) { + if (time_us_64() - reactive_timeout_timestamp >= REACTIVE_TIMEOUT_MAX) { + ws2812b_data[i] = base_color; + } else { + ws2812b_data[i].r = lights_report.lights.rgb[0].r; + ws2812b_data[i].g = lights_report.lights.rgb[0].g; + ws2812b_data[i].b = lights_report.lights.rgb[0].b; + } + } + /* Switches */ + for (int i = 0; i < SW_GPIO_SIZE - 3; i++) { + if (time_us_64() - reactive_timeout_timestamp >= REACTIVE_TIMEOUT_MAX) { + if ((report.buttons >> i) % 2 == 1) { + ws2812b_data[2 * i + 2] = SW_COLORS[i + 1]; + } else { + ws2812b_data[2 * i + 2] = COLOR_BLACK; + } + } else { + if (lights_report.lights.buttons[i] == 0) { + ws2812b_data[2 * i + 2] = COLOR_BLACK; + } else { + ws2812b_data[2 * i + 2] = SW_COLORS[i + 1]; + } + } + } + /* start button sw_val index is offset by two with respect to LED_GPIO */ + if (time_us_64() - reactive_timeout_timestamp >= REACTIVE_TIMEOUT_MAX) { + if ((report.buttons >> (SW_GPIO_SIZE - 1)) % 2 == 1) { + ws2812b_data[0] = SW_COLORS[0]; + } else { + ws2812b_data[0] = COLOR_BLACK; + } + } else { + if (lights_report.lights.buttons[SW_GPIO_SIZE - 3] == 0) { + ws2812b_data[0] = COLOR_BLACK; + } else { + ws2812b_data[0] = SW_COLORS[0]; + } + } + /* Switch Labels */ + for (int i = 0; i < SW_GPIO_SIZE - 2; i++) { + ws2812b_data[2 * i + 1] = SW_LABEL_COLORS[i]; + } + for (int i = 0; i < WS2812B_LED_SIZE; ++i) { + put_pixel(urgb_u32(ws2812b_data[i].r * WS2812B_BRIGHTNESS, + ws2812b_data[i].g * WS2812B_BRIGHTNESS, + ws2812b_data[i].b * WS2812B_BRIGHTNESS)); + } +} \ No newline at end of file diff --git a/src/rgb/rgb_include.h b/src/rgb/rgb_include.h index b4de733..77c3b78 100644 --- a/src/rgb/rgb_include.h +++ b/src/rgb/rgb_include.h @@ -1,12 +1,17 @@ +// clang-format off /** * Simple header file to include all files in the folder * @author SpeedyPotato - * - * To add a lighting mode, create a function which accepts a uint32_t as a parameter. - * Create lighting mode as desired and then add the #include here. + * + * To add a lighting mode, create a function which accepts a uint32_t as a + *parameter. Create lighting mode as desired and then add the #include here. **/ extern uint32_t enc_val[ENC_GPIO_SIZE]; +extern report_t report; +extern lights_report_t lights_report; +extern uint64_t reactive_timeout_timestamp; #include "ws2812b_util.c" #include "color_cycle.c" +#include "color_cycle_v5.c" #include "turbocharger.c" \ No newline at end of file diff --git a/src/rgb/ws2812b_util.c b/src/rgb/ws2812b_util.c index aae7f18..c364758 100644 --- a/src/rgb/ws2812b_util.c +++ b/src/rgb/ws2812b_util.c @@ -4,10 +4,6 @@ */ #include "ws2812.pio.h" -typedef struct { - uint8_t r, g, b; -} RGB_t; - /** * WS2812B RGB Format Helper **/ @@ -32,6 +28,31 @@ static inline uint32_t color_wheel(uint16_t wheel_pos) { } } +/** + * 768 Color Wheel Picker + * @param wheel_pos Color value, r->g->b->r... + **/ +static inline RGB_t color_wheel_rgbt(uint16_t wheel_pos) { + wheel_pos %= 768; + RGB_t init; + if (wheel_pos < 256) { + init.r = wheel_pos; + init.g = 255 - wheel_pos; + init.b = 0; + } else if (wheel_pos < 512) { + wheel_pos -= 256; + init.r = 255 - wheel_pos; + init.g = 0; + init.b = wheel_pos; + } else { + wheel_pos -= 512; + init.r = 0; + init.g = wheel_pos; + init.b = 255 - wheel_pos; + }; + return init; +} + /** * WS2812B RGB Assignment * @param pixel_grb The pixel color to set diff --git a/src/types.h b/src/types.h new file mode 100644 index 0000000..54c11d6 --- /dev/null +++ b/src/types.h @@ -0,0 +1,19 @@ +typedef struct { + uint8_t r, g, b; +} RGB_t; + +typedef struct { + uint16_t buttons; + uint8_t joy0; + uint8_t joy1; +} report_t; + +typedef struct { + uint8_t buttons[LED_GPIO_SIZE]; + RGB_t rgb[WS2812B_LED_ZONES]; +} lights_t; + +typedef union { + lights_t lights; + uint8_t raw[LED_GPIO_SIZE + WS2812B_LED_ZONES * 3]; +} lights_report_t; \ No newline at end of file diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c index 0c0aaaa..954445d 100644 --- a/src/usb_descriptors.c +++ b/src/usb_descriptors.c @@ -162,12 +162,9 @@ char const* string_desc_arr[] = { "FX-L", "FX-R", "Start", - "Left R", - "Left G", - "Left B", - "Right R", - "Right G", - "Right B", + "Controller R", + "Controller G", + "Controller B", }; static uint16_t _desc_str[64];