diff --git a/pocket-reform-keyboard-fw/pocket-hid/CMakeLists.txt b/pocket-reform-keyboard-fw/pocket-hid/CMakeLists.txt index 3cbf88b..8267dd6 100644 --- a/pocket-reform-keyboard-fw/pocket-hid/CMakeLists.txt +++ b/pocket-reform-keyboard-fw/pocket-hid/CMakeLists.txt @@ -28,7 +28,7 @@ target_include_directories(${PROJECT} PUBLIC # in hw/bsp/FAMILY/family.cmake for details. family_configure_device_example(${PROJECT}) -target_link_libraries(${PROJECT} PRIVATE pico_stdlib pico_multicore tinyusb_device tinyusb_board hardware_pwm hardware_i2c) +target_link_libraries(${PROJECT} PRIVATE pico_stdlib pico_multicore tinyusb_device tinyusb_board hardware_pwm hardware_i2c hardware_pio) target_compile_definitions(${PROJECT} PUBLIC PICO_XOSC_STARTUP_DELAY_MULTIPLIER=64 diff --git a/pocket-reform-keyboard-fw/pocket-hid/src/main.c b/pocket-reform-keyboard-fw/pocket-hid/src/main.c index ee9fb80..635de36 100644 --- a/pocket-reform-keyboard-fw/pocket-hid/src/main.c +++ b/pocket-reform-keyboard-fw/pocket-hid/src/main.c @@ -40,6 +40,8 @@ #include "usb_descriptors.h" #include "oled.h" +#include "ws2812.pio.h" + #define KBD_VARIANT_QWERTY_US #define KBD_COLS 12 #define KBD_ROWS 6 @@ -81,9 +83,15 @@ static uint8_t pressed_scancodes[MAX_SCANCODES] = {0,0,0,0,0,0}; static int pressed_keys = 0; +static volatile uint32_t led_value = 0; + void hid_task(void); +void led_set(uint32_t rgb); void led_task(uint32_t rgb); -void led_core(void); +void led_mod_hue(int d); +void led_mod_brightness(int d); +void led_set_brightness(int b); +void led_cycle_hue(); int process_keyboard(uint8_t* resulting_scancodes); #define UART_ID uart1 @@ -124,17 +132,17 @@ void on_uart_rx() { if (c == '\n') { // TODO hack if (uart_rx_i>6) { - gfx_clear(); - //gfx_poke_str(0, 3, uart_rx_line); + gfx_clear(); + //gfx_poke_str(0, 3, uart_rx_line); // cut off after 4 digits uart_rx_line[4] = 0; float percentage = ((float)atoi(uart_rx_line))/(float)10.0; - char batinfo[32]; - sprintf(batinfo, " %.1f%%", (double)percentage); - insert_bat_icon(batinfo, 0, percentage); - gfx_poke_str(0, 0, batinfo); - gfx_flush(); + char batinfo[32]; + sprintf(batinfo, " %.1f%%", (double)percentage); + insert_bat_icon(batinfo, 0, percentage); + gfx_poke_str(0, 0, batinfo); + gfx_flush(); } uart_rx_i = 0; } @@ -241,9 +249,14 @@ int main(void) buf[1] = 0x01; i2c_write_blocking(i2c0, ADDR_SENSOR, buf, 2, false); - //multicore_launch_core1(led_core); - - led_task(0x000000); + PIO pio = pio0; + int sm = 0; + uint offset = pio_add_program(pio, &ws2812_program); + + ws2812_program_init(pio, sm, offset, PIN_LEDS, 800000, false); + + led_set_brightness(0x80); + gfx_init(false); anim_hello(); @@ -292,7 +305,7 @@ void tud_resume_cb(void) int __attribute__((optimize("Os"))) delay300ns() { // ~300ns asm volatile( - "mov r0, #6\n" // 1 cycle (was 10) + "mov r0, #9\n" // 1 cycle (was 10) "loop1: sub r0, r0, #1\n" // 1 cycle "bne loop1\n" // 2 cycles if loop taken, 1 if not ); @@ -402,62 +415,23 @@ int process_keyboard(uint8_t* resulting_scancodes) { // Is circle key pressed? // FIXME HACK - if (keycode == KEY_COMPOSE && (matrix_state[0] - || matrix_state[1] - || matrix_state[2] - || matrix_state[3] - || matrix_state[4] - || matrix_state[5] - || matrix_state[6] - || matrix_state[7] - || matrix_state[8] - || matrix_state[11] + if (keycode == KEY_COMPOSE && + ( matrix_state[1] + || matrix_state[10] ) && !command_sent) { - if (matrix_state[0]) { - // ESC + if (matrix_state[1]) { + // 1 //remote_turn_som_power_on(); - uart_puts(UART_ID, "1p\r\n"); - led_task(0x010101); + uart_puts(UART_ID, "\r\n1p\r\n"); + led_set_brightness(10); command_sent = 1; //anim_hello(); - } else if (matrix_state[11]) { + } else if (matrix_state[10]) { //remote_turn_som_power_off(); - led_task(0x000000); - uart_puts(UART_ID, "0p\r\n"); + led_set_brightness(0); + uart_puts(UART_ID, "\r\n0p\r\n"); command_sent = 1; - } else if (matrix_state[1]) { - // 1 - led_task(0x444444); - command_sent = 1; - } else if (matrix_state[2]) { - // 2 - led_task(0x222222); - command_sent = 1; - } else if (matrix_state[3]) { - // 3 - led_task(0x111111); - command_sent = 1; - } else if (matrix_state[4]) { - // 4 - led_task(0x010101); - command_sent = 1; - } else if (matrix_state[5]) { - // 5 - led_task(0x220022); - command_sent = 1; - } else if (matrix_state[6]) { - // 6 - led_task(0x110011); - command_sent = 1; - } else if (matrix_state[7]) { - // 7 - led_task(0x000022); - command_sent = 1; - } else if (matrix_state[8]) { - // 8 - led_task(0x000000); - command_sent = 1; - } + } } else if (keycode == HID_KEY_EXECUTE) { fn_key = 1; //active_matrix = matrix_fn; @@ -592,6 +566,17 @@ static void send_hid_report(uint8_t report_id) } else { tud_hid_mouse_report(REPORT_ID_MOUSE, (uint8_t)buttons, -2*nx, -2*ny, 0, 0); } + + // HACK hue/value wheel + if (matrix_state[KBD_COLS*4+0]) { + if (ny) { + led_mod_brightness(ny); + } + if (nx) { + led_mod_hue(nx); + } + } + } else { //if (buttons != prev_buttons) { tud_hid_mouse_report(REPORT_ID_MOUSE, (uint8_t)buttons, 0, 0, 0, 0); @@ -655,47 +640,15 @@ static void send_hid_report(uint8_t report_id) } } -int led_counter = 0; -int rgb_channel = 0; -int rgb_val = 0; +void led_task(uint32_t color) { + uint32_t pixel_grb = color; -void led_task(uint32_t rgb) { - uint32_t color = rgb; - - for (int j=0; j<4; j++) { - for (int y=0; y<6; y++) { - int w = 12; - if (y==5) w = 4; - for (int x=0; x=0; i--) { - if (bits & (1<<23)) { - // one - gpio_put(PIN_LEDS, 1); - delay300ns(); - delay300ns(); - delay300ns(); - gpio_put(PIN_LEDS, 0); - // ~600ms delay - delay300ns(); - delay300ns(); - } else { - // zero - gpio_put(PIN_LEDS, 1); - delay300ns(); - gpio_put(PIN_LEDS, 0); - // ~1.2ms delay - delay300ns(); - delay300ns(); - delay300ns(); - delay300ns(); - //delay300ns(); - } - bits <<= 1; - } - } - } + for (int y=0; y<6; y++) { + int w = 12; + if (y==5) w = 4; + for (int x=0; x> 8; + q = (hsv.v * (255 - ((hsv.s * remainder) >> 8))) >> 8; + t = (hsv.v * (255 - ((hsv.s * (255 - remainder)) >> 8))) >> 8; + + switch (region) + { + case 0: + rgb.r = hsv.v; rgb.g = t; rgb.b = p; + break; + case 1: + rgb.r = q; rgb.g = hsv.v; rgb.b = p; + break; + case 2: + rgb.r = p; rgb.g = hsv.v; rgb.b = t; + break; + case 3: + rgb.r = p; rgb.g = q; rgb.b = hsv.v; + break; + case 4: + rgb.r = t; rgb.g = p; rgb.b = hsv.v; + break; + default: + rgb.r = hsv.v; rgb.g = p; rgb.b = q; + break; + } + + return rgb; } +void led_set(uint32_t rgb) { + led_task(rgb); +} + +void led_set_hsv() { + HsvColor hsv; + RgbColor rgb; + hsv.h = led_hue; + hsv.s = 0xff; + hsv.v = led_brightness; + + rgb = HsvToRgb(hsv); + led_set((rgb.r<<16)|(rgb.g<<8)|(rgb.b)); +} + +void led_mod_brightness(int d) { + led_brightness+=d; + if (led_brightness>0xff) led_brightness = 0xff; + if (led_brightness<0) led_brightness = 0; + led_set_hsv(); +} + +void led_mod_hue(int d) { + led_hue+=d; + if (led_hue>0xff) led_hue = 0xff; + if (led_hue<0) led_hue = 0; + led_set_hsv(); +} + +void led_set_brightness(int b) { + led_brightness = b; + led_set_hsv(); +} + +void led_cycle_hue() { + led_hue++; + if (led_hue>0xff) led_hue = 0; + led_set_hsv(); +} + + // Invoked when sent REPORT successfully to host // Application can use this to send the next report // Note: For composite reports, report[0] is report ID diff --git a/pocket-reform-keyboard-fw/pocket-hid/src/ws2812.pio b/pocket-reform-keyboard-fw/pocket-hid/src/ws2812.pio new file mode 100644 index 0000000..3c31fd6 --- /dev/null +++ b/pocket-reform-keyboard-fw/pocket-hid/src/ws2812.pio @@ -0,0 +1,85 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +.program ws2812 +.side_set 1 + +.define public T1 2 +.define public T2 5 +.define public T3 3 + +.lang_opt python sideset_init = pico.PIO.OUT_HIGH +.lang_opt python out_init = pico.PIO.OUT_HIGH +.lang_opt python out_shiftdir = 1 + +.wrap_target +bitloop: + out x, 1 side 0 [T3 - 1] ; Side-set still takes place when instruction stalls + jmp !x do_zero side 1 [T1 - 1] ; Branch on the bit we shifted out. Positive pulse +do_one: + jmp bitloop side 1 [T2 - 1] ; Continue driving high, for a long pulse +do_zero: + nop side 0 [T2 - 1] ; Or drive low, for a short pulse +.wrap + +% c-sdk { +#include "hardware/clocks.h" + +static inline void ws2812_program_init(PIO pio, uint sm, uint offset, uint pin, float freq, bool rgbw) { + + pio_gpio_init(pio, pin); + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true); + + pio_sm_config c = ws2812_program_get_default_config(offset); + sm_config_set_sideset_pins(&c, pin); + sm_config_set_out_shift(&c, false, true, rgbw ? 32 : 24); + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + + int cycles_per_bit = ws2812_T1 + ws2812_T2 + ws2812_T3; + float div = clock_get_hz(clk_sys) / (freq * cycles_per_bit); + sm_config_set_clkdiv(&c, div); + + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} +%} + +.program ws2812_parallel + +.define public T1 2 +.define public T2 5 +.define public T3 3 + +.wrap_target + out x, 32 + mov pins, !null [T1-1] + mov pins, x [T2-1] + mov pins, null [T3-2] +.wrap + +% c-sdk { +#include "hardware/clocks.h" + +static inline void ws2812_parallel_program_init(PIO pio, uint sm, uint offset, uint pin_base, uint pin_count, float freq) { + for(uint i=pin_base; i