diff --git a/Production/Firmware/chu_pico.uf2 b/Production/Firmware/chu_pico.uf2 index a7955af..a996468 100644 Binary files a/Production/Firmware/chu_pico.uf2 and b/Production/Firmware/chu_pico.uf2 differ diff --git a/firmware/src/CMakeLists.txt b/firmware/src/CMakeLists.txt index 86ebe41..dc7fa09 100644 --- a/firmware/src/CMakeLists.txt +++ b/firmware/src/CMakeLists.txt @@ -8,7 +8,7 @@ link_libraries(pico_multicore pico_stdlib hardware_i2c hardware_spi function(make_firmware board board_def) add_executable(${board} - main.c slider.c air.c rgb.c save.c config.c commands.c + main.c slider.c air.c rgb.c button.c save.c config.c commands.c cli.c lzfx.c vl53l0x.c mpr121.c usb_descriptors.c) target_compile_definitions(${board} PUBLIC ${board_def}) pico_enable_stdio_usb(${board} 1) diff --git a/firmware/src/board_defs.h b/firmware/src/board_defs.h index bfa38a7..bdd468c 100644 --- a/firmware/src/board_defs.h +++ b/firmware/src/board_defs.h @@ -17,12 +17,13 @@ #define IR_GROUP_ABC_GPIO { 3, 4, 5 } #define IR_SIG_ADC_CHANNEL { 0, 1 } +#define BUTTON_DEF { 13, 14, 15 } #define RGB_MAIN_PIN 2 #define RGB_TOWER_LEFT_PIN 0 #define RGB_TOWER_RIGHT_PIN 1 #define RGB_ORDER GRB // or RGB -#define NKRO_KEYMAP "1aqz2swx3dec4frv5gtb6hyn7jum8ki90olp,." +#define NKRO_KEYMAP "1aqz2swx3dec4frv5gtb6hyn7jum8ki90olp,.[]\\" #else #endif diff --git a/firmware/src/button.c b/firmware/src/button.c new file mode 100644 index 0000000..ae3f602 --- /dev/null +++ b/firmware/src/button.c @@ -0,0 +1,82 @@ +/* + * Controller Buttons + * WHowe + * + */ + +#include "button.h" + +#include +#include + +#include "hardware/gpio.h" +#include "hardware/timer.h" + +#include "board_defs.h" + +static const uint8_t button_gpio[] = BUTTON_DEF; + +#define BUTTON_NUM (sizeof(button_gpio)) + +static bool sw_val[BUTTON_NUM]; /* true if pressed */ +static uint64_t sw_freeze_time[BUTTON_NUM]; + +static uint16_t button_reading; + +void button_init() +{ + for (int i = 0; i < BUTTON_NUM; i++) { + sw_val[i] = false; + sw_freeze_time[i] = 0; + int8_t gpio = button_gpio[i]; + gpio_init(gpio); + gpio_set_function(gpio, GPIO_FUNC_SIO); + gpio_set_dir(gpio, GPIO_IN); + gpio_pull_up(gpio); + } + + /* make valid initial reading */ + button_reading = 0; + for (int i = 0; i < BUTTON_NUM; i++) { + sw_val[i] = !gpio_get(button_gpio[i]); + if (sw_val[i]) { + button_reading |= (1 << i); + } + } +} + +uint8_t button_num() +{ + return BUTTON_NUM; +} + +/* If a switch flips, it freezes for a while */ +#define DEBOUNCE_FREEZE_TIME_US 3000 +void button_update() +{ + uint64_t now = time_us_64(); + uint16_t buttons = 0; + + for (int i = BUTTON_NUM - 1; i >= 0; i--) { + bool sw_pressed = !gpio_get(button_gpio[i]); + + if (now >= sw_freeze_time[i]) { + if (sw_pressed != sw_val[i]) { + sw_val[i] = sw_pressed; + sw_freeze_time[i] = now + DEBOUNCE_FREEZE_TIME_US; + } + } + + buttons <<= 1; + if (sw_val[i]) { + buttons |= 1; + } + } + + button_reading = buttons; +} + +uint16_t button_read() +{ + return button_reading; +} diff --git a/firmware/src/button.h b/firmware/src/button.h new file mode 100644 index 0000000..273c928 --- /dev/null +++ b/firmware/src/button.h @@ -0,0 +1,18 @@ +/* + * Controller Buttons + * WHowe + */ + +#ifndef BUTTON_H +#define BUTTON_H + +#include +#include +#include "hardware/flash.h" + +void button_init(); +uint8_t button_num(); +void button_update(); +uint16_t button_read(); + +#endif diff --git a/firmware/src/main.c b/firmware/src/main.c index 592db21..228354c 100644 --- a/firmware/src/main.c +++ b/firmware/src/main.c @@ -35,6 +35,7 @@ #include "slider.h" #include "air.h" #include "rgb.h" +#include "button.h" #include "lzfx.h" struct __attribute__((packed)) { @@ -82,10 +83,15 @@ static void gen_joy_report() /* to cope with Redboard mapping which I don't really understand why */ hid_joy.buttons = ((airmap >> 1) & 0x07) | ((airmap & 0x01) << 3) | (airmap & 0x30); + + uint16_t aux = button_read(); + hid_joy.buttons |= (aux & 0x01) ? 0x200 : 0; // START + hid_joy.buttons |= (aux & 0x02) ? 0x100 : 0; // SERVICE + hid_joy.buttons |= (aux & 0x04) ? 0x1000 : 0; // TEST } const uint8_t keycode_table[128][2] = { HID_ASCII_TO_KEYCODE }; -const uint8_t keymap[38 + 1] = NKRO_KEYMAP; // 32 keys, 6 air keys, 1 terminator +const uint8_t keymap[41 + 1] = NKRO_KEYMAP; // 32 keys, 6 air keys, 3 aux, 1 terminator static void gen_nkro_report() { for (int i = 0; i < 32; i++) { @@ -110,6 +116,18 @@ static void gen_nkro_report() hid_nkro.keymap[byte] &= ~(1 << bit); } } + + uint16_t aux = button_read(); + for (int i = 0; i < 3; i++) { + uint8_t code = keycode_table[keymap[38 + i]][1]; + uint8_t byte = code / 8; + uint8_t bit = code % 8; + if (aux & (1 << i)) { + hid_nkro.keymap[byte] |= (1 << bit); + } else { + hid_nkro.keymap[byte] &= ~(1 << bit); + } + } } static uint64_t last_hid_time = 0; @@ -172,6 +190,28 @@ static void aime_run() } } +static void runtime_ctrl() +{ + /* Just use long-press SERVICE to reset touch in runtime */ + static bool applied = false; + static uint64_t press_time = 0; + static bool last_svc_button = false; + bool svc_button = button_read() & 0x02; + + if (svc_button) { + if (!last_svc_button) { + press_time = time_us_64(); + applied = false; + } + if (!applied && (time_us_64() - press_time > 2000000)) { + slider_sensor_init(); + applied = true; + } + } + + last_svc_button = svc_button; +} + static mutex_t core1_io_lock; static void core1_loop() { @@ -199,10 +239,37 @@ static void core0_loop() slider_update(); air_update(); + button_update(); gen_joy_report(); gen_nkro_report(); report_usb_hid(); + + runtime_ctrl(); + } +} + +/* if certain key pressed when booting, enter update mode */ +static void update_check() +{ + const uint8_t pins[] = BUTTON_DEF; + int pressed = 0; + for (int i = 0; i < count_of(pins); i++) { + uint8_t gpio = pins[i]; + gpio_init(gpio); + gpio_set_function(gpio, GPIO_FUNC_SIO); + gpio_set_dir(gpio, GPIO_IN); + gpio_pull_up(gpio); + sleep_ms(1); + if (!gpio_get(gpio)) { + pressed++; + } + } + + if (pressed >= 2) { + sleep_ms(100); + reset_usb_boot(0, 2); + return; } } @@ -211,6 +278,9 @@ void init() sleep_ms(50); set_sys_clock_khz(150000, true); board_init(); + + update_check(); + tusb_init(); stdio_init_all(); @@ -218,6 +288,7 @@ void init() mutex_init(&core1_io_lock); save_init(0xca34cafe, &core1_io_lock); + button_init(); slider_init(); air_init(); rgb_init(); diff --git a/firmware/src/slider.c b/firmware/src/slider.c index 46cbc82..fd6d9ed 100644 --- a/firmware/src/slider.c +++ b/firmware/src/slider.c @@ -27,6 +27,14 @@ static uint16_t touch[3]; static unsigned touch_count[36]; static bool present[3]; +void slider_sensor_init() +{ + for (int m = 0; m < 3; m++) { + mpr121_init(MPR121_ADDR + m); + } + slider_update_config(); +} + void slider_init() { i2c_init(I2C_PORT, I2C_FREQ); @@ -35,10 +43,7 @@ void slider_init() gpio_pull_up(I2C_SDA); gpio_pull_up(I2C_SCL); - for (int m = 0; m < 3; m++) { - present[m] = mpr121_init(MPR121_ADDR + m); - } - slider_update_config(); + slider_sensor_init(); } const char *slider_sensor_status() diff --git a/firmware/src/slider.h b/firmware/src/slider.h index fb2495a..92e5d07 100644 --- a/firmware/src/slider.h +++ b/firmware/src/slider.h @@ -10,6 +10,7 @@ #include void slider_init(); +void slider_sensor_init(); void slider_update(); bool slider_touched(unsigned key); const uint16_t *slider_raw();