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 6defee37f9939991bbf3152e2cd4e18593baa541
parent 20c38dd87e618713ff9bd131e39cc95dfdb949c8
Author: Louis Burda <quent.burda@gmail.com>
Date:   Tue, 29 Nov 2022 04:50:45 +0100

Fix pio uart integration with neopix pio

Diffstat:
Msrc/main.c | 4+++-
Msrc/neopix.c | 14+++++++++-----
Msrc/neopix.h | 2+-
Msrc/split.c | 81++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/util.c | 22++++++++++++----------
Msrc/util.h | 15+++++++++------
6 files changed, 79 insertions(+), 59 deletions(-)

diff --git a/src/main.c b/src/main.c @@ -45,11 +45,13 @@ main(void) board_init(); tud_init(BOARD_TUD_RHPORT); usb_stdio_init(); - neopix_init(&onboard_led, pio0, 0, 25); + neopix_init(&onboard_led, ONBOARD_LED_PIN); matrix_init(); split_init(); //hid_init(); + ASSERT(1 == 0); + while (true) { tud_task(); blink_task(); diff --git a/src/neopix.c b/src/neopix.c @@ -1,15 +1,19 @@ -#include "hardware/pio.h" - #include "neopix.h" #include "ws2812.pio.h" +#include "util.h" + +#include "hardware/pio.h" void -neopix_init(struct neopix *pix, PIO pio, uint sm, uint pin) +neopix_init(struct neopix *pix, uint pin) { uint offset; + int sm; - pix->sm = sm; - pix->pio = pio; + pix->pio = pio0; + sm = pio_claim_unused_sm(pix->pio, true); + ASSERT(sm >= 0); + pix->sm = (uint) sm; pix->pin = pin; offset = pio_add_program(pix->pio, &ws2812_program); ws2812_program_init(pix->pio, pix->sm, offset, diff --git a/src/neopix.h b/src/neopix.h @@ -12,7 +12,7 @@ struct neopix { bool init; }; -void neopix_init(struct neopix *pix, PIO pio, uint sm, uint pin); +void neopix_init(struct neopix *pix, uint pin); void neopix_put(struct neopix *pix, uint32_t rgb); inline uint32_t diff --git a/src/split.c b/src/split.c @@ -1,4 +1,5 @@ #include "split.h" +#include "class/cdc/cdc_device.h" #include "util.h" #include "matrix.h" @@ -16,8 +17,10 @@ #define UART_TIMEOUT 20 #define UART_BAUD 115200 + +/* same pin since half-duplex */ #define UART_TX_PIN 0 -#define UART_RX_PIN 1 +#define UART_RX_PIN 0 enum { CMD_SCAN_MATRIX_REQ = 0x80, @@ -30,12 +33,18 @@ enum { LEFT, RIGHT }; static void uart_tx_init(void); static void uart_rx_init(void); + static void uart_enter_rx(void); static void uart_leave_rx(void); + static int uart_sync_rx(void); static int uart_sync_tx(void); -static bool uart_recv(uint8_t *data, uint len); -static bool uart_send(const uint8_t *data, uint len); + +static uint8_t uart_in_byte(void); +static void uart_out_byte(uint8_t c); + +static uint uart_recv(uint8_t *data, uint len); +static uint uart_send(const uint8_t *data, uint len); static void irq_rx_cmd(uint8_t cmd); static void irq_rx(void); @@ -105,7 +114,7 @@ uart_tx_init(void) sm_config_set_sideset_pins(&config, UART_TX_PIN); sm_config_set_fifo_join(&config, PIO_FIFO_JOIN_TX); sm_config_set_clkdiv(&config, - (float) clock_get_hz(clk_sys) / (8.f * UART_BAUD)); + (float) clock_get_hz(clk_sys) / (8 * UART_BAUD)); pio_sm_init(pio0, uart_tx_sm, offset, &config); pio_sm_set_enabled(pio0, uart_tx_sm, true); @@ -132,7 +141,7 @@ uart_rx_init(void) sm_config_set_in_shift(&config, true, false, 32); sm_config_set_fifo_join(&config, PIO_FIFO_JOIN_RX); sm_config_set_clkdiv(&config, - (float) clock_get_hz(clk_sys) / (8.f * UART_BAUD)); + (float) clock_get_hz(clk_sys) / (8 * UART_BAUD)); pio_sm_init(pio0, uart_rx_sm, offset, &config); pio_sm_set_enabled(pio0, uart_rx_sm, true); @@ -201,7 +210,19 @@ uart_sync_tx(void) return full; } -bool +uint8_t +uart_in_byte(void) +{ + return *(uint8_t*)((uintptr_t)&pio0->rxf[uart_rx_sm] + 3); +} + +void +uart_out_byte(uint8_t c) +{ + pio_sm_put(pio0, uart_tx_sm, c); +} + +uint uart_recv(uint8_t *data, uint len) { uint recv; @@ -211,14 +232,14 @@ uart_recv(uint8_t *data, uint len) if (pio_sm_is_rx_fifo_empty(pio0, uart_rx_sm)) { if (uart_sync_rx()) break; } - *data++ = *(uint8_t*)((uintptr_t)&pio0->rxf[uart_rx_sm] + 3); + *data++ = uart_in_byte(); recv++; } - return recv == len; + return recv; } -bool +uint uart_send(const uint8_t *data, uint len) { uint sent; @@ -229,20 +250,18 @@ uart_send(const uint8_t *data, uint len) if (pio_sm_is_tx_fifo_full(pio0, uart_tx_sm)) { if (uart_sync_tx()) break; } - pio_sm_put(pio0, uart_tx_sm, *data++); + uart_out_byte(*data++); sent++; } uart_enter_rx(); - return sent == len; + return sent; } void irq_rx_cmd(uint8_t cmd) { - char buf[64]; - uint8_t c; - uint len; + uint8_t buf[64]; switch (cmd) { case CMD_SCAN_MATRIX_REQ: @@ -258,20 +277,9 @@ irq_rx_cmd(uint8_t cmd) case CMD_STDIO_PUTS: if (SPLIT_ROLE != MASTER) break; - len = 0; - while (uart_recv(&c, 1) && c) { - 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(); - } + memset(buf, 0, sizeof(buf)); + uart_recv(buf, sizeof(buf)-1); + printf("SLAVE: %s\n", buf); return; } @@ -283,8 +291,10 @@ irq_rx(void) { uint8_t cmd; - while (uart_is_readable(uart0)) { - uart_recv(&cmd, 1); + DEBUG("UART IRQ\n"); + while (!pio_sm_is_rx_fifo_empty(pio0, uart_rx_sm)) { + cmd = uart_in_byte(); + DEBUG("UART RX CMD %i\n", cmd); irq_rx_cmd(cmd); } } @@ -296,17 +306,16 @@ split_init(void) uart_rx_init(); pio_set_irq0_source_enabled(pio0, - pis_sm0_rx_fifo_not_empty + uart_rx_sm, true); + pis_sm0_rx_fifo_not_empty + uart_rx_sm, false); pio_set_irq0_source_enabled(pio0, - pis_sm0_tx_fifo_not_full + uart_tx_sm, true); - pio_set_irq0_source_enabled(pio0, pis_interrupt0, true); + pis_sm0_tx_fifo_not_full + uart_tx_sm, false); + pio_set_irq0_source_enabled(pio0, pis_interrupt0, false); irq_set_priority(PIO0_IRQ_0, PICO_HIGHEST_IRQ_PRIORITY); irq_set_exclusive_handler(PIO0_IRQ_0, irq_rx); irq_set_enabled(PIO0_IRQ_0, true); uart_enter_rx(); - } void @@ -319,13 +328,13 @@ split_task(void) if (scan_pending) { scan_matrix(); cmd = CMD_SCAN_MATRIX_RESP; - uart_send(&cmd, 1); + ASSERT(uart_send(&cmd, 1)); scan_pending = false; } } else if (SPLIT_ROLE == MASTER) { scan_pending = true; cmd = CMD_SCAN_MATRIX_REQ; - uart_send(&cmd, 1); + ASSERT(uart_send(&cmd, 1)); scan_matrix(); /* scan our side in parallel */ start_ms = board_millis(); while (scan_pending && board_millis() < start_ms + 50) diff --git a/src/util.c b/src/util.c @@ -12,20 +12,24 @@ int loglevel = LOG_DEBUG; static void __attribute__((format(printf, 1, 0))) -panic_task(const char *fmtstr, va_list ap) +panic_task(const char *fmtstr, va_list ap, uint32_t sleep_ms) { + static uint32_t start_ms = 0; va_list cpy; - char c; if (!tud_cdc_available()) return; - if (!tud_cdc_read(&c, 1)) + if (!start_ms) start_ms = board_millis(); + + if (board_millis() < start_ms + sleep_ms) return; va_copy(cpy, ap); vprintf(fmtstr, cpy); printf("\n\r"); + + start_ms += sleep_ms; } static void @@ -36,12 +40,12 @@ blink_task(struct neopix *pix, uint32_t blink_ms) if (!start_ms) start_ms = board_millis(); - if (board_millis() - start_ms < blink_ms) + if (board_millis() < start_ms + blink_ms) return; neopix_put(pix, neopix_u32rgb(255 * led_state, 0, 0)); - led_state ^= true; + start_ms += blink_ms; } @@ -71,13 +75,11 @@ blink_panic(const char *fmtstr, ...) va_start(ap, fmtstr); - if (!onboard_led.init) - neopix_init(&onboard_led, pio0, 0, ONBOARD_LED_PIN); - while (1) { tud_task(); - panic_task(fmtstr, ap); - blink_task(&onboard_led, 200); + panic_task(fmtstr, ap, 1000); + if (onboard_led.init) + blink_task(&onboard_led, 200); } va_end(ap); diff --git a/src/util.h b/src/util.h @@ -5,13 +5,16 @@ #define ARRLEN(x) (sizeof(x) / sizeof((x)[0])) -#define ERR(...) stdio_log(LOG_ERR, __VA_ARGS__) -#define WARN(...) stdio_log(LOG_WARN, __VA_ARGS__) -#define INFO(...) stdio_log(LOG_INFO, __VA_ARGS__) -#define DEBUG(...) stdio_log(LOG_DEBUG, __VA_ARGS__) +#define ERR(...) stdio_log(LOG_ERR, "ERR : " __VA_ARGS__) +#define WARN(...) stdio_log(LOG_WARN, "WARN : " __VA_ARGS__) +#define INFO(...) stdio_log(LOG_INFO, "INFO : " __VA_ARGS__) +#define DEBUG(...) stdio_log(LOG_DEBUG, "DEBUG: " __VA_ARGS__) + #define PANIC(...) blink_panic(__VA_ARGS__); -#define ASSERT(cond) blink_panic("Assertion failed: (%s) in %s:%i", \ - #cond, __FILE__, __LINE__) +#define ASSERT(cond) do { \ + if (!(cond)) blink_panic("Assertion failed: (%s) in %s:%i", \ + #cond, __FILE__, __LINE__); \ + } while (0) enum { LOG_NONE,