sxkbd

Firmware for RP2040-based corne split keyboard
git clone https://git.sinitax.com/sinitax/sxkbd
Log | Files | Refs | Submodules | README | LICENSE | sfeed.txt

commit a90347438e51bbd5f65c1c58c76ba339df7fc814
parent a7bfb47f666c8fadffb80b1beeee1905ad3fe029
Author: Louis Burda <quent.burda@gmail.com>
Date:   Tue, 29 Nov 2022 00:53:17 +0100

Refactoring and added sdk uart (not working)

Diffstat:
MCMakeLists.txt | 9+++++++++
MMakefile | 30+++++++++++++++++++++---------
Dcompile_commands.json | 128-------------------------------------------------------------------------------
Msrc/hid.c | 65++---------------------------------------------------------------
Msrc/main.c | 69++++++++++-----------------------------------------------------------
Asrc/matrix.c | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/matrix.h | 17+++++++++++++++++
Asrc/split.c | 124+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/split.h | 4++++
Asrc/usb_stdio.c | 40++++++++++++++++++++++++++++++++++++++++
Asrc/usb_stdio.h | 3+++
Msrc/util.c | 2+-
12 files changed, 284 insertions(+), 260 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt @@ -14,8 +14,11 @@ target_sources(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/util.c ${CMAKE_CURRENT_SOURCE_DIR}/src/hid.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/split.c ${CMAKE_CURRENT_SOURCE_DIR}/src/neopix.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/matrix.c ${CMAKE_CURRENT_SOURCE_DIR}/src/keymap.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_stdio.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) @@ -24,6 +27,7 @@ target_include_directories(${PROJECT} PUBLIC ${PICO_SDK_PATH}/src/rp2_common/hardware_gpio/include ${PICO_SDK_PATH}/src/rp2_common/hardware_pio/include ${PICO_SDK_PATH}/src/rp2_common/hardware_timer/include + ${PICO_SDK_PATH}/src/rp2_common/hardware_uart/include ) target_link_libraries(${PROJECT} PRIVATE @@ -40,6 +44,11 @@ target_compile_options(pico_stdio INTERFACE -Wno-unused-parameter ) +target_compile_options(${PROJECT} PRIVATE + "-DSPLIT_SIDE=${SPLIT_LEFT}" + "-DSPLIT_ROLE=${SPLIT_ROLE}" +) + family_configure_target(${PROJECT}) family_add_default_example_warnings(${PROJECT}) suppress_tinyusb_warnings() diff --git a/Makefile b/Makefile @@ -1,22 +1,34 @@ FAMILY ?= rp2040 PICO_SDK_PATH ?= lib/picosdk -all: cmake +all: left clean: rm -rf .build -cmake: | $(PICO_SDK_PATH) .build - cmake -B .build -DFAMILY=$(FAMILY) -DPICO_SDK_PATH=$(PICO_SDK_PATH) - make -C .build +left: | $(PICO_SDK_PATH) .build/left + cmake -B .build/left -DFAMILY=$(FAMILY) -DPICO_SDK_PATH=$(PICO_SDK_PATH) \ + -DSPLIT_SIDE=LEFT -DSPLIT_ROLE=MASTER + make -C .build/left + +right: | $(PICO_SDK_PATH) .build/right + cmake -B .build/right -DFAMILY=$(FAMILY) -DPICO_SDK_PATH=$(PICO_SDK_PATH) \ + -DSPLIT_SIDE=RIGHT -DSPLIT_ROLE=SLAVE + make -C .build/right lib/picosdk: git submodule update --init lib/picosdk -.build: - mkdir $@ +.build/left: + mkdir -p $@ + +.build/right: + mkdir -p $@ + +flash_left: + picotool load .build/left/sxkbd.uf2 -flash: - picotool load .build/sxkbd.uf2 +flash_right: + picotool load .build/right/sxkbd.uf2 -.PHONY: all clean cmake upload +.PHONY: all clean left right upload diff --git a/compile_commands.json b/compile_commands.json @@ -1,128 +0,0 @@ -[ - { - "arguments": [ - "/usr/bin/arm-none-eabi-gcc", - "-DCFG_TUSB_MCU=OPT_MCU_RP2040", - "-DCFG_TUSB_OS=OPT_OS_PICO", - "-DLIB_PICO_BIT_OPS=1", - "-DLIB_PICO_BIT_OPS_PICO=1", - "-DLIB_PICO_BOOTSEL_VIA_DOUBLE_RESET=1", - "-DLIB_PICO_DIVIDER=1", - "-DLIB_PICO_DIVIDER_HARDWARE=1", - "-DLIB_PICO_DOUBLE=1", - "-DLIB_PICO_DOUBLE_PICO=1", - "-DLIB_PICO_FIX_RP2040_USB_DEVICE_ENUMERATION=1", - "-DLIB_PICO_FLOAT=1", - "-DLIB_PICO_FLOAT_PICO=1", - "-DLIB_PICO_INT64_OPS=1", - "-DLIB_PICO_INT64_OPS_PICO=1", - "-DLIB_PICO_MALLOC=1", - "-DLIB_PICO_MEM_OPS=1", - "-DLIB_PICO_MEM_OPS_PICO=1", - "-DLIB_PICO_PLATFORM=1", - "-DLIB_PICO_PRINTF=1", - "-DLIB_PICO_PRINTF_PICO=1", - "-DLIB_PICO_RUNTIME=1", - "-DLIB_PICO_STANDARD_LINK=1", - "-DLIB_PICO_STDIO=1", - "-DLIB_PICO_STDIO_UART=1", - "-DLIB_PICO_STDLIB=1", - "-DLIB_PICO_SYNC=1", - "-DLIB_PICO_SYNC_CORE=1", - "-DLIB_PICO_SYNC_CRITICAL_SECTION=1", - "-DLIB_PICO_SYNC_MUTEX=1", - "-DLIB_PICO_SYNC_SEM=1", - "-DLIB_PICO_TIME=1", - "-DLIB_PICO_UTIL=1", - "-DLIB_TINYUSB_BOARD=1", - "-DLIB_TINYUSB_DEVICE=1", - "-DPICO_BOARD=\"pico\"", - "-DPICO_BUILD=1", - "-DPICO_CMAKE_BUILD_TYPE=\"Release\"", - "-DPICO_COPY_TO_RAM=0", - "-DPICO_CXX_ENABLE_EXCEPTIONS=0", - "-DPICO_NO_FLASH=0", - "-DPICO_NO_HARDWARE=0", - "-DPICO_ON_DEVICE=1", - "-DPICO_RP2040_USB_DEVICE_ENUMERATION_FIX=1", - "-DPICO_TARGET_NAME=\"sxkbd\"", - "-DPICO_USE_BLOCKED_RAM=0", - "-I/snx/dev/sxkbd/src", - "-I/usr/share/pico-sdk/src/common/pico_stdlib/include", - "-I/usr/share/pico-sdk/src/rp2_common/hardware_gpio/include", - "-I/usr/share/pico-sdk/src/common/pico_base/include", - "-I/snx/dev/sxkbd/.build/generated/pico_base", - "-I/usr/share/pico-sdk/src/boards/include", - "-I/usr/share/pico-sdk/src/rp2_common/pico_platform/include", - "-I/usr/share/pico-sdk/src/rp2040/hardware_regs/include", - "-I/usr/share/pico-sdk/src/rp2_common/hardware_base/include", - "-I/usr/share/pico-sdk/src/rp2040/hardware_structs/include", - "-I/usr/share/pico-sdk/src/rp2_common/hardware_claim/include", - "-I/usr/share/pico-sdk/src/rp2_common/hardware_sync/include", - "-I/usr/share/pico-sdk/src/rp2_common/hardware_irq/include", - "-I/usr/share/pico-sdk/src/common/pico_sync/include", - "-I/usr/share/pico-sdk/src/common/pico_time/include", - "-I/usr/share/pico-sdk/src/rp2_common/hardware_timer/include", - "-I/usr/share/pico-sdk/src/common/pico_util/include", - "-I/usr/share/pico-sdk/src/rp2_common/hardware_uart/include", - "-I/usr/share/pico-sdk/src/rp2_common/hardware_divider/include", - "-I/usr/share/pico-sdk/src/rp2_common/pico_runtime/include", - "-I/usr/share/pico-sdk/src/rp2_common/hardware_clocks/include", - "-I/usr/share/pico-sdk/src/rp2_common/hardware_resets/include", - "-I/usr/share/pico-sdk/src/rp2_common/hardware_pll/include", - "-I/usr/share/pico-sdk/src/rp2_common/hardware_vreg/include", - "-I/usr/share/pico-sdk/src/rp2_common/hardware_watchdog/include", - "-I/usr/share/pico-sdk/src/rp2_common/hardware_xosc/include", - "-I/usr/share/pico-sdk/src/rp2_common/pico_printf/include", - "-I/usr/share/pico-sdk/src/rp2_common/pico_bootrom/include", - "-I/usr/share/pico-sdk/src/common/pico_bit_ops/include", - "-I/usr/share/pico-sdk/src/common/pico_divider/include", - "-I/usr/share/pico-sdk/src/rp2_common/pico_double/include", - "-I/usr/share/pico-sdk/src/rp2_common/pico_int64_ops/include", - "-I/usr/share/pico-sdk/src/rp2_common/pico_float/include", - "-I/usr/share/pico-sdk/src/rp2_common/pico_malloc/include", - "-I/usr/share/pico-sdk/src/rp2_common/boot_stage2/include", - "-I/usr/share/pico-sdk/src/common/pico_binary_info/include", - "-I/usr/share/pico-sdk/src/rp2_common/pico_stdio/include", - "-I/usr/share/pico-sdk/src/rp2_common/pico_stdio_uart/include", - "-I/snx/dev/sxkbd/lib/tinyusb/src", - "-I/snx/dev/sxkbd/lib/tinyusb/src/common", - "-I/snx/dev/sxkbd/lib/tinyusb/hw", - "-I/usr/share/pico-sdk/src/rp2_common/pico_fix/rp2040_usb_device_enumeration/include", - "-mcpu=cortex-m0plus", - "-mthumb", - "-O3", - "-DNDEBUG", - "-Wall", - "-Wextra", - "-Werror", - "-Wfatal-errors", - "-Wdouble-promotion", - "-Wfloat-equal", - "-Wshadow", - "-Wwrite-strings", - "-Wsign-compare", - "-Wmissing-format-attribute", - "-Wunreachable-code", - "-Wcast-align", - "-Wcast-qual", - "-Wnull-dereference", - "-Wuninitialized", - "-Wunused", - "-Wredundant-decls", - "-Wconversion", - "-Wcast-function-type", - "-Wstrict-overflow", - "-Wno-strict-aliasing", - "-ffunction-sections", - "-fdata-sections", - "-c", - "-o", - "CMakeFiles/sxkbd.dir/src/main.c.obj", - "/snx/dev/sxkbd/src/main.c" - ], - "directory": "/snx/dev/sxkbd/.build", - "file": "/snx/dev/sxkbd/src/main.c", - "output": "/snx/dev/sxkbd/.build/CMakeFiles/sxkbd.dir/src/main.c.obj" - } -] diff --git a/src/hid.c b/src/hid.c @@ -1,75 +1,14 @@ -#include "board.h" -#include "util.h" - -#include "hardware/timer.h" - -#define KEY_ROWS ARRLEN(matrix_row_pins) -#define KEY_COLS ARRLEN(matrix_col_pins) -#define KEY_COUNT (KEY_ROWS * KEY_COLS) - -static void handle_press(uint x, uint y); -static void handle_release(uint x, uint y); - -static const uint matrix_col_pins[] = { 4, 5, 6, 7 }; -static const uint matrix_row_pins[] = { 29, 28, 27, 26, 22, 20 }; - -//static uint press_index = 0; -static bool press_map[KEY_COUNT] = { 0 }; -//static uint32_t press_syms[KEY_COUNT] = { 0 }; -//static uint8_t press_order[KEY_COUNT] = { 0 }; - -void -handle_press(uint x, uint y) -{ - -} - -void -handle_release(uint x, uint y) -{ - -} +#include "hid.h" void hid_init(void) { - uint x, y; - - for (y = 0; y < ARRLEN(matrix_row_pins); y++) { - gpio_init(matrix_row_pins[y]); - gpio_set_dir(matrix_row_pins[y], GPIO_IN); - gpio_pull_up(matrix_row_pins[y]); - } - - for (x = 0; x < ARRLEN(matrix_col_pins); x++) { - gpio_init(matrix_col_pins[x]); - gpio_set_dir(matrix_col_pins[x], GPIO_OUT); - } + } void hid_task(void) { - bool pressed; - uint x, y; - - /* scan matrix */ - for (y = 0; y < ARRLEN(matrix_row_pins); y++) { - for (x = 0; x < ARRLEN(matrix_col_pins); x++) { - gpio_put(matrix_col_pins[x], 0); - busy_wait_us(5); - pressed = !gpio_get(matrix_row_pins[y]); - if (pressed && !press_map[y * KEY_COLS + x]) { - handle_press(x, y); - press_map[y * KEY_COLS + x] = true; - } else if (!pressed && press_map[y * KEY_COLS + x]) { - handle_release(x, y); - press_map[y * KEY_COLS + x] = false; - } - gpio_put(matrix_col_pins[x], 1); - busy_wait_us(5); - } - } /* assemble hid report */ } diff --git a/src/main.c b/src/main.c @@ -1,4 +1,7 @@ #include "board.h" +#include "usb_stdio.h" +#include "matrix.h" +#include "split.h" #include "hid.h" #include "keymap.h" #include "neopix.h" @@ -8,7 +11,6 @@ #include "class/cdc/cdc_device.h" #include "class/hid/hid.h" #include "device/usbd.h" -#include "pico/stdio/driver.h" #include "pico/stdlib.h" #include "bsp/board.h" #include "pico/time.h" @@ -25,21 +27,10 @@ enum { BLINK_SUSPENDED = 2500, }; -void stub_stdio_write(const char *buf, int len); -void stub_stdio_flush(void); -int stub_stdio_read(char *buf, int len); - bool send_hid_report(int id, bool state); void blink_task(void); -static struct stdio_driver usb_stdio = { - .out_chars = stub_stdio_write, - .out_flush = stub_stdio_flush, - .in_chars = stub_stdio_read, - .next = NULL -}; - static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; static bool hit_state = false; @@ -52,44 +43,24 @@ int main(void) { board_init(); - - stdio_set_driver_enabled(&usb_stdio, true); - stdio_init_all(); - - neopix_init(&onboard_led, pio0, 0, 25); tud_init(BOARD_TUD_RHPORT); - hid_init(); - - DEBUG("Init done."); + usb_stdio_init(); + neopix_init(&onboard_led, pio0, 0, 25); + matrix_init(); + split_init(); + //hid_init(); while (true) { tud_task(); blink_task(); - hid_task(); + split_task(); + //hid_task(); } return 0; } void -stub_stdio_write(const char *buf, int len) -{ - tud_cdc_write(buf, (uint32_t) len); -} - -void -stub_stdio_flush(void) -{ - tud_cdc_write_flush(); -} - -int -stub_stdio_read(char *buf, int len) -{ - return (int) tud_cdc_read(buf, (uint32_t) len); -} - -void tud_mount_cb(void) { blink_interval_ms = BLINK_MOUNTED; @@ -104,7 +75,6 @@ tud_umount_cb(void) void tud_suspend_cb(bool remote_wakeup_en) { - (void) remote_wakeup_en; blink_interval_ms = BLINK_SUSPENDED; } @@ -117,27 +87,17 @@ tud_resume_cb(void) void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { - (void) itf; - (void) rts; - (void) dtr; } void tud_cdc_rx_cb(uint8_t itf) { - (void) itf; } uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) { - (void) itf; - (void) report_id; - (void) report_type; - (void) buffer; - (void) reqlen; - return 0; } @@ -145,11 +105,6 @@ void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) { - (void) itf; - (void) report_id; - (void) report_type; - (void) buffer; - (void) bufsize; } void @@ -158,10 +113,6 @@ tud_hid_report_complete_cb(uint8_t instance, { uint8_t id; - (void) instance; - (void) report; - (void) len; - for (id = report[0] + 1; id < REPORT_ID_MAX; id++) { if (send_hid_report(id, hit_state)) break; diff --git a/src/matrix.c b/src/matrix.c @@ -0,0 +1,53 @@ +#include "keymap.h" + +#include "matrix.h" +#include "pico/types.h" +#include "hardware/gpio.h" +#include "hardware/timer.h" + +#include <string.h> + +static const uint matrix_row_pins[] = { 4, 5, 6, 7 }; +static const uint matrix_col_pins[] = { 29, 28, 27, 26, 22, 20 }; +static_assert(ARRLEN(matrix_row_pins) == KEY_ROWS); +static_assert(ARRLEN(matrix_col_pins) == KEY_COLS); + +bool prev_state_matrix[KEY_COUNT]; +bool state_matrix[KEY_COUNT]; + +void +matrix_init(void) +{ + uint x, y; + + for (y = 0; y < KEY_ROWS; y++) { + gpio_init(matrix_row_pins[y]); + gpio_set_dir(matrix_row_pins[y], GPIO_IN); + gpio_pull_up(matrix_row_pins[y]); + } + + for (x = 0; x < KEY_COLS; x++) { + gpio_init(matrix_col_pins[x]); + gpio_set_dir(matrix_col_pins[x], GPIO_OUT); + } +} + +void +scan_matrix(void) +{ + bool pressed; + uint x, y; + + memcpy(prev_state_matrix, state_matrix, sizeof(state_matrix)); + + for (y = 0; y < KEY_ROWS; y++) { + for (x = 0; x < KEY_COLS; x++) { + gpio_put(matrix_col_pins[x], 0); + busy_wait_us(5); + pressed = !gpio_get(matrix_row_pins[y]); + state_matrix[y * KEY_COLS + x] = pressed; + gpio_put(matrix_col_pins[x], 1); + busy_wait_us(5); + } + } +} diff --git a/src/matrix.h b/src/matrix.h @@ -0,0 +1,17 @@ +#pragma once + +#include "util.h" + +#include <stdint.h> + +#define KEY_ROWS 4 +#define KEY_COLS 6 +#define KEY_COUNT (KEY_ROWS * KEY_COLS) + +void matrix_init(void); +void scan_matrix(void); + +extern bool prev_state_matrix[KEY_COUNT]; +extern bool state_matrix[KEY_COUNT]; +extern uint32_t sym_matrix[KEY_COUNT]; + diff --git a/src/split.c b/src/split.c @@ -0,0 +1,124 @@ +#include "split.h" +#include "util.h" +#include "matrix.h" + +#include "hardware/gpio.h" +#include "hardware/regs/intctrl.h" +#include "hardware/uart.h" +#include "hardware/timer.h" +#include "bsp/board.h" +#include "tusb.h" + +#define UART_TX_PIN 0 +#define UART_RX_PIN 1 + +enum { + CMD_SCAN_MATRIX_REQ = 0x80, + CMD_SCAN_MATRIX_RESP, + CMD_STDIO_PUTS +}; + +enum { SLAVE, MASTER }; +enum { LEFT, RIGHT }; + +static void split_rx_cmd(uint8_t cmd); +static void split_rx(void); + +static bool scan_pending = false; + +void +split_rx_cmd(uint8_t cmd) +{ + char buf[64]; + uint8_t c; + uint len; + + switch (cmd) { + case CMD_SCAN_MATRIX_REQ: + if (SPLIT_ROLE != SLAVE); + break; + scan_pending = true; + return; + case CMD_SCAN_MATRIX_RESP: + if (SPLIT_ROLE != MASTER); + break; + scan_pending = false; + return; + case CMD_STDIO_PUTS: + if (SPLIT_ROLE != MASTER); + break; + len = 0; + while (uart_is_readable(uart0) && (c = uart_getc(uart0))) { + if (len == ARRLEN(buf)) { + tud_cdc_write(buf, len); + buf[0] = c; + len = 1; + } else { + buf[len++] = c; + } + } + if (len) { + tud_cdc_write(buf, len); + tud_cdc_write_flush(); + } + return; + } + + WARN("Unexpected uart cmd: %i", cmd); +} + +void +split_rx(void) +{ + while (uart_is_readable(uart0)) + split_rx_cmd(uart_getc(uart0)); +} + +void +split_init(void) +{ + uart_init(uart0, 2400); + + gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART); + gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART); + + uart_set_baudrate(uart0, 115200); + + uart_set_hw_flow(uart0, false, false); + + uart_set_format(uart0, 8, 1, UART_PARITY_NONE); + + uart_set_fifo_enabled(uart0, true); + + irq_set_exclusive_handler(UART0_IRQ, split_rx); + irq_set_enabled(UART0_IRQ, true); + + uart_set_irq_enables(uart0, true, false); +} + +void +split_task(void) +{ + uint32_t start_ms; + + if (SPLIT_ROLE == SLAVE) { + if (scan_pending) { + scan_matrix(); + uart_putc_raw(uart0, CMD_SCAN_MATRIX_RESP); + scan_pending = false; + } + uart_putc_raw(uart0, CMD_STDIO_PUTS); + uart_putc_raw(uart0, '.'); + uart_putc_raw(uart0, 0); + } else if (SPLIT_ROLE == MASTER) { + scan_pending = true; + uart_putc_raw(uart0, CMD_SCAN_MATRIX_REQ); + scan_matrix(); /* scan our side in parallel */ + start_ms = board_millis(); + while (scan_pending && board_millis() < start_ms + 50) + tud_task(); + if (scan_pending) WARN("Slave matrix scan timeout"); + else DEBUG("Slave matrix scan success"); + scan_pending = false; + } +} diff --git a/src/split.h b/src/split.h @@ -0,0 +1,4 @@ +#pragma once + +void split_init(void); +void split_task(void); diff --git a/src/usb_stdio.c b/src/usb_stdio.c @@ -0,0 +1,40 @@ +#include "usb_stdio.h" + +#include "pico/stdio/driver.h" +#include "tusb.h" + +static void usb_stdio_write(const char *buf, int len); +static void usb_stdio_flush(void); +static int usb_stdio_read(char *buf, int len); + +static struct stdio_driver usb_stdio = { + .out_chars = usb_stdio_write, + .out_flush = usb_stdio_flush, + .in_chars = usb_stdio_read, + .next = NULL +}; + +void +usb_stdio_write(const char *buf, int len) +{ + tud_cdc_write(buf, (uint32_t) len); +} + +void +usb_stdio_flush(void) +{ + tud_cdc_write_flush(); +} + +int +usb_stdio_read(char *buf, int len) +{ + return (int) tud_cdc_read(buf, (uint32_t) len); +} + +void +usb_stdio_init(void) +{ + stdio_set_driver_enabled(&usb_stdio, true); + stdio_init_all(); +} diff --git a/src/usb_stdio.h b/src/usb_stdio.h @@ -0,0 +1,3 @@ +#pragma once + +void usb_stdio_init(void); diff --git a/src/util.c b/src/util.c @@ -15,7 +15,7 @@ __attribute__((format(printf, 1, 0))) panic_task(const char *fmtstr, va_list ap) { va_list cpy; - char c; + char c; if (!tud_cdc_available()) return;