diff options
Diffstat (limited to 'src/split.c')
| -rw-r--r-- | src/split.c | 299 |
1 files changed, 158 insertions, 141 deletions
diff --git a/src/split.c b/src/split.c index 75505ff..7bc7e63 100644 --- a/src/split.c +++ b/src/split.c @@ -1,29 +1,34 @@ +#include "hardware/regs/io_bank0.h" +#include "hardware/structs/padsbank0.h" +#include "uart_rx.pio.h" +#include "uart_tx.pio.h" + #include "split.h" -#include "class/cdc/cdc_device.h" #include "util.h" #include "matrix.h" #include "hardware/pio.h" #include "hardware/irq.h" #include "hardware/gpio.h" +#include "hardware/address_mapped.h" #include "hardware/regs/intctrl.h" +#include "hardware/regs/pads_bank0.h" #include "hardware/uart.h" #include "hardware/timer.h" #include "hardware/clocks.h" #include "pico/time.h" #include "bsp/board.h" +#include "class/cdc/cdc_device.h" #include "tusb.h" + #include <stdint.h> #define UART_TIMEOUT 20 #define UART_BAUD 115200 - -/* same pin since half-duplex */ -#define UART_TX_PIN 0 -#define UART_RX_PIN 0 +#define UART_PIN 1 enum { - CMD_SCAN_MATRIX_REQ = 0x80, + CMD_SCAN_MATRIX_REQ = 0x0F, CMD_SCAN_MATRIX_RESP, CMD_STDIO_PUTS }; @@ -33,15 +38,16 @@ enum { LEFT, RIGHT }; static void uart_tx_init(void); static void uart_rx_init(void); +static void uart_full_init(void); -static void uart_enter_rx(void); static void uart_leave_rx(void); +static void uart_enter_rx(void); -static int uart_sync_rx(void); -static int uart_sync_tx(void); +static bool uart_await_rx(void); +static bool uart_await_tx(void); -static uint8_t uart_in_byte(void); -static void uart_out_byte(uint8_t c); +static uint8_t uart_rx_byte(void); +static void uart_tx_byte(uint8_t c); static uint uart_recv(uint8_t *data, uint len); static uint uart_send(const uint8_t *data, uint len); @@ -49,43 +55,11 @@ static uint uart_send(const uint8_t *data, uint len); static void irq_rx_cmd(uint8_t cmd); static void irq_rx(void); -static const uint16_t uart_tx_program_asm[] = { - // .wrap_target - 0x9fa0, // 0: pull block side 1 [7] - 0xf727, // 1: set x, 7 side 0 [7] - 0x6081, // 2: out pindirs, 1 - 0x0642, // 3: jmp x--, 2 [6] - // .wrap -}; - -static const uint16_t uart_rx_program_asm[] = { - // .wrap_target - 0x2020, // 0: wait 0 pin, 0 - 0xea27, // 1: set x, 7 [10] - 0x4001, // 2: in pins, 1 - 0x0642, // 3: jmp x--, 2 [6] - 0x00c8, // 4: jmp pin, 8 - 0xc020, // 5: irq wait 0 - 0x20a0, // 6: wait 1 pin, 0 - 0x0000, // 7: jmp 0 - 0x8020, // 8: push block - // .wrap -}; - -static const pio_program_t uart_tx_program = { - .instructions = uart_tx_program_asm, - .length = 4, - .origin = -1, -}; - -static const pio_program_t uart_rx_program = { - .instructions = uart_rx_program_asm, - .length = 9, - .origin = -1, -}; - static uint uart_tx_sm; +static uint uart_tx_sm_offset; + static uint uart_rx_sm; +static uint uart_rx_sm_offset; static bool scan_pending = false; @@ -93,93 +67,112 @@ void uart_tx_init(void) { pio_sm_config config; - uint offset; - int sm; - - sm = pio_claim_unused_sm(pio0, true); - ASSERT(sm >= 0); - uart_tx_sm = (uint) sm; - - offset = pio_add_program(pio0, &uart_tx_program); - pio_sm_set_pins_with_mask(pio0, uart_tx_sm, 0, 1 << UART_TX_PIN); - pio_sm_set_consecutive_pindirs(pio0, - uart_tx_sm, UART_TX_PIN, 1, true); - - config = pio_get_default_sm_config(); - sm_config_set_wrap(&config, offset, - offset + ARRLEN(uart_tx_program_asm) - 1); - sm_config_set_sideset(&config, 2, true, true); + + uart_tx_sm = CLAIM_UNUSED_SM(pio0); + uart_tx_sm_offset = pio_add_program(pio0, &uart_tx_program); + + config = uart_tx_program_get_default_config(uart_tx_sm_offset); sm_config_set_out_shift(&config, true, false, 32); - sm_config_set_out_pins(&config, UART_TX_PIN, 1); - sm_config_set_sideset_pins(&config, UART_TX_PIN); + sm_config_set_out_pins(&config, UART_PIN, 1); + sm_config_set_sideset_pins(&config, UART_PIN); sm_config_set_fifo_join(&config, PIO_FIFO_JOIN_TX); sm_config_set_clkdiv(&config, - (float) clock_get_hz(clk_sys) / (8 * 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); + pio_sm_init(pio0, uart_tx_sm, uart_tx_sm_offset, &config); + pio_sm_set_enabled(pio0, uart_tx_sm, false); } void uart_rx_init(void) { pio_sm_config config; - uint offset; - int sm; - - sm = pio_claim_unused_sm(pio0, true); - ASSERT(sm >= 0); - uart_rx_sm = (uint) sm; - offset = pio_add_program(pio0, &uart_rx_program); + uart_rx_sm = CLAIM_UNUSED_SM(pio0); + uart_rx_sm_offset = pio_add_program(pio0, &uart_rx_program); - config = pio_get_default_sm_config(); - sm_config_set_wrap(&config, offset, - offset + ARRLEN(uart_rx_program_asm) - 1); - sm_config_set_in_pins(&config, UART_RX_PIN); - sm_config_set_jmp_pin(&config, UART_RX_PIN); + config = uart_rx_program_get_default_config(uart_rx_sm_offset); + sm_config_set_in_pins(&config, UART_PIN); + sm_config_set_jmp_pin(&config, UART_PIN); 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 * 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); + pio_sm_init(pio0, uart_rx_sm, uart_rx_sm_offset, &config); + pio_sm_set_enabled(pio0, uart_rx_sm, false); } void -uart_enter_rx(void) +uart_full_init(void) { - while (!pio_sm_is_tx_fifo_empty(pio0, uart_tx_sm)); - /* even after fifo is empty, we still need to wait until last byte - * = max (1 start + 8 data + 1 stop + 1 par) is fully transmitted */ - sleep_us(1000000U * 11 / UART_BAUD); + pio_sm_set_pins_with_mask(pio0, uart_tx_sm, 0U, 1U << UART_PIN); + pio_sm_set_consecutive_pindirs(pio0, uart_tx_sm, UART_PIN, 1, true); - pio_sm_set_enabled(pio0, uart_tx_sm, false); - gpio_set_drive_strength(UART_TX_PIN, GPIO_DRIVE_STRENGTH_2MA); - pio_sm_set_pins_with_mask(pio0, - uart_tx_sm, 1U << UART_TX_PIN, 1U << UART_TX_PIN); - pio_sm_set_consecutive_pindirs(pio0, - uart_tx_sm, UART_TX_PIN, 1, false); - pio_sm_set_enabled(pio0, uart_rx_sm, true); + pio_gpio_init(pio0, UART_PIN); + gpio_pull_up(UART_PIN); + gpio_set_slew_rate(UART_PIN, GPIO_SLEW_RATE_FAST); + /* 1 => set INPUT and pull line HIGH from pullup + * 0 => set OUTPUT and pull line LOW from signal */ + gpio_set_oeover(UART_PIN, GPIO_OVERRIDE_INVERT); + + uart_rx_init(); + uart_tx_init(); + + pio_set_irq0_source_enabled(pio0, + 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, false); + pio_set_irq0_source_enabled(pio0, pis_interrupt0, true); + pio_set_irq0_source_enabled(pio0, pis_interrupt1, true); + + 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); + + pio_sm_set_enabled(pio0, uart_tx_sm, true); + uart_enter_rx(); } void uart_leave_rx(void) { - /* disable rx to not receive when we send */ + irq_set_enabled(USBCTRL_IRQ, false); pio_sm_set_enabled(pio0, uart_rx_sm, false); - pio_sm_set_consecutive_pindirs(pio0, - uart_tx_sm, UART_TX_PIN, 1, true); - pio_sm_set_pins_with_mask(UART_TX_PIN, - uart_tx_sm, 0, 1U << UART_TX_PIN); - gpio_set_drive_strength(UART_TX_PIN, GPIO_DRIVE_STRENGTH_12MA); + + /* because of OE override pindir true = INPUT (!) */ + pio_sm_set_consecutive_pindirs(pio0, uart_tx_sm, UART_PIN, 1, true); + + /* drive LOW with high drive-current for steep falling edges */ + pio_sm_set_pins_with_mask(pio0, uart_tx_sm, 0U, 1 << UART_PIN); + gpio_set_drive_strength(UART_PIN, GPIO_DRIVE_STRENGTH_12MA); + pio_sm_restart(pio0, uart_tx_sm); pio_sm_set_enabled(pio0, uart_tx_sm, true); } -int -uart_sync_rx(void) +void +uart_enter_rx(void) +{ + /* wait for tx fifo to empty and final byte to transmit + * + extra max. 1 start + 8 data + 1 stop + 1 par bits */ + while (!pio_sm_is_tx_fifo_empty(pio0, uart_tx_sm)); + sleep_us(1000000U * 11 / UART_BAUD); + pio_sm_set_enabled(pio0, uart_tx_sm, false); + + /* pull HIGH with low drive-current for steeper rising edge */ + gpio_set_drive_strength(UART_PIN, GPIO_DRIVE_STRENGTH_2MA); + pio_sm_set_pins_with_mask(pio0, uart_tx_sm, ~0U, 1 << UART_PIN); + + /* because of OE override pindir false = OUTPUT (!) */ + pio_sm_set_consecutive_pindirs(pio0, uart_tx_sm, UART_PIN, 1, false); + + pio_sm_set_enabled(pio0, uart_rx_sm, true); + irq_set_enabled(USBCTRL_IRQ, true); +} + +bool +uart_await_rx(void) { uint32_t start_ms; bool empty; @@ -191,11 +184,11 @@ uart_sync_rx(void) tud_task(); } while (board_millis() < start_ms + UART_TIMEOUT); - return empty; + return !empty; } -int -uart_sync_tx(void) +bool +uart_await_tx(void) { uint32_t start_ms; bool full; @@ -207,17 +200,17 @@ uart_sync_tx(void) tud_task(); } while (board_millis() < start_ms + UART_TIMEOUT); - return full; + return !full; } uint8_t -uart_in_byte(void) +uart_rx_byte(void) { return *(uint8_t*)((uintptr_t)&pio0->rxf[uart_rx_sm] + 3); } void -uart_out_byte(uint8_t c) +uart_tx_byte(uint8_t c) { pio_sm_put(pio0, uart_tx_sm, c); } @@ -227,13 +220,11 @@ uart_recv(uint8_t *data, uint len) { uint recv; - recv = 0; - while (recv < len) { + for (recv = 0; recv < len; recv++) { if (pio_sm_is_rx_fifo_empty(pio0, uart_rx_sm)) { - if (uart_sync_rx()) break; + if (!uart_await_rx()) break; } - *data++ = uart_in_byte(); - recv++; + *data++ = uart_rx_byte(); } return recv; @@ -245,13 +236,11 @@ uart_send(const uint8_t *data, uint len) uint sent; uart_leave_rx(); - sent = 0; - while (sent < len) { + for (sent = 0; sent < len; sent++) { if (pio_sm_is_tx_fifo_full(pio0, uart_tx_sm)) { - if (uart_sync_tx()) break; + if (!uart_await_tx()) break; } - uart_out_byte(*data++); - sent++; + uart_tx_byte(*data++); } uart_enter_rx(); @@ -291,9 +280,21 @@ irq_rx(void) { uint8_t cmd; - DEBUG("UART IRQ\n"); + (void) cmd; + (void) irq_rx_cmd; + + if (pio_interrupt_get(pio0, 0)) { + DEBUG("RX ERR"); + pio_interrupt_clear(pio0, 0); + } + + //DEBUG("UART IRQ"); + // while (!pio_sm_is_rx_fifo_empty(pio0, uart_rx_sm)) + // uart_rx_byte(); + // ASSERT(1 == 0); + while (!pio_sm_is_rx_fifo_empty(pio0, uart_rx_sm)) { - cmd = uart_in_byte(); + cmd = uart_rx_byte(); DEBUG("UART RX CMD %i\n", cmd); irq_rx_cmd(cmd); } @@ -302,20 +303,22 @@ irq_rx(void) void split_init(void) { - uart_tx_init(); - uart_rx_init(); + uart_full_init(); +} - pio_set_irq0_source_enabled(pio0, - 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, false); - pio_set_irq0_source_enabled(pio0, pis_interrupt0, false); +void +split_test(void) +{ + pio_sm_set_pins_with_mask(pio0, uart_tx_sm, 0U, 1U << UART_PIN); + pio_sm_set_consecutive_pindirs(pio0, uart_tx_sm, UART_PIN, 1, 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); + pio_gpio_init(pio0, UART_PIN); + gpio_pull_up(UART_PIN); + gpio_set_slew_rate(UART_PIN, GPIO_SLEW_RATE_FAST); - uart_enter_rx(); + /* 1 => set INPUT and pull line HIGH from pullup + * 0 => set OUTPUT and pull line LOW from signal */ + gpio_set_oeover(UART_PIN, GPIO_OVERRIDE_INVERT); } void @@ -324,17 +327,20 @@ split_task(void) uint32_t start_ms; uint8_t cmd; - if (SPLIT_ROLE == SLAVE) { - if (scan_pending) { - scan_matrix(); - cmd = CMD_SCAN_MATRIX_RESP; - ASSERT(uart_send(&cmd, 1)); - scan_pending = false; - } - } else if (SPLIT_ROLE == MASTER) { + // if (!uart_await_tx()) + // return; + + // sleep_us(100); + // uart_leave_rx(); + // uart_tx_byte(0xAA); + // uart_enter_rx(); + + // return; + + if (SPLIT_ROLE == MASTER) { scan_pending = true; cmd = CMD_SCAN_MATRIX_REQ; - ASSERT(uart_send(&cmd, 1)); + ASSERT(uart_send(&cmd, 1) == 1); scan_matrix(); /* scan our side in parallel */ start_ms = board_millis(); while (scan_pending && board_millis() < start_ms + 50) @@ -342,5 +348,16 @@ split_task(void) if (scan_pending) WARN("Slave matrix scan timeout"); else DEBUG("Slave matrix scan success"); scan_pending = false; - } + } else { + if (!uart_await_rx()) + return; + cmd = uart_rx_byte(); + DEBUG("GOT RX: %i", cmd); + if (scan_pending) { + scan_matrix(); + cmd = CMD_SCAN_MATRIX_RESP; + ASSERT(uart_send(&cmd, 1) == 1); + scan_pending = false; + } + } } |
